It is currently Mon Oct 14, 2019 3:25 am

 All times are UTC - 7 hours

 Page 1 of 2 [ 23 posts ] Go to page 1, 2  Next
 Print view Previous topic | Next topic
Author Message
 Post subject: Compact /10 and %10 operations?Posted: Thu Sep 06, 2018 11:44 pm

Joined: Mon May 27, 2013 9:40 am
Posts: 543
I use a couple of /10 and %10 in my code (to display numbers), which import fairly big portions of runtime.lib I'd like to leave out. Anybody knows of any compat ubyte/10 and ubyte%10 functions in assembly?

I found this ubyte/10 by Omegamatrix https://forums.nesdev.com/viewtopic.php?f=2&t=11336
Code:
;Divide by 10
;17 bytes, 30 cycles
lsr
sta  temp
lsr
ror
lsr
lsr
ror
ror
lsr
lsr

Anybody knows something for ubyte%10? I could multiply by 10 (adding N<<3 and N<<1) the above results and substract, but is there a better method?

_________________
http://www.mojontwins.com

Top

 Post subject: Re: Compact /10 and %10 operations?Posted: Thu Sep 06, 2018 11:50 pm

Joined: Sun Apr 13, 2008 11:12 am
Posts: 8608
Location: Seattle
Tepples has an unrolled fast 8-bit-to-BCD converter here.

I bet there's other fast ones.

Top

 Post subject: Re: Compact /10 and %10 operations?Posted: Fri Sep 07, 2018 12:19 am

Joined: Fri Nov 12, 2004 2:49 pm
Posts: 7744
Location: Chexbres, VD, Switzerland
It's not fast however it's the shortest:
Code:
; A = number (0-99)

ldx #ff
sec
-   inx
sbc #10
bcs -

; A = lower digit (0-9), X=upper digit(0-9)

Even in the worst case (number is in the 90s) it's still reasonably fast. If you want to go up to 255, it's simple to add a quick check for a number greater than 200, then 100 before this code.

Code:
; A = number (0-255)

ldy #0
cmp #200
bcc +
sbc #200
ldy #2        ; Range 200-255
bne ++

+   cmp #100
bcc ++
sbc #100      ; Range 100-199
iny

++
ldx #ff       ; Conversion for lower 2 digits like before
sec
-   inx
sbc #10
bcc -

; A = lower digit (0-9), X=middle digit(0-9), Y=upper digit (0-2)

If you have a 16-bit number then it becomes worth doing an actual division/modulo operation.

