******************************************************************************* * * SOUND.S by Kevin G. Osborn * Contains subroutines * TUNER * SCRAPALL * SCRAPONE * TUNIN ******************************************************************************* ******************************************************************************** * SIMPSONG VERSION 0.03 * * THIS SIMPLE SOUND DRIVER HAS, IN SOME WAYS, FEWER FEATURES BUT USES LESS RAM * AND ROM AND DOES NOT BACK UP SOUNDS FOR LATER (SOMETIMES MUCH LATER) * CONTINUATION. IT FEATURES 256 NOTE TUNES, SINGLE DURATION PER TUNE, ENDLESS * TUNES. IF A VALUE IN THE CONTROL OR VOLUME TABLES HAS THE HIGH BIT SET, THAT * VOLUME OR CONTROL WILL REMAIN IN EFFECT TILL THE END OF THE TUNE. * AN FF IN THE FREQUENCY TABLE WILL TERMINATE THE TUNE, AN FE WILL CAUSE IT TO * RESTART. AN FD WILL CALL THE TUNE NUMBER FOLLOWING (IN THE FREQ TABLE). * * SUBROUTINES: * SCRAPALL -- KILL ALL TUNES. SHOULD BE CALLED AT POWERUP, CHANGING PLAYERS, * AND GAME OVER * * SCRAPONE -- KILL A PARTICULAR TUNE. PUT THE NUMBER OF THE TUNE YA WANNA * AXE IN THE ACCUMULATOR. * * TUNIN -- START THAT TUNE YOU PUT IN ACC. * * THE ABOVE ROUTINES PRESERVE THE X AND Y REGS * * TABLES NEEDED ARE: * RAM: *DCH0 DS 1 ONE BYTE--DURATION CNTR CHAN. 0 *DCH1 DS 1 ONE BYTE--DURATION CNTR CHAN. 1 *TUNNUM DS 1 ONE BYTE--TUNE NUM FOR CHAN. 0 *TUNNUM1 DS 1 ONE BYTE--TUNE NUM FOR CHAN. 1 *TINDEX0 DS 1 ONE BYTE--NOTE POINTER 0 *TINDEX1 DS 1 ONE BYTE--NOTE POINTER 1 *CINDEX0 DS 1 CONTROL INDEX *CINDEX1 DS 1 *VINDEX0 DS 1 VOLUME INDEX *VINDEX1 DS 1 *MPTRL EQU KTEMP0 ZERO PAGE TEMP(NOT GAMEPLAY) *MPTRH EQU KTEMP1 ZERO PAGE TEMP(NOT GAMEPLAY) *TUNTEMP EQU TEMP0 ANY GAMEPLAY TEMP * ROM: * DURTABL ONE DURATION IN FRAMES PER TUNE * TBASE LOW ADDRESS OF THE START OF FREQ DATA BY TUNE NUMBER * TBASEH DITTO FOR HIGH ADDRESS * VBASE LOW ADDRESS OF THE START OF VOL DATA BY TUNE NUMBER * VBASEH DITTO FOR HIGH ADDRESS * CBASE LOW ADDRESS OF THE START OF CTRL DATA BY TUNE NUMBER * CBASEH DITTO FOR HIGH ADDRESS * PRYOR PRIORITY BY TUNE NUMBERS -- ZERO THE LOWEST * VOLTABL VOLUMES * FREQTABL FREQUENCIES * CTLTABL CONTROLS GLBL DURTABL,TBASE,TBASEH,VBASE,VBASEH,CBASE,CBASEH GLBL VOLTABL,FREQTABL GLBL DCH0,DCH1,TUNNUM,TUNNUM1,TINDEX0,TINDEX1,CINDEX0 GLBL VINDEX0,VINDEX1,MPTRL,MPTRH,TUNTEMP GLBL STATATTR GLBL IRTNDONE GLBL TUNEDONE GLBL SCRAPALL,SCRAPONE,TUNIN,TUNER GLBL MATTRACT GLBL MPAUSE,MBLANK GLBL TRUE,FALSE ; globals in Tables.s GLBL CTRLTABL,PRYOR,ZTUNE0F GLBL ZTUNE1F,ZTUNE2F,ZTUNE1V,ZTUNE2V,ZTUNE0V GLBL ZTUNE3F,ZTUNE3V,ZTUNE4F,ZTUNE4V,ZTUNE5F,ZTUNE5V GLBL ZTUNE6F,ZTUNE6V,ZTUNE7F,ZTUNE7V,ZTUNE8F,ZTUNE8V GLBL ZTUNE9F,ZTUNE9V,ATUNE10F,ZTUNE10V,ATUNE11F,ZTUNE11V GLBL ATUNE12F,ZTUNE12V,ATUNE13F,ZTUNE13V,ZTUNE14F,ZTUNE14V GLBL ZTUNE15F,ZTUNE15V,ZTUNE16F,ZTUNE16V,ZTUNE17F,ZTUNE17V GLBL ZTUNE18F,ZTUNE18V,ZTUNE19F,ZTUNE19V,ZTUNE20F,ZTUNE20V GLBL ZTUNE21F,ZTUNE21V,ZTUNE22F,ZTUNE22V,ZTUNE23F,ZTUNE23V GLBL ZTUNE24F,ZTUNE24V,ZTUNE25F,ZTUNE25V,ZTUNE26F,ZTUNE26V GLBL ZTUNE27F,ZTUNE27V,ZTUNE28F,ZTUNE28V,ZTUNE29F,ZTUNE29V GLBL ZTUNE30F,ZTUNE30V,ZTUNE31F,ZTUNE31V,ZTUNE32F,ZTUNE32V RAMDEF ; ZERO PAGE RSEG CODE1 ******************************************************************************** * SCRAPALL * KILL ALL TUNES. SHOULD BE CALLED AT POWERUP, CHANGING PLAYERS, * AND GAME OVER * ALSO BEFORE INITIATING A TUNE WITH TWO VOICES SCRAPALL TYA PHA TXA PHA LDY #0 STY AUDV0 STY AUDV1 DEY STY TUNNUM STY TUNNUM1 PLA TAX PLA TAY RTS ; IF YOU WANT, LOOP THIS UP ******************************************************************************** * SCRAPONE * KILL A PARTICULAR TUNE. PUT THE NUMBER OF THE TUNE YA WANNA * AXE IN THE ACCUMULATOR. ;SCRAPONE CMP TUNNUM ; BNE CKCH1 ; LDA #0 ; STA AUDV0 ; LDA #$FF ; STA TUNNUM ; RTS ;CKCH1 SEC ; SBC TUNNUM1 ; BNE REETS ; STA AUDV1 ; LDA #$FF ; STA TUNNUM1 ;REETS RTS ******************************************************************************** * TUNEDONE * RETURNS TRUE IF NO TUNES ARE PLAYING * IF BOTH TUNNUM CHANNELS ARE FF, THEN RETURN TRUE ;TUNEDONE LDA TUNNUM1 ; CMP #$FF ; BNE TDRTNF ; LDA TUNNUM ; CMP #$FF ; BNE TDRTNF ; LDA #TRUE ; RTS ;TDRTNF LDA #FALSE REETS RTS ******************************************************************************** * TUNIN * START THAT TUNE YOU PUT IN ACC. TUNIN STA TUNTEMP LDA MODE ; NO SOUND IN ATTRACT CMP #MATTRACT BEQ REETS LDA DOITOVER ; NO SOUND IN REPLAY BNE REETS TYA PHA TXA PHA LDY #1 LDX TUNTEMP TROIKA LDA TUNNUM,Y ;FIRST CHECK FOR AN EMPTY CHANNEL CMP #$FF BEQ DO TRKNX DEY BPL TROIKA LDA TUNNUM1 ;THIS IS DONE TO PREVENT GLITCHINESS AND #$7F TAY LDA PRYOR,X CMP PRYOR,Y ;CHECK FOR LOWEST PRIORITY LDY #1 BCS DO LDA TUNNUM ;THIS IS DONE TO PREVENT GLITCHINESS AND #$7F TAY LDA PRYOR,X CMP PRYOR,Y ;CHECK FOR LOWEST PRIORITY BCC ROOTS LDY #0 DO TXA ORA #$80 STA TUNNUM,Y ROOTS PLA TAX PLA TAY RTS ******************************************************************************** *TUNER SHOULD BE CALLED ONCE PER FRAME, NO INPUTS, AND IT OPERATES WITH *A TOTAL DISREGARD FOR REGISTER SANCTITY. EACH TUNE CAN BE 256 NOTES LONG *IF YOUR TUNES ARE VERY SMALL, YOU COULD DO AWAY WITH ALL THE INDIRECT STUFF TUNER LDA STATUS CMP #STATATTR BEQ REETS ; RTS LDA MODE ; DURING PAUSE, RETAIN STATE OF CMP #MPAUSE ; CURRENT SOUNDS BEQ REETS CMP #MBLANK BEQ REETS LDX #1 TUNLOP LDY TUNNUM,X INY BNE NETN ;TUNNUM=FF DO NEXT CHANNEL JNXTCH JMP NXTCH NETN DEY BPL BOOGIE TYA ;NEW TUNE--INTITIATE AND #$7F STA TUNNUM,X TAY LDA CTRLTABL,Y STA AUDC0,X ; IN EFFECT UNTIL CHANGED LDA #1 STA DCH0,X ;START LDA #$FF ; INCREMENTS ON THE FIRST CALL STA TINDEX0,X * STA CINDEX0,X STA VINDEX0,X BOOGIE LDA TBASE,Y STA MPTRL LDA TBASEH,Y STA MPTRH DEC DCH0,X BNE JNXTCH ; SAME AS PATTY'S SOUND EDITOR LDA DURTABL,Y STA DCH0,X LDY TINDEX0,X * INC CINDEX0,X INC VINDEX0,X TESTBYTE INY TBYTE0 LDA (MPTRL),Y ;FREQ CMP #$FF BNE CKNXTT STA TUNNUM,X ;END THIS FUNKY TUNE LDA #0 STA AUDV0,X BEQ JNXTCH ;CKENL CMP #$FE ; NO REPEATS FOR ME ! ; BEQ FOOBEQ CKNXTT CMP #$FD ; CONTINUE WITH THE NEXT TUNE BEQ NEXTTUNE CMP #$FC ; A VALID STOPPING POINT BEQ SIRTRUE CMP #$FB ; NO LONGER VALID FOR STOPPING BEQ SIRFALSE JMP STFREQ SIRTRUE LDA #TRUE JMP SETIRTN SIRFALSE LDA #FALSE SETIRTN STA IRTNDONE JMP TESTBYTE ; PROCESS THE NEXT BYTE NEXTTUNE INY ; NEXT BYTE IS TUNE INDEX LDA (MPTRL),Y TAY ORA #$80 ; SO THAT NEW CTRL AND VOLUME GET READ STA TUNNUM,X LDA TBASE,Y ; GET ADDRESS OF NEW TUNE STA MPTRL LDA TBASEH,Y STA MPTRH LDY #0 ; JUMP HERE FOR REPEAT TYA ; Y MUST BE 0, IT'S THE FREQ. INDEX * STA CINDEX0,X STA VINDEX0,X JMP TBYTE0 ; IN CASE IT'S AN IR SPECIAL FRQLOOP LDA (MPTRL),Y STFREQ BPL SKIP0 ; IF BIT 7 SET, GET NEW DURATION INY LDA (MPTRL),Y STA DCH0,X DEY LDA (MPTRL),Y INY JMP STIT0 SKIP0 ASL A BPL SKIP1 ; IF BIT 6 SET, THIS IS A REST LSR A AND #$BF STA DCH0,X TYA STA TINDEX0,X DEC VINDEX0,X * DEC CINDEX0,X LDA #0 STA AUDV0,X BEQ NXTCH SKIP1 ASL A BPL STIT ; IF BIT 5 IS SET, THIS IS A NEW CTRL LSR A LSR A AND #$1F STA AUDC0,X INY JMP FRQLOOP ; DO NEXT BYTE BEFORE RETURNING STIT LSR A LSR A STIT0 STA AUDF0,X TYA STA TINDEX0,X LDY TUNNUM,X LDA VBASE,Y STA MPTRL LDA VBASEH,Y STA MPTRH LDY VINDEX0,X LDA (MPTRL),Y BPL STVL DEY STVL STA AUDV0,X TYA STA VINDEX0,X * LDY TUNNUM,X * LDA CBASE,Y * STA MPTRL * LDA CBASEH,Y * STA MPTRH * LDY CINDEX0,X * LDA (MPTRL),Y * BPL STCTRL * DEY *STCTRL STA AUDC0,X * TYA * STA CINDEX0,X NXTCH DEX BMI ROTS JMP TUNLOP ROTS RTS ******************************************************************************** * pointer tables. TBASE DB L(ZTUNE0F),L(ZTUNE1F),L(ZTUNE2F),L(ZTUNE3F) DB L(ZTUNE4F),L(ZTUNE5F),L(ZTUNE6F),L(ZTUNE7F),L(ZTUNE8F) DB L(ZTUNE9F),L(ATUNE10F),L(ATUNE11F),L(ATUNE12F) DB L(ATUNE13F),L(ZTUNE14F),L(ZTUNE15F),L(ZTUNE16F) DB L(ZTUNE17F),L(ZTUNE18F),L(ZTUNE19F),L(ZTUNE20F) DB L(ZTUNE21F),L(ZTUNE22F),L(ZTUNE23F) DB L(ZTUNE24F),L(ZTUNE25F),L(ZTUNE26F) DB L(ZTUNE27F),L(ZTUNE28F),L(ZTUNE29F) DB L(ZTUNE30F),L(ZTUNE31F),L(ZTUNE32F) TBASEH DB H(ZTUNE0F),H(ZTUNE1F),H(ZTUNE2F),H(ZTUNE3F) DB H(ZTUNE4F),H(ZTUNE5F),H(ZTUNE6F),H(ZTUNE7F),H(ZTUNE8F) DB H(ZTUNE9F),H(ATUNE10F),H(ATUNE11F),H(ATUNE12F) DB H(ATUNE13F),H(ZTUNE14F),H(ZTUNE15F),H(ZTUNE16F) DB H(ZTUNE17F),H(ZTUNE18F),H(ZTUNE19F),H(ZTUNE20F) DB H(ZTUNE21F),H(ZTUNE22F),H(ZTUNE23F) DB H(ZTUNE24F),H(ZTUNE25F),H(ZTUNE26F) DB H(ZTUNE27F),H(ZTUNE28F),H(ZTUNE29F) DB H(ZTUNE30F),H(ZTUNE31F),H(ZTUNE32F) VBASE DB L(ZTUNE0V),L(ZTUNE1V),L(ZTUNE2V),L(ZTUNE3V) DB L(ZTUNE4V),L(ZTUNE5V),L(ZTUNE6V),L(ZTUNE7V),L(ZTUNE8V) DB L(ZTUNE9V),L(ZTUNE10V),L(ZTUNE11V),L(ZTUNE12V) DB L(ZTUNE13V),L(ZTUNE14V),L(ZTUNE15V),L(ZTUNE16V) DB L(ZTUNE17V),L(ZTUNE18V),L(ZTUNE19V),L(ZTUNE20V) DB L(ZTUNE21V),L(ZTUNE22V),L(ZTUNE23V) DB L(ZTUNE24V),L(ZTUNE25V),L(ZTUNE26V) DB L(ZTUNE27V),L(ZTUNE28V),L(ZTUNE29V) DB L(ZTUNE30V),L(ZTUNE31V),L(ZTUNE32V) VBASEH DB H(ZTUNE0V),H(ZTUNE1V),H(ZTUNE2V),H(ZTUNE3V) DB H(ZTUNE4V),H(ZTUNE5V),H(ZTUNE6V),H(ZTUNE7V),H(ZTUNE8V) DB H(ZTUNE9V),H(ZTUNE10V),H(ZTUNE11V),H(ZTUNE12V) DB H(ZTUNE13V),H(ZTUNE14V),H(ZTUNE15V),H(ZTUNE16V) DB H(ZTUNE17V),H(ZTUNE18V),H(ZTUNE19V),H(ZTUNE20V) DB H(ZTUNE21V),H(ZTUNE22V),H(ZTUNE23V) DB H(ZTUNE24V),H(ZTUNE25V),H(ZTUNE26V) DB H(ZTUNE27V),H(ZTUNE28V),H(ZTUNE29V) DB H(ZTUNE30V),H(ZTUNE31V),H(ZTUNE32V) END