Left button crashing code when checking position...

Discuss technical or other issues relating to programming the Nintendo Entertainment System, Famicom, or compatible systems. See the NESdev wiki for more information.

Moderator: Moderators

Post Reply
JoeGtake2
Posts: 333
Joined: Tue Jul 01, 2014 4:02 pm

Left button crashing code when checking position...

Post by JoeGtake2 »

Hello, all. Relatively new to Assembly, but actually very proud of some headway I've made. I'm absolutely positive there are more efficient ways to do what I am doing, but as I learn the code, I am muscling through on my own trying to really understand what it is I am doing.

Thanks to a plethora of online resources, I have been able to create a metasprite made up of four sprites that move together around the room based on joystick input. I am trying to keep them contained within the screen area. Up, right, and down are all successfully working. However, whenever I press Left, the game freezes in the emulator. If I remove the three lines of code that check for position before moving, it works fine. This checking position method works in ALL the other directions, so I'm not sure why left is crashing things.

For brevity, I'll just provide a working piece of the code (for Down) and then the problem piece (left). Let me know if you need more in order to help track down the issue!

Code: Select all

MovePlayerDown:   ;; THIS IS WORKING FINE, as are all directions except left.
	LDA buttons
	AND #%00000100 ;; if down is pressed
	BEQ movePlayerLeft ;; if these things are not true, jump to movePlayerLeft
	LDX $0200       ;;Load the player's Y position into X
	CPX #$D4; compare the Y value to bottom of screen
	BCS movePlayerLeft   ;; if the player is too close to the bottom, skip the rest of the code and jump to movePlayerLeft
	;;Move Player part...need to move all four sprites
	LDA $0200
	CLC
	ADC #playerWalkSpeed
	STA $0200
	LDA $0204
	CLC
	ADC #playerWalkSpeed
	STA $0204
	LDA $0208
	CLC
	ADC #playerWalkSpeed
	STA $0208
	LDA $020C
	CLC
	ADC #playerWalkSpeed
	STA $020C
	
movePlayerLeft:   ;; You'll notice, this is coded the same way, yet causes the game to freeze.
	LDA buttons
	AND #%00000010 ;; if left is pressed
	BEQ movePlayerUp ;; if these things aren't true, jump to movePlayerUp 
             ;;;;;;;;THIS IS THE PROBLEM;;;;;;;;;;;
	LDX $0203            ;; load the x value into X
	CPX #$08             ;; Compare X to position towards the left of the screen
	BCC movePlayerUp  ;; if close to the edge, skip the rest and jump down to movePlayerUp
	;;;;;;;;;;END PROBLEM;;;;;;;;;;;;;;;;;;;
	;;Move Player part...need to move all four sprites
	LDA $0203
	SEC
	SBC #playerWalkSpeed
	STA $0203
	LDA $0207
	SEC
	SBC #playerWalkSpeed
	STA $0207
	LDA $020B
	SEC
	SBC #playerWalkSpeed
	STA $020B
	LDA $020F
	SEC
	SBC #playerWalkSpeed
	STA $020F
I realize there are probably many more efficient ways to do all of the above, and I'm very open to anyone providing me info...but I genuinely want to know why this would cause the game to crash in the emulator even if there is a better solution.

Thanks!
lidnariq
Posts: 11432
Joined: Sun Apr 13, 2008 11:12 am

Re: Left button crashing code when checking position...

Post by lidnariq »

Are you perhaps using NESASM? It's kind of famous for not giving an error on an out of range argument (i.e. the final BCC may be trying to jump more than 128 bytes earlier in the code).
JoeGtake2
Posts: 333
Joined: Tue Jul 01, 2014 4:02 pm

Re: Left button crashing code when checking position...

Post by JoeGtake2 »

Yes, I am using NESASM3. What you're suggesting is possible, I suppose, but I don't think so. Again, this is not the last direction...the two that follow work flawlessly (and jump the same distance in the code), unless I am misunderstanding. Also, when I tried to diagnose the problem by trying to jump down to the end of the directions, it told me it was out of range (and I'm assuming that's what it would do if this were true). Thank you for the suggestion though! And it's good to know that NESASM potentially has that issue, I will watch for it.

Any other thoughts or suggestions, lidnariq or anyone else?
User avatar
tokumaru
Posts: 12427
Joined: Sat Feb 12, 2005 9:43 pm
Location: Rio de Janeiro - Brazil

Re: Left button crashing code when checking position...

Post by tokumaru »

