Jump to content
IGNORED

Need help: checking for new high score


Lumi

Recommended Posts

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 by Lumi
Link to comment
Share on other sites

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
Link to comment
Share on other sites

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 by Lumi
Link to comment
Share on other sites

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!

Link to comment
Share on other sites

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

Link to comment
Share on other sites

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.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Loading...
  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...