aboutsummaryrefslogtreecommitdiff
path: root/mmss.s
blob: de60485f8ebbd412364fff3d6d92ef58c4c52da6 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164

;;; 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), fptmp (6 bytes), and tmp1
;;; (1 byte). 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
 ldy #>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.
 lda FR0
 and #$03
 sta tmp1
 inc tmp1
 ldx #0
floop:
 lda FR0+1,x
 jsr printhex
 inx
 cpx tmp1
 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
 ldy #>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