Jump to content

Photo

Score, large numbers, and BCDs


7 replies to this topic

#1 bjbest60 OFFLINE  

bjbest60

    Star Raider

  • 92 posts
  • Location:Space Cactus Canyon

Posted Wed Nov 28, 2018 11:46 PM

Every time I've tried to add a variable to a score, I feel like I've quickly gone wrong because I can't seem to figure out BCDs and the dec statement.  Often my solution is a simple loop: 

for x = 1 to level : score = score + 50 : next

That works well for small, repeatable instances.  But I've got a game concept I'd like to implement where the score can be large, and with that amount (let's assume it's money), you can purchase things that have variable prices and are larger than 255.

 

So, for example, with a score of 25,000, I could purchase an item that costs 9,876.

 

The question is how to make this work.  I understand the _sc1, _sc2, and _sc3 parts of the score.  My idea would be to store prices in data arrays similarly named, with two digits per price.  So, for something that costs 9,876, item1 would have an entry of $00 (first two digits), item2 would be $98 (second two digits), and item3 would have an entry of $76.  I also understand how to store _sc1 et al. into other variables and replace them when necessary.  But I can't figure out the math and the proper way to store things to have the calculations come out correctly.  Ideally, I'd like the score to display the cost upon hovering over a graphic of the item to be bought (by using a missile as a mouse pointer, say), then you could press fire to buy the item, and then upon leaving the correct new score would display (old score - price of item).  I'm trying to do this by comparing each pair of digits and subtracting where appropriate (and "carrying the one" when necessary).

 

