Are you new to 6502, NES, or even programming in general? Post any of your questions here. Remember - the only dumb question is the question that remains unasked.
unregistered wrote:
In nintendulator it pops up a small box that says "Bad opcode, CPU locked". So that is different...
Just for the record, this specifically means your program has hit an invalid instruction. It usually happens when your program counter runs through data instead of code.
This should be a fairly easy one to debug by logging, because it's pretty likely the program halts very soon after the issue, instead of a wild goose chase when it could be anything like before.
Debug by logging! Thank you Kasumi! Thanks also Dwedit and smkd... yall's suggestions will help me too.
Ok, well I found something happened here's the code
0C23C 68 pla ;<---------------------------------------------------------0
0C23D ;now our attributetable is ready to be written
0C23D ;SO WE WRITE!!
0C23D
0C23D C9 14 cmp #20
0C23F F0 0D beq +
0C241
0C241 A9 23 lda #$23
0C243 8D 06 20 sta $2006 ;Sets the high byte of the address $2007 will write to.
0C246 A9 C0 lda #$C0
0C248 8D 06 20 sta $2006 ;Sets the low byte of the address $2007 will write to.
0C24B 4C 58 C2 jmp +write
0C24E
0C24E A9 27 + lda #$27
0C250 8D 06 20 sta $2006 ;Sets the high byte of the address $2007 will write to.
0C253 A9 C0 lda #$C0
0C255 8D 06 20 sta $2006 ;Sets the low byte of the address $2007 will write to.
0C258
0C258 +write:
0C258 BD F0 04 - lda attributes, x
0C25B 8D 07 20 sta $2007
0C25E E8 inx
0C25F E0 3F cpx #63
0C261 ; ; dex
0C261 D0 F5 bne -
0C263
0C263 60 rts ;end of attributetable ********************************************************
I don't think there's enough info here to help you out specifically, but I suggest you just use a ram value instead of pla/pha unless you absolutely need them. (You usually don't, and it's actually faster to not use them if the temp ram value is on the zero page.)
You've got a path in your code where it hits a pha without a pla or vice versa.
Things clearly went wrong after the RTS, when the CPU started trying to execute code at $0001. You probably misused the stack somehow, causing it to point to an invalid return address by the time the RTS is executed.
I second Kasumi's suggestion: avoid using the stack for temporary storage unless you absolutely need it. When you use the stack in the middle of code that makes decisions it's very easy forget bytes on it or pull more than you've pushed. A corrupted stack is absolutely disastrous, 99.99% of the time your program will crash because of it.
I don't get it...even when JSR'd too, does it just shove the attributes to VRAM? Because that should probably just be straight NMI update code with "switch" in the engine IMO. And what does it need to CMP to anyway? The pulled A value? If so you need it, it just seems out of place...there wouldn't be any more code from the subroutine not shown would there?
3gengames wrote:there wouldn't be any more code from the subroutine not shown would there?
There MUST be a part of the subroutine he's not showing. If that's the complete routine, that PLA obviously screws things up by removing part of the return address from the stack.
unregistered wrote: I don't have a clue what was on the stack...
Well, then that's what you have to find out now. When you do a JSR, the current program counter is put on the stack so that later you can return to the place where the call was made. If you do any stack manipulation after that, you must make sure to leave the stack exactly like it was before such manipulation, so that the return address can be used by the RTS. Your program crashed because it returned to an invalid address, so you have to find out why there was an invalid address on the stack by the time the RTS was executed.
I just spent hours searching for an answer to my question... tokumaru, it's on what we were talking about. Sorry for traveling back in time.
tokumaru[color=violet], on page 41,[/color] wrote:
unregistered wrote:What is a 6502 simulator? I dont understand.
I'm talking about this. It's a 6502 simulator with integrated debug features. You write some code, assemble it (to memory, no files are generated), and then you run it and use a multitude of debugging features to analyze...
LDA #<MetatileRhombus
STA rhombusCollision_low
LDA #>MetatileRhombus
STA rhombusCollision_high
How can I make this assemble correctly using the simulator? I don't know what to use for obtaining the Least Significant Bit or Most Significant Bit. I even successfully updated the .hlp program so I could access the help, but now I'm missing the .hlp file. It didn't come with it.
unregistered wrote:i read the error message fully slowly and found that my sister's file wasn't included and can't be included.
Yeah, there are things this simulator just doesn't do. I find it good to test small pieces of code and study how the CPU works, but you really can't expect it to interpret correctly large portions of game code made for another assembler.
Back when I was getting started on NES programming, I actually used this simulator as my assembler, as it can save binaries. The biggest issue is the lack of "INCBIN", so all your data has to be defined in text form with "DB" and "DW" statements.
tokumaru wrote:Things clearly went wrong after the RTS, when the CPU started trying to execute code at $0001. You probably misused the stack somehow, causing it to point to an invalid return address by the time the RTS is executed.
Yes, I have found two zeros on the top of the stack and then it hits the rts and it returns to $0001. That's how it is supposed to work, I think. I need to now figure out how they get to the top of the stack.
tokumaru wrote:I second Kasumi's suggestion: avoid using the stack for temporary storage unless you absolutely need it. When you use the stack in the middle of code that makes decisions it's very easy forget bytes on it or pull more than you've pushed. A corrupted stack is absolutely disastrous, 99.99% of the time your program will crash because of it.
Thank you Kasumi and tokumaru for helping me to learn through all of this!
tokumaru wrote:
3gengames wrote:there wouldn't be any more code from the subroutine not shown would there?
There MUST be a part of the subroutine he's not showing. If that's the complete routine, that PLA obviously screws things up by removing part of the return address from the stack.
Yes 3gengames that wasn't the whole routine... if it was I would have included the function's label at the top. It's much longer.
tokumaru wrote:
unregistered wrote: I don't have a clue what was on the stack...
Well, then that's what you have to find out now. When you do a JSR, the current program counter is put on the stack so that later you can return to the place where the call was made. If you do any stack manipulation after that, you must make sure to leave the stack exactly like it was before such manipulation, so that the return address can be used by the RTS. Your program crashed because it returned to an invalid address, so you have to find out why there was an invalid address on the stack by the time the RTS was executed.
unregistered wrote:Yes, I have found two zeros on the top of the stack and then it hits the rts and it returns to $0001. That's how it is supposed to work, I think. I need to now figure out how they get to the top of the stack.
In a decent debugger, watching for writes to CPU memory $0100-$01FF should catch all pushes.
unregistered wrote:Yes, I have found two zeros on the top of the stack and then it hits the rts and it returns to $0001. That's how it is supposed to work, I think. I need to now figure out how they get to the top of the stack.
In a decent debugger, watching for writes to CPU memory $0100-$01FF should catch all pushes.
Is FCEUX a decent debugger? I tried to set that breakpoint and it only found all of the zeroing out at the beginning.