SPECTRUM128_STEREO = 1 ; L = A+Bx0.5, R = C'+B'x0.5 DUAL_MONO = 0 ; L = A+B+C, R=A'+B'+C' USE_PHASOR = 1 !macro MB_Init1 .RegSongNum { ; Pre: A = Song# [0..NUM_SONGS-1] ; Post: .RegSongNum = Song# ; jmp .skip_data nSongNum: !byte 0 ; Song# nFrameNum: !byte 0,0,0 ; Minute:Second:FrameNum (@ 50Hz) ; nMaskA: !byte 0 ; Voice-A mask (0=enable) nMaskB: !byte 0 ; Voice-B mask (0=enable) nMaskC: !byte 0 ; Voice-C mask (0=enable) ; nAttA: !byte 0 ; Attenuation of Voice-A nAttB: !byte 1 ; Attenuation of Voice-B : B Volume / 2 (logarithmic, so: if (B) B--) nAttC: !byte 0 ; Attenuation of Voice-C ; pAYRegValues: !word AYRegValues ; For VU-meter ; .skip_data: lda nSongNum cmp #NUM_SONGS bcc SongNumOK lda #255 ; Uninit sta nSongNum SongNumOK: ; lda nMBBaseHi beq FindMB ; Need to disable Timer1 IRQ before: ; . Scanning for MB card ; . Saving ZPBlock lda #1<<6 MB0: sta CARD_BASE+SY6522_IER+SY6522_A_PH_BASE ; Disable Timer1 IRQ FindMB: ;---------------------------------- +SaveRegs ZPBlock jsr SF_GetMBSlot bne GotMBSlot ; MB not found! jmp InitExit2 GotMBSlot: ; Setup correct address in IRQ handler code: !if SPECTRUM128_STEREO { stx MBx1+2 stx MBx2+2 stx MBx3+2 stx MBx4+2 } !if DUAL_MONO { stx MB1+2 stx MB1b+2 stx MB2+2 stx MB2b+2 stx MB3+2 stx MB3b+2 stx MB4+2 stx MB4b+2 stx MB5+2 stx MB5b+2 stx MB6+2 stx MB6b+2 } stx MB0+2 stx MB7+2 stx nMBBaseHi ; !if USE_PHASOR { ; Phasor 2MHz mode lda MBBaseH asl asl asl asl ; slot * 16 clc adc #PH_PHASOR tax lda $c080,x } !if USE_PHASOR { lda #$1f ; Phasor has 2 extra chip-select bits (b4:3) }else{ lda #$07 } ldy #SY6522_DDRB+SY6522_A_PH_BASE sta (MBBase),y ldy #SY6522_DDRB+SY6522_B_BASE sta (MBBase),y lda #$ff ldy #SY6522_DDRA+SY6522_A_PH_BASE sta (MBBase),y ldy #SY6522_DDRA+SY6522_B_BASE sta (MBBase),y lda #AY_RESET ; Phasor chip-select b4:3=%00 (so select both AY's) ldy #SY6522_ORB+SY6522_A_PH_BASE sta (MBBase),y ldy #SY6522_ORB+SY6522_B_BASE sta (MBBase),y ldx nSongNum cpx #255 bne NotFini jmp InitExit NotFini: lda SongTbl,x sta .RegSongNum } ;-------------------------------------- !macro MB_Init2 { lda #0 sta nFrameNum+0 sta nFrameNum+1 sta nFrameNum+2 ; Setup Timer1 IRQ to trigger at 50Hz ; Apple NTSC CLK = 1.022727 MHz, so set Timer1=0x4fe7 sei lda #$e7 ldy #SY6522_TIMER1L_COUNTER+SY6522_A_PH_BASE sta (MBBase),y lda #$4f ldy #SY6522_TIMER1H_COUNTER+SY6522_A_PH_BASE sta (MBBase),y lda #1<<6 ldy #SY6522_ACR+SY6522_A_PH_BASE sta (MBBase),y ; Free running timer lda #1<<7 | 1<<6 ldy #SY6522_IER+SY6522_A_PH_BASE sta (MBBase),y ; Enable Timer1 IRQ lda #Interrupt ; ADDR_H sta IRQH InitExit: cli +SaveRegs Z80Block InitExit2: +RestoreRegs ZPBlock } ;-------------------------------------- !if USE_PHASOR { PHASOR_CS_MASK = %10000 ; Phasor: b4=1 (don't select), b3=0 (select) } else { PHASOR_CS_MASK = 0 } ; Skyfox's routine to update AY regs: !macro SF_UpdateAY { SF_SelectReg: MBx1: sta CARD_BASE+SY6522_ORA,x lda #AY_LATCH | PHASOR_CS_MASK bne .l675e SF_WriteReg: MBx2: sta CARD_BASE+SY6522_ORA,x lda #AY_WRITE | PHASOR_CS_MASK bne .l675e SF_ChipReset: lda #AY_RESET | PHASOR_CS_MASK .l675e: MBx3: sta CARD_BASE+SY6522_ORB,x lda #AY_INACTIVE | PHASOR_CS_MASK MBx4: sta CARD_BASE+SY6522_ORB,x rts } ;-------------------------------------- !if SPECTRUM128_STEREO { ; L = A+Bx0.5, R = C'+B'x0.5 ; !macro MB_WriteAYRegs .ay_regs_base { ; Enable SLOTXROM while accessing MB regs lda SW_SLOTXROM_R pha bpl .ay_init ; branch if b7=0 (enabled) sta SW_SLOTXROM_ENA .ay_init: ldy #$0D .ay_loop: lda .ay_regs_base,y cpy #AY_ENABLE bne .ay_cont tax ; Save AY_ENABLE ora #AY_DIS_C sta .ay0_regs,y txa ; Restore AY_ENABLE ora #AY_DIS_A sta .ay1_regs,y dey bpl .ay_loop ; branch always taken ; .ay_cont: sta .ay0_regs,y sta .ay1_regs,y dey bpl .ay_loop ; ; Post processing AYPostProc: lda #0 sta .ay1_regs+AY_AVOL sta .ay0_regs+AY_CVOL ; ; Attenuate AVOL ; lda .ay_regs_base+AY_AVOL ; and #AY_AMPLITUDE_MODE ; bne + ; don't attenuate if amp.mode=envelope (Cybernoid doesn't use envelopes) lda .ay_regs_base+AY_AVOL sec sbc nAttA bpl .ay_set_a_vol lda #0 .ay_set_a_vol sta .ay0_regs+AY_AVOL + ; ; Attenuate BVOL ; lda .ay_regs_base+AY_BVOL ; and #AY_AMPLITUDE_MODE ; bne + ; don't attenuate if amp.mode=envelope (Cybernoid doesn't use envelopes) lda .ay_regs_base+AY_BVOL sec sbc nAttB bpl .ay_set_b_vol lda #0 .ay_set_b_vol sta .ay0_regs+AY_BVOL sta .ay1_regs+AY_BVOL + ; ; Attenuate CVOL ; lda .ay_regs_base+AY_CVOL ; and #AY_AMPLITUDE_MODE ; bne + ; don't attenuate if amp.mode=envelope (Cybernoid doesn't use envelopes) lda .ay_regs_base+AY_CVOL sec sbc nAttC bpl .ay_set_c_vol lda #0 .ay_set_c_vol sta .ay1_regs+AY_CVOL + ; ; User disable A/B/C .ay_chk_maska: lda nMaskA beq .ay_chk_maskb lda #0 sta .ay0_regs+AY_AVOL lda .ay0_regs+AY_ENABLE ora #AY_DIS_A sta .ay0_regs+AY_ENABLE .ay_chk_maskb: lda nMaskB beq .ay_chk_maskc lda #0 sta .ay0_regs+AY_BVOL sta .ay1_regs+AY_BVOL lda .ay0_regs+AY_ENABLE ora #AY_DIS_B sta .ay0_regs+AY_ENABLE lda .ay1_regs+AY_ENABLE ora #AY_DIS_B sta .ay1_regs+AY_ENABLE .ay_chk_maskc: lda nMaskC beq .ay_chk_mask_done lda #0 sta .ay1_regs+AY_CVOL lda .ay1_regs+AY_ENABLE ora #AY_DIS_C sta .ay1_regs+AY_ENABLE .ay_chk_mask_done: ; ldx #SY6522_A_PH_BASE ; Works for both MB & Phasor modes ldy #$0D .sf_loop0: tya jsr SF_SelectReg lda .ay0_regs,y jsr SF_WriteReg dey bpl .sf_loop0 ; ldx #SY6522_B_BASE ldy #$0D .sf_loop1: tya jsr SF_SelectReg lda .ay1_regs,y jsr SF_WriteReg dey bpl .sf_loop1 ; Disable SLOTXROM if necessary pla bpl .ay_done ; branch if b7=0 (enabled) sta SW_SLOTXROM_DIS bmi .ay_done ; branch always taken ;-------------- .ay0_regs: !fill 14,0 .ay1_regs: !fill 14,0 +SF_UpdateAY ;-------------- .ay_done: } } ; !if SPECTRUM128_STEREO ;------------------ !if DUAL_MONO { ; L = A+B+C, R=A'+B'+C' ; !macro MB_WriteAYRegs .ay_regs_base { ; Enable SLOTXROM while accessing MB regs lda SW_SLOTXROM_R pha bpl .ay_init ; branch if b7=0 (enabled) sta SW_SLOTXROM_ENA .ay_init: ldy #$0D lda #<.ay_regs_base sta TmpL lda #>.ay_regs_base sta TmpH .ay_loop: ; Select AY reg MB1: sty CARD_BASE+SY6522_ORA+SY6522_A_PH_BASE MB1b: sty CARD_BASE+SY6522_ORA+$80 lda #$07 ; LATCH MB2: sta CARD_BASE+SY6522_ORB+SY6522_A_PH_BASE MB2b: sta CARD_BASE+SY6522_ORB+$80 lda #$04 ; INACTIVE MB3: sta CARD_BASE+SY6522_ORB+SY6522_A_PH_BASE MB3b: sta CARD_BASE+SY6522_ORB+$80 ; Write AY reg lda (TmpL),y MB4: sta CARD_BASE+SY6522_ORA+SY6522_A_PH_BASE MB4b: sta CARD_BASE+SY6522_ORA+$80 lda #$06 ; WRITE MB5: sta CARD_BASE+SY6522_ORB+SY6522_A_PH_BASE MB5b: sta CARD_BASE+SY6522_ORB+$80 lda #$04 ; INACTIVE MB6: sta CARD_BASE+SY6522_ORB+SY6522_A_PH_BASE MB6b: sta CARD_BASE+SY6522_ORB+$80 dey bpl .ay_loop ; Disable SLOTXROM if necessary pla bpl .ay_done ; branch if b7=0 (enabled) sta SW_SLOTXROM_DIS .ay_done: } } ; !if DUAL_MONO ;-------------------------------------- !macro MB_ISR .isr_main { ; Pre: ; 6502 has pushed P ; Apple ROM has stored A to $45 (not Apple //e ROM!) ; txa pha tya pha +SaveRegs ZPBlock +RestoreRegs Z80Block jsr .isr_main +SaveRegs Z80Block +RestoreRegs ZPBlock lda #1<<6 MB7: sta CARD_BASE+SY6522_IFR+SY6522_A_PH_BASE ; Clear Timer1 IRQ flag pla tay pla tax lda $45 rti }