https://atariage.com/forums/topic/320982-sfx-engine/
LEVEL1: wersja minimum, jedna komenda plus pętle
LEVEL2: brak sampli, brak funkcji, brak pluginów, brak syntezy mowy
LEVEL3: pełna wersja
opt l+
SFXZP equ $80 ; ZPAGE
VPOKEY equ $D200
org $2000
runme
LDA #$00
STA $D208
LDA #$03
STA $D20F
loop lda $D40B
cmp #4
bcs loop
@ lda $D40B
cmp #$10
bcc @-
lda #$0f
sta $D01A
jsr xSFX_ENGINE
lda #$00
sta $D01A
lda $2FC
cmp #$1f ; klawisz "1" play 1e=2 1a=3 18=4 1d=5 1b=6 33=7 35=8 30=9 32=0
beq insert
cmp #$1e ; klawisz "2" stop
bne loop
ldx #0
jsr xSFX_ENGINE+6
ldx #1
jsr xSFX_ENGINE+6
ldx #2
jsr xSFX_ENGINE+6
ldx #3
jsr xSFX_ENGINE+6
@ lda #255
sta $2FC
jmp loop
insert lda #5 ; sfx5
ldx #0 ; ch1
sec ; force
jsr xSFX_ENGINE+3
jmp @-
; ================================================ LEVEL 2
; === SFX ENGINE ====
;xSFX_ENGINE - jump here 1 per frame at least
;
;xSFX_ENGINE+3 in: A=sfx, X=channel, C=1 (force)
; A=sfx, C=0 (find free channel)
; out: C=1 no free channel
; C=0 ok
;
;xSFX_ENGINE+6 in: X=channel - will immediately terminate SFX on the specified channel
; ===
;
; Command:
;
;1. TIME,AUDF,AUDC ; graj TIME ilość ramek, zapisz rejestry AUDF, AUDC
;2. REPF,TIME,COUNT,AUDC ; powtórz COUNT razy: graj TIME ilosc ramek, zainicjuj AUDC, wpisuj AUDF COUNT razy
;3. REPC,TIME,COUNT,AUDF ; powtórz COUNT razy: graj TIME ilosc ramek, zainicjuj AUDF, wpisuj AUDC COUNT razy
;4. LOOP ; powtórz ten sam dźwięk od komendy na pozycji loop
;5. RTS ; koniec opisu dźwięku
;6. JSR nnnnn ; wywołaj SFX nr. nn i po jego zakończeniu wróć kontynuuj odtwarzanie obecnego
;7. JMP nnnnn ; skocz do SFX nr.
xSFX_ENGINE jmp xSFX_PROCEED ; xSFX_ENGINE
xSFX_START jmp SFX_INSERT ; xSFX_ENGINE+3
xSFX_STOP jmp SFX_CHANNEL_OFF ; xSFX_ENGINE+6
SFX_ENDRTS iny
lda (SFXZP),Y
tay
dey
cmp #$ff
beq SFX_RTSEND
jmp SFX_RELOAD
SFX_RTSEND lda SFX_RTS,x
bne SFX_DORTS
jsr SFX_CHANNEL_OFF
jmp SFX_NXTCH
SFX_DORTS pha
lda #$00
sta SFX_RTS,x
lda SFX_RCNT,x
sta SFX_CNT,x
jmp SFX_DORTSF
SFX_REP dec SFX_REPEAT,x
lda SFX_RTIME,x
sta SFX_TIME,x
lda #$00
lda SFX_FLAG,x
asl @
bcs SFX_DF
bcc SFX_DC
xSFX_PROCEED ldx #3
SFX_CONTCH lda SFX_NO,x
bne SFX_PROCED
SFX_NXTCH dex
bpl SFX_CONTCH
rts
SFX_PROCED ldy SFX_TIME,x
bne SFX_CONTTONE
SFX_CONTCHJ tay
lda SFX_ADR_TAB-2,y
sta SFXZP
lda SFX_ADR_TAB-1,y
sta SFXZP+1
ldy SFX_CNT,x
lda SFX_REPEAT,x
bne SFX_REP
SFX_RELOAD iny
lda (SFXZP),Y
beq SFX_ENDRTS
SFX_TOKEN asl @
bcc SFX_TIM
asl @
ror SFX_FLAG,x
asl @
bcs SFX_JUMP
iny
lda (SFXZP),Y
sta SFX_RTIME,x
iny
lda (SFXZP),Y
sta SFX_REPEAT,x
lda SFX_FLAG,x
asl @
iny
lda (SFXZP),Y
bcs SFX_C0C
sta SFX_AUDF,x
bcc SFX_REP
SFX_C0C sta SFX_AUDC,x
bcs SFX_REP
SFX_TIM lsr @
sta SFX_TIME,x
SFX_DF iny
lda (SFXZP),Y
sta SFX_AUDF,x
bcs SFX_N3
SFX_DC iny
lda (SFXZP),Y
sta SFX_AUDC,x
SFX_N3 tya
sta SFX_CNT,x
SFX_CONTTONE txa
asl @
tay
lda SFX_AUDF,x
sta VPOKEY,y
lda SFX_AUDC,x
sta VPOKEY+1,y
dec SFX_TIME,x
jmp SFX_NXTCH
SFX_JUMP lsr @
lsr @
pha
lda SFX_FLAG,x
bmi SFX_JMP
lda SFX_NO,x
sta SFX_RTS,x
tya
sta SFX_RCNT,x
SFX_JMP lda #$ff
sta SFX_CNT,x
SFX_DORTSF pla
sta SFX_NO,x
jmp SFX_CONTCHJ
SFX_CHANNEL_OFF
txa
asl @
tay
lda #$ff
sta SFX_CNT,x
lda #$00
sta SFX_NO,x
sta SFX_TIME,x
sta SFX_REPEAT,x
sta SFX_RTS,x
sta VPOKEY,y
sta VPOKEY+1,y
rts
SFX_INSERT bcs SFX_FORCE
ldx #$03
SFX_FIND ldy SFX_NO,x
beq SFX_SETNO
dex
bpl SFX_FIND
sec
rts
SFX_FORCE pha
jsr SFX_CHANNEL_OFF
pla
SFX_SETNO asl @
sta SFX_NO,x
clc
rts
SFX_NO .HE 00 00 00 00
SFX_CNT .HE FF,FF,FF,FF
SFX_TIME .HE 00 00 00 00
SFX_AUDC .HE 00 00 00 00
SFX_AUDF .HE 00 00 00 00
SFX_FLAG .HE 00 00 00 00
SFX_REPEAT .HE 00 00 00 00
SFX_RTIME .HE 00 00 00 00
SFX_RTS .HE 00 00 00 00
SFX_RCNT .HE 00 00 00 00
SFX_ADR_TAB .word sfx1,sfx2,sfx3,sfx4,sfx5
; =====================
sfx1 ; upadek Preliminary Monte
.HE C0 01 06 8A ; C0 = REPF
; 01 = zapisuj rejestr AUDF co 1 ramke
; 06 = mamy 6 wartosci do pobrania
; 8A = wartosc inicjujaca zapisywana do AUDC
.HE C0 C0 01 C0 C0 01 ; 6 wartosci po kolei beda zapisywane co jedna ramke do AUDF
.HE 00 FF ; 00 FF = RTS w tym przypadku koniec odtwarzania
; =====================
sfx2 ; local perfect w Gyruss
.HE 80 01 03 00 ; 80 = REPC
.HE 07 27 47
.HE 80 01 03 00
.HE 06 26 46
.HE 80 01 03 00
.HE 05 27 45
.HE 80 01 03 00
.HE 04 24 44
.HE 80 01 03 00
.HE 03 23 43
.HE 80 01 03 00
.HE 02 22 42
.HE 80 01 03 00
.HE 01 21 41
.HE 00 FF
; =====================
sfx3 ; Donkey Kong
.HE 02 44 A7 ; zagraj 2 ramki wartosci AUDF i AUDC
.HE 01 43 A7
.HE 01 44 A7
.HE 01 3C A7
.HE 01 3D A7
.HE 01 3C A7
.HE 01 35 A7
.HE 02 34 A7
.HE 01 35 A7
.HE 01 34 A7
.HE 01 28 A7
.HE 01 27 A7
.HE 01 29 A7
.HE 01 28 A6
.HE 01 27 A6
.HE 02 28 A5
.HE 01 27 A5
.HE 01 28 A5
.HE 01 29 A4
.HE 01 28 A3
.HE 04 28 A0
.HE 04 32 A7
.HE 01 33 A7
.HE 03 32 A7
.HE 01 33 A7
.HE 03 32 A7
.HE 01 33 A7
.HE 04 32 A7
.HE 01 32 A7
.HE 01 32 00
.HE 00 FF
; =====================
sfx4
.HE C0 01 03 84 ; chodzenie Preliminary Monty
.HE C0 FE 01
.HE 05 00 00 ; 05 = piec ramek
; 00 do AUDF
; 00 do AUDC = 5 ramek ciszy
.HE 00 00 ; 00 00 = LOOP zagraj tego SFX jeszcze raz od pozycji 00
; =====================
sfx5 ; Pacman BG2
.HE A3 ; A0 = JSR; E0 = JMP starsze 3 bity %1110 0000
; 03 = SFX nr. 03 mlodszy 5 bitow %0001 1111
.HE C0 01 0A A5
.HE 80 70 60 50 40 50 60 70 80 90
.HE C0 01 0A A4 ; loop
.HE 80 70 60 50 40 50 60 70 80 90
.HE C0 01 0A A3
.HE 80 70 60 50 40 50 60 70 80 90
.HE 00 0F ; 00 0F = LOOP do pozycji 0F
; =====================
run runme
end
Wersja minimum LEVEL 1:
; ================================================ LEVEL 1
; === SFX ENGINE ====
;xSFX_PROCEED - jump here 1 per frame at least
;
;xSFX_START in: A=sfx, X=channel, C=1 (force)
; A=sfx, C=0 (find free channel)
; out: C=1 no free channel
; C=0 ok
;
;xSFX_STOP in: X=channel - will immediately terminate SFX on the specified channel
; ===
;
; Command:
;
;1. TIME,AUDF,AUDC ; graj TIME ilość ramek, zapisz rejestry AUDF, AUDC
;4. LOOP ; powtórz ten sam dźwięk od komendy na pozycji loop
;5. RTS ; koniec opisu dźwięku
xSFX_ENGINE jmp xSFX_PROCEED ; xSFX_ENGINE
xSFX_START jmp SFX_INSERT ; xSFX_ENGINE+3
xSFX_STOP jmp SFX_CHANNEL_OFF ; xSFX_ENGINE+6
SFX_ENDRTS iny
lda (SFXZP),Y
tay
dey
cmp #$ff
bne SFX_RELOAD
jsr SFX_CHANNEL_OFF
jmp SFX_NXTCH
xSFX_PROCEED ldx #3
SFX_CONTCH lda SFX_NO,x
bne SFX_PROCED
SFX_NXTCH dex
bpl SFX_CONTCH
rts
SFX_PROCED ldy SFX_TIME,x
bne SFX_CONTTONE
tay
lda SFX_ADR_TAB-2,y
sta SFXZP
lda SFX_ADR_TAB-1,y
sta SFXZP+1
ldy SFX_CNT,x
SFX_RELOAD iny
lda (SFXZP),Y
beq SFX_ENDRTS
sta SFX_TIME,x
iny
lda (SFXZP),Y
sta SFX_AUDF,x
iny
lda (SFXZP),Y
sta SFX_AUDC,x
tya
sta SFX_CNT,x
SFX_CONTTONE txa
asl @
tay
lda SFX_AUDF,x
sta VPOKEY,y
lda SFX_AUDC,x
sta VPOKEY+1,y
dec SFX_TIME,x
jmp SFX_NXTCH
SFX_CHANNEL_OFF
txa
asl @
tay
lda #$ff
sta SFX_CNT,x
lda #$00
sta SFX_NO,x
sta SFX_TIME,x
sta VPOKEY,y
sta VPOKEY+1,y
rts
SFX_INSERT bcs SFX_FORCE
ldx #$03
SFX_FIND ldy SFX_NO,x
beq SFX_SETNO
dex
bpl SFX_FIND
sec
rts
SFX_FORCE pha
jsr SFX_CHANNEL_OFF
pla
SFX_SETNO asl @
sta SFX_NO,x
clc
rts
SFX_NO .HE 00 00 00 00
SFX_CNT .HE FF,FF,FF,FF
SFX_TIME .HE 00 00 00 00
SFX_AUDC .HE 00 00 00 00
SFX_AUDF .HE 00 00 00 00
SFX_ADR_TAB .word sfx1,sfx2,sfx3
; =====================
sfx1 ; Bruce Lee death
.HE 01 54 A2
.HE 01 54 44
.HE 01 54 A6
.HE 01 54 48
.HE 01 54 A8
.HE 01 54 4A
.HE 01 54 AA
.HE 01 00 4A
.HE 01 00 AA
.HE 01 00 4A
.HE 01 00 AA
.HE 01 00 48
.HE 01 00 A8
.HE 01 00 46
.HE 01 00 A4
.HE 01 00 42
.HE 01 00 A2
.HE 01 00 42
.HE 00 FF
; =====================
sfx2 ; Bruce Lee collecting
.HE 01 24 C2
.HE 01 20 C6
.HE 01 2C C8
.HE 01 38 CC
.HE 01 20 C8
.HE 01 44 C4
.HE 01 58 C2
.HE 01 00 00
.HE 01 00 00
.HE 01 00 00
.HE 01 58 C2
.HE 01 18 C4
.HE 01 78 C6
.HE 01 08 C8
.HE 01 08 E2
.HE 00 FF
; =====================
sfx3 ; syrena loop
.HE 01 50 A5
.HE 01 48 A5
.HE 01 40 A5
.HE 01 38 A5
.HE 01 30 A5
.HE 01 28 A5
.HE 01 20 A3
.HE 01 18 A2
.HE 00 00
