; ; 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