Jump to content
IGNORED

How do we keep a high score?


Random Terrain

Recommended Posts

This really needed to be done. Great work as always RT.

Thanks, but all I did was ask a question. I knew the big brains around here could figure it out.

The one I posted should work fine-- but it also depends on how you've defined the bytes. There's nothing magic about sc1, sc2, sc3-- you can define sc1 as the highest byte or the lowest byte, whichever you want. I was using the variable names from supercat's example. Using your variable names, it should be like this:

 

  if sc1 < High_Score01 then Skip_High_Score
  if sc2 < High_Score02 then Skip_High_Score
  if sc3 < High_Score03 then Skip_High_Score

  High_Score01 = sc1
  High_Score02 = sc2
  High_Score03 = sc3

Skip_High_Score

This assumes that sc1 is for the two leftmost digits of the current score (the most significant byte), sc2 is the middle byte, and sc3 is the rightmost two digits (the least significant byte). Likewise for High_Score01, High_Score02, and High_Score03.

 

Michael

Link to comment
Share on other sites

The problem is that falling though test 1 allows tests 2 or 3 to take their branch and skip the high score reset -regardless- if the first 2 digits were higher or equal than the argument.

 

Consider 110000 (current score) vs. 11000 (current highscore)...the branch at the first decision is not taken because 11 is greater than 1. However, the branch is taken on the next test because 0 is less than 10. Incorrectly leaving and not resetting the high score.

 

This problem will happen regardless of which direction you do the tests.

 

In assembly, you could follow carry status for each subsequent test as posted above by supercat to eliminate that problem.

Link to comment
Share on other sites

In assembly, you could follow carry status for each subsequent test as posted above by supercat to eliminate that problem.

 

Would it not be easier to include that routine in an assembler file? Then game programmers can be told not to use certain bB variables because they are already allocated to the high score. It would make life much easier and the resultant ROM image more compact.

Link to comment
Share on other sites

Can't you just use the variable names you chose in an inline routine? It's only 26 bytes.

 

  inline
 lda  High_Score03
 cmp  sc3
 lda  High_Score02
 sbc  sc2
 lda  High_Score01
 sbc  sc1
 bcs  No_High_Score
 lda  sc3
 sta  High_Score03
 lda  sc2
 sta  High_Score02
 lda  sc1
 sta  High_Score01
No_High_Score:
 end

Link to comment
Share on other sites

Would it not be easier to include that routine in an assembler file? Then game programmers can be told not to use certain bB variables because they are already allocated to the high score. It would make life much easier and the resultant ROM image more compact.

 

The following works fine and it's easy enough for a new batari Basic user to understand:

 

http://www.atariage.com/forums/topic/168926-how-do-we-keep-a-high-score/page__view__findpost__p__2089754

  if sc1 > High_Score01 then New_High_Score
  if sc1 < High_Score01 then Skip_High_Score

  rem  *  First byte equal. Do the next test.

  if sc2 > High_Score02 then New_High_Score
  if sc2 < High_Score02 then Skip_High_Score

  rem  *  Second byte equal. Do the next test.

  if sc3 > High_Score03 then New_High_Score
  if sc3 < High_Score03 then Skip_High_Score

  rem  *  All bytes equal.

  goto Skip_High_Score

New_High_Score

  High_Score01 = sc1 : High_Score02 = sc2 : High_Score03 = sc3

Skip_High_Score

 

If batari wants, we can start including asm alternatives, but we'll need the bB version too.

Link to comment
Share on other sites

Consider 110000 (current score) vs. 11000 (current highscore)...the branch at the first decision is not taken because 11 is greater than 1. However, the branch is taken on the next test because 0 is less than 10. Incorrectly leaving and not resetting the high score.

