GSCats/utility.s

221 lines
3.5 KiB
ArmAsm

;
; utility
; Helper routines
;
; Created by Quinn Dunki on 8/14/17
;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; intToString
;
; PARAML0 = Number to convert
; Returns result as pascal string in intToStringResult
;
intToString:
SAVE_AXY
; Convert value to BCD digits
; This section courtesy of John Brooks
sep #9
tdc
rol PARAML0
intToStringLoop:
sta SCRATCHL
adc SCRATCHL
rol intToStringBCD
asl PARAML0
bne intToStringLoop
cld
xba
sta intToStringBCD+1
; Convert digits to characters
BITS8
; Skip leading double zeros
ldx #0
ldy #1
intToStringSkipLoop:
lda intToStringBCD,x
bne intToStringSkipSingle
inx
cpx #3
bne intToStringSkipLoop
; Special case for full zero
sty intToStringResult
lda #'0'
sta intToStringResult+1
bra intToStringDone
intToStringSkipSingle:
; Process transition from leading-zero nibble
lda intToStringBCD,x
and #$f0
bne intToStringFullDigitsLoop
lda intToStringBCD,x
clc
adc #'0'
sta intToStringResult,y
iny
inx
cpx #3
beq intToStringFinish ; Single digit number so we're done
intToStringFullDigitsLoop:
; Remaining bytes all contain two digits
lda intToStringBCD,x
lsr
lsr
lsr
lsr
clc
adc #'0'
sta intToStringResult,y
iny
lda intToStringBCD,x
and #$0f
clc
adc #'0'
sta intToStringResult,y
iny
inx
cpx #3
bne intToStringFullDigitsLoop
intToStringFinish:
; Store final length and we're done
dey
sty intToStringResult
intToStringDone:
BITS16
RESTORE_AXY
rts
intToStringBCD: .byte 0,0,0
intToStringPrefix: .byte 0
intToStringResult: .byte 0,0,0,0,0,0
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; mult16
;
; PARAML0 = Operand 1 (16 bits)
; PARAML1 = Operand 2 (16 bits)
; A => Op1 * Op2 (16 bits)
; Algorithm from https://apple2.gs/downloads/Programmanual.pdf
;
; Trashes X,PARAML0,PARAML1
;
mult16:
lda #0 ; Initialize result
mult16L1:
ldx PARAML0 ; Get operand 1
beq mult16Done ; If operand is zero, we're done
lsr PARAML0 ; Get low bit
bcc mult16L2 ; If clear, no additions to previous products
clc ; Otherwise add oeprand 2 to partial result
adc PARAML1
mult16L2:
asl PARAML1 ; Now shift operand 2 left for possible add next time
bra mult16L1
mult16Done:
rts
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; mult88
;
; PARAML0 = Operand 1 (8.8 fixed point)
; PARAML1 = Operand 2 (8.8 fixed point)
; A => Op1 * Op2 (8.8 fixed point)
; Substantial precision loss occurs here, but it's usually good enough
;
mult88:
lda PARAML0 ; Convert operands to 12.4
lsr
lsr
lsr
lsr
sta PARAML0
lda PARAML1
lsr
lsr
lsr
lsr
sta PARAML1
jsr mult16 ; Result is 8.8
rts
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; delayShort
; Sleeps for a teeny bit
;
delayShort:
SAVE_AXY
ldy #$01 ; Loop a bit
delayShortOuter:
ldx #$ff
delayShortInner:
nop
nop
nop
nop
nop
nop
nop
dex
bne delayShortInner
dey
bne delayShortOuter
RESTORE_AXY
rts
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; delayMedium
; Sleeps for medium time (about 0.25 sec, but not calculated as such)
;
delayMedium:
SAVE_AX
ldx #$50
delayMediumInner:
jsr delayShort
dex
bne delayMediumInner
RESTORE_AX
rts
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; delayLong
; Sleeps for long time (about 1.5 sec, but not calculated as such)
;
delayLong:
SAVE_AXY
ldy #$03 ; Loop a bit
delayLongOuter:
ldx #$ff
delayLongInner:
jsr delayShort
dex
bne delayLongInner
dey
bne delayLongOuter
RESTORE_AXY
rts