Applecorn/auxmem.audio.s

158 lines
6.1 KiB
ArmAsm

* AUXMEM.AUDIO.S
* (c) Bobbi 2022 GPLv3
*
* Applecorn audio and buffer management code.
* This auxiliary memory code implements OSWORD &07 and &08, enqueueing events
* for the audio engine that lives in main memory (MAINMEM.AUDIO.S).
*
BYTE0F
BYTE15
BYTE8A
BYTE91
BYTE98
BYTE99
BUFFLUSH
BUFFLUSHALL
BUFINSERT
BUFREM
BUFINS
BUFCNP
RTS
* OSWORD &07 - Make a sound
* On entry: (OSCTRL),Y points to eight byte parameter block (2 bytes each for
* channel, amplitude, pitch, duration)
WORD07 INY
LDA (OSCTRL),Y ; Get channel system bits
DEY
CMP #$20 ; Sound system is %000xxxxx:xxxxxxxx
BCS :RTS ; *TO DO* Should pass to service call
LDA (OSCTRL),Y ; Get channel number/flush byte
ORA #$04 ; Convert to buffer number 4-7
AND #$0F ; Mask off flush nybble
PHA ; Stash
LDA (OSCTRL),Y ; Get channel number/flush byte
AND #$F0 ; Mask off channel number nybble
BEQ :WAITLOOP ; If no flush, skip
PLX ; Buffer num -> X
PHX
PHY
BIT :RTS ; Set V, means flush buffer
JSR CNPHND ; Go flush buffer
PLY
:WAITLOOP CLI ; Allow IRQS for a few cycles
SEI ; (So queue can be emptied)
LDA $C000 ; See if key pressed
BPL :NOKEY
EOR #$80
JSR KBDCHKESC ; Was Escape pressed?
BIT ESCFLAG
* ; *TO DO* Replace above with JSR ESCPOLL
BMI :ESCAPE ; If so, bail!
:NOKEY PLX ; Buffer num -> X
PHX
CLV ; Ask to count buffer
SEC ; Ask for space remaining
JSR CNPHND ; Go count it
CPX #3 ; Less than 4 bytes remaining?
BMI :WAITLOOP
PLX ; Buffer num -> X
INY ; Point to channel num MSB
LDA (OSCTRL),Y
JSR INSHND ; Insert into queue X
INY ; Point to amplitude LSB
LDA (OSCTRL),Y
JSR INSHND ; Insert into queue X
INY ; Point to amplitude MSB
INY ; Point to pitch LSB
LDA (OSCTRL),Y
JSR INSHND ; Insert into queue X
INY ; Point to pitch MSB
INY ; Point to duration LSB
LDA (OSCTRL),Y
JSR INSHND ; Insert into queue X
:RTS RTS
:ESCAPE PLX ; Fix up stack
STA KBDSTRB ; Ack keypress
RTS
* OSWORD &08 - Envelope
* On entry: (OSCTRL),Y points to 14 byte parameter block
* Supports 4 envelopes for now, could be extended for more
WORD08 LDA (OSCTRL),Y ; Get envelope number
DEC A ; Make it zero-based
CMP #$15 ; Check in range
BPL :RTS ; Ignore if out of range
TAX
LDA #$00
:L0 CPX #$00 ; Calculate EnvNum * 13
BEQ :S1 ; Faster to do n*12+n to get n*13
CLC
ADC #13
DEX
BRA :L0
:S1 TAX ; Dest offset in X
INY ; Skip over env number parm
:L1 LDA (OSCTRL),Y ; Copy CB to mainmem
>>> WRTMAIN
STA ENVBUF0,X
>>> WRTAUX
INY
INX
CPY #14
BNE :L1
:RTS RTS
* Insert value into buffer (INSV)
* On entry: A is value, X is buffer number.
* On exit: A, X, Y preserved. C clear on success.
* Stub that calls into main memory
INSHND PHA ; Preserve all regs
PHX
PHY
PHX ; X->Y for transfer
PLY
>>> XF2MAIN,MAININS
INSHNDRET >>> IENTAUX ; Do NOT enable interrupts
PHA ; A->Flags after transfer
PLP
PLY ; Recover all regs
PLX
PLA
RTS
* Count space in buffer or purge buffer (CNPV)
* On entry: X is buffer number. V set means purge, V clear means count.
* C set means space left, C clear means entries used
* On exit: For purge, X & Y are preserved.
* For count, value in X (Y=0).
* A undef. V,C flags preserved.
* Stub that calls into main memory
CNPHND PHP
PHX
PHY
PHP ; Flags->A for transfer
PLA
PHX ; X->Y for transfer
PLY
>>> XF2MAIN,MAINCNP
CNPHNDRET1 >>> IENTAUX ; Return after count
PHY ; Y->X after transfer
PLX
PLY ; Discard stacked Y
PLY ; Discard stacked X
LDY #$00 ; Y=0 for count
PLP
RTS
CNPHNDRET2 >>> IENTAUX ; Return after purge
PLY ; Recover X,Y and flags
PLX
PLP
RTS