git.y1.nz

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.