mirror of
https://github.com/cc65/cc65.git
synced 2024-08-17 19:29:12 +00:00
1271 lines
32 KiB
ArmAsm
1271 lines
32 KiB
ArmAsm
;
|
|
; Sound driver for the Atari Lynx.
|
|
;
|
|
; Karri Kaksonen and Bjoern Spruck, 11.12.2012
|
|
;
|
|
|
|
.include "lynx.inc"
|
|
.include "zeropage.inc"
|
|
|
|
.export _lynx_snd_init
|
|
.export _lynx_snd_active
|
|
.export _lynx_snd_play
|
|
.export _lynx_snd_stop
|
|
.export _lynx_snd_stop_channel
|
|
.export _lynx_snd_pause
|
|
.export _lynx_snd_continue
|
|
.interruptor lynx_snd_handler
|
|
.import popa
|
|
.importzp ptr1
|
|
|
|
;----------------------------------------------------------------------------
|
|
; ZP variables that go into APPZP
|
|
;
|
|
|
|
.segment "APPZP" : zeropage
|
|
|
|
SndSema: .res 1
|
|
SndPtrTmp: .res 2
|
|
SndTmp: .res 2
|
|
SndEnvPtr: .res 2
|
|
|
|
;----------------------------------------------------------------------------
|
|
; Global variables
|
|
;
|
|
|
|
.bss
|
|
|
|
SndRetAFlag2: .res 1
|
|
SndRetAFlag: .res 1
|
|
SndPtrLo: .res 4
|
|
SndPtrHi: .res 4
|
|
SndDelay: .res 4
|
|
SndLoopCnt: .res 4
|
|
SndLoopPtrLo: .res 4
|
|
SndLoopPtrHi: .res 4
|
|
SndVolume: .res 4
|
|
SndMaxVolume: .res 4
|
|
SndNotePlaying: .res 4
|
|
SndRetAddr: .res 8
|
|
SndActive: .res 4
|
|
SndReqStop: .res 4
|
|
SndEnvVol: .res 4
|
|
SndEnvFrq: .res 4
|
|
SndEnvWave: .res 4
|
|
SndChannel: .res 32
|
|
SndEnvVolCnt: .res 4
|
|
SndEnvVolInc: .res 4
|
|
SndEnvVolOff: .res 4
|
|
SndEnvVolLoop: .res 4
|
|
SndEnvVolParts: .res 4
|
|
SndEnvVolParts2: .res 4
|
|
SndEnvFrqCnt: .res 4
|
|
SndEnvFrqInc: .res 4
|
|
SndEnvFrqOff: .res 4
|
|
SndEnvFrqLoop: .res 4
|
|
SndEnvFrqParts: .res 4
|
|
SndEnvFrqParts2: .res 4
|
|
SndEnvWaveCnt: .res 4
|
|
SndEnvWaveOff: .res 4
|
|
SndEnvWaveLoop: .res 4
|
|
SndEnvWaveParts: .res 4
|
|
SndEnvWaveParts2: .res 4
|
|
|
|
MAX_INSTRUMENTS .set 64
|
|
SndEnvVolPtrLo: .res MAX_INSTRUMENTS
|
|
SndEnvVolPtrHi: .res MAX_INSTRUMENTS
|
|
SndEnvFrqPtrLo: .res MAX_INSTRUMENTS
|
|
SndEnvFrqPtrHi: .res MAX_INSTRUMENTS
|
|
SndEnvWavePtrLo: .res MAX_INSTRUMENTS
|
|
SndEnvWavePtrHi: .res MAX_INSTRUMENTS
|
|
|
|
.rodata
|
|
|
|
SndOffsets: .byte $00,$08,$10,$18
|
|
|
|
;----------------------------------------------------------------------------
|
|
; Macros
|
|
;
|
|
|
|
if_count .set 0
|
|
nest_count .set 0
|
|
|
|
.macro _IFNE
|
|
if_count .set if_count +1
|
|
nest_count .set nest_count +1
|
|
beq .ident (.sprintf ("else%04d", if_count))
|
|
.ident (.sprintf ("push%04d", nest_count)) .set if_count
|
|
.endmacro
|
|
|
|
.macro _IFEQ
|
|
if_count .set if_count +1
|
|
nest_count .set nest_count +1
|
|
bne .ident (.sprintf ("else%04d", if_count))
|
|
.ident (.sprintf ("push%04d", nest_count)) .set if_count
|
|
.endmacro
|
|
|
|
.macro _IFMI
|
|
if_count .set if_count +1
|
|
nest_count .set nest_count +1
|
|
bpl .ident (.sprintf ("else%04d", if_count))
|
|
.ident (.sprintf ("push%04d", nest_count)) .set if_count
|
|
.endmacro
|
|
|
|
.macro _IFPL
|
|
if_count .set if_count +1
|
|
nest_count .set nest_count +1
|
|
bmi .ident (.sprintf ("else%04d", if_count))
|
|
.ident (.sprintf ("push%04d", nest_count)) .set if_count
|
|
.endmacro
|
|
|
|
.macro _IFGE
|
|
if_count .set if_count +1
|
|
nest_count .set nest_count +1
|
|
bcc .ident (.sprintf ("else%04d", if_count))
|
|
.ident (.sprintf ("push%04d", nest_count)) .set if_count
|
|
.endmacro
|
|
|
|
.macro _IFCS
|
|
if_count .set if_count +1
|
|
nest_count .set nest_count +1
|
|
bcc .ident (.sprintf ("else%04d", if_count))
|
|
.ident (.sprintf ("push%04d", nest_count)) .set if_count
|
|
.endmacro
|
|
|
|
.macro _IFCC
|
|
if_count .set if_count +1
|
|
nest_count .set nest_count +1
|
|
bcs .ident (.sprintf ("else%04d", if_count))
|
|
.ident (.sprintf ("push%04d", nest_count)) .set if_count
|
|
.endmacro
|
|
|
|
.macro _ELSE
|
|
bra .ident (.sprintf ("endif%04d", .ident (.sprintf ("push%04d", nest_count))))
|
|
.ident (.sprintf ("else%04d", .ident (.sprintf ("push%04d", nest_count)))) := *
|
|
.endmacro
|
|
|
|
.macro _ENDIF
|
|
.if .not .defined( .ident (.sprintf ("else%04d", .ident (.sprintf ("push%04d", nest_count)))))
|
|
.ident (.sprintf ("else%04d", .ident (.sprintf ("push%04d", nest_count)))) := *
|
|
.endif
|
|
.ident (.sprintf ("endif%04d", .ident (.sprintf ("push%04d", nest_count)))) := *
|
|
nest_count .set nest_count -1
|
|
.endmacro
|
|
|
|
.code
|
|
|
|
;----------------------------------------------------------------------------
|
|
; void lynx_snd_init() will initialize the sound engine.
|
|
;
|
|
|
|
_31250Hz .set %101
|
|
|
|
_lynx_snd_init:
|
|
php
|
|
sei
|
|
lda #%10011000|_31250Hz
|
|
sta STIMCTLA
|
|
lda #129
|
|
sta STIMBKUP ; set up a 240Hz IRQ
|
|
|
|
stz AUD0VOL
|
|
stz AUD1VOL
|
|
stz AUD2VOL
|
|
stz AUD3VOL
|
|
|
|
stz $fd44 ; all channels full volume / no attenuation
|
|
lda #$ff
|
|
stz MSTEREO
|
|
|
|
lda #0
|
|
sta AUD0CTLA
|
|
sta AUD1CTLA
|
|
sta AUD2CTLA
|
|
sta AUD3CTLA
|
|
|
|
ldx #3
|
|
lda #0
|
|
init0: stz SndActive,x
|
|
stz SndReqStop,x
|
|
stz SndEnvVol,x
|
|
stz SndEnvFrq,x
|
|
stz SndEnvWave,x
|
|
ldy SndOffsets,x
|
|
sta SndChannel+2,y
|
|
dex
|
|
bpl init0
|
|
stz SndRetAFlag
|
|
stz SndRetAFlag2
|
|
stz SndSema
|
|
plp
|
|
rts
|
|
|
|
;----------------------------------------------------------------------------
|
|
; lynx_snd_handler is run at every sound interrupt
|
|
;
|
|
|
|
lynx_snd_handler:
|
|
lda INTSET
|
|
and #SND_INTERRUPT
|
|
bne @L0
|
|
clc
|
|
rts
|
|
@L0:
|
|
lda #$ff
|
|
tsb SndSema
|
|
bne endirq
|
|
phy
|
|
; *NOW* set all values which were "pre-set" in last interrupt
|
|
jsr SndSetValues
|
|
cli
|
|
|
|
lda SndRetAFlag ; reset the return flag, but save it first
|
|
_IFNE
|
|
lda #$0F ; MASK
|
|
sta SndRetAFlag2
|
|
stz SndRetAFlag
|
|
_ENDIF
|
|
|
|
ldx #3
|
|
irq0: phx
|
|
lda SndActive,x
|
|
_IFNE
|
|
lda SndEnvVol,x
|
|
_IFNE
|
|
phx
|
|
jsr SndChangeVol
|
|
plx
|
|
_ENDIF
|
|
lda SndEnvFrq,x
|
|
_IFNE
|
|
phx
|
|
jsr SndChangeFrq
|
|
plx
|
|
_ENDIF
|
|
lda SndEnvWave,x
|
|
_IFNE
|
|
phx
|
|
jsr SndChangeWave
|
|
plx
|
|
_ENDIF
|
|
jsr SndGetCmd
|
|
_ENDIF
|
|
plx
|
|
dex
|
|
bpl irq0
|
|
sei
|
|
ply
|
|
stz SndSema
|
|
endirq:
|
|
clc
|
|
rts
|
|
|
|
;----------------------------------------------------------------------------
|
|
; A process table with addresses to sound functions
|
|
;
|
|
|
|
SndCmdsLo:
|
|
.byte <((SndLoop)-1)
|
|
.byte <((SndDo)-1)
|
|
.byte <((SndPause)-1)
|
|
.byte <((SndNoteOff)-1)
|
|
.byte <((SndSetInstr)-1)
|
|
.byte <((SndNewNote2)-1)
|
|
.byte <((SndCallPattern)-1)
|
|
.byte <((SndRetToSong)-1)
|
|
.byte <((SndDefEnvVol)-1)
|
|
.byte <((SndSetEnvVol)-1)
|
|
.byte <((SndDefEnvFrq)-1)
|
|
.byte <((SndSetEnvFrq)-1)
|
|
.byte <((SndDefEnvWave)-1)
|
|
.byte <((SndSetEnvWave)-1)
|
|
.byte <((SndSetStereo)-1)
|
|
.byte <((SndSetAttenuationOn)-1)
|
|
.byte <((SndSetChnAttenution)-1)
|
|
.byte <((SndPlayerFreq)-1)
|
|
.byte <((SndReturnAll)-1)
|
|
|
|
SndCmdsHi:
|
|
.byte >((SndLoop)-1)
|
|
.byte >((SndDo)-1)
|
|
.byte >((SndPause)-1)
|
|
.byte >((SndNoteOff)-1)
|
|
.byte >((SndSetInstr)-1)
|
|
.byte >((SndNewNote2)-1)
|
|
.byte >((SndCallPattern)-1)
|
|
.byte >((SndRetToSong)-1)
|
|
.byte >((SndDefEnvVol)-1)
|
|
.byte >((SndSetEnvVol)-1)
|
|
.byte >((SndDefEnvFrq)-1)
|
|
.byte >((SndSetEnvFrq)-1)
|
|
.byte >((SndDefEnvWave)-1)
|
|
.byte >((SndSetEnvWave)-1)
|
|
.byte >((SndSetStereo)-1)
|
|
.byte >((SndSetAttenuationOn)-1)
|
|
.byte >((SndSetChnAttenution)-1)
|
|
.byte >((SndPlayerFreq)-1)
|
|
.byte >((SndReturnAll)-1)
|
|
|
|
;----------------------------------------------------------------------------
|
|
; Get next sound command from stream
|
|
;
|
|
|
|
SndGetCmd:
|
|
lda SndReqStop,x
|
|
bne SndStop
|
|
|
|
lda SndRetAFlag2
|
|
and SndMask,x
|
|
_IFNE
|
|
eor SndRetAFlag2
|
|
sta SndRetAFlag2
|
|
lda SndRetAddr,x
|
|
sta SndPtrLo,x
|
|
lda SndRetAddr+4,x
|
|
sta SndPtrHi,x
|
|
;;; force the direct continue return
|
|
_ELSE
|
|
dec SndDelay,x
|
|
bne cmd991 ;; check special case
|
|
_ENDIF
|
|
|
|
lda SndPtrLo,x
|
|
sta SndPtrTmp
|
|
lda SndPtrHi,x
|
|
sta SndPtrTmp+1
|
|
cmd0: lda (SndPtrTmp)
|
|
beq SndStop
|
|
_IFMI
|
|
and #$7f
|
|
tay
|
|
jsr SndCallCmd
|
|
_ELSE
|
|
jsr SndNewNote
|
|
_ENDIF
|
|
clc
|
|
tya
|
|
and #$7f
|
|
adc SndPtrTmp
|
|
sta SndPtrLo,x
|
|
sta SndPtrTmp
|
|
lda #0
|
|
adc SndPtrTmp+1
|
|
sta SndPtrHi,x
|
|
sta SndPtrTmp+1
|
|
|
|
tya
|
|
bmi cmd0
|
|
cmd991:
|
|
;; now check if delay is only 1 AND next one is return all.
|
|
lda #1
|
|
cmp SndDelay,x
|
|
bne cmd99
|
|
|
|
;; NOW read ahead ONE
|
|
lda SndPtrLo,x
|
|
sta SndPtrTmp
|
|
lda SndPtrHi,x
|
|
sta SndPtrTmp+1
|
|
|
|
lda (SndPtrTmp)
|
|
cmp #$92 ;; Return all
|
|
_IFEQ
|
|
sta SndRetAFlag ; just set !=0
|
|
_ENDIF
|
|
cmd99: rts
|
|
|
|
;----------------------------------------------------------------------------
|
|
; Call function pointed to by y
|
|
;
|
|
|
|
SndCallCmd:
|
|
lda SndCmdsHi,y
|
|
pha
|
|
lda SndCmdsLo,y
|
|
pha
|
|
ldy #1
|
|
rts
|
|
|
|
;----------------------------------------------------------------------------
|
|
; Stop sound on one channel
|
|
;
|
|
|
|
SndStop:
|
|
stz SndReqStop,x
|
|
stz SndActive,x
|
|
ldy SndOffsets,x
|
|
lda #0
|
|
sta SndChannel,y
|
|
ina ;lda #1
|
|
sta SndChannel+2,y
|
|
tay ;ldy #1
|
|
rts
|
|
|
|
|
|
;----------------------------------------------------------------------------
|
|
; Send a new note, length, volume triplet
|
|
;
|
|
|
|
SndNewNote:
|
|
phx
|
|
sta SndNotePlaying,x
|
|
pha
|
|
ldy #1
|
|
lda (SndPtrTmp),y
|
|
sta SndDelay,x
|
|
ldy SndOffsets,x
|
|
lda SndVolume,x
|
|
sta SndChannel,y
|
|
plx
|
|
lda SndPrescaler,x
|
|
sta SndChannel+5,y
|
|
lda SndReload,x
|
|
sta SndChannel+4,y
|
|
lda #$FF ; = -1
|
|
sta SndChannel+2,y
|
|
plx
|
|
lda SndEnvVol,x
|
|
_IFNE
|
|
jsr SndSetEnvVol1
|
|
_ENDIF
|
|
lda SndEnvFrq,x
|
|
_IFNE
|
|
jsr SndSetEnvFrq1
|
|
_ENDIF
|
|
lda SndEnvWave,x
|
|
_IFNE
|
|
jsr SndSetEnvWave1
|
|
_ENDIF
|
|
lda #$2
|
|
ldy SndDelay,x
|
|
_IFNE
|
|
ora #$80
|
|
_ENDIF
|
|
tay
|
|
rts
|
|
|
|
;----------------------------------------------------------------------------
|
|
; Start a loop with count
|
|
;
|
|
|
|
SndLoop:
|
|
lda (SndPtrTmp),y
|
|
sta SndLoopCnt,x
|
|
lda SndPtrTmp
|
|
sta SndLoopPtrLo,x
|
|
lda SndPtrTmp+1
|
|
sta SndLoopPtrHi,x
|
|
ldy #$82
|
|
rts
|
|
|
|
SndDo:
|
|
dec SndLoopCnt,x
|
|
_IFNE
|
|
lda SndLoopPtrLo,x
|
|
sta SndPtrTmp
|
|
lda SndLoopPtrHi,x
|
|
sta SndPtrTmp+1
|
|
ldy #$82
|
|
_ELSE
|
|
ldy #$81
|
|
_ENDIF
|
|
rts
|
|
|
|
;----------------------------------------------------------------------------
|
|
; Sound volume envelope
|
|
;
|
|
|
|
SndDefEnvVol:
|
|
phx
|
|
lda (SndPtrTmp),y ; env #
|
|
tax
|
|
|
|
iny
|
|
lda (SndPtrTmp),y
|
|
sta SndEnvVolPtrLo,x
|
|
iny
|
|
lda (SndPtrTmp),y
|
|
sta SndEnvVolPtrHi,x ; Ptr to [cnt,inc]
|
|
|
|
ldy #$84
|
|
plx
|
|
rts
|
|
|
|
SndSetEnvVol:
|
|
lda (SndPtrTmp),y ; # env
|
|
|
|
SndSetEnvVol1:
|
|
and #$7f
|
|
sta SndEnvVol,x ; save
|
|
_IFEQ
|
|
ldy #$82
|
|
rts
|
|
_ENDIF
|
|
|
|
tay
|
|
|
|
lda SndEnvVolPtrLo,y
|
|
sta SndEnvPtr
|
|
lda SndEnvVolPtrHi,y
|
|
sta SndEnvPtr+1
|
|
|
|
lda (SndEnvPtr)
|
|
sta SndTmp
|
|
asl
|
|
sta SndEnvVolLoop,x ; here is the loop-start
|
|
|
|
ldy #1
|
|
lda (SndEnvPtr),y
|
|
sta SndEnvVolParts,x
|
|
sec
|
|
sbc SndTmp
|
|
sta SndEnvVolParts2,x
|
|
|
|
stz SndEnvVolCnt,x
|
|
lda #2
|
|
sta SndEnvVolOff,x
|
|
|
|
ldy #$82
|
|
rts
|
|
|
|
;----------------------------------------------------------------------------
|
|
; Sound frequency envelope
|
|
;
|
|
|
|
SndDefEnvFrq:
|
|
phx
|
|
lda (SndPtrTmp),y ; env #
|
|
tax
|
|
|
|
iny
|
|
lda (SndPtrTmp),y
|
|
sta SndEnvFrqPtrLo,x
|
|
iny
|
|
lda (SndPtrTmp),y
|
|
sta SndEnvFrqPtrHi,x ; Ptr to [inc,cnt]
|
|
plx
|
|
ldy #$84
|
|
rts
|
|
|
|
SndSetEnvFrq:
|
|
lda (SndPtrTmp),y ; # env
|
|
|
|
SndSetEnvFrq1:
|
|
and #$7f
|
|
sta SndEnvFrq,x ; save
|
|
_IFEQ
|
|
ldy #$82
|
|
rts
|
|
_ENDIF
|
|
|
|
tay
|
|
|
|
lda SndEnvFrqPtrLo,y
|
|
sta SndEnvPtr
|
|
lda SndEnvFrqPtrHi,y
|
|
sta SndEnvPtr+1
|
|
|
|
lda (SndEnvPtr)
|
|
sta SndTmp
|
|
asl
|
|
sta SndEnvFrqLoop,x
|
|
|
|
ldy #1
|
|
lda (SndEnvPtr),y
|
|
sta SndEnvFrqParts,x
|
|
sec
|
|
sbc SndTmp
|
|
sta SndEnvFrqParts2,x
|
|
|
|
stz SndEnvFrqCnt,x
|
|
lda #2
|
|
sta SndEnvFrqOff,x
|
|
|
|
ldy #$82
|
|
rts
|
|
|
|
;----------------------------------------------------------------------------
|
|
; Sound frequency envelope
|
|
;
|
|
|
|
SndDefEnvWave:
|
|
|
|
phx
|
|
lda (SndPtrTmp),y ; env #
|
|
tax
|
|
|
|
iny
|
|
lda (SndPtrTmp),y
|
|
sta SndEnvWavePtrLo,x
|
|
iny
|
|
lda (SndPtrTmp),y
|
|
sta SndEnvWavePtrHi,x ; Ptr to [inc,cnt]
|
|
plx
|
|
ldy #$84
|
|
rts
|
|
|
|
SndSetEnvWave:
|
|
lda (SndPtrTmp),y ; # env
|
|
|
|
SndSetEnvWave1:
|
|
and #$7f
|
|
sta SndEnvWave,x ; save
|
|
_IFEQ
|
|
ldy #$82
|
|
rts
|
|
_ENDIF
|
|
|
|
tay
|
|
|
|
lda SndEnvWavePtrLo,y
|
|
sta SndEnvPtr
|
|
lda SndEnvWavePtrHi,y
|
|
sta SndEnvPtr+1
|
|
|
|
lda (SndEnvPtr)
|
|
sta SndTmp
|
|
asl ; *4 -2
|
|
dea
|
|
asl
|
|
sta SndEnvWaveLoop,x
|
|
|
|
ldy #1
|
|
lda (SndEnvPtr),y
|
|
sta SndEnvWaveParts,x
|
|
sec
|
|
sbc SndTmp
|
|
sta SndEnvWaveParts2,x
|
|
|
|
stz SndEnvWaveCnt,x
|
|
lda #2
|
|
sta SndEnvWaveOff,x
|
|
|
|
ldy #$82
|
|
rts
|
|
|
|
;----------------------------------------------------------------------------
|
|
; Pause sound
|
|
;
|
|
|
|
SndPause:
|
|
lda (SndPtrTmp),y
|
|
sta SndDelay,x
|
|
iny
|
|
SndDummy: rts
|
|
;;;* This set the new Player Freq instantanious!!!
|
|
SndPlayerFreq:
|
|
lda (SndPtrTmp),y
|
|
sta STIMCTLA
|
|
iny
|
|
lda (SndPtrTmp),y
|
|
sta STIMBKUP
|
|
ldy #$83
|
|
rts
|
|
|
|
SndNoteOff:
|
|
ldy SndOffsets,x
|
|
stz SndNotePlaying,x
|
|
lda SndEnvVol,x
|
|
ora #$80
|
|
sta SndEnvVol,x
|
|
lda SndEnvFrq,x
|
|
ora #$80
|
|
sta SndEnvFrq,x
|
|
lda SndEnvWave,x
|
|
ora #$80
|
|
sta SndEnvWave,x
|
|
lda #0
|
|
sta SndChannel,y
|
|
sta SndChannel+4,y
|
|
sta SndChannel+5,y
|
|
dea
|
|
sta SndChannel+2,y
|
|
ldy #$81
|
|
rts
|
|
SndSetInstr:
|
|
phx
|
|
lda SndOffsets,x
|
|
tax
|
|
lda (SndPtrTmp),y
|
|
sta SndChannel+3,x
|
|
iny
|
|
lda (SndPtrTmp),y
|
|
sta SndChannel+7,x
|
|
iny
|
|
lda (SndPtrTmp),y
|
|
sta SndChannel+1,x
|
|
plx
|
|
iny
|
|
lda (SndPtrTmp),y
|
|
sta SndVolume,x
|
|
iny
|
|
lda (SndPtrTmp),y
|
|
sta SndMaxVolume,x
|
|
|
|
ldy #$86
|
|
rts
|
|
SndCallPattern:
|
|
clc
|
|
lda SndPtrTmp
|
|
adc #3
|
|
sta SndRetAddr,x
|
|
lda SndPtrTmp+1
|
|
adc #0
|
|
sta SndRetAddr+4,x
|
|
ldy #1
|
|
lda (SndPtrTmp),y
|
|
pha
|
|
iny
|
|
lda (SndPtrTmp),y
|
|
sta SndPtrTmp+1
|
|
pla
|
|
sta SndPtrTmp
|
|
ldy #$80
|
|
rts
|
|
|
|
SndRetToSong:
|
|
lda SndRetAddr,x
|
|
sta SndPtrTmp
|
|
lda SndRetAddr+4,x
|
|
sta SndPtrTmp+1
|
|
ldy #$80
|
|
rts
|
|
|
|
SndReturnAll:
|
|
lda #1
|
|
sta SndRetAFlag
|
|
sta SndDelay,x
|
|
ldy #$0
|
|
rts
|
|
SndNewNote2:
|
|
;;; Note,length,volume
|
|
|
|
phx
|
|
sta SndNotePlaying,x
|
|
ldy #1
|
|
lda (SndPtrTmp),y ; reload
|
|
pha
|
|
iny
|
|
lda (SndPtrTmp),y ; prescale
|
|
pha
|
|
iny
|
|
lda (SndPtrTmp),y ; laenge
|
|
sta SndDelay,x
|
|
|
|
ldy SndOffsets,x
|
|
lda SndVolume,x
|
|
sta SndChannel,y
|
|
pla
|
|
sta SndChannel+5,y
|
|
pla
|
|
sta SndChannel+4,y
|
|
lda #$FF ; = -1
|
|
sta SndChannel+2,y
|
|
plx
|
|
lda SndEnvVol,x
|
|
_IFNE
|
|
jsr SndSetEnvVol1
|
|
_ENDIF
|
|
lda SndEnvFrq,x
|
|
_IFNE
|
|
jsr SndSetEnvFrq1
|
|
_ENDIF
|
|
lda SndEnvWave,x
|
|
_IFNE
|
|
jsr SndSetEnvWave1
|
|
_ENDIF
|
|
ldy #4
|
|
rts
|
|
|
|
SndSetStereo:
|
|
ldy #1
|
|
lda (SndPtrTmp),y
|
|
sta MSTEREO
|
|
ldy #$82
|
|
rts
|
|
|
|
SndSetAttenuationOn:
|
|
ldy #1
|
|
lda (SndPtrTmp),y
|
|
sta $FD44
|
|
ldy #$82
|
|
rts
|
|
|
|
SndSetChnAttenution:
|
|
ldy #1
|
|
lda (SndPtrTmp),y
|
|
sta $FD40,x
|
|
ldy #$82
|
|
rts
|
|
|
|
SndChangeVol:
|
|
tay
|
|
_IFMI
|
|
vol99: rts
|
|
_ENDIF
|
|
lda SndNotePlaying,x
|
|
beq vol99
|
|
|
|
lda SndEnvVolPtrLo,y
|
|
sta SndEnvPtr
|
|
lda SndEnvVolPtrHi,y
|
|
sta SndEnvPtr+1
|
|
|
|
dec SndEnvVolCnt,x
|
|
_IFMI
|
|
dec SndEnvVolParts,x
|
|
_IFMI
|
|
lda SndEnvVolLoop,x
|
|
_IFNE
|
|
tay
|
|
lda SndEnvVolParts2,x
|
|
sta SndEnvVolParts,x
|
|
bra vol1v
|
|
_ELSE
|
|
tya
|
|
ora #$80
|
|
sta SndEnvVol,x
|
|
_ENDIF
|
|
_ELSE
|
|
ldy SndEnvVolOff,x
|
|
vol1v: lda (SndEnvPtr),y
|
|
sta SndEnvVolCnt,x
|
|
iny
|
|
lda (SndEnvPtr),y
|
|
sta SndEnvVolInc,x
|
|
iny
|
|
tya
|
|
sta SndEnvVolOff,x
|
|
_ENDIF
|
|
rts
|
|
_ENDIF
|
|
|
|
ldy SndOffsets,x
|
|
clc
|
|
lda SndEnvVolInc,x
|
|
_IFEQ
|
|
rts
|
|
_ENDIF
|
|
_IFPL
|
|
adc SndChannel,y
|
|
cmp SndMaxVolume,x
|
|
_IFCS
|
|
lda SndMaxVolume,x
|
|
stz SndEnvVolInc,x
|
|
_ENDIF
|
|
cmp #$80
|
|
_IFGE
|
|
lda #$7f
|
|
stz SndEnvVolInc,x
|
|
_ENDIF
|
|
_ELSE
|
|
adc SndChannel,y
|
|
_IFCC
|
|
lda #0
|
|
sta SndEnvVolInc,x
|
|
;; NEU: switch Tremolo off
|
|
sta SndNotePlaying,x
|
|
_ENDIF
|
|
cmp #$80
|
|
_IFGE
|
|
lda #0
|
|
sta SndEnvVolInc,x
|
|
;; NEU: switch Tremolo off
|
|
sta SndNotePlaying,x
|
|
_ENDIF
|
|
_ENDIF
|
|
sta SndChannel,y
|
|
lda SndChannel+2,y
|
|
ora #1 ;; if already -1 ... no effect
|
|
sta SndChannel+2,y
|
|
rts
|
|
|
|
|
|
SndChangeFrq:
|
|
tay
|
|
_IFMI
|
|
frq99: rts
|
|
_ENDIF
|
|
lda SndNotePlaying,x
|
|
beq frq99
|
|
|
|
lda SndEnvFrqPtrLo,y
|
|
sta SndEnvPtr
|
|
lda SndEnvFrqPtrHi,y
|
|
sta SndEnvPtr+1
|
|
|
|
dec SndEnvFrqCnt,x
|
|
_IFMI
|
|
dec SndEnvFrqParts,x
|
|
_IFMI
|
|
lda SndEnvFrqLoop,x
|
|
_IFNE
|
|
tay
|
|
lda SndEnvFrqParts2,x
|
|
sta SndEnvFrqParts,x
|
|
bra frq1f
|
|
_ELSE
|
|
tya
|
|
ora #$80
|
|
sta SndEnvFrq,x
|
|
_ENDIF
|
|
_ELSE
|
|
ldy SndEnvFrqOff,x
|
|
frq1f: lda (SndEnvPtr),y
|
|
sta SndEnvFrqCnt,x
|
|
iny
|
|
lda (SndEnvPtr),y
|
|
eor #$ff
|
|
ina
|
|
sta SndEnvFrqInc,x
|
|
iny
|
|
tya
|
|
sta SndEnvFrqOff,x
|
|
_ENDIF
|
|
rts
|
|
_ENDIF
|
|
ldy SndOffsets,x
|
|
clc
|
|
lda SndEnvFrqInc,x
|
|
_IFEQ
|
|
rts
|
|
_ENDIF
|
|
|
|
_IFMI
|
|
adc SndChannel+4,y
|
|
_IFPL
|
|
pha
|
|
lda SndChannel+5,y
|
|
_IFNE
|
|
dea
|
|
sta SndChannel+5,y
|
|
pla
|
|
eor #128
|
|
_ELSE
|
|
pla
|
|
pha
|
|
clc
|
|
adc SndEnvFrqInc,x
|
|
pla
|
|
_ENDIF
|
|
_ELSE
|
|
pha
|
|
lda SndChannel+5,y
|
|
_IFEQ
|
|
pla
|
|
sta SndChannel+4,y
|
|
rts
|
|
_ENDIF
|
|
pla
|
|
_ENDIF
|
|
_ELSE
|
|
adc SndChannel+4,y
|
|
_IFPL
|
|
pha
|
|
lda SndChannel+5,y
|
|
cmp #6
|
|
_IFNE
|
|
ina
|
|
sta SndChannel+5,y
|
|
pla
|
|
eor #128
|
|
_ELSE
|
|
lda SndChannel+4,y
|
|
_IFMI
|
|
pla
|
|
rts
|
|
_ENDIF
|
|
pla
|
|
_ENDIF
|
|
_ELSE
|
|
pha
|
|
lda SndChannel+5,y
|
|
cmp #6
|
|
_IFEQ
|
|
lda SndChannel+4,y
|
|
_IFPL
|
|
pla
|
|
rts
|
|
_ENDIF
|
|
_ENDIF
|
|
pla
|
|
_ENDIF
|
|
_ENDIF
|
|
sta SndChannel+4,y
|
|
|
|
ora #1 ;; if already -1 -> no effect
|
|
rts
|
|
|
|
SndChangeWave:
|
|
tay
|
|
;; Ab hier x Kanal 0-3, y Environment
|
|
_IFMI
|
|
wav99: rts
|
|
_ENDIF
|
|
lda SndNotePlaying,x
|
|
beq wav99
|
|
|
|
|
|
lda SndEnvWavePtrLo,y
|
|
sta SndEnvPtr
|
|
lda SndEnvWavePtrHi,y
|
|
sta SndEnvPtr+1
|
|
|
|
dec SndEnvWaveCnt,x
|
|
_IFMI
|
|
dec SndEnvWaveParts,x
|
|
_IFMI
|
|
lda SndEnvWaveLoop,x
|
|
_IFNE
|
|
tay
|
|
;; Ab hier x Kanal 0-3, y Offset im Environment
|
|
lda SndEnvWaveParts2,x
|
|
sta SndEnvWaveParts,x
|
|
bra wav1v
|
|
_ELSE
|
|
tya
|
|
ora #$80 ;; beende Env
|
|
sta SndEnvWave,x
|
|
_ENDIF
|
|
_ELSE
|
|
ldy SndEnvWaveOff,x
|
|
;; Ab hier x Kanal 0-3, y Offset im Environment
|
|
wav1v: lda (SndEnvPtr),y
|
|
sta SndEnvWaveCnt,x
|
|
phx
|
|
lda SndOffsets,x
|
|
tax
|
|
;; Ab hier x Kanal (0-3)*8, y Offset im Environment
|
|
|
|
iny
|
|
lda (SndEnvPtr),y
|
|
sta SndChannel+3,x ; Shift LO
|
|
iny
|
|
lda (SndEnvPtr),y
|
|
sta SndChannel+7,x ; Shift HI
|
|
iny
|
|
lda (SndEnvPtr),y
|
|
sta SndChannel+1,x ; Feedback
|
|
iny
|
|
tya
|
|
ply
|
|
;; Ab hier x Kanal (0-3)*8, y Kanal 0-3
|
|
sta SndEnvWaveOff,y
|
|
lda #$FF ; =-1 ;; stop timer to set new values...
|
|
sta SndChannel+2,x
|
|
_ENDIF
|
|
_ENDIF
|
|
rts
|
|
|
|
|
|
SndSetValues:
|
|
ldx #4-1
|
|
set0: ldy SndOffsets,x
|
|
lda SndChannel+2,y
|
|
_IFNE ; flag == 0 => don`t set
|
|
|
|
bit #$80
|
|
_IFNE ;
|
|
lda #0
|
|
sta $fd25,y ; stop sound timer
|
|
|
|
lda SndChannel+3,y
|
|
sta $fd23,y ; shifter 1
|
|
;;lda $fd27,y
|
|
;;and #$0F
|
|
;;ora SndChannel+7,y ; shifter 2
|
|
lda SndChannel+7,y ; shifter 2
|
|
sta $fd27,y
|
|
lda SndChannel+1,y
|
|
sta $fd21,y ; feedback
|
|
_ENDIF
|
|
|
|
lda SndChannel,y
|
|
sta $fd20,y ; volume
|
|
lda SndChannel+2,y
|
|
bit #$80
|
|
_IFNE ;
|
|
lda SndChannel+4,y
|
|
sta $fd24,y ; reload
|
|
lda SndChannel+5,y
|
|
ora #%00011000 ;;; #%01011000
|
|
;; and #%00111111
|
|
sta $fd25,y ; re-enable timer
|
|
_ENDIF
|
|
|
|
lda #0
|
|
sta SndChannel+2,y ; clear flag
|
|
_ENDIF
|
|
|
|
dex
|
|
_IFPL
|
|
jmp set0
|
|
_ENDIF
|
|
rts
|
|
|
|
_lynx_snd_play:
|
|
sta ptr1
|
|
stx ptr1+1
|
|
jsr popa
|
|
tax
|
|
lda ptr1
|
|
ldy ptr1+1
|
|
php
|
|
pha
|
|
lda SndActive,x
|
|
_IFNE
|
|
dec SndReqStop,x
|
|
lda #1
|
|
sta SndDelay,x
|
|
start0: lda SndActive,x
|
|
bne start0
|
|
_ENDIF
|
|
bra start1
|
|
SndStartSoundx:
|
|
php
|
|
pha
|
|
start1:
|
|
sei
|
|
pla
|
|
sta SndPtrLo,x
|
|
tya
|
|
sta SndPtrHi,x
|
|
lda #1
|
|
sta SndDelay,x
|
|
stz SndEnvVol,x
|
|
stz SndEnvFrq,x
|
|
stz SndEnvWave,x
|
|
sta SndActive,x
|
|
stz SndReqStop,x
|
|
plp
|
|
rts
|
|
SndStartSound2:
|
|
pha
|
|
lda SndActive,x ; check default
|
|
beq start20 ; inactive => ok
|
|
phx
|
|
ldx #3 ; search free channel
|
|
start21:
|
|
lda SndActive,x
|
|
beq start22 ; found =>
|
|
dex
|
|
bpl start21
|
|
plx ; not found
|
|
dec SndReqStop,x ; stop default-channel
|
|
lda #1
|
|
sta SndDelay,x
|
|
start23:
|
|
lda SndActive,x
|
|
bne start23
|
|
bra start20
|
|
start22:
|
|
pla ; clear stack
|
|
start20:
|
|
pla
|
|
phx
|
|
jsr SndStartSoundx ; launch new sound
|
|
plx
|
|
rts
|
|
|
|
_lynx_snd_stop:
|
|
ldx #3
|
|
lda SndActive,x
|
|
_IFNE
|
|
stop0: dec SndReqStop,x
|
|
lda #1
|
|
sta SndDelay,x
|
|
stop1: lda SndActive,x
|
|
bne stop1
|
|
_ENDIF
|
|
dex
|
|
bpl stop0
|
|
rts
|
|
|
|
_lynx_snd_stop_channel:
|
|
tax
|
|
lda SndActive,x
|
|
_IFNE
|
|
dec SndReqStop,x
|
|
lda #1
|
|
sta SndDelay,x
|
|
stopc1: lda SndActive,x
|
|
bne stopc1
|
|
_ENDIF
|
|
rts
|
|
|
|
_lynx_snd_active:
|
|
ldx #3
|
|
lda #0
|
|
act0: ldy SndActive,x
|
|
_IFNE
|
|
ora SndMask,x
|
|
_ENDIF
|
|
dex
|
|
bpl act0
|
|
rts
|
|
|
|
_lynx_snd_pause:
|
|
php
|
|
sei
|
|
lda STIMCTLA
|
|
sta SndPauseOff1+1
|
|
stz STIMCTLA
|
|
lda MSTEREO
|
|
sta SndPauseOff2+1
|
|
lda #$ff
|
|
sta MSTEREO
|
|
lda #$18
|
|
trb AUD0CTLA
|
|
trb AUD1CTLA
|
|
trb AUD2CTLA
|
|
trb AUD3CTLA
|
|
plp
|
|
rts
|
|
|
|
_lynx_snd_continue:
|
|
php
|
|
sei
|
|
SndPauseOff1:
|
|
lda #0 ; Selbsmodifizierter Code!!!
|
|
sta STIMCTLA
|
|
SndPauseOff2:
|
|
lda #0 ; Selbsmodifizierter Code!!!
|
|
sta MSTEREO
|
|
|
|
lda #$18
|
|
tsb AUD0CTLA
|
|
tsb AUD1CTLA
|
|
tsb AUD2CTLA
|
|
tsb AUD3CTLA
|
|
|
|
plp
|
|
rts
|
|
|
|
.rodata
|
|
|
|
SndMask:
|
|
.byte 1,2,4,8
|
|
|
|
SndPrescaler:
|
|
.byte $00,$06,$06,$06,$06,$05,$05,$05,$05,$05,$05,$05,$04,$04,$04,$04
|
|
.byte $04,$04,$04,$04,$03,$03,$03,$03,$03,$03,$03,$03,$03,$03,$02,$02
|
|
.byte $02,$02,$02,$02,$02,$02,$02,$02,$02,$02,$02,$01,$01,$01,$01,$01
|
|
.byte $01,$01,$01,$01,$01,$01,$01,$01,$01,$01,$01,$01,$01,$01,$00,$00
|
|
.byte $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00
|
|
.byte $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00
|
|
.byte $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00
|
|
.byte $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00
|
|
|
|
SndReload:
|
|
.byte $00,$9A,$96,$8F,$86,$FA,$E5,$D1,$BE,$AC,$9C,$8D,$00,$E8,$D3,$C0
|
|
.byte $AF,$A0,$93,$87,$FA,$E7,$D6,$C6,$B8,$AC,$A1,$96,$8D,$84,$FA,$EB
|
|
.byte $DE,$D2,$C7,$BC,$B3,$AA,$A1,$9A,$93,$8C,$86,$00,$F5,$EB,$E1,$D8
|
|
.byte $CF,$C7,$C0,$B9,$B2,$AB,$A5,$A0,$9A,$95,$90,$8B,$87,$82,$FD,$F5
|
|
.byte $EE,$E7,$E0,$D9,$D3,$CD,$C8,$C2,$BD,$B8,$B3,$AE,$AA,$A5,$A1,$9D
|
|
.byte $99,$96,$92,$8F,$8B,$88,$85,$82,$7F,$7C,$79,$77,$74,$72,$6F,$6D
|
|
.byte $6B,$69,$67,$64,$63,$61,$5F,$5D,$5B,$59,$58,$56,$55,$53,$51,$50
|
|
.byte $4F,$4D,$4C,$4B,$49,$48,$47,$46,$44,$43,$42,$41,$40,$3F,$3E,$3D
|
|
|
|
|
|
|