I can't catch anything obvious from looking at the code. Which emulator are you using? Does the program crash in other emulators as well? You should try debugging it in FCEUX to see if the CPU is doing what you think it should be doing. Open the debugger and set a breakpoint for, say, reads to $0203. So whenever $0203 is read (which happen right in the middle of the problematic code), the emulator will pause, and from there you can step through the instructions and see what the CPU is doing.
User avatar
Kasumi
Posts: 1293
Joined: Wed Apr 02, 2008 2:09 pm

Re: Left button crashing code when checking position...

Post by Kasumi »

Are you open to posting a rom?
User avatar
Omegamatrix
Posts: 35
Joined: Tue Jun 10, 2014 8:15 pm
Location: Canada

Re: Left button crashing code when checking position...

Post by Omegamatrix »

lidnariq wrote:Are you perhaps using NESASM? It's kind of famous for not giving an error on an out of range argument (i.e. the final BCC may be trying to jump more than 128 bytes earlier in the code).
Wow. :shock: That is just not practical to use without branch error checking. Good to know.
User avatar
Kasumi
Posts: 1293
Joined: Wed Apr 02, 2008 2:09 pm

Re: Left button crashing code when checking position...

Post by Kasumi »

Really sure the branching thing has been fixed a long time ago, though. Because I'm sure I'd have encountered it by now, if not, having used it for the last five years. I encourage you to create a test case in the latest version of the software. I'd be happy to be proven wrong. It is open source, the problem could even be fixed if it does still exist. To get off topic, maybe this is why I do not have much interest in releasing software other than games. People will remember and post about the bugs far after they've been fixed. People will make bug reports without having the latest version of the software. And all of that sounds so fun. With games people might lose their save or progress, but not actual work which is easier to deal with.

I don't deny nesasm has other problems, but at least post about those. Or create a test case for this branching error in the program found here. If you can, I'll take my lumps.
User avatar
Omegamatrix
Posts: 35
Joined: Tue Jun 10, 2014 8:15 pm
Location: Canada

Re: Left button crashing code when checking position...

Post by Omegamatrix »

tokumaru gave the best advice here. You'll always solve your problems way quicker by simply seeing what value is actually getting loaded with a debugger.


If it is not a branch problem, then maybe some other things you might try/check are:
- check if 'buttons' is really, truly getting updated with the correct bit for the left direction.
- I noticed those 3 lines of code load X. Make sure that you are not depending on X for a different value later in the code.
- make sure you are not getting stuck in an endless loop branching to 'movePlayerUp'. Try hardcoding the branch to be always taken, i.e.:

Code: Select all

   LDX #$07             ;; to always branch
   CPX #$08             ;; Compare X to position towards the left of the screen
   BCC movePlayerUp  ;; if close to the edge, skip the rest and jump down to movePlayerUp
If that works then repeat with a case that will never branch.

Code: Select all

   LDX #$09             ;; will never branch
   CPX #$08             ;; Compare X to position towards the left of the screen
   BCC movePlayerUp  ;; if close to the edge, skip the rest and jump down to movePlayerUp
I can't help you out much more then that as I'm new to the NES.
JoeGtake2
Posts: 333
Joined: Tue Jul 01, 2014 4:02 pm

Re: Left button crashing code when checking position...

Post by JoeGtake2 »

Alright, the plot thickens...

With some help from Kasumi, I did a little housekeeping with the code. It's a tiny bit cleaner, and I have found the one line that is causing the problem. Setting the carry flag (SEC) in the left direction is what causes the 'crash' (the game freezes, the emulator does not crash...experience with other programming languages makes me think it is getting stuck in a loop).

What's bizarre, my UP direction utilizes the SEC and does not crash. Left, however, crashes. I'll post the updated code snippet for both of those directions:

Code: Select all


movePlayerLeft:
	LDA buttons
	AND #%00000010
	BEQ movePlayerUp
	LDA $0203
	CMP #$08
	BCC movePlayerUp
	SEC        ;; IF I REMOVE THIS, EVERYTHING WORKS FINE...
	SBC #playerWalkSpeed
	STA $0203
	LDA $0207
	SBC #playerWalkSpeed
	STA $0207
	LDA $020B
	SBC #playerWalkSpeed
	STA $020B
	LDA $020F
	SBC #playerWalkSpeed
	STA $020F
	
movePlayerUp:
	LDA buttons
	AND #%00001000
	BEQ movePlayerRight
	LDA $0200
	CMP #$08
	BCC movePlayerRight
	SEC        ;;THIS WORKS WHETHER I REMOVE IT OR LEAVE IT IN
	SBC #playerWalkSpeed
	STA $0200
	LDA $0204
	SBC #playerWalkSpeed
	STA $0204
	LDA $0208
	SBC #playerWalkSpeed
	STA $0208
	LDA $020C
	SBC #playerWalkSpeed
	STA $020C


