mirror of
https://github.com/tomcw/Cybernoid.git
synced 2025-01-18 23:29:41 +00:00
474 lines
7.6 KiB
Plaintext
474 lines
7.6 KiB
Plaintext
|
|
SPECTRUM128_STEREO = 1 ; L = A+Bx0.5, R = C'+B'x0.5
|
|
DUAL_MONO = 0 ; L = A+B+C, R=A'+B'+C'
|
|
|
|
|
|
!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_L
|
|
sta IRQL
|
|
lda #>Interrupt ; ADDR_H
|
|
sta IRQH
|
|
|
|
InitExit:
|
|
cli
|
|
|
|
+SaveRegs Z80Block
|
|
|
|
InitExit2:
|
|
+RestoreRegs ZPBlock
|
|
}
|
|
|
|
;--------------------------------------
|
|
|
|
!if USE_PHASOR {
|
|
PHASOR_CS_MASK = AY_CS1 ; Phasor: b4=0 (select), b3=1 (not 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
|
|
}
|