gbdk-2020 | GameBoy Development Kit |
| download: https://git.y1.nz/archives/gbdk.tar.gz | |
| README | Files | Log | Refs | LICENSE |
gbdk-lib/libc/asm/mos6502/bcd.s
1 ;--------------------------------------------------------------------------
2 ; bcd.s
3 ;
4 ; Copyright (C) 2024, Michel Iwaniec
5 ;
6 ; This library is free software; you can redistribute it and/or modify it
7 ; under the terms of the GNU General Public License as published by the
8 ; Free Software Foundation; either version 2, or (at your option) any
9 ; later version.
10 ;
11 ; This library is distributed in the hope that it will be useful,
12 ; but WITHOUT ANY WARRANTY; without even the implied warranty of
13 ; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 ; GNU General Public License for more details.
15 ;
16 ; You should have received a copy of the GNU General Public License
17 ; along with this library; see the file COPYING. If not, write to the
18 ; Free Software Foundation, 51 Franklin Street, Fifth Floor, Boston,
19 ; MA 02110-1301, USA.
20 ;
21 ; As a special exception, if you link this library with other files,
22 ; to produce an executable, this library does not by itself cause the
23 ; resulting executable to be covered by the GNU General Public License.
24 ; This exception does not however invalidate any other reasons why the
25 ; executable file might be covered by the GNU General Public License.
26 ;--------------------------------------------------------------------------
27
28 .module bcd
29
30 .area OSEG (PAG, OVR)
31 _bcd2text_bcd:
32 _bcd2text_tile_offset:
33 _bcd2text_PARM_2:: .ds 1
34 _bcd2text_buffer:
35 _bcd2text_PARM_3:: .ds 2
36 _bcd2text_BCD: .ds 4
37 _bcd_sub_PARM_2::
38 _uint2bcd_PARM_2::
39 _bcd_add_PARM_2:: .ds 4
40
41 .area _HOME
42
43 ; void uint2bcd(uint16_t i, BCD * value) __naked
44 _uint2bcd::
45 .define tmp "REGTEMP+2"
46 .define losub "REGTEMP+4"
47 .define hisub "REGTEMP+5"
48 .define v "REGTEMP+6"
49 ;.define value "_uint2bcd_PARM_2"
50
51 sta *tmp
52 stx *tmp+1
53 ; First two digits are always for uint16 -> BCD conversion
54 ldy #3
55 lda #0
56 sta [*_uint2bcd_PARM_2],y
57 dey
58 lda #0xFF
59 sta *v
60 tax
61 jmp 4$
62 1$:
63 inc *v
64 lda *tmp
65 sec
66 sbc *losub
67 sta *tmp
68 lda *tmp+1
69 sbc *hisub
70 sta *tmp+1
71 bcs 1$
72 ; Undo last sub. This should be faster on average
73 lda *tmp
74 adc *losub
75 sta *tmp
76 lda *tmp+1
77 adc *hisub
78 sta *tmp+1
79 ; Check odd/even x to determine if upper/lower nibble completed.
80 txa
81 lsr
82 lda *v
83 bcc 3$
84 ; Upper digit completed. Shift value to upper nibble.
85 asl
86 asl
87 asl
88 asl
89 adc #0xFF
90 sta *v
91 jmp 4$
92 3$:
93 ; Lower digit completed. Write value, move index and re-initialize v.
94 sta [*_uint2bcd_PARM_2],y
95 lda #0xFF
96 sta *v
97 dey
98 beq 5$
99 4$:
100 inx
101 lda losub_tab,x
102 sta *losub
103 lda hisub_tab,x
104 sta *hisub
105 jmp 1$
106 5$:
107 ; Switch to single-byte mode for second-last digit
108 ldx #0xFF
109 lda *tmp
110 6$:
111 inx
112 sec
113 sbc #10
114 bcs 6$
115 ; Undo last sub
116 adc #10
117 ; Combine last digit with second-last
118 and #0x0F
119 sta *tmp
120 txa
121 asl
122 asl
123 asl
124 asl
125 ora *tmp
126 ; Write combined result
127 sta [*_uint2bcd_PARM_2],y
128 rts
129
130 losub_tab:
131 .db <10000
132 .db <1000
133 .db <100
134
135 hisub_tab:
136 .db >10000
137 .db >1000
138 .db >100
139
140 ;void bcd_add(BCD * sour, BCD * value) __naked
141 _bcd_add::
142 .define sour "REGTEMP"
143 .define value "_bcd_add_PARM_2"
144 ;.define tmp "REGTEMP+2"
145 .define .c "REGTEMP+3"
146 .define .n "REGTEMP+4"
147 sta *sour
148 stx *sour+1
149 ldy #0
150 lda #4
151 sta *.n
152 clc
153 1$:
154 lda [*sour],y
155 adc [*value],y
156 ror *.c
157 tax
158 eor [*sour],y
159 eor [*value],y
160 and #0x10
161 ; Add 0x06 if half-carry was set
162 bne 2$
163 ; ...or if low nibble result >= 0xA
164 txa
165 and #0x0F
166 cmp #0x0A
167 txa
168 bcc 3$
169 2$:
170 txa
171 clc
172 adc #0x06
173 3$:
174 ; Add 0x60 if carry was set
175 bit *.c
176 bmi 4$
177 ; ...or if high nibble result >= 0xA
178 cmp #0xA0
179 bcc 5$
180 4$:
181 clc
182 adc #0x60
183 sec
184 5$:
185 sta [*sour],y
186 iny
187 dec *.n
188 bne 1$
189 rts
190
191 ; void bcd_sub(BCD * sour, BCD * value) __naked
192 _bcd_sub::
193 .define sour "REGTEMP"
194 .define value "_bcd_add_PARM_2"
195 .define tmp "REGTEMP+2"
196 .define .c "REGTEMP+3"
197 .define .n "REGTEMP+4"
198 sta *sour
199 stx *sour+1
200 ldy #0
201 lda #4
202 sta *.n
203 sec
204 1$:
205 lda [*sour],y
206 sbc [*value],y
207 ror *.c
208 tax
209 eor [*sour],y
210 eor [*value],y
211 and #0x10
212 ; Add 0x06 if half-carry was set
213 bne 2$
214 ; ...or if low nibble result >= 0xA
215 txa
216 and #0x0F
217 cmp #0x0A
218 txa
219 bcc 3$
220 2$:
221 txa
222 clc
223 adc #0x06
224 3$:
225 ; Add 0x60 if carry was *clear*
226 bit *.c
227 bpl 4$
228 ; ...or if high nibble result >= 0xA
229 cmp #0xA0
230 bcc 5$
231 4$:
232 clc
233 adc #0x60
234 clc
235 bcc 6$
236 5$:
237 sec
238 6$:
239 sta [*sour],y
240 iny
241 dec *.n
242 bne 1$
243 rts
244
245 ;uint8_t bcd2text(BCD * bcd, uint8_t tile_offset, uint8_t * buffer) __naked
246 _bcd2text::
247 sta *REGTEMP
248 stx *REGTEMP+1
249
250 ldy #3
251 0$:
252 lda [*REGTEMP],y
253 sta *_bcd2text_BCD,y
254 dey
255 bpl 0$
256
257 ldy #0
258 ldx #3
259 1$:
260 lda *_bcd2text_BCD,x
261 pha
262 lsr
263 lsr
264 lsr
265 lsr
266 clc
267 adc *_bcd2text_tile_offset
268 sta [*_bcd2text_buffer],y
269 iny
270 pla
271 and #0x0F
272 clc
273 adc *_bcd2text_tile_offset
274 sta [*_bcd2text_buffer],y
275 iny
276 dex
277 bpl 1$
278 ; Store 0 at end
279 lda #0
280 sta [*_bcd2text_buffer],y
281 ; Return length of string as 8
282 lda #8
283 rts
This webpage is intended to be an accessible preview of this repository. To get a fuller picture, clone it and use the git CLI.