; Mockingboad programming: ; + Has two 6522 I/O chips connected to two AY-3-8910 chips ; + Optionally has some speech chips controlled via the outport on the AY ; + Often in slot 4 ; TODO: how to auto-detect? ; References used: ; http://macgui.com/usenet/?group=2&id=8366 ; 6522 Data Sheet ; AY-3-8910 Data Sheet ;======================== ; Mockingboard card ; Essentially two 6522s hooked to the Apple II bus ; Connected to AY-3-8910 chips ; PA0-PA7 on 6522 connected to DA0-DA7 on AY ; PB0 on 6522 connected to BC1 ; PB1 on 6522 connected to BDIR ; PB2 on 6522 connected to RESET ; left speaker MOCK_6522_ORB1 = $C400 ; 6522 #1 port b data MOCK_6522_ORA1 = $C401 ; 6522 #1 port a data MOCK_6522_DDRB1 = $C402 ; 6522 #1 data direction port B MOCK_6522_DDRA1 = $C403 ; 6522 #1 data direction port A MOCK_6522_T1CL = $C404 ; 6522 #1 t1 low order latches MOCK_6522_T1CH = $C405 ; 6522 #1 t1 high order counter MOCK_6522_T1LL = $C406 ; 6522 #1 t1 low order latches MOCK_6522_T1LH = $C407 ; 6522 #1 t1 high order latches MOCK_6522_T2CL = $C408 ; 6522 #1 t2 low order latches MOCK_6522_T2CH = $C409 ; 6522 #1 t2 high order counters MOCK_6522_SR = $C40A ; 6522 #1 shift register MOCK_6522_ACR = $C40B ; 6522 #1 auxilliary control register MOCK_6522_PCR = $C40C ; 6522 #1 peripheral control register MOCK_6522_IFR = $C40D ; 6522 #1 interrupt flag register MOCK_6522_IER = $C40E ; 6522 #1 interrupt enable register MOCK_6522_ORANH = $C40F ; 6522 #1 port a data no handshake ; right speaker MOCK_6522_ORB2 = $C480 ; 6522 #2 port b data MOCK_6522_ORA2 = $C481 ; 6522 #2 port a data MOCK_6522_DDRB2 = $C482 ; 6522 #2 data direction port B MOCK_6522_DDRA2 = $C483 ; 6522 #2 data direction port A ; AY-3-8910 commands on port B ; RESET BDIR BC1 MOCK_AY_RESET = $0 ; 0 0 0 MOCK_AY_INACTIVE = $4 ; 1 0 0 MOCK_AY_READ = $5 ; 1 0 1 MOCK_AY_WRITE = $6 ; 1 1 0 MOCK_AY_LATCH_ADDR = $7 ; 1 1 1 ;======================== ;======================== ; Mockingboard Init ;======================== ;======================== ; Left channel only mockingboard_init: sei ; disable interrupts, is this necessary? ;========================= ; Setup Interrupt Handler ;========================= ; NOTE: we don't support IIc as it's a hack ; traditionally Mockingboard on IIc was rare ;======================== ; set up interrupt ; Vector address goes to 0x3fe/0x3ff lda #interrupt_handler sta $03ff ;========================= ; Initialize the 6522s ; Reset Left AY-3-8910 ;=========================== ; entries=10 ; 14 + 2*entries = 34 bytes ; to beat = 46 bytes ldy #0 init_it_loop: lda init_values,Y ; 3 ldx init_addresses,Y ; 3 bmi doneit ; 2 iny ; 1 sta $c400,X ; 3 bne init_it_loop ; 2 doneit: init_registers: ; init song data lda #0 sta SONG_OFFSET sta SONG_COUNTDOWN ; read 14 bytes from beginning of song to init ldx #13 init_loop: init_smc: txa tay lda (SONG_L),Y jsr ay3_write_reg ; trashes Y dex bne init_loop ; update SONG_L to point past the init lda SONG_L clc adc #14 sta SONG_L bcc no_oflo inc SONG_H no_oflo: ; create Frequency Table ldx #11 make_freq_loop: sec lda frequency_lookup_low,X ror sta frequency_lookup_low+16,X lsr sta frequency_lookup_low+32,X lsr sta frequency_lookup_low+48,X dex bpl make_freq_loop inx stx frequency_lookup_low+28 rts ;===================== ;===================== ;===================== ; ay3 write reg ;===================== ;===================== ;===================== ; writes to one chip ; address in X ; data in A ay3_write_reg: pha lda #MOCK_AY_LATCH_ADDR ; latch_address for PB1 ; 2 ldy #MOCK_AY_INACTIVE ; go inactive ; 2 stx MOCK_6522_ORA1 ; put address on PA1 ; 4 sta MOCK_6522_ORB1 ; latch_address on PB1 ; 4 sty MOCK_6522_ORB1 ; 4 pla ; value sta MOCK_6522_ORA1 ; put value on PA1 ; 4 lda #MOCK_AY_WRITE ; ; 2 sta MOCK_6522_ORB1 ; write on PB1 ; 4 sty MOCK_6522_ORB1 ; 4 rts ; starts at C4 frequency_lookup_low: .byte $E8,$CD,$B3,$9B,$83,$6E,$59,$46,$33,$22,$12,$02 ;$1E8,$1CD,$1B3,$19B,$183,$16E,$159,$146,$133,$122,$112,$102, ;.byte $F4,$E6,$D9,$CD,$C1,$B7,$AC,$A3,$99,$91,$89,$81,$00,$00,$00,$00 ;.byte $7A,$73,$6C,$66,$60,$5B,$56,$51,$4C,$48,$44,$40,$00,$00,$00,$00 ;.byte $3D,$39,$36,$33,$30,$2D,$2B,$28,$26,$24,$22,$20,$00,$00,$00,$00 init_addresses: .byte