* 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