Lumi Posted December 17, 2015 Share Posted December 17, 2015 (edited) Hi, I'm pretty new to 6502 assembly and I need some help. Basically, I'm creating a game with a 5-digit score. The game keeps track of it using 3 bytes of RAM in BCD format. That works fine, but when the game is over I want to compare this score to a high score elsewhere in RAM. The code I've written starts by comparing the most significant bytes. If the score's MSB < the high score's MSB, it exits the subroutine. Otherwise it moves on, comparing the second and least significant bytes the same way. If it never exited the routine, it'll overwrite the high score with the current score. For some reason it doesn't work, and I can't figure out why. The first problem is, it doesn't seem to check the MSB at all. For example, I tried getting a score of 10050, with a high score of 1200. It thought 1200 was larger! If both digits are 9999 or less, it seems to work 90% of the time, but occasionally it'll just fail for no discernable reason at all. I feel like the answer is obvious, but I don't know what I'm overlooking. Below is the code I'm using. SCORE+2/HIGHSCORE+2 is the MSB, while SCORE/HIGHSCORE is the LSB. checkhs lda SCORE+2 ; compare most significant bytes cmp HIGHSCORE+2 bcc ret ; if score's MSB < high score's MSB, exit the subroutine lda SCORE+1 ; compare middle bytes cmp HIGHSCORE+1 bcc ret ; if score's middle byte < high score's middle byte, exit the subroutine lda SCORE ; compare least significant bytes cmp HIGHSCORE bcc ret ; if score's LSB < high score's LSB, exit the subroutine lda SCORE ; if all checks passed, set new high score and exit sta HIGHSCORE lda SCORE+1 sta HIGHSCORE+1 lda SCORE+2 sta HIGHSCORE+2 ret rts Thanks! Edited December 17, 2015 by Lumi Quote Link to comment Share on other sites More sharing options...
+SpiceWare Posted December 17, 2015 Share Posted December 17, 2015 Have you used Stella to step thru the code with the integrated debugger? Watching it execute instruction by instruction will most likely show you what's wrong. Quote Link to comment Share on other sites More sharing options...
+Omegamatrix Posted December 18, 2015 Share Posted December 18, 2015 Hi, I'm pretty new to 6502 assembly and I need some help. Basically, I'm creating a game with a 5-digit score. The game keeps track of it using 3 bytes of RAM in BCD format. That works fine, but when the game is over I want to compare this score to a high score elsewhere in RAM. The code I've written starts by comparing the most significant bytes. If the score's MSB < the high score's MSB, it exits the subroutine. Otherwise it moves on, comparing the second and least significant bytes the same way. If it never exited the routine, it'll overwrite the high score with the current score. For some reason it doesn't work, and I can't figure out why. The first problem is, it doesn't seem to check the MSB at all. For example, I tried getting a score of 10050, with a high score of 1200. It thought 1200 was larger! If both digits are 9999 or less, it seems to work 90% of the time, but occasionally it'll just fail for no discernable reason at all. I feel like the answer is obvious, but I don't know what I'm overlooking. Below is the code I'm using. SCORE+2/HIGHSCORE+2 is the MSB, while SCORE/HIGHSCORE is the LSB. checkhs lda SCORE+2 ; compare most significant bytes cmp HIGHSCORE+2 bcc ret ; if score's MSB < high score's MSB, exit the subroutine lda SCORE+1 ; compare middle bytes cmp HIGHSCORE+1 bcc ret ; if score's middle byte < high score's middle byte, exit the subroutine lda SCORE ; compare least significant bytes cmp HIGHSCORE bcc ret ; if score's LSB < high score's LSB, exit the subroutine lda SCORE ; if all checks passed, set new high score and exit sta HIGHSCORE lda SCORE+1 sta HIGHSCORE+1 lda SCORE+2 sta HIGHSCORE+2 ret rts Thanks! There is a logic problem. Look at this case and see if it makes sense: HighScore 9850 ($00,$98,$50) SCORE,SCORE+1,SCORE+2 NewScore 10200 ($01,$02,$00) SCORE,SCORE+1,SCORE+2 checkhs lda SCORE+2 ; $00 cmp HIGHSCORE+2; $50 bcc ret ; branch taken, score not updated, but we wanted it to be... Something like this should work, but I haven't tested it: checkhs lda SCORE ; start with most significant byte and work down cmp HIGHSCORE beq .checkMid ; no change, check next significant byte bcs .updateScore ; new high score! .checkMid: lda SCORE+1 cmp HIGHSCORE+1 beq .checkLow bcs .updateScore .checkLow: lda SCORE+2 cmp HIGHSCORE+2 beq .ret ; no change at all bcc .ret ; score is to low... .updateScore: lda SCORE ; all checks passed, set new high score and exit sta HIGHSCORE lda SCORE+1 sta HIGHSCORE+1 lda SCORE+2 sta HIGHSCORE+2 .ret: rts Quote Link to comment Share on other sites More sharing options...
Lumi Posted December 18, 2015 Author Share Posted December 18, 2015 (edited) Wow... you're right, I made a major logical error! Thanks for pointing it out. The code you posted didn't work, but I was able to identify where it was failing. Here's a working routine, for anyone who needs help with this: checkhs: lda SCORE+2 ; start with most significant byte and work down cmp HIGHSCORE+2 beq checkMid ; if score byte = high score byte, the next digit needs to be examined bcc ret ; if score byte < high score byte, we know the player got a lower score bcs updateScore ; if neither branch was taken, we have a new high score checkMid: lda SCORE+1 cmp HIGHSCORE+1 beq checkLow ; same as above bcc ret bcs updateScore checkLow: lda SCORE cmp HIGHSCORE beq ret ; at this point, we know the player got the same score, so don't bother updating bcc ret ; if SCORE is less than HIGHSCORE, the player did not get a high score updateScore: lda SCORE ; all checks passed, set new high score and exit sta HIGHSCORE lda SCORE+1 sta HIGHSCORE+1 lda SCORE+2 sta HIGHSCORE+2 ret: rts Edited December 18, 2015 by Lumi Quote Link to comment Share on other sites More sharing options...
+Omegamatrix Posted December 18, 2015 Share Posted December 18, 2015 I think it didn't work because you defined MSB as SCORE+2, and LSB as SCORE. I defined MSB as SCORE, and LSB as SCORE+2 (I always do it that way). When you look in Stella's debugger it will be easy to read, i.e. the entire score is in order left to right. Quote Link to comment Share on other sites More sharing options...
+SpiceWare Posted December 18, 2015 Share Posted December 18, 2015 Did you take any time to figure out how to use Stella's debugger? It's really useful - as soon as you saw the code execute I bet you'd have realized what the problem was. Quote Link to comment Share on other sites More sharing options...
Lumi Posted December 19, 2015 Author Share Posted December 19, 2015 Did you take any time to figure out how to use Stella's debugger? It's really useful - as soon as you saw the code execute I bet you'd have realized what the problem was. I did, but I fixed the problem before trying it out. Thanks for letting me know, though! Quote Link to comment Share on other sites More sharing options...
Nukey Shay Posted December 19, 2015 Share Posted December 19, 2015 Shorter version using loops ;check high score subroutine ldx #$02 ;2 set initial index Check_Score_Loop: lda SCORE,x ;4 load current score cmp HIGHSCORE,x ;4 compare against hiscore beq Next_Digits ;2 branch if the same bcc No_HiScore ;2 abort if lower ;New high score...overwrite old one ldx #$02 ;2 reset index Set_Hiscore_Loop: lda SCORE,x ;4 sta HIGHSCORE,x ;4 dex ;2 bpl Set_Hiscore_Loop ;2 rts ;6 Next_Digits: dex ;2 bump index bpl Check_Score_Loop ;2 branch if more to check No_HiScore: rts ;2 Quote Link to comment Share on other sites More sharing options...
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.