NESDev and Strangulation Records messageboards
Forum Index | FAQ | New User | Login | Search

Previous ThreadView All ThreadsNext Thread*Show in Threaded Mode


Subjecthexadecimal-to-decimal conversion routine  
Posted byzero soul
Posted on1/22/03 00:43 AM
From IP12.225.33.21  



here's a routine I cooked up a while ago that can take either an 8-bit or 16-bit number and output decimal versions into memory (one decimal digit per byte of memory, which could then be added with the tile # of the "0" to be put on-screen). it even counts up the number of significant digits, which you could use when writing to the screen (so 16 wouldn't be written as 016 or 00016).

it works by looking at each bit and if set, performing a decimal math operation "by hand" using a table of decimal values.

anyhow, I just thought I'd throw this out there for you to use if you'd like, or if you have any suggestions on how to optimize it or make it less "hackish", I'm definetely open to them. I've used this before, and it works.

here goes:

hex2dec_d4:
.db 0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,3
hex2dec_d3:
.db 0,0,0,0,0,0,0,0,0,0,1,2,4,8,6,2
hex2dec_d2:
.db 0,0,0,0,0,0,0,1,2,5,0,0,0,1,3,7
hex2dec_d1:
.db 0,0,0,0,1,3,6,2,5,1,2,4,9,9,8,6
hex2dec_d0:
.db 1,2,4,8,6,2,4,8,6,2,4,8,6,2,4,8

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; ;
; HEX2DEC8 / HEX2DEC16 ;
; ;
; Converts hex numbers to decimal and counts digits. ;
; ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; ;
; HEX2DEC8 (converts 8-bit hex to 3-digit decimal) ;
; ;
; In: A (number to be converted) ;
; ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; ;
; HEX2DEC16 (converts 16-bit hex to 5-digit decimal) ;
; ;
; In: A (low byte of number to be converted) ;
; X (high byte ") ;
; ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; ;
; Out: OUT.0 - OUT.4 (the converted number) ;
; DIGITS (digit count; 1 = 1-digit, etc) ;
; ;
; Modifies: A, X, IN.0, IN.1, OUT.0 - OUT.4 ;
; ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

hex2dec8:
ldx #0
hex2dec16:
sta IN.0
stx IN.1
ldx #0
stx OUT.0
stx OUT.1
stx OUT.2
stx OUT.3
stx OUT.4

do_hex2dec:
lsr IN.1
ror IN.0
bcc hex2dec_no_add
lda OUT.0
adc hex2dec_d0,x
cmp #10
bcs no_d0_carry
sec
sbc #10
inc OUT.1
no_d0_carry:
sta OUT.0
lda OUT.1
adc hex2dec_d1,x
cmp #10
bcs no_d1_carry
sec
sbc #10
inc OUT.2
no_d1_carry:
sta OUT.1
lda OUT.2
adc hex2dec_d2,x
cmp #10
bcs no_d2_carry
sec
sbc #10
inc OUT.3
no_d2_carry:
sta OUT.2
lda OUT.3
adc hex2dec_d3,x
cmp #10
bcs no_d3_carry
sec
sbc #10
inc OUT.3
no_d3_carry:
sta OUT.3
lda OUT.4
adc hex2dec_d4,x
sta OUT.4
hex2dec_no_add:
inx
cpx #5
bne do_hex2dec

digit_count:
dex
cpx #$FF
bne digit_count_continue
ldx #1
jmp digit_count_finished
digit_count_continue:
lda OUT.0,x
beq digit_count
digit_count_finished:
stx DIGITS
rts


I copied-and-pasted it right out of some code I wrote, I only edited out the "<"s which NESASM seems to require for zero-page addressing (otherwise it'll use 16-bit addressing in the assembled code... go figure).

The DIGITS-counting routine will return 1 if the resulting number was all zeroes, so at least the one "0" will be printed.

note that the decimal number is output backwards (eg., for a number "123", OUT.0 = 3, OUT.1 = 2, OUT.2 = 1, OUT.3 = 0, OUT.4 = 0), so to read it, you'd do something like this:

print_decimal:
ldx DIGITS
print_decimal_2:
lda OUT.0 - 1,x
adc #PATTERN_TABLE_TILE_OF_NUMBER_ZERO
sta $2007
dex
bne print_decimal_2
rts

That could be modified to align numbers to the right by explicitly doing 'LDX #5' and then writing a blank tile if X>DIGITS, but I don't feel like doing that now. :)

The whole routine could be modified to do even larger numbers (24-bit hex to 8-digit decimal, for example), but it'd be even more hackish; plus, some of the branches may be too long, which would require taking out the body of the code and moving it elsewhere, and JSRing to it or something.

Anyhow, that's that. Any thoughts?


...just another vision... Studios


SubjectRe: hexadecimal-to-decimal conversion routine new  
Posted byMemblers
Posted on2/14/03 00:42 AM
From IP68.58.99.218  



Looks good. Right now I'm working on some kind of library of common routines to use, I'll include this in it.

BTW, if the branches become too long it's usually better to reverse the branch condition and add a JMP after it. JMP absolute uses 3 cycles, but a JSR/RTS add 12 cycles.




SubjectRe: hexadecimal-to-decimal conversion routine new  
Posted bykoitsu
Posted on2/14/03 01:43 AM
From IP66.93.182.111  



Sadly, if the NES had decimal mode support, the conversion routine could be dropped down to 6 cycles per nybble:

sed
cmp #$0a
adc #'0'
cld

Otherwise, try using this:

cmp #$0a
bcc noadj
adc #6
adj: adc #'0'

-- jdc


SubjectRe: hexadecimal-to-decimal conversion routine new  
Posted bykoitsu
Posted on2/14/03 01:44 AM
From IP66.93.182.111  



Sorry, that should be "noadj:" not "adj:". *sigh*

-- jdc


SubjectRe: hexadecimal-to-decimal conversion routine new  
Posted bymcmartin
Posted on2/14/03 07:35 AM
From IP128.12.190.38  



I found an ancient book on Apple II assembly programming, and managed to construct a general 32-bit division/remainder routine for the C64 from it. It should work on the Nintendo, too. I can post it (appropriately cleaned up and generalized) if anyone wants such a beast...




Previous ThreadView All ThreadsNext Thread*Show in Threaded Mode
Jump to

Memblers' homepage             Contact Me

Forums powered by WWWThreads Demo