;;; Subroutine: print_mmss ;;; Print the 3-byte jiffy count at cloksav as minute/seconds/centisec. ;;; ;;; Will print up to 10 characters using printchr. Normally it's only 8, ;;; because normally, the number of minutes is less than 100, even if ;;; the user unwisely enters a 5-digit particle count. ;;; ;;; Uses the floating point ROM routines, because it's easier to code ;;; this way (or so I thought!), and we don't need speed here. ;;; ;;; Caller must define cloksav (3 bytes) and fptmp (6 bytes). ;;; These don't absolutely have to be in zero page, but ;;; it's nice if they are. ;;; print_mmss: ldx #0 ; low byte of 256 (0) stx FR0 inx stx FR0+1 ; high byte of 256 (1) jsr IFP ; FR0 now FP 256.0 jsr FMOVE ; FR1 = FR0 (both are 256.0) jsr FMUL ; FR0 = FR0 * FR1 (65536.0) (and FR1 is now garbage, but...) jsr FMOVE ; FR1 = FR0 (didn't need it anyway) ; cloksav is 3 bytes, MSB-first (like RTCLOK). ; first, convert the highest byte to jiffies: ldx #0 stx FR0+1 lda cloksav sta FR0 jsr IFP ; FR0 now cloksav in FP, FR1 = 65536.0 jsr FMUL ; FR0 = FR0 * FR1 jsr FMOVE ; FR1 = FR0, aka the high byte of cloksav in jiffies ; next, convert low 2 bytes of cloksav to FP... lda cloksav+1 sta FR0+1 lda cloksav+2 sta FR0 jsr IFP ; ...ok, now: jsr FADD ; add the high bytes in jiffies, result in FR0 again ; at this point, FR0 holds the 24-bit jiffy count, converted to FP. ; copy to fptmp before dividing (we need it later). ldx #fptmp jsr FST0R ; 3600 NTSC jiffies or 3000 PAL jiffies = 1 minute, so divide. jsr load_jpm_fr1 jsr FDIV ; FR0 = FR0 / FR1 (and FR1 is now garbage) ; FR0 is now minutes elapsed (e.g. 1.5, for 90 sec). Only print the ; integer part... ; FP ROM has no equivalent to trunc(). You might think you could call ; FPI followed by IFP, but FPI rounds up (e.g. 1.5 comes out as 2, ; not 1). But it's not hard to do: lda FR0 ; exponent beq truncdone and #$4f ; ignore sign sec sbc #$3f ; A gets either 1 or 2 tax lda #0 truncloop: sta FR0+1,x inx cpx #5 bne truncloop truncdone: ; print digits in FR0 ; don't use FASC, easier to do it this way. ; here we use the first byte of FR1 as a temp. lda FR0 and #$03 sta FR1 inc FR1 ldx #0 floop: lda FR0+1,x jsr printhex inx cpx FR1 bcc floop floopdone: ; done printing minutes, let's have the separator lda #':' jsr printchr ; we don't have a modulus or remainder operation in the ROM, so ; handroll one here. ; multiplication and division trash FR1, which is annoying. jsr load_jpm_fr1 jsr FMUL jsr FMOVE ; reload original jiffy count into FR0 ldx #fptmp jsr FLD0R ; subtract FR1. FR0 ends up with jiffies modulo jiffies-per-sec. jsr FSUB ; load 0.6 into FR1 so we can divide by it. ; result will be number of centisec (e.g. 1050 for 10.5 sec). jsr zero_fr1 lda #$3f sta FR1 lda #$60 sta FR1+1 jsr FDIV ; *now* we can actually make use of FPI's rounding! jsr FPI jsr IFP ; FR0 has division result, which is centiseconds. ; if the exponent is 0, we're OK. otherwise, shift down ; one byte so we print 00 for the seconds. ; again, avoid FASC. lda FR0 and #$0f bne twodigits lda FR0+1 sta FR0+2 lda #0 sta FR0+1 twodigits: lda FR0+1 jsr printhex lda #'.' jsr printchr lda FR0+2 jmp printhex ; load jiffies-per-minute into FR1. needs done twice so ; it's a subroutine. ; floating point constants: ; 3600.0 is $41,$36,$00,$00,$00,$00 ; 3000.0 is $41,$30,$00,$00,$00,$00 load_jpm_fr1: jsr zero_fr1 lda #$41 ; excess-64 base-100 exponent and sign (bit 7 = 0 means positive) sta FR1 ldx #$36 ; 1st mantissa BCD byte, NTSC lda PAL ; ask the GTIA what TV standard we're using and #$0e bne ntsc ldx #$30 ; 1st mantissa BCD byte, PAL ntsc: stx FR1+1 rts ;;; Subroutine: zero_fr1. Zeroes out all 6 bytes of FR1. Counterpart ;;; to the OS's ZFR0. ;;; Note: ZF1 does *not* just clear out FR1, it uses the X reg as an 8-bit ;;; pointer (to zero page only). zero_fr1: ldx #FR1 jmp ZF1