8x16 and whatever else unreg wants to know

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.

Moderator: Moderators

unregistered
Posts: 1038
Joined: Thu Apr 23, 2009 11:21 pm
Location: cypress, texas

Post by unregistered » Tue Jun 19, 2012 3:59 pm

Kasumi wrote:
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! :D Thanks also Dwedit and smkd... yall's suggestions will help me too. :)
Ok, well I found something happened here's the code

Code: Select all

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 ********************************************************

and here is the end-part of my logging...

Code: Select all

C25E:E8        INX                        A:55 X:3C Y:00 P:nvUbdizc
$C25F:E0 3F     CPX #$3F                   A:55 X:3D Y:00 P:nvUbdizc
$C261:D0 F5     BNE $C258                  A:55 X:3D Y:00 P:NvUbdizc
$C258:BD F0 04  LDA $04F0,X @ $052D = #$55 A:55 X:3D Y:00 P:NvUbdizc
$C25B:8D 07 20  STA $2007 = #$00           A:55 X:3D Y:00 P:nvUbdizc
$C25E:E8        INX                        A:55 X:3D Y:00 P:nvUbdizc
$C25F:E0 3F     CPX #$3F                   A:55 X:3E Y:00 P:nvUbdizc
$C261:D0 F5     BNE $C258                  A:55 X:3E Y:00 P:NvUbdizc
$C258:BD F0 04  LDA $04F0,X @ $052E = #$55 A:55 X:3E Y:00 P:NvUbdizc
$C25B:8D 07 20  STA $2007 = #$00           A:55 X:3E Y:00 P:nvUbdizc
$C25E:E8        INX                        A:55 X:3E Y:00 P:nvUbdizc
$C25F:E0 3F     CPX #$3F                   A:55 X:3F Y:00 P:nvUbdizc
$C261:D0 F5     BNE $C258                  A:55 X:3F Y:00 P:nvUbdiZC
$C263:60        RTS                        A:55 X:3F Y:00 P:nvUbdiZC
$0001:00        BRK                        A:55 X:3F Y:00 P:nvUbdiZC
$C3DB:40        RTI                        A:55 X:3F Y:00 P:nvUbdIZC
$0003:00        BRK                        A:55 X:3F Y:00 P:nvUBdiZC
$C3DB:40        RTI                        A:55 X:3F Y:00 P:nvUBdIZC
$0005:8B        UNDEFINED                  A:55 X:3F Y:00 P:nvUBdiZC
$0007:00        BRK                        A:00 X:3F Y:00 P:nvUBdiZC
$C3DB:40        RTI                        A:00 X:3F Y:00 P:nvUBdIZC
$0009:00        BRK                        A:00 X:3F Y:00 P:nvUBdiZC
$C3DB:40        RTI                        A:00 X:3F Y:00 P:nvUBdIZC
$000B:00        BRK                        A:00 X:3F Y:00 P:nvUBdiZC
$C3DB:40        RTI                        A:00 X:3F Y:00 P:nvUBdIZC
$000D:C7        UNDEFINED                  A:00 X:3F Y:00 P:nvUBdiZC
$000F:00        BRK                        A:00 X:3F Y:00 P:nvUBdizc
$C3DB:40        RTI                        A:00 X:3F Y:00 P:nvUBdIzc
$0011:CC 00 00  CPY $0000 = #$FF           A:00 X:3F Y:00 P:nvUBdizc
$0014:00        BRK                        A:00 X:3F Y:00 P:nvUBdizc
$C3DB:40        RTI                        A:00 X:3F Y:00 P:nvUBdIzc
$0016:00        BRK                        A:00 X:3F Y:00 P:nvUBdizc
$C3DB:40        RTI                        A:00 X:3F Y:00 P:nvUBdIzc
$0018:00        BRK                        A:00 X:3F Y:00 P:nvUBdizc
$C3DB:40        RTI                        A:00 X:3F Y:00 P:nvUBdIzc
$001A:00        BRK                        A:00 X:3F Y:00 P:nvUBdizc
$C3DB:40        RTI                        A:00 X:3F Y:00 P:nvUBdIzc
$001C:02        UNDEFINED                  A:00 X:3F Y:00 P:nvUBdizc
$001C:02        UNDEFINED                  A:00 X:3F Y:00 P:nvUBdizc
$001C:02        UNDEFINED                  A:00 X:3F Y:00 P:nvUBdizc
$001C:02        UNDEFINED                  A:00 X:3F Y:00 P:nvUBdizc
And it just kept running that UNDEFINED instruction with
A:00 X:3F Y:00
until I stopped the logging.

