-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathchip-sc01.a
395 lines (303 loc) · 7.04 KB
/
chip-sc01.a
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
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
;license:MIT
;(c) 2021 by Tom Charlesworth
;
; SC01 related
;
;------------------------------------------------------------------------------
DetectSC01
; Pre: zpTmp1 = 6522 bitmap in b1:0
; Post:
; SC01 is only on SMS's Speech, SMS's Sound/Speech, AppleWin's hybrid MB + MAME's hybrid MB
; - Speech using 6522 PCR w/o IRQ (based on Crimewave's SC01 code)
lda zpTmp1
and #HAS_6522A
beq +
lda #IER_CLR|IxR_VOTRAX
ldy #SY6522_IER
sta (MBBase),y ; disable CB1(Speech) IRQ
dey ; Y=IFR
sta (MBBase),y ; clear CB1(Speech) IRQ flag
jsr KickSC01
lda #$FF
jsr WAIT ; delay for 0x28882 (166018) cycles / ~163ms
ldy #SY6522_IFR
lda #IxR_VOTRAX ; check CB1(Speech) IRQ
and (MBBase),y
beq ++
sta (MBBase),y ; clear CB1(Speech) IRQ
inc hasSC01
++ jsr DisableSC01
+ rts
;------------------------------------------------------------------------------
DisableSC01
; NB. Called from userland & ISR
; https://github.com/a2-4am/4cade:
; . turn off cb2 pulse mode to disable false writes to sc01 (to fix random MB noise)
lda #$00
ldy #SY6522_PCR
sta (MBBase),y
rts
;------------------------------------------------------------------------------
KickSC01
lda #$B0
ldy #SY6522_PCR
sta (MBBase),y
ldy #SY6522_IFR
lda #IxR_VOTRAX
sta (MBBase),y ; clear CB1(Speech) IRQ after setting PCR
ldy #SY6522_DDRB
lda #$FF
sta (MBBase),y
ldy #SY6522_ORB
lda #$3F ; STOP (47ms on average)
sta (MBBase),y
rts
;------------------------------------------------------------------------------
PlaySC01
; Pre: X:A = phoneme data
sta SpeechDataL
stx SpeechDataH
sei
inc doingSpeechSC01
lda #0
sta irqT1IntCount
jsr KickSC01
lda #$ff ; T1C = T1L = $FFFF
ldy #SY6522_TIMER1L_COUNTER
sta (MBTimer),y
iny ; SY6522_TIMER1H_COUNTER
sta (MBTimer),y ; (and clears IFR.b6)
lda #ACR_FREERUNNING
ldy #SY6522_ACR
sta (MBTimer),y ; Free-running timer
lda #IER_SET|IxR_TIMER1|IxR_VOTRAX
ldy #SY6522_IER
sta (MBTimer),y ; Enable Timer1 IRQ & SC01/Votrax IRQ
cli
rts
;------------------------------------------------------------------------------
TestSC01
; Pre: has6522, hasSC01
; Post: C=0(OK), C=1(NG)
lda has6522
and #1
beq @exitOK
lda hasSC01
beq @exitOK
lda #IER_CLR|IxR_TIMER1|IxR_TIMER2|IxR_VOTRAX
ldy #SY6522_IER ; disable IRQ
sta (MBBase),y
ldy #SY6522_IFR ; clear IRQ flag
sta (MBBase),y
lda #<TestSC01ISR
ldx #>TestSC01ISR
jsr SetIrqNmiVectors
lda #COMPONENT_SC01+1 ; test component $31
sta testComponentNum
lda #$ff
sta testNum ; test #00
lda MBBaseH
sta MBTimerH
lda MBBaseL
sta MBTimerL ; NB. MBTimer is used for TIMER1
; SC01 is only accessed by 6522 at $Cn00
inc testNum ; test #00
jsr TSC01_0
bcs @error
@exitOK
clc
bcc @done
@error
; Pre: zpTmp2 = expected value
; A = actual value
; Post: C=1(NG)
sta errorActual
lda zpTmp2
sta errorExpected
sec
@done
php
jsr WaitT1OneShotUnderflow ; Pre: MBBaseH/L (restore to one-shot mode)
plp
rts
;------------------------------------------------------------------------------
TSC01_0
; Pre: MBBaseL = SY6522_A_BASE
; Post: C=0(OK), C=1(NG)
;
; Test#0
; . Play phrase "THE SPY STRIKES BACK" and check total duration is within tolerance
; . NB. "Speech/Sound I" card has a potentiometer to manually control the speech rate.
jsr resetSubTest ; subTest #0
jsr incTotalTests
lda #<TheSpyStrikesBack
ldx #>TheSpyStrikesBack
jsr PlaySC01
ldy #0 ; delay of ~41.95s
- lda #$ff
jsr WAIT
lda doingSpeechSC01 ; done? (or user hit ESC to skip)
beq @ok
dey
bne -
beq @error
@ok clc ; C=0(OK)
bcc @done
@error
; Error: phrase not complete
lda #0
sta zpTmp2 ; expected
sec ; C=1(NG)
@done
sei
php
lda #0
sta doingSpeechSC01
jsr DisableSC01
ldy #SY6522_IER
lda #IER_CLR|IxR_VOTRAX
sta (MBBase),y ; Disable SC01/Votrax IRQ
lda #IER_CLR|IxR_TIMER1
sta (MBTimer),y ; Disable Timer1 IRQ
lda #IxR_VOTRAX
ldy #SY6522_IFR
sta (MBBase),y ; Clear SC01/Votrax IRQ
jsr CalcPhraseDuration ; Real MB: <TODO> (MAME 0.230: 0x15E0BE; AppleWin: 0x250229,0x250C9B/running; 0x260B7B/stepping)
lda #1 ; actual
plp
rts
;------------------------------------------------------------------------------
TestSC01ISR
; Pre:
; 6502 has pushed P
; Apple ROM has stored A to $45 (not Apple //e ROM!)
; MBBaseL = SY6522_A_BASE
; MBTimer (== MBBase)
; SpeechData
; Post:
; irqT1IntCount, irqT1H, irqT1H2, irqT1L
; isrFlag=1 (on SC01 IRQ)
; SpeechData (incremented)
;
txa
pha
tya
pha
;------
ldy #SY6522_TIMER1H_COUNTER
lda (MBTimer),y
sta irqT1H
; Read IFR.T1 before reading T1C_l (which clears IFR.T1)
; NB. read IFR.T1 between the 2 reads of T1H, so that irqT1IntCount is consistent with T1H vs T1H2
; Eg. IFR.T1 could become 1 between reading T1H & T1H2
ldy #SY6522_IFR
lda (MBTimer),y
and #IxR_TIMER1
tax ; save IFR.T1
ldy #SY6522_TIMER1L_COUNTER
lda (MBTimer),y ; (reading T1C_l clears IFR.b6)
sta irqT1L
ldy #SY6522_TIMER1H_COUNTER
lda (MBTimer),y
sta irqT1H2
txa ; test IFR.T1
beq +
inc irqT1IntCount ; Timer1 IRQ
jmp @exit
;
+ ldy #SY6522_IFR
lda #IxR_VOTRAX
sta (MBBase),y ; clear all remaining IRQs (ie. Speech)
lda #1
sta isrFlag
;------
lda KBD
bpl +
bit KBDSTRB
cmp #$80+27 ; ESC?
bne +
; Skip to final STOP phoneme
lda #<TheSpyStrikesBack_end
sta SpeechDataL
lda #>TheSpyStrikesBack_end
sta SpeechDataH
+
;------
lda #0
ldy #4
- ora (SpeechData),y
dey
bpl -
tay ; tst a
bne +
; last phoneme complete, disable SC01 IRQ + disable 6522 T1 IRQ
@endSpeech
sta doingSpeechSC01 ; =0
jsr DisableSC01
lda #IER_CLR|IxR_TIMER1
ldy #SY6522_IER
sta (MBTimer),y ; Disable Timer1 IRQ
jmp @exit ; NB. don't go via code to set SpeechData+=1
+ ldy #0
lda (SpeechData),y
sta (MBBase),y
; NB. don't reset T1C to $ffff - just let it continue to count down
; So total speech phrase will be more accurate, but individual phonemes won't be. Maybe use T2 for each phoneme?
lda SpeechDataL
clc
adc #1
sta SpeechDataL
bcc +
inc SpeechDataH
+
@exit
pla
tay
pla
tax
lda $45 ; for Apple II/II+
rti
;------------------------------------------------------------------------------
!zone data
doingSpeechSC01 !byte 0
TheSpyStrikesBack
; Penguin Software's "The Spy Strikes Back"
; NB. For MAME 0.230 inflection (b7:6) changes the pitch, but the overall phrase duration remains constant at 0x15E0D0 cycles (model=applee)
!byte $03
!byte $38
!byte $32
!byte $03
!byte $1F
!byte $25
!byte $15
!byte $22
!byte $03
!byte $1F
!byte $2A
!byte $2B
!byte $15
!byte $22
!byte $19
!byte $1F
!byte $03
!byte $0E
!byte $2E
!byte $19
!byte $03
TheSpyStrikesBack_end
!byte $3F
NullPhraseSC01
!byte 0,0,0,0,0
!if 0 {
Ouch
; Penguin Software's "The Spy Strikes Back" - "Ouch!"
; NB. For MAME 0.230 the overall phrase duration is 0x0679D4 cycles (model=applee)
!byte $03
!byte $13
!byte $37
!byte $2A
!byte $10
!byte $03
!byte $3F
!byte 0,0,0,0,0
}