I'm fairly certain that I understand that generally prior to using ADC, clear the carry flag and prior to using SBC, set the carry flag. I know it is more complicated than that, but that seems to be the general rule for what I have gleaned. And it seems to work fine for UP in the exact same context...but not for LEFT.

Any further thoughts on why this could be the case?

You guys rock.
User avatar
Quietust
Posts: 1920
Joined: Sun Sep 19, 2004 10:59 pm
Contact:

Re: Left button crashing code when checking position...

Post by Quietust »

Incidentally, having an SEC immediately after a (not-taken) BCC instruction is indeed redundant - BCC only branches if carry is clear, so if it didn't branch then carry must be set. The fact that removing a single byte causes the problem to go away suggests that this is indeed a problem with trying to branch too far, but we'd need to see the entire program to be able to confirm that possibility.
Quietust, QMT Productions
P.S. If you don't get this note, let me know and I'll write you another.
User avatar
koitsu
Posts: 4201
Joined: Sun Sep 19, 2004 9:28 pm
Location: A world gone mad

Re: Left button crashing code when checking position...

Post by koitsu »

NESASM3 (specifically version 3.1) can generate what is called a "code listing", which is basically an ASCII representation of what the assembled code looks like (including all bytes of opcodes and operands). A code listing would provide the necessary insights to determine if the branches are going to the right place or not. Taken from the NESASM3 docs:

Code: Select all

         -l #   Control output of the listing file:

                    0 - disable completely the listing file even if the
                        LIST directive is used in the input file
                    1 - minimun level; code produced by DB, DW and DEFCHR
                        will not be dumped
                    2 - normal level; only code produced by DEFCHR will not
                        be dumped
                    3 - maximun level; all the code is dumped in the
                        listing file

                The default level is level 2.
I believe the default level (2), ex. -l 2 would be fine. That's dash-lowercase-ELL, not dash-one.

Otherwise I'd consider ceasing use of such broken assemblers; when an assembler itself contains bugs of this nature and doesn't report such errors, that should pretty much be a deal-breaker, i.e. it's time to look at using asm6 or ca65 (pure opinion and not really relevant to this thread per se: I tend to recommend the former, while the latter has lots of capability the learning curve is humongous and you'll spend more time screwing around with the "setup" of the assembler/project than you will actually writing code).
User avatar
tokumaru
Posts: 12427
Joined: Sat Feb 12, 2005 9:43 pm
Location: Rio de Janeiro - Brazil

Re: Left button crashing code when checking position...

Post by tokumaru »

I have to agree that this looks like an out of range branch that was assembled incorrectly... It's the second time you say that removing seemingly unrelated code prevents the crash.
User avatar
Kasumi
Posts: 1293
Joined: Wed Apr 02, 2008 2:09 pm

Re: Left button crashing code when checking position...

Post by Kasumi »

I have to agree that this looks like an out of range branch that was assembled incorrectly...
Still waiting for the test case.

I have the code in hand (as was implied earlier by JoeGtake2's last post, I'm giving some help through PM), and there's definitely some other stuff that needs fixing before I consider this a nesasm failure. Currently, the program wraps the PC across all the RAM (as in $0000-$8000 where the program actually starts) because it hits an RTS before a JSR. That means whatever opcode the RAM for buttons represents could be one that kills the CPU. Or it could be moving left at walk speed changes any of the meta sprites to a value that kills the CPU.

If after fixing the things that cause this, it's still broken I'll be happy to accept it's nesasm AND there will be a test case.

Edit: Fixed, totally wasn't nesasm. One issue was described above, another problem was an RTI after an .org statement after the NMI, instead of an RTI after the NMI. 8-)

Edit2: The technical reason for why this happened, and why adding and removing code made a difference is because nesasm assembles undefined bytes as $FF. $FF is ISC absolute,x. The code ran past the end of the NMI into a long string of $FFs with exactly one $40 (RTI). Recall that the RTI was also after an .org statement, so changing previous code would change its relative position to that code, rather than always having the same number of $FFs between the final instruction and the RTI. Because ISC is absolute, the program could potentially skip the single RTI depending on how many bytes of $FF preceded it. (Running either ISC $40FF,x or ISC $FF40,x). If the RTI happened to be skipped in this manner, the program would run back through $FFFF and start executing the RAM. The opcode $02 (which happens to be what the RAM is set to when only left is pressed on the joypad) kills the CPU.

Edit3: In fact, I just checked. The program would not crash if both left and down are pressed, or if both left and up were pressed. It's just that specifically $02 crashes the CPU.
Post Reply