NES Advantage

Making NES Development Less Hard

Converting Hexadecimal to Decimal Numbers

Numbers in the NES are stored as 8-bit binary values, usually represented via the hexadecimal number system. This is all well and good, except when it comes time to show those numbers to the player. 0 through 9 are fine, but we'd rather display 10 and 11 than A and B.

So before we can display things like scores, lives, experience points, and gold, we need to convert those values' hex representations into their decimal equivalents. Unfortunately, the NES lacks any built-in capability for doing so. Fortunately, there are any number of clever algorithms to do it for us. Here's one of them. (Note: this only works for positive numbers!)

To begin, we'll need to reserve seven bytes in the zero page. The first two store the high and low bytes of the hex value we're converting. The other five each store a single digit of our decimal output, enabling us to store any value from 0 to 99,999 (though 16 bits will max out at 65,535).

.segment "ZEROPAGE" hex_value: .res 2 ascii_result: .res 5

Let's move on to the code. Make sure to import those zero page values. Next, we'll create a table in the read-only data portion of memory. This table stores the decimal representations of each hex number, and will be accessed via table offsets as we lop each bit off our hex value. Notice how each five-byte row of the table represents a power of two, and there are sixteen rows in total—one for each digit of the starting value.

.segment "RODATA" decimal_table: .byte 0,0,0,0,1 .byte 0,0,0,0,2 .byte 0,0,0,0,4 .byte 0,0,0,0,8 .byte 0,0,0,1,6 .byte 0,0,0,3,2 .byte 0,0,0,6,4 .byte 0,0,1,2,8 .byte 0,0,2,5,6 .byte 0,0,5,1,2 .byte 0,1,0,2,4 .byte 0,2,0,4,8 .byte 0,4,0,9,6 .byte 0,8,1,9,2 .byte 1,6,3,8,4 .byte 3,2,7,6,8

And finally, the subroutine itself. A key thing to remember is that the zero-page variable hex_value must already be set with whatever we want to convert before this subroutine is called.

.proc hex_to_ascii LDA #$00 LDY #$04 clear: STA ascii_result,y DEY BNE clear LDX #$4F loop1: CLC ROL hex_value ROL hex_value+1 BCS calculate TXA SEC SBC #$05 TAX BPL loop1 RTS calculate: CLC LDY #$04 loop2: LDA decimal_table,x ADC #$00 BEQ zero ADC ascii_result,y CMP #$0a BCC notten SBC #$0A notten: STA ascii_result,y zero: DEX DEY BPL loop2 JMP loop1 .endproc
Copyright ©2024 Nathaniel Webb/Nat20 Games