aboutsummaryrefslogtreecommitdiff
path: root/vendor/bcd16.s
diff options
context:
space:
mode:
authorMiquel Sabaté Solà <msabate@suse.com>2023-12-03 10:41:39 +0100
committerMiquel Sabaté Solà <msabate@suse.com>2023-12-03 10:41:39 +0100
commitc0d6966592a0aaeda220fff1171f057ef14a7ea6 (patch)
tree195cd2573ee5ce423281385ae92bad1715f0c02f /vendor/bcd16.s
parent03760c25d6a0609480c0ef5672ba0861f2838153 (diff)
downloadaoc2023.nes-c0d6966592a0aaeda220fff1171f057ef14a7ea6.tar.gz
aoc2023.nes-c0d6966592a0aaeda220fff1171f057ef14a7ea6.zip
Let's print the result to the screen
I have found and vendored a piece of code that allows me to convert a 16-bit number so it can be easily printed on screen. With this, let's be a bit more flashy and print the result to the screen. Signed-off-by: Miquel Sabaté Solà <msabate@suse.com>
Diffstat (limited to 'vendor/bcd16.s')
-rw-r--r--vendor/bcd16.s124
1 files changed, 124 insertions, 0 deletions
diff --git a/vendor/bcd16.s b/vendor/bcd16.s
new file mode 100644
index 0000000..452b294
--- /dev/null
+++ b/vendor/bcd16.s
@@ -0,0 +1,124 @@
+; bcd16.s
+; version 20060201
+;
+; Copyright (C) 2006 Damian Yerrick
+;
+; Copying and distribution of this file, with or without
+; modification, are permitted in any medium without royalty provided
+; the copyright notice and this notice are preserved in any source
+; code copies. This file is offered as-is, without any warranty.
+;
+; @mssola: The memory addresses being used here have been modified so they don't
+; clash with my programs (from $0x to $8x).
+
+.p02
+
+.exportzp bcdNum, bcdResult
+.export bcdConvert
+
+; bcdConvert
+;
+; Given a number in bcdNum (16-bit), converts it to 5 decimal digits
+; in bcdResult. Unlike most 6502 binary-to-decimal converters, this
+; subroutine doesn't use the decimal mode that was removed from the
+; 2A03 variant of the 6502 processor.
+;
+; For each value of n from 4 to 1, it compares the number to 8*10^n,
+; then 4*10^n, then 2*10^n, then 1*10^n, each time subtracting if
+; possible. After finishing all the comparisons and subtractions in
+; each decimal place value, it writes the digit to the output array
+; as a byte value in the range [0, 9]. Finally, it writes the
+; remainder to element 0.
+;
+; Extension to 24-bit and larger numbers is straightforward:
+; Add a third bcdTable, increase BCD_BITS, and extend the
+; trial subtraction.
+
+; Constants _________________________________________________________
+; BCD_BITS
+; The highest possible number of bits in the BCD output. Should
+; roughly equal 4 * log10(2) * x, where x is the width in bits
+; of the largest binary number to be put in bcdNum.
+; bcdTableLo[y], bcdTableHi[y]
+; Contains (1 << y) converted from BCD to binary.
+BCD_BITS = 19
+
+; Variables _________________________________________________________
+; bcdNum (input)
+; Number to be converted to decimal (16-bit little endian).
+; Overwritten.
+; bcdResult (output)
+; Decimal digits of result (5-digit little endian).
+; X
+; Offset of current digit being worked on.
+; Y
+; Offset into bcdTable*.
+; curDigit
+; The lower holds the digit being constructed.
+; The upper nibble contains a sentinel value; when a 1 is shifted
+; out, the byte is complete and should be copied to result.
+; (This behavior is called a "ring counter".)
+; Overwritten.
+; b
+; Low byte of the result of trial subtraction.
+; Overwritten.
+bcdNum = $80
+bcdResult = $82
+curDigit = $87
+b = $82
+
+;
+; Completes within 670 cycles.
+;
+
+bcdConvert:
+ lda #$80 >> ((BCD_BITS - 1) & 3)
+ sta curDigit
+ ldx #(BCD_BITS - 1) >> 2
+ ldy #BCD_BITS - 5
+
+@loop:
+ ; Trial subtract this bit to A:b
+ sec
+ lda bcdNum
+ sbc bcdTableLo,y
+ sta b
+ lda bcdNum+1
+ sbc bcdTableHi,y
+
+ ; If A:b > bcdNum then bcdNum = A:b
+ bcc @trial_lower
+ sta bcdNum+1
+ lda b
+ sta bcdNum
+@trial_lower:
+
+ ; Copy bit from carry into digit and pick up
+ ; end-of-digit sentinel into carry
+ rol curDigit
+ dey
+ bcc @loop
+
+ ; Copy digit into result
+ lda curDigit
+ sta bcdResult,x
+ lda #$10 ; Empty digit; sentinel at 4 bits
+ sta curDigit
+ ; If there are digits left, do those
+ dex
+ bne @loop
+ lda bcdNum
+ sta bcdResult
+ rts
+
+bcdTableLo:
+ .byt <10, <20, <40, <80
+ .byt <100, <200, <400, <800
+ .byt <1000, <2000, <4000, <8000
+ .byt <10000, <20000, <40000
+
+bcdTableHi:
+ .byt >10, >20, >40, >80
+ .byt >100, >200, >400, >800
+ .byt >1000, >2000, >4000, >8000
+ .byt >10000, >20000, >40000