I'm trying to find a way to replace the missing decimal mode on the 2A03. Currently I handle scores with each of the 6 digits separately, but I figured out that I could pack 2 digits in one byte, so it'd take 3 bytes of RAM instead of 6.
For this, I'd need some system that reliably add 2 packed BCD numbers together, and set the carry if the result is greater than 100, while keeping the low 2 digits correctly. I don't care the results for invalid BCD numbers.
Now the question is, is it more efficient (ROM and Speed wise) to do so ?
1st idea : Do a binary addition, and do a software "decimal adjust"
2nd idea : Handle each digit separatedly :
I think both solutions are somewhat complex and un-elegant.
For this, I'd need some system that reliably add 2 packed BCD numbers together, and set the carry if the result is greater than 100, while keeping the low 2 digits correctly. I don't care the results for invalid BCD numbers.
Now the question is, is it more efficient (ROM and Speed wise) to do so ?
1st idea : Do a binary addition, and do a software "decimal adjust"
Code:
lda _packed_bcd1
clc
adc _packed_bcd2
php
sta _packed_result
eor _packed_bcd1
eor _packed_bcd2 ;Check if half-carry was set
and #$10
bne halfcarryset
lda _packed_result
and #$0f ;Check if any non-valid BCD number
cmp #$0a
bcc nohalfcarry
halfcarryset:
lda #$06 ;If any of those was true -> decimal adjust low digit
clc
adc _packed_result
sta _packed_result
bcc nohalfcarry
pla
php
nohalfcarry:
lda _packed_result
plp
bcs carryset ;Check if full carry was set
cmp #$a0 ;Check for invalid high digit
bcc nocarry
carryset:
adc #$60-1 ;If any of those true -> decimal adjust high digit
sta _packed_result
sec
nocarry:
clc
adc _packed_bcd2
php
sta _packed_result
eor _packed_bcd1
eor _packed_bcd2 ;Check if half-carry was set
and #$10
bne halfcarryset
lda _packed_result
and #$0f ;Check if any non-valid BCD number
cmp #$0a
bcc nohalfcarry
halfcarryset:
lda #$06 ;If any of those was true -> decimal adjust low digit
clc
adc _packed_result
sta _packed_result
bcc nohalfcarry
pla
php
nohalfcarry:
lda _packed_result
plp
bcs carryset ;Check if full carry was set
cmp #$a0 ;Check for invalid high digit
bcc nocarry
carryset:
adc #$60-1 ;If any of those true -> decimal adjust high digit
sta _packed_result
sec
nocarry:
2nd idea : Handle each digit separatedly :
Code:
lda _packed_bcd2
and #$0f
sta _c
lda _packed_bcd1
and #$0f
clc
adc _c
cmp #$0a
bcc nouovfl
sbc #$0a
nouovfl:
sta _packed_result
lda #$00
bcc nodadjust
lda #$0f
nodadjust:
adc _packed_bcd1
and #$f0
adc _packed_bcd2
and #$f0
bcs dovfl
cmp #$a0
bcc nodovfl
dovfl:
sbc #$a0
sec
nodovfl:
ora _packed_result
sta _packed_result
and #$0f
sta _c
lda _packed_bcd1
and #$0f
clc
adc _c
cmp #$0a
bcc nouovfl
sbc #$0a
nouovfl:
sta _packed_result
lda #$00
bcc nodadjust
lda #$0f
nodadjust:
adc _packed_bcd1
and #$f0
adc _packed_bcd2
and #$f0
bcs dovfl
cmp #$a0
bcc nodovfl
dovfl:
sbc #$a0
sec
nodovfl:
ora _packed_result
sta _packed_result
I think both solutions are somewhat complex and un-elegant.