mirror of
https://github.com/a2-4am/4cade.git
synced 2025-02-20 12:29:04 +00:00
292 lines
9.1 KiB
Plaintext
292 lines
9.1 KiB
Plaintext
;license:MIT
|
|
;(c) 2019-2022 by Andrew Roughan, qkumba, 4am, Tom Charlesworth, Rob Justice
|
|
;
|
|
; Mockingboard support functions
|
|
;
|
|
|
|
;------------------------------------------------------------------------------
|
|
; GetMockingboardStuff
|
|
; detect Mockingboard card by searching for 6522 timers across all slots 7->1
|
|
; access 6522 timers with deterministic cycle counts
|
|
;
|
|
; based on prior art in Mockingboard Developers Toolkit
|
|
; with optimisation from deater/french touch
|
|
; also takes into account FastChip //e clock difference
|
|
;
|
|
; in: A/Y contains address of callback to call if card was found
|
|
; (this will be called before the speech detection routine, and
|
|
; (zp$81 will contain the slot in form $Cx)
|
|
; /!\ ALL ACCELERATORS MUST BE OFF OR SET TO 1 MHZ
|
|
; ROM must be banked in for reading
|
|
; out: if card was found, X = #$?n where n is the slot number of the card, otherwise #$00
|
|
; and bit 5 = 0 if Mockingboard Sound I found
|
|
; or bit 5 = 1 if Mockingboard Sound II or "A"-"D" found
|
|
; and bit 6 = 1 if SSI-263 speech chip found
|
|
; or bit 7 = 1 if SC-01 speech chip found
|
|
; flags clobbered
|
|
; zp $80-$82 clobbered
|
|
; A/Y clobbered
|
|
; ROM banked in, no write
|
|
;------------------------------------------------------------------------------
|
|
|
|
MAGIC_Z80_LOCATION=$FFD
|
|
|
|
GetMockingboardStuff
|
|
+ST16 @callback+1
|
|
|
|
lda ROM_MACHINEID
|
|
cmp #$06
|
|
bne @not_iic
|
|
ldx ROM_MACHINE2C
|
|
bne @not_iic
|
|
|
|
; from mgcaret
|
|
; https://github.com/a2-4am/4cade/issues/483
|
|
; the Mockingboard init can accidentally enable the Softcard Z80
|
|
; and can crash the machine
|
|
; solved by loading a small Z80 routine at $0FFD (FFFDh in the Z80 space):
|
|
; $32 $00 $E4 $C3 FD FF which is
|
|
; NOP
|
|
; LD (E400h),A ; card is at $E400 due to memory translation
|
|
; JP FFFDh
|
|
; returns the system to 6502 mode and leaves it in the same state as the Z80 after RESET:
|
|
; ready to execute the instruction at 0000h (from the Z80 perspective)
|
|
ldx #5
|
|
- lda magic_z80_bytes, x
|
|
sta MAGIC_Z80_LOCATION, x
|
|
dex
|
|
bpl -
|
|
stx $C403 ; enable Mockingboard 4C support
|
|
stx $C404
|
|
|
|
@not_iic
|
|
lda #$00
|
|
sta $80
|
|
sta $82 ; type
|
|
ldx #$C1
|
|
@slotLoop
|
|
stx $81
|
|
ldy #$04 ; 6522 #1 $Cx04
|
|
jsr @timercheck
|
|
bcc @foundI
|
|
|
|
@nextSlot
|
|
inx
|
|
cpx #$C8
|
|
bne @slotLoop
|
|
ldx #$00 ; not found
|
|
rts
|
|
|
|
@foundI ; sound I or better
|
|
jsr @callback
|
|
ldy #$84 ; 6522 #2 $Cx84
|
|
jsr @timercheck
|
|
bcc @foundII
|
|
|
|
ldy #$0c
|
|
sty @mb_smc1 + 1
|
|
iny
|
|
sty @mb_smc10 + 1
|
|
iny
|
|
sty @mb_smc5 + 1
|
|
sty @mb_smc14 + 1
|
|
clc
|
|
|
|
+HIDE_NEXT_BYTE
|
|
@foundII ;stereo
|
|
sec
|
|
ror $82
|
|
|
|
lda $81
|
|
sta @mb_smc1 + 2
|
|
sta @mb_smc2 + 2
|
|
sta @mb_smc3 + 2
|
|
sta @mb_smc4 + 2
|
|
sta @mb_smc5 + 2
|
|
sta @mb_smc6 + 2
|
|
sta @mb_smc7 + 2
|
|
sta @mb_smc8 + 2
|
|
sta @mb_smc9 + 2
|
|
sta @mb_smc10 + 2
|
|
sta @mb_smc11 + 2
|
|
sta @mb_smc12 + 2
|
|
sta @mb_smc13 + 2
|
|
sta @mb_smc14 + 2
|
|
sta @mb_smc15 + 2
|
|
sta @mb_smc17 + 2
|
|
sta @mb_smc18 + 2
|
|
sta @mb_smc19 + 2
|
|
sta @mb_smc20 + 2
|
|
sta @mb_smc21 + 2
|
|
sta @mb_smc22 + 2
|
|
sta @mb_smc23 + 2
|
|
|
|
; detect speech - SSI263
|
|
|
|
sei
|
|
+READ_RAM2_WRITE_RAM2
|
|
lda #$40 ; setup NMI vector (rti)
|
|
sta $3fb
|
|
lda #$fb
|
|
sta $fffa
|
|
lda #3
|
|
sta $fffb
|
|
lda #<@mb_irq ; setup IRQ vector
|
|
sta $3fe
|
|
sta $fffe
|
|
lda #>@mb_irq
|
|
sta $3ff
|
|
sta $ffff
|
|
|
|
lda #$0c ; CB2 - input neg edge, CB1 neg edge, CA2 low output, CA1 neg edge
|
|
@mb_smc1
|
|
sta $c48c ; peripheral control register 6522#2
|
|
lda #$80 ; ctl=1
|
|
@mb_smc2
|
|
sta $c443 ; C = SSI reg 3, S/S I or A = 6522#1 ddr a
|
|
lda #$c0 ; duration=11 phoneme=000000 (pause)
|
|
@mb_smc3
|
|
sta $c440 ; C = SSI reg 0, S/S I or A = 6522#1 port b data
|
|
lda #$70 ; ctl=0 (A/R active - phoneme timing response)
|
|
@mb_smc4
|
|
sta $c443 ; C = SSI reg 3, S/S I or A = 6522#1 ddr a
|
|
lda #$82 ; enable CA1 interrupt
|
|
@mb_smc5
|
|
sta $c48e ; interrupt enable register 6522#2
|
|
|
|
ldx #$80 ; 0= ~650ms, 80 = ~325ms
|
|
ldy #0
|
|
sec
|
|
cli
|
|
|
|
@wait_irq
|
|
lda $80
|
|
bne +
|
|
iny
|
|
bne @wait_irq
|
|
inx
|
|
bne @wait_irq
|
|
clc
|
|
+ ror $82
|
|
|
|
; detect speech - SC-01
|
|
;based on S/S I demo dsk
|
|
;init sc-01 interface
|
|
lda #$ff
|
|
@mb_smc15
|
|
sta $c402 ; ddr portb - all outputs
|
|
lda #$b0 ; cb2 pulse output,cb1 pos edge
|
|
@mb_smc17
|
|
sta $c40c ; pcr
|
|
lda #$10 ; clear all interrupt flags
|
|
@mb_smc18
|
|
sta $c40d ; ifr
|
|
;output stop phoneme
|
|
lda #$3f ; stop
|
|
@mb_smc19
|
|
sta $c400 ; orb, write phoneme & pitch
|
|
lda #$10
|
|
@mb_smc23
|
|
bit $c40d ; ifr, check for cb1 interrupt flag
|
|
bne @got_irq ; work around A2FPGA bug that does not clear cb1
|
|
|
|
ldx #$D0 ; wait ~120ms, stop takes 47ms
|
|
- lda #$10
|
|
@mb_smc20
|
|
bit $c40d ; ifr, check for cb1 interrupt flag
|
|
bne + ; flag set, we found one
|
|
iny
|
|
bne -
|
|
inx
|
|
bne -
|
|
beq @got_irq
|
|
|
|
@mb_smc21
|
|
+ sta $c40d ; ifr, clear flag
|
|
lda #$00 ; turn off cb2 pulse mode to disable false writes to sc01
|
|
@mb_smc22
|
|
sta $c40c ; pcr
|
|
sec ; found, we have an SC-01
|
|
ror $82
|
|
bne @ssI
|
|
|
|
@got_irq
|
|
sei
|
|
clc ; not found
|
|
ror $82
|
|
|
|
ldy #$ff
|
|
@mb_smc6
|
|
sty $c403 ; 6522#1 ddra
|
|
lda #7
|
|
@mb_smc7
|
|
sta $c402 ; 6522#1 ddrb
|
|
|
|
iny
|
|
sty $80
|
|
tya
|
|
sta ($80),y ; 6522#1 orb
|
|
lda #4
|
|
sta ($80),y ; 6522#1 orb
|
|
|
|
@ssI
|
|
ldy #$ff
|
|
@mb_smc8
|
|
sty $c483 ; 6522#2 ddra
|
|
lda #7
|
|
@mb_smc9
|
|
sta $c482 ; 6522#2 ddrb
|
|
|
|
lda #0
|
|
ldy #$80
|
|
sta ($80),y ; 6522#2 orb
|
|
lda #4
|
|
sta ($80),y ; 6522#2 orb
|
|
|
|
lda #7
|
|
and $81
|
|
ora $82
|
|
tax
|
|
lda #<Ignore
|
|
sta $fffe
|
|
lda #>Ignore
|
|
sta $ffff
|
|
+READ_ROM_NO_WRITE
|
|
|
|
rts ; found
|
|
|
|
@timercheck
|
|
sec
|
|
lda ($80),y ; read 6522 timer low byte
|
|
sbc ($80),y ; second time
|
|
sec
|
|
sbc #5 ; looking for 5 cycles between reads
|
|
cmp #2 ; or 6 cycles with the FastChip //e
|
|
rts
|
|
|
|
@mb_irq
|
|
lda #2 ; clear CA1 interrupt flag
|
|
@mb_smc10
|
|
sta $c48d ; interrupt flag register 6522#2
|
|
lda #$80 ; ctl=1
|
|
@mb_smc11
|
|
sta $c443 ; C = SSI reg 3, S/S I or A = 6522#1 ddr a
|
|
lda #0 ; duration=00 phoneme=000000 (pause)
|
|
@mb_smc12
|
|
sta $c440 ; C = SSI reg 0, S/S I or A = 6522#1 port b data
|
|
lda #$70 ; ctl=0 (A/R active - phoneme timing response)
|
|
@mb_smc13
|
|
sta $c443 ; C = SSI reg 3, S/S I or A = 6522#1 ddr a
|
|
sta $80 ; found
|
|
lda #2 ; disable CA1 interrupt
|
|
@mb_smc14
|
|
sta $c48e ; interrupt enable register 6522#2
|
|
lda $45
|
|
rti
|
|
|
|
@callback
|
|
jmp $FDFD ; SMC
|
|
|
|
magic_z80_bytes
|
|
!byte $32, $00, $E4, $C3, $FD, $FF
|