Okay, I see that now. :(

 

Michael

Link to comment
Share on other sites

The following works fine and it's easy enough for a new batari Basic user to understand:

 

Um.. no? I put the following into my DK3 game:

 

byte1=score

byte2=score+1

byte3=score+2

dim High_Score02=o

dim High_Score03=t

dim level=p

level=1

n{5}=1

const screenheight=84

title_screen
if byte2 > High_Score02 then New_High_Score
if byte2 < High_Score02 then Skip_High_Score

rem * Second byte equal. Do the next test.

if byte3 > High_Score03 then New_High_Score
if byte3 < High_Score03 then Skip_High_Score

rem * All bytes equal.

goto Skip_High_Score

New_High_Score

High_Score02 = byte2 : High_Score03 = byte3

Skip_High_Score

Suppose I get 22 points as a high score. I go in and get a lower amount of points, and it doesn't display 22 at the game over.[/size]

 

[/font]

dk3_v9.bas

Link to comment
Share on other sites

Nowhere. I'm just about ready to give up. If someone else wants to take a crack at adding a high score to this, be my guest and post the code if you do. Otherwise, I guess I won't be adding this feature because bB hates me. I've tried just about everything, added the word "then," adding the values, everything. Argh! icon_mad.gif

dk3_v9.bas

Link to comment
Share on other sites

Nowhere. I'm just about ready to give up. If someone else wants to take a crack at adding a high score to this, be my guest and post the code if you do. Otherwise, I guess I won't be adding this feature because bB hates me. I've tried just about everything, added the word "then," adding the values, everything. Argh! icon_mad.gif

The bB page has an example program:

 

http://www.randomterrain.com/atari-2600-memories-batari-basic-commands.html#score

 

It can't get much simpler than that. If you mangle the code, of course it isn't going to work.

Link to comment
Share on other sites

I took a quick look, and I think atari2600land is missing the part that actually displays the high score.

 

One way to do that is to set the score variables to the saved high score while displaying the titlepage. Or you can get more fancy and swap the saved high score with the current high score every few seconds.

Edited by RevEng
Link to comment
Share on other sites

  • 8 years later...

An efficient multi-byte comparison requires use of the carry flag for multi-precision arithmetic; a three-byte comparison can be done with six instructions totaling 12 bytes to get the result into the carry flag. If multi-precision arithmetic is not available, the logic should be:

  if score_top > highscore_top then YEP
  if score_top < highscore_top then NOPE
  if score_mid > highscore_mid then YEP
  if score_mid < highscore_mid then NOPE
  if score_bot > highscore_bot then YEP
  if score_bot < highscore_bot then NOPE
Otherwise, optimal 6502 code would be:

   lda highscore_bot
   cmp score_bot
   lda highscore_mid
   sbc score_mid
   lda highscore_top
   sbc score_top
  ; Carry will be clear if score > highscore
The CMP will clear the carry if score_bot > highscore_bot and set it otherwise. Each SBC will clear the carry if the corresponding byte of score is greater than the corresponding byte of highscore, set it if the corresponding byte of score is less than the corresponding byte of highscore, and leave it alone if they're equal. Thus, the state of the flag after earlier comparisons is relevant only if later bytes are equal.

 

 

If I want to turn that into an asm statement, first, do I have the variable names in the correct order in the asm statement below, then what do I do with the "carry will be clear" part? I don't know how to do an if-then based on that.

 

   ;```````````````````````````````````````````````````````````````
   ;  Remembers the high score until the game is turned off.
   ;
   dim _High_Score1 = v
   dim _High_Score2 = w
   dim _High_Score3 = x

   ;,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
   ;```````````````````````````````````````````````````````````````
   ;  Converts 6 digit score to 3 sets of two digits.
   ;
   ;  The 100 thousands and 10 thousands digits are held by _sc1.
   ;  The thousands and hundreds digits are held by _sc2.
   ;  The tens and ones digits are held by _sc3.
   ;
   dim _sc1 = score
   dim _sc2 = score+1
   dim _sc3 = score+2

   asm
   lda _High_Score1
   cmp _sc1
   lda _High_Score2
   sbc _sc2
   lda _High_Score3
   sbc _sc3
   ; Carry will be clear if score > _High_Score
end
Link to comment
Share on other sites

 

 

If I want to turn that into an asm statement, first, do I have the variable names in the correct order in the asm statement below, then what do I do with the "carry will be clear" part? I don't know how to do an if-then based on that.

 

   ;```````````````````````````````````````````````````````````````
   ;  Remembers the high score until the game is turned off.
   ;
   dim _High_Score1 = v
   dim _High_Score2 = w
   dim _High_Score3 = x

   ;,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
   ;```````````````````````````````````````````````````````````````
   ;  Converts 6 digit score to 3 sets of two digits.
   ;
   ;  The 100 thousands and 10 thousands digits are held by _sc1.
   ;  The thousands and hundreds digits are held by _sc2.
   ;  The tens and ones digits are held by _sc3.
   ;
   dim _sc1 = score
   dim _sc2 = score+1
   dim _sc3 = score+2

   asm
   lda _High_Score1
   cmp _sc1
   lda _High_Score2
   sbc _sc2
   lda _High_Score3
   sbc _sc3
   ; Carry will be clear if score > _High_Score
end

 

You have the variables in the reverse order. Just like doing a multi-digit subtraction problem, you start with the smallest and borrow from the next digit (the borrow is the "carry". At the end of the assembly block before the end, you would add something like this:

   bcc ___New_High_Score ; Branch if Carry Clear (goto ___New_High_Score label if carry not set)

This will go to the ___New_High_Score label you define where your new high score is. Alternately you could do:

   bcs ___No_High_Score ; Branch if Carry Set (goto ___No_High_Score label if carry is set)

Go to the ___No_High_Score label you define if the carry is not set (new high score not achieved).

  • Like 1
Link to comment
Share on other sites

This is untested, but you should be able to do something like this:

   ;```````````````````````````````````````````````````````````````
   ;  Remembers the high score until the game is turned off.
   ;
   dim _High_Score1 = v
   dim _High_Score2 = w
   dim _High_Score3 = x

   ;,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
   ;```````````````````````````````````````````````````````````````
   ;  Converts 6 digit score to 3 sets of two digits.
   ;
   ;  The 100 thousands and 10 thousands digits are held by _sc1.
   ;  The thousands and hundreds digits are held by _sc2.
   ;  The tens and ones digits are held by _sc3.
   ;
   dim _sc1 = score
   dim _sc2 = score+1
   dim _sc3 = score+2

   asm
   sed
   lda _High_Score3
   cmp _sc3
   lda _High_Score2
   sbc _sc2
   lda _High_Score1
   sbc _sc1
   cld
   ; Carry will be clear if score > _High_Score
   bcs ___No_High_Score ; Branch if Carry Set (goto ___No_High_Score label if carry is set)
end

   ; New High Score code - this is skipped if we goto  ___No_High_Score
   _High_Score1 = _sc1
   _High_Score2 = _sc2
   _High_Score3 = _sc3

___No_High_Score
   ; (more bB code)
  • Like 1
Link to comment
Share on other sites

 

This is untested, but you should be able to do something like this:

   ;```````````````````````````````````````````````````````````````
   ;  Remembers the high score until the game is turned off.
   ;
   dim _High_Score1 = v
   dim _High_Score2 = w
   dim _High_Score3 = x

   ;,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
   ;```````````````````````````````````````````````````````````````
   ;  Converts 6 digit score to 3 sets of two digits.
   ;
   ;  The 100 thousands and 10 thousands digits are held by _sc1.
   ;  The thousands and hundreds digits are held by _sc2.
   ;  The tens and ones digits are held by _sc3.
   ;
   dim _sc1 = score
   dim _sc2 = score+1
   dim _sc3 = score+2

   asm
   lda _High_Score3
   cmp _sc3
   lda _High_Score2
   sbc _sc2
   lda _High_Score1
   sbc _sc1
   ; Carry will be clear if score > _High_Score
   bcs ___No_High_Score ; Branch if Carry Set (goto ___No_High_Score label if carry is set)
end

   ; New High Score code - this is skipped if we goto  ___No_High_Score
   _High_Score1 = _sc1
   _High_Score2 = _sc2
   _High_Score3 = _sc3

___No_High_Score
   ; (more bB code)

 

you need decimal mode

  • Like 1
Link to comment
Share on other sites

forgot, bB prepends a "." to labels

 

here's RT's/your code slightly modified and your/RT's code stuffed in to a macro

 

just supply the first byte of high score as a parameter

 ;```````````````````````````````````````````````````````````````
   ;  Remembers the high score until the game is turned off.
   ;
   dim _High_Score1 = v
   dim _High_Score2 = w
   dim _High_Score3 = x
 
   ;,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
   ;```````````````````````````````````````````````````````````````
   ;  Converts 6 digit score to 3 sets of two digits.
   ;
   ;  The 100 thousands and 10 thousands digits are held by _sc1.
   ;  The thousands and hundreds digits are held by _sc2.
   ;  The tens and ones digits are held by _sc3.
   ;
   dim _sc1 = score
   dim _sc2 = score+1
   dim _sc3 = score+2
 
mk0
 
   asm
   sed
   lda _High_Score3
   cmp _sc3
   lda _High_Score2
   sbc _sc2
   lda _High_Score1
   sbc _sc1
   cld

   ; Carry will be clear if score > _High_Score
 
   ; need to prepend a . to the label as bB does
   bcs .No_High_Score ; Branch if Carry Set (goto ___No_High_Score label if carry is set)
end
 
   ; New High Score code - this is skipped if we goto  ___No_High_Score
   _High_Score1 = _sc1
   _High_Score2 = _sc2
   _High_Score3 = _sc3
 
No_High_Score
 
   ; (more bB code)
 
mk1
 
 
  def do_hiscore = callmacro _nh
 
  macro _nh
 
   asm
   sed
   lda {1} + 2
   cmp score + 2
   lda {1} + 1
   sbc score + 1
   lda {1}
   sbc score
   cld
   ; Carry will be clear if score > _High_Score
   bcs *+12 ; Branch if Carry Set (goto ___No_High_Score label if carry is set)
   lda score
   sta {1}
   lda score + 1
   sta {1} + 1
   lda score + 2
   sta {1} + 2
end
end
 
  do_hiscore _High_Score1

edit now I left out the sed :P (now fixed)

Edited by bogax
  • Like 1
Link to comment
Share on other sites

This is untested, but you should be able to do something like this:

bB was choking on the label, so I had to add a period:


   ;***************************************************************
   ;
   ;  High score check using asm.
   ;
   ;  The original supercat code was adapted by Karl G with input
   ;  from bogax.
   ;
   asm
   sed
   lda _High_Score3
   cmp _sc3
   lda _High_Score2
   sbc _sc2
   lda _High_Score1
   sbc _sc1
   cld
   bcs .__Skip_High_Score ; Branch if Carry Set (goto __Skip_High_Score label if carry is set)
end

   ;```````````````````````````````````````````````````````````````
   ;  New high score!
   ;
   _High_Score1 = _sc1 : _High_Score2 = _sc2 : _High_Score3 = _sc3

__Skip_High_Score


It seems to be working correctly so far. See if you can break it:

 

ex_shoot_with_scrolling_2018y_10m_05d_1757t_asm_highscore.bin

 

 

It's on the bB page now:

 

randomterrain.com/atari-2600-memories-batari-basic-commands.html#asm_savehighscore

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