I'm working on a game for the Atari VCS and have been dusting off my 30+ year old skills in writing MOS 6502 assembly language.
The VCS runs at 1.19 MHz and is based on a MOS 6507 chip with some custom logic and 128 bytes only of RAM.
Outline of Problem
The game needs to display a value as 3 ASCII digits, but I'm working in full range signed and unsigned bytes, rather than BCD, so I now have the problem of converting from a full range byte to ASCII digits.
What I have so Far
I have been able to put the following together, and it appears to work. I'd welcome any tips for making it smaller, faster etc.
Currently the program is estimated to run in around 114+ cycles, just counting the instruction cycle counts with no branches taken.
;
; FormatUnsigned.asm
;
; 6502 routine to format an unsigned byte into a space
; followed by 2 decimal digits if < 100, or 3 decimal
; digits if >= 100.
;
seg.u Variables
org $80
char1 .byte ; output chars
char2 .byte
char3 .byte
Temp .byte ; temp
seg Code
org $f000
TestFormat
lda #211 ; sample value
jsr FormatUnsigned ; format
brk ; halt
; A = value to format unsigned
FormatUnsigned:
ldy #$20 ; default hundreds digit
sty char1 ; is a space
; calculate char1
ldy #$30 ; '0'
sec ; set carry for sub loop
Sub100
sbc #100
iny ; y = '1', '2'
bcs Sub100 ; loop whilst carry is not borrowed
adc #100 ; add 100 back
dey ; and take back the inc to y
cpy #$30 ; if y is '0', just leave the space in there
beq SkipHundreds
sty char1 ; save '1' or '2' into char1
SkipHundreds
; format value < 100 into BCD
tay ; save a in y
lsr
lsr
lsr
lsr
and #$F ; get high nybble
tax ; into x for indexing
lda highNybble,x
sta Temp ; save in temp
tya ; get value - 100s back
and #$0f ; low nybble
tay ; low nybble in y
cmp #$0a ; <10?
bcc NoSub10
sbc #$0a ; subtract 10
tay ; save in y
clc
lda #$10 ; Add '10' to bcd saved value
adc Temp
sta Temp
tya
NoSub10
sed ; decimal mode
adc Temp ; add bcd value to 0-9 in a
sta Temp ; save bcd value
cld ; leave decimal mode
Write2ndChar
lsr ; get high nybble
lsr
lsr
lsr
and #$0f
adc #$30
sta char2 ; save 2nd character
Write3rdChar
lda Temp
and #$0f ; get low nybble
adc #$30
sta char3 ; save 3rd character
rts
highNybble
.byte $00
.byte $16
.byte $32
.byte $48
.byte $64
.byte $80
.byte $96
The program works correctly for tested inputs, producing an output of $32 $31 $31 for the decimal value 211.