mirror of
https://github.com/Michaelangel007/apple2_mockingboard.git
synced 2024-12-26 08:30:45 +00:00
Add C scale demo
This commit is contained in:
parent
ef1763aad7
commit
1dca9e69e0
6
Makefile
6
Makefile
@ -1,4 +1,4 @@
|
||||
all: test_mock freq
|
||||
all: test_mock scales freq
|
||||
|
||||
.PHONY: test_mock
|
||||
|
||||
@ -8,6 +8,10 @@ test_mock:
|
||||
src2dsk test_mock.s
|
||||
applewin.sh -d1 test_mock.dsk
|
||||
|
||||
scales: scales.s
|
||||
src2dsk $<
|
||||
applewin.sh -d1 $(basename $<).dsk
|
||||
|
||||
freq: freq.c
|
||||
g++ $(C_FLAGS) $< -o $@
|
||||
|
||||
|
BIN
scales.dsk
Normal file
BIN
scales.dsk
Normal file
Binary file not shown.
431
scales.s
Normal file
431
scales.s
Normal file
@ -0,0 +1,431 @@
|
||||
; Mockingboard Demo Scales
|
||||
; Clean up by Michael Pohoreski
|
||||
; http: https://github.com/Michaelangel007/apple2_mockingboard.git
|
||||
; Assembler: cc65
|
||||
|
||||
__MAIN = $8000
|
||||
|
||||
; Uncomment next 2 lines for ProDOS
|
||||
.word __MAIN ; 2 byte BLOAD address
|
||||
.word __END - __MAIN ; 2 byte BLOAD size
|
||||
|
||||
; Mockingboard Base Address
|
||||
ADDR6522 = $C400 ; *** Default Mockingboard to slot 4 ***
|
||||
|
||||
; Programmable Sound Generator
|
||||
MOCK_TONE_LOW = $0 ; Tone Control Fine Reg 0/2/4: lo 8-bit
|
||||
MOCK_TONE_HIGH = $1 ; Tone Control Coarse Reg 1/3/5: hi 4-bit
|
||||
|
||||
MOCK_TONE_A_LO = $0 ; 12-bit
|
||||
MOCK_TONE_A_HI = $1
|
||||
|
||||
MOCK_TONE_B_LO = $2 ; 12-bit
|
||||
MOCK_TONE_B_HI = $3
|
||||
|
||||
MOCK_TONE_C_LO = $4 ; 12-bit
|
||||
MOCK_TONE_C_HI = $5
|
||||
|
||||
MOCK_NOISE = $6 ; Noise Period Reg 6 : 5-bit
|
||||
|
||||
; a b x x x y y y
|
||||
; \___/
|
||||
; C B A
|
||||
; 0=Tone Disabled
|
||||
; \___/
|
||||
; C B A
|
||||
; 0=Noise Disabled
|
||||
; B input=0
|
||||
; A input=0
|
||||
DISABLE_TONE_A = %000001 ; $01
|
||||
DISABLE_TONE_B = %000010 ; $02
|
||||
DISABLE_TONE_C = %000100 ; $04
|
||||
DISABLE_NOISE_A = %001000 ; $08
|
||||
DISABLE_NOISE_B = %010000 ; $10
|
||||
DISABLE_NOISE_C = %100000 ; $20
|
||||
MOCK_CHANNELS = $7 ; Disabled Chans Mask Reg 7 : 6-bit
|
||||
|
||||
; D s s s s
|
||||
; \_____/
|
||||
; Static
|
||||
; 1=Dynamic
|
||||
AMP_STATIC = %01111
|
||||
AMP_DYNAMIC = %10000
|
||||
MOCK_AMPLITUDE = $8 ; Amplitude Reg 8/9/A: 5-bit
|
||||
MOCK_AMP_A = $8
|
||||
MOCK_AMP_B = $9
|
||||
MOCK_AMP_C = $A
|
||||
|
||||
MOCK_ENV_LOW = $B ; Envelope Fine Reg B : lo 8-bit
|
||||
MOCK_ENV_HIGH = $C ; Envelope Coarse Reg C : hi 8-bit
|
||||
|
||||
; C K A H
|
||||
; Continue
|
||||
; Attack
|
||||
; Alternate
|
||||
; Hold
|
||||
ENV_CONT = %0001
|
||||
ENV_ATTACK = %0010
|
||||
ENV_ALT = %0100
|
||||
ENV_HOLD = %1000
|
||||
MOCK_ENV_TYPE = $D ; Envelope Shape Reg D : 4-bit
|
||||
|
||||
MOCK_REG_FIRST = $0
|
||||
MOCK_REG_LAST = $D
|
||||
MOCK_REG_NUM = $E
|
||||
|
||||
; Left Speaker
|
||||
MOCK1_OR_B = ADDR6522+0 ; OR Register B
|
||||
MOCK1_OR_A = ADDR6522+1 ; OR Register A
|
||||
MOCK1_DIR_B = ADDR6522+2 ; Data Direction Reg B
|
||||
MOCK1_DIR_A = ADDR6522+3 ; Data Direction Reg A
|
||||
; Right Speaker
|
||||
MOCK2_OR_B = ADDR6522+0+$80
|
||||
MOCK2_OR_A = ADDR6522+1+$80
|
||||
MOCK2_DIR_B = ADDR6522+2+$80
|
||||
MOCK2_DIR_A = ADDR6522+3+$80
|
||||
|
||||
; 6522 Commands
|
||||
; DIR BC1 BC0
|
||||
_6522_RESET = $0 ; 0 0 0
|
||||
_6522_PORT_B = $4 ; 1 0 0
|
||||
_6522_WRITE = $6 ; 1 1 0
|
||||
_6522_LATCH = $7 ; 1 1 1
|
||||
|
||||
_6522_PORT_A_OUT = $07 ; TODO: is $FF safe?
|
||||
_6522_PORT_B_OUT = $FF
|
||||
|
||||
|
||||
note_index = $FF
|
||||
|
||||
; === CODE ===
|
||||
|
||||
.org __MAIN ; .org must come after header else offsets are wrong
|
||||
|
||||
; Cleaned up code
|
||||
jsr MOCK1_Init
|
||||
jsr MOCK2_Init
|
||||
|
||||
lda #0
|
||||
sta note_index
|
||||
|
||||
ldx #<demo_regs_1
|
||||
ldy #>demo_regs_1
|
||||
jsr MOCK1_Play
|
||||
|
||||
play_loop:
|
||||
ldy note_index
|
||||
ldx demo_half_notes,y
|
||||
bmi play_done
|
||||
|
||||
jsr MOCK1_ANoteX
|
||||
lda #0
|
||||
jsr DelayA
|
||||
|
||||
inc note_index
|
||||
bne play_loop
|
||||
|
||||
play_done:
|
||||
jmp MOCK1_Stop
|
||||
|
||||
; === DATA ===
|
||||
|
||||
; $3E = Only enable Tone A
|
||||
channels = DISABLE_NOISE_C | DISABLE_NOISE_B | DISABLE_NOISE_A | DISABLE_TONE_C | DISABLE_TONE_B
|
||||
|
||||
demo_regs_1:
|
||||
.byte $80,$00 ; [0] Tone A
|
||||
.byte $80,$00 ; [2] Tone B
|
||||
.byte $80,$00 ; [4] Tone C
|
||||
.byte $00 ; [6] Noise
|
||||
.byte channels ; [7] Disable
|
||||
.byte $0F,$0F,$0F ; [8] Amp A, B, C
|
||||
.byte $00 ; [B] Env Lo
|
||||
.byte $00 ; [C] Env Hi
|
||||
.byte $00 ; [D] Env Type
|
||||
|
||||
demo_half_notes:
|
||||
.byte $00 ; C4
|
||||
.byte $02 ; D4
|
||||
.byte $04 ; E4
|
||||
.byte $05 ; F4
|
||||
.byte $07 ; G4
|
||||
.byte $09 ; A4
|
||||
.byte $0B ; B4
|
||||
.byte $0C ; C5
|
||||
.byte $FF ; end-of-music
|
||||
|
||||
;Tone Control Fine 128 ($80) Register 0/2/4
|
||||
;Tone Control Coarse 0 Register 1/3/5
|
||||
;Noise Period 0 Register 6
|
||||
;Enable Mask 62 ($3E) Register 7
|
||||
;Amplitude 15 ($0F) Register 8/9/A
|
||||
;Envelope Fine 0 Register B
|
||||
;Envelope Coarse 0 Register C
|
||||
;Envelope Shape 0 Register D
|
||||
|
||||
; ____________________ Utility ____________________
|
||||
|
||||
; ====================
|
||||
; Delay ((A * ? + ?) * (A * ? + ?)
|
||||
; ====================
|
||||
DelayA:
|
||||
tax
|
||||
tay
|
||||
@1: inx
|
||||
bne @1
|
||||
iny
|
||||
bne @1
|
||||
rts
|
||||
|
||||
; ____________________ Mockingboard 1 ____________________
|
||||
|
||||
; ====================
|
||||
; Initialize Mockingboard
|
||||
; ====================
|
||||
MOCK1_Init:
|
||||
lda #_6522_PORT_B_OUT
|
||||
sta MOCK1_DIR_B
|
||||
; lda #_6522_PORT_A_OUT
|
||||
sta MOCK1_DIR_A
|
||||
; NOTE: Intentional fall-into reset!
|
||||
MOCK1_Reset:
|
||||
lda #_6522_RESET ; -->+
|
||||
.byte $2C ; |
|
||||
MOCK1_SetReg: ; |
|
||||
lda #_6522_LATCH ;-->+ |
|
||||
.byte $2C ; | |
|
||||
MOCK1_SetData: ; | |
|
||||
lda #_6522_WRITE ; | |
|
||||
sta MOCK1_OR_B ;<--+ <--+
|
||||
lda #_6522_PORT_B
|
||||
sta MOCK1_OR_B
|
||||
rts
|
||||
|
||||
; ====================
|
||||
; IN:
|
||||
; X = Note Index
|
||||
; OUT:
|
||||
; A = trash
|
||||
; X = trash
|
||||
; Y = trash
|
||||
; ====================
|
||||
MOCK1_ANoteX:
|
||||
lda #MOCK_TONE_A_LO
|
||||
.byte $2c
|
||||
MOCK1_BNoteX:
|
||||
lda #MOCK_TONE_B_LO
|
||||
.byte $2c
|
||||
MOCK1_CNoteX:
|
||||
lda #MOCK_TONE_C_LO
|
||||
|
||||
MOCK1_nNoteX:
|
||||
sta _mock_note+1 ; X = Mockingboard Register, 0=Tone A, 2=Tone B, 4=Tone C
|
||||
|
||||
lda note_to_tone_hi,x
|
||||
pha
|
||||
lda note_to_tone_lo,x
|
||||
_mock_note:
|
||||
ldx #MOCK_TONE_A_LO ; *** SELF-MODIFIED!
|
||||
jsr MOCK1_PokeXA
|
||||
inx ; X = MOCK_TONE_A_HI
|
||||
pla
|
||||
; NOTE: Intentional fall-into MOCK1_PokeXA !
|
||||
|
||||
; ====================
|
||||
; Plays one note
|
||||
; IN:
|
||||
; X = Register: $0 .. $D
|
||||
; A = Value
|
||||
; OUT:
|
||||
; A = trash
|
||||
; X = unchanged
|
||||
; Y = trash
|
||||
; ====================
|
||||
MOCK1_PokeXA:
|
||||
TAY
|
||||
; NOTE: Intentional fall-into!
|
||||
|
||||
; ====================
|
||||
; Poke (set) byte to Mockingboard
|
||||
; IN:
|
||||
; X = Register: $0 .. $D
|
||||
; Y = Value
|
||||
; OUT:
|
||||
; A = trash
|
||||
; X = unchanged
|
||||
; Y = unchanged
|
||||
; ====================
|
||||
MOCK1_PokeXY:
|
||||
stx MOCK1_OR_A
|
||||
jsr MOCK1_SetReg
|
||||
sty MOCK1_OR_A
|
||||
jmp MOCK1_SetData
|
||||
|
||||
; ====================
|
||||
; Stop all sounds by setting all regs to zero
|
||||
; ====================
|
||||
MOCK1_Stop:
|
||||
LDX #<mockN_off_data ; *** SELF-MODIFIES!
|
||||
LDY #>mockN_off_data
|
||||
; NOTE: Intentional fall-into!
|
||||
|
||||
; ====================
|
||||
; Plays one note by setting all Mockingboard registers
|
||||
; IN:
|
||||
; X = Low Address of registers
|
||||
; Y = High Address of
|
||||
; ====================
|
||||
MOCK1_Play:
|
||||
STX _mock1_load_reg+1 ; *** SELF-MODIFIES!
|
||||
STY _mock1_load_reg+2
|
||||
_mock1all_regs:
|
||||
ldy #0
|
||||
ldx #MOCK_REG_FIRST
|
||||
_mock1_load_reg:
|
||||
lda mockN_off_data,X ; *** SELF-MODIFIED!
|
||||
jsr MOCK1_PokeXA
|
||||
inx
|
||||
cpx #MOCK_REG_NUM ; BUG: $B !
|
||||
bcc _mock1_load_reg
|
||||
rts
|
||||
|
||||
; === DATA ===
|
||||
|
||||
note_to_tone_lo:
|
||||
.byte $F4 ; C4 261.626 Hz
|
||||
.byte $E6 ; C4# 277.183 Hz
|
||||
.byte $D9 ; D4 293.665 Hz
|
||||
.byte $CD ; D4# 311.127 Hz
|
||||
.byte $C1 ; E4 329.628 Hz
|
||||
.byte $B7 ; F4 349.228 Hz
|
||||
.byte $AC ; F4# 369.994 Hz
|
||||
.byte $A3 ; G4 391.995 Hz
|
||||
.byte $99 ; G4# 415.305 Hz
|
||||
.byte $91 ; A4 440.000 Hz
|
||||
.byte $89 ; A4# 466.164 Hz
|
||||
.byte $81 ; B4 493.883 Hz
|
||||
|
||||
.byte $7A ; C5 523.251 Hz
|
||||
.byte $73 ; C5# 554.365 Hz
|
||||
|
||||
note_to_tone_hi:
|
||||
|
||||
; NOTE: Intentional Data overlap/re-use
|
||||
; .byte $00 ; C4 261.626 Hz
|
||||
; .byte $00 ; C4# 277.183 Hz
|
||||
; .byte $00 ; D4 293.665 Hz
|
||||
; .byte $00 ; D4# 311.127 Hz
|
||||
; .byte $00 ; E4 329.628 Hz
|
||||
; .byte $00 ; F4 349.228 Hz
|
||||
; .byte $00 ; F4# 369.994 Hz
|
||||
; .byte $00 ; G4 391.995 Hz
|
||||
; .byte $00 ; G4# 415.305 Hz
|
||||
; .byte $00 ; A4 440.000 Hz
|
||||
; .byte $00 ; A4# 466.164 Hz
|
||||
; .byte $00 ; B4 493.883 Hz
|
||||
; .byte $00 ; C5 523.251 Hz
|
||||
; .byte $00 ; C5# 554.365 Hz
|
||||
|
||||
mockN_off_data:
|
||||
BRK ; Reg 0,1 Tone A
|
||||
BRK
|
||||
BRK ; Reg 2,3 Tone B
|
||||
BRK
|
||||
BRK ; Reg 4,5 Tone C
|
||||
BRK
|
||||
BRK ; Reg 6 Noise
|
||||
BRK ; Reg 7 Enable
|
||||
BRK ; Reg 8 Amp A
|
||||
BRK ; Reg 9 Amp B
|
||||
BRK ; Reg A Amp C
|
||||
BRK ; Reg B Env Low
|
||||
|
||||
BRK ; Reg C Env Hi
|
||||
BRK ; Reg D Env Type
|
||||
|
||||
|
||||
|
||||
; ____________________ Mockingboard 2 ____________________
|
||||
|
||||
; ====================
|
||||
; Initialize Mockingboard
|
||||
; ====================
|
||||
MOCK2_Init:
|
||||
lda #_6522_PORT_B_OUT
|
||||
sta MOCK2_DIR_B
|
||||
; lda #_6522_PORT_A_OUT
|
||||
sta MOCK2_DIR_A
|
||||
; NOTE: Intentional fall-into reset!
|
||||
MOCK2_Reset:
|
||||
lda #_6522_RESET ; -->+
|
||||
.byte $2C ; |
|
||||
MOCK2_SetReg: ; |
|
||||
lda #_6522_LATCH ;-->+ |
|
||||
.byte $2C ; | |
|
||||
MOCK2_SetData: ; | |
|
||||
lda #_6522_WRITE ; | |
|
||||
sta MOCK2_OR_B ;<--+ <--+
|
||||
lda #_6522_PORT_B
|
||||
sta MOCK2_OR_B
|
||||
rts
|
||||
|
||||
; ====================
|
||||
; Plays one note
|
||||
; IN:
|
||||
; X = Register: $0 .. $D
|
||||
; A = Value
|
||||
; OUT:
|
||||
; A = trash
|
||||
; X = unchanged
|
||||
; Y = trash
|
||||
; ====================
|
||||
MOCK2_PokeXA:
|
||||
TAY
|
||||
; NOTE: Intentional fall-into!
|
||||
|
||||
; ====================
|
||||
; Poke (set) byte to Mockingboard
|
||||
; IN:
|
||||
; X = Register: $0 .. $D
|
||||
; Y = Value
|
||||
; OUT:
|
||||
; A = trash
|
||||
; X = unchanged
|
||||
; Y = unchanged
|
||||
; ====================
|
||||
MOCK2_PokeXY:
|
||||
stx MOCK2_OR_A
|
||||
jsr MOCK2_SetReg
|
||||
sty MOCK2_OR_A
|
||||
jmp MOCK2_SetData
|
||||
|
||||
; ====================
|
||||
; Stop all sounds by setting all regs to zero
|
||||
; ====================
|
||||
MOCK2_Stop:
|
||||
LDX #<mockN_off_data ; *** SELF-MODIFIES!
|
||||
LDY #>mockN_off_data
|
||||
; NOTE: Intentional fall-into!
|
||||
|
||||
; ====================
|
||||
; Plays one note by setting all Mockingboard registers
|
||||
; IN:
|
||||
; X = Low Address of registers
|
||||
; Y = High Address of
|
||||
; ====================
|
||||
MOCK2_Play:
|
||||
STX _mock2_load_reg+1 ; *** SELF-MODIFIES!
|
||||
STY _mock2_load_reg+2
|
||||
_mock2_all_regs:
|
||||
ldy #0
|
||||
ldx #MOCK_REG_FIRST
|
||||
_mock2_load_reg:
|
||||
lda mockN_off_data,X ; *** SELF-MODIFIED!
|
||||
jsr MOCK2_PokeXA
|
||||
inx
|
||||
cpx #MOCK_REG_NUM ; BUG: $B !
|
||||
bcc _mock2_load_reg
|
||||
rts
|
||||
|
||||
__END:
|
||||
|
Loading…
Reference in New Issue
Block a user