(Note this code is untested so don't copy/paste without understanding and blame me if you get bugs)

Top

 Post subject: Re: Compact /10 and %10 operations?Posted: Fri Sep 07, 2018 12:41 am

Joined: Mon May 27, 2013 9:40 am
Posts: 543
Thank you, that's exactly what I needed It doesn't to be very fast, as it is only called once in a while. Up to 99 is enough.

_________________
http://www.mojontwins.com

Top

 Post subject: Re: Compact /10 and %10 operations?Posted: Fri Sep 07, 2018 5:37 am

Joined: Tue Feb 07, 2017 2:03 am
Posts: 764
Gee not having BCD is a bit of a pain here isn't it... Just typed out a nice response, and then remembered NES doesn't have BCD... ouch

Top

 Post subject: Re: Compact /10 and %10 operations?Posted: Fri Sep 07, 2018 5:47 am

Joined: Fri May 08, 2015 7:17 pm
Posts: 2574
Location: DIGDUG
Quote:
NES doesn't have BCD

There's nothing stopping you from storing values this way, and modifying your code to make it work.

I like to keep values 0-9. If it goes higher, add another byte, but keep them both 0-9.

Then %10 is as simple as reading the lowest byte.

_________________
nesdoug.com -- blog/tutorial on programming for the NES

Top

 Post subject: Re: Compact /10 and %10 operations?Posted: Fri Sep 07, 2018 6:01 am

Joined: Fri Nov 12, 2004 2:49 pm
Posts: 7744
Location: Chexbres, VD, Switzerland
Just for the annedote, Castlevania games 1 and 3 (but not 2 which uses a very different engine) stores the number of hearts in BCD, so if you have, say, 99 hearts it will be stored as \$99. Personally I find this inneficient, as many shifts and bitmask operations are needed to retrive the digits, and this only saves a single byte of RAM (negligible). Storing data in BCD only makes sense for large arrays of numbers, where the RAM savings would be significant.

Top

 Post subject: Re: Compact /10 and %10 operations?Posted: Fri Sep 07, 2018 6:09 am

Joined: Sun Sep 19, 2004 11:12 pm
Posts: 21625
Location: NE Indiana, USA (NTSC)
Thwaite stores the score in what amounts to base 100. In its representation, \$1163 has high byte 17, low byte 99, interpreted as 1799. Add 1, and you get 0x1200 (interpreted as 1800). This lets it correct for carry only between bytes (not between nibbles of one byte) while using the unrolled converter that lidnariq linked for display.

_________________
Pin Eight | Twitter | GitHub | Patreon

Top

 Post subject: Re: Compact /10 and %10 operations?Posted: Fri Sep 07, 2018 10:49 am

Joined: Sat Feb 12, 2005 9:43 pm
Posts: 11415
Location: Rio de Janeiro - Brazil
For decimal numbers that are involved only in additions or subtractions, I store each digit (0-9) in a byte and do all the math in that format, manually generating a carry when the result for each digit is larger than 9.

Modifying the numbers requires more code, but no conventions are necessary for displaying them.

Top

 Post subject: Re: Compact /10 and %10 operations?Posted: Mon Sep 10, 2018 2:08 am

Joined: Mon May 27, 2013 9:40 am
Posts: 543
I use unpacked bcd (byte per digit) when I have to display large scores, i.e. 5, or 6 digits. I just needed something simple to display numbers 0-99.

_________________
http://www.mojontwins.com

Top

 Post subject: Re: Compact /10 and %10 operations?Posted: Mon Sep 10, 2018 5:58 am

Joined: Fri Nov 12, 2004 2:49 pm
Posts: 7744
Location: Chexbres, VD, Switzerland
That was my point exactly, the usage of "unpacked BCD" (each digit being stored separatedly) makes most sense, and the usage of "packed by 100" such as what tepples describes is great too, considering how compact it is to decode a number 0-99 into its two separate digits (see my code above). However, using packed BCD makes little sense; retriving digits is barely easier than doing so from "packed by 100" BCD, but also it requires much more complex code to do calculations, and that only for saving a single RAM byte per digit. That's why it's notable Castlevania does this, despite this making few sense technically.

Top

 Post subject: Re: Compact /10 and %10 operations?Posted: Mon Sep 10, 2018 8:17 am

Joined: Tue Feb 07, 2017 2:03 am
Posts: 764
if you do it digit per byte, and handle the roll over case yourself ( as once must without BCD) it makes sense to store your numbers like scores etc in "tileset" numbers. Rarealy do you put 0-9 at tiles 0-9 you put them somewhere else.
Say its at 40 - 49. You can then Start at 40, if you hit 50, sub 10 and then add 1 to the next etc.
On the C64 quite a few games actually store the score, lives etc variables in the screen RAM( as in what you see on the screen is the variable ), not really that practical to do on a NES I guess.

If you want a fixed time, or a tight loop version you can shift bits and add the digits for it
say 0-99
you test bit 6 if set tens = 6 digits = 4
bit 5 if set add 3 2
bit 4 if set add 1 6
bit 3 if set add 0 8
bit 2 if set add 0 4
bit 1 if set add 0 2
bit 0 if set add 0 1
etc
here having BCD makes the code more compact and faster, as you need 1 table and 1 add. For larger bits 16/24/32 you can just repeat but change the byte you modify. (after also adding in the 1 28 case. )

Top

 Post subject: Re: Compact /10 and %10 operations?Posted: Mon Sep 10, 2018 8:35 am

Joined: Fri Nov 12, 2004 2:49 pm
Posts: 7744
Location: Chexbres, VD, Switzerland
Oziphantom wrote:
if you do it digit per byte, and handle the roll over case yourself ( as once must without BCD) it makes sense to store your numbers like scores etc in "tileset" numbers. Rarealy do you put 0-9 at tiles 0-9 you put them somewhere else.

Actually, avoiding an useless ADD or OR operation is in my opinion a good reason to put them at tiles 0-9 precisely. And if you have to put them somewhere else, at least put the "0" in the first column (i.e. tile \$x0) so that the conversion can be done with an "OR" operation, and a "CLC" instruction can be saved

Top

 Post subject: Re: Compact /10 and %10 operations?Posted: Mon Sep 10, 2018 9:08 am

Joined: Tue Feb 07, 2017 2:03 am
Posts: 764
or you can put 0 at 246 and thus gain the natural overflow detection, so you code looks like
Code:
sta Digit
bcc _noOver
inc DigitTens
adc #245 ; carry is set
_noOver

And you avoid having to do any other adc/ora to convert them for display. If you need to worry about a tens overflow you can php/plp and then check to see if it was bpl _tensOverflow (or beq )

Top

 Post subject: Re: Compact /10 and %10 operations?Posted: Mon Sep 10, 2018 10:07 am

Joined: Sat Feb 12, 2005 9:43 pm
Posts: 11415
Location: Rio de Janeiro - Brazil
Offsetting the values to line them up with the pattern indices for 0-9 is a good idea, as long as only the final number is offset and any values you add/subtract to/from it are still 0-based. You'll only get automatic wrap around detection in one direction anyway (either when adding or subtracting).

Top

 Display posts from previous: All posts1 day7 days2 weeks1 month3 months6 months1 year Sort by AuthorPost timeSubject AscendingDescending
 Page 1 of 2 [ 23 posts ] Go to page 1, 2  Next

 All times are UTC - 7 hours

#### Who is online

Users browsing this forum: No registered users and 3 guests

 You cannot post new topics in this forumYou cannot reply to topics in this forumYou cannot edit your posts in this forumYou cannot delete your posts in this forumYou cannot post attachments in this forum

Search for:
 Jump to:  Select a forum ------------------ NES / Famicom    NESdev    NESemdev    NES Graphics    NES Music    Homebrew Projects       2019 NESdev Competition       2018 NESdev Competition       2017 NESdev Competition       2016 NESdev Competition       2014 NESdev Competition       2011 NESdev Competition    Newbie Help Center    NES Hardware and Flash Equipment       Reproduction    NESdev International       FCdev       NESdev China       NESdev Middle East Other    General Stuff    Membler Industries    Other Retro Dev       SNESdev       GBDev    Test Forum Site Issues    phpBB Issues    Web Issues    nesdevWiki