It hits the rts and then it runs memory location $0001 and then it runs the RTI at $C3DB... over and over... Im confused! :?
Last edited by unregistered on Tue Jun 19, 2012 4:06 pm, edited 1 time in total.

3gengames
Formerly 65024U
Posts: 2269
Joined: Sat Mar 27, 2010 12:57 pm

Post by 3gengames » Tue Jun 19, 2012 4:03 pm

Did you JSR to it? Was there something on the stack you needed to PLA to get or just mistakenly used it? Just some ideas to look into. :)

unregistered
Posts: 1038
Joined: Thu Apr 23, 2009 11:21 pm
Location: cypress, texas

Post by unregistered » Tue Jun 19, 2012 4:09 pm

3gengames wrote:Did you JSR to it? Was there something on the stack you needed to PLA to get or just mistakenly used it? Just some ideas to look into. :)
yes I did JSR to it. I don't have a clue what was on the stack... thank you 3gengames! :) :D

User avatar
Kasumi
Posts: 1291
Joined: Wed Apr 02, 2008 2:09 pm

Post by Kasumi » Tue Jun 19, 2012 5:12 pm

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.

User avatar
tokumaru
Posts: 11469
Joined: Sat Feb 12, 2005 9:43 pm
Location: Rio de Janeiro - Brazil

Post by tokumaru » Tue Jun 19, 2012 6:43 pm

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.

3gengames
Formerly 65024U
Posts: 2269
Joined: Sat Mar 27, 2010 12:57 pm

Post by 3gengames » Tue Jun 19, 2012 7:37 pm

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? :P

User avatar
tokumaru
Posts: 11469
Joined: Sat Feb 12, 2005 9:43 pm
Location: Rio de Janeiro - Brazil

Post by tokumaru » Tue Jun 19, 2012 8:17 pm

3gengames wrote:there wouldn't be any more code from the subroutine not shown would there? :P
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.

unregistered
Posts: 1038
Joined: Thu Apr 23, 2009 11:21 pm
Location: cypress, texas

Post by unregistered » Wed Jun 20, 2012 9:10 pm

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...

Code: Select all

	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. :(

User avatar
Kasumi
Posts: 1291
Joined: Wed Apr 02, 2008 2:09 pm

Post by Kasumi » Wed Jun 20, 2012 10:04 pm

unregistered wrote: How can I make this assemble correctly using the simulator? :?
Does that not work? Then what errors are you getting?

I did this:

Code: Select all

	.org $8000
	LDA #<label
	lda #>label
	.ORG $9001
label:
And it loaded #$01 and #$90 as expected.

unregistered
Posts: 1038
Joined: Thu Apr 23, 2009 11:21 pm
Location: cypress, texas

Post by unregistered » Wed Jun 20, 2012 10:20 pm

Kasumi wrote:
unregistered wrote: How can I make this assemble correctly using the simulator? :?
Does that not work? Then what errors are you getting?

I did this:

Code: Select all

	.org $8000
	LDA #<label
	lda #>label
	.ORG $9001
label:
And it loaded #$01 and #$90 as expected.
sorry, i read the error message fully slowly and found that my sister's file wasn't included and can't be included. Thank you I'm sorry.

User avatar
tokumaru
Posts: 11469
Joined: Sat Feb 12, 2005 9:43 pm
Location: Rio de Janeiro - Brazil

Post by tokumaru » Thu Jun 21, 2012 7:18 am

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.

unregistered
Posts: 1038
Joined: Thu Apr 23, 2009 11:21 pm
Location: cypress, texas

Post by unregistered » Thu Jun 21, 2012 7:27 am

tokumaru wrote:...biggest issue is the lack of "INCBIN", so all your data has to be defined in text form with "DB" and "DW" statements.
Ah well all of our files of data are actually in text form with "DB" statements... it's just that we made up our own extensions. : )

edit.

unregistered
Posts: 1038
Joined: Thu Apr 23, 2009 11:21 pm
Location: cypress, texas

Post by unregistered » Sat Jun 23, 2012 1:36 pm

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! :D
tokumaru wrote:
3gengames wrote:there wouldn't be any more code from the subroutine not shown would there? :P
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.
Thank you tokumaru :D; you are wise, I still think. :)

tepples
Posts: 21755
Joined: Sun Sep 19, 2004 11:12 pm
Location: NE Indiana, USA (NTSC)
Contact:

Post by tepples » Sat Jun 23, 2012 1:49 pm

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
Posts: 1038
Joined: Thu Apr 23, 2009 11:21 pm
Location: cypress, texas

Post by unregistered » Mon Jun 25, 2012 8:54 am

tepples wrote:
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.

Post Reply