I've fought with BCDs and dec statements and trying to parse how the score works and I can't seem to get anywhere.  I'm running into some hex issues where if I store $10 into my data array and load it into _sc3, It's actually hex 10 = decimal 16.  (And I think I've tried every combination of dec statements and dollar signs to combat this, to no avail.)  So there's some definite hex / dec conversion issues I'm failing to navigate.

 

Anyway, I'd really appreciate any assistance in trying to make this work.  I've looked at RT's page, sample programs, the forums, etc., and haven't found the right combination of operations yet.  Thanks.


Edited by bjbest60, Wed Nov 28, 2018 11:47 PM.


#2 Gemintronic OFFLINE  

Gemintronic

    Jason S. - Lead Developer & CEO

  • 9,245 posts

Posted Thu Nov 29, 2018 8:04 AM

The score supports only a small subset of math operations as bB only directly supports 8-bit (0-255) variables.  I usually end up just treating the score as a display then use 8-bit variables internally.

 

For instance: in my latest game I used the score to display a timer BUT internally I counted the time down using a variable that decrements down to 0 when the timer display also happens to run down to 0.

 

You could do the same thing with purchasable items in your game.  Internally you could store a 1 but display a score of 1000 for the end user.



#3 bjbest60 OFFLINE  

bjbest60

    Star Raider

  • Topic Starter
  • 92 posts
  • Location:Space Cactus Canyon

Posted Thu Nov 29, 2018 9:48 AM

Ok, I think I've figured it out.  It's a matter of keeping everything decimal all the time.  So every mathematical operation needs to be preceded by dec, and every number needs to be preceded by a dollar sign.  "Carrying the one" is a bit tricky.  So, for 1234 - 57, you have to reduce the number 12 by 1.  That's easy (and needs to be done with a dec statement and a dollar sign).  But then you need to add 100 to the 34.  This needs to be done in two terms because $100 isn't a valid BCD.  So instead it's $99 - 57 + 34 + $01 (where 57 and 34 would actually be variables).

 

I'm attaching the files that show how this works; press fire to "buy" a rectangle when hovering over it.  (It changes color when you hover, and then again when you buy.)  I'm hopeful this is the correct and robust solution, but I will post further if I find mistakes.

Attached Files



#4 Random Terrain OFFLINE  

Random Terrain

    Visual batari Basic User

  • 28,797 posts
  • Controlled Randomness
    Replay Value
    Nonlinear
  • Location:North Carolina (USA)

Posted Sat Dec 1, 2018 7:34 PM

When I can get back to using my computer more than a couple times a week, I'll link to your finished example from the bB page. After you are sure that you have it totally figured out, maybe you can make a new thread about, even if it's just an adapted version of what you posted above.



#5 bogax ONLINE  

bogax

    Dragonstomper

  • 782 posts

Posted Sun Dec 2, 2018 11:07 AM

Ok, I think I've figured it out.  It's a matter of keeping everything decimal all the time.  So every mathematical operation needs to be preceded by dec, and every number needs to be preceded by a dollar sign.  "Carrying the one" is a bit tricky.  So, for 1234 - 57, you have to reduce the number 12 by 1.  That's easy (and needs to be done with a dec statement and a dollar sign).  But then you need to add 100 to the 34.  This needs to be done in two terms because $100 isn't a valid BCD.  So instead it's $99 - 57 + 34 + $01 (where 57 and 34 would actually be variables).

 

I'm attaching the files that show how this works; press fire to "buy" a rectangle when hovering over it.  (It changes color when you hover, and then again when you buy.)  I'm hopeful this is the correct and robust solution, but I will post further if I find mistakes.

 

 
Not exactly sure what you're trying to do
 
dec wont have any effect on simple assignment statements
 
Somewhere I think RevEng posted some BCD routines for use with the score
 
You would do something like
 
 
 
 dim sc1 = score + 2
 dim sc2 = score + 1
 dim sc3 = score
 
score_add
 asm
 sed
 clc
 lda sc1
 adc temp1
 sta sc1
 lda sc2
 adc temp2
 sta sc2
 lda sc3
 adc temp3
 sta sc3
 cld
 rts
end
 
 
score_sub
 asm
 sed
 sec
 lda sc1
 sbc temp1
 sta sc1
 lda sc2
 sbc temp2
 sta sc2
 lda sc3
 adc temp3
 sbc sc3
 cld
 rts
end
 
 
You can do that in Bb but (as you're learning) it gets messy
 
 
If you just have to do it in Bb I think I'd do it a nybble at a time and use tables

Edited by bogax, Sun Dec 2, 2018 2:55 PM.


#6 bogax ONLINE  

bogax

    Dragonstomper

  • 782 posts

Posted Sun Dec 2, 2018 9:14 PM

 

If you just have to do it in Bb I think I'd do it a nybble at a time and use tables

 

 
 On second thought, since you've got decimal mode math in Bb I think you could do it byte wise like this (untested)
 
 
  dim sc1 = score + 2
  dim sc2 = score + 1
  dim sc3 = score
  dim carry = temp5
 
 
  temp4 = sc1
  dec sc1 = sc1 + temp1
  carry = 0 : if sc1 < temp4 then carry = carry + 1
  temp4 = sc2
  dec sc2 = sc2 + temp2 + carry
  carry = 0 : if sc2 < temp4 then carry = carry + 1 
  dec sc3 = sc3 + temp3 + carry
 

Edited by bogax, Sun Dec 2, 2018 9:18 PM.


#7 bjbest60 OFFLINE  

bjbest60

    Star Raider

  • Topic Starter
  • 92 posts
  • Location:Space Cactus Canyon

Posted Thu Dec 6, 2018 8:42 PM

Thanks for both suggestions.  I have a feeling they're both probably more efficient than what I came up with.  But the file I posted above does seem to work, so I went with those strategies.  I'll make a more complete post as RT suggests with a "final" version of my code, but I'll also link here.  Thanks!



#8 bogax ONLINE  

bogax

    Dragonstomper

  • 782 posts

Posted Sat Dec 8, 2018 4:08 PM

 
 
 BCD is Binary Coded Decimal, ie base ten digits represented by binary.
 Binary is base 2 and you need 4 bits to represent the largest decimal digit 9.
 A byte is eight bits so you can have two BCD digits per byte.
 4 bits gives you numbers 0..15.
 Hexadecimal is 0..15 and corresponds more or less directly to 4 bits (hexadecimal is base 16, 16 is 2^4) 
 For hexadecimal you have 0..9 with A..F for 10..15d so 14d is $0E, 16d is $10
 10d is represented by 16d (which is $10 in hexadecimal)
 If you add two BCD digits and they add up to < 10d all is good
 If you add two BCD digits and they add up to >= 10d you're 6 short so you add 6
 So eg 9 + 5 = 14d, 14 + 6 = 20 which is 16 + 4 or $14
 You have 2 digits per byte and you have to do that for both digits which is why
 I suggested nybbles ie a digit at a time
 
 But with decimal mode the processor does it for you a byte (two BCD digits) at a time
 
 The score is 6 BCD digits, but think of a byte as a single 0..99 digit and the score
 as three digits and you can do it bytewise just like you'd do any other digits
 
 I can't think of a simple way to explain, but if you add two digits
 you'll have a carry iff the result is less than either of the two digits
 So you can generate a carry by looking at how the digit changed
 
 
 here's your code after I got through mangling it
 
 (I reversed the order of the bytes, the screen displays left to right
 but I prefer the math to be right (least significant) to (left most signicant))

Attached Files


Edited by bogax, Sat Dec 8, 2018 4:57 PM.





0 user(s) are browsing this forum

0 members, 0 guests, 0 anonymous users