diff --git a/vic20/fxtest.c02 b/vic20/fxtest.c02 new file mode 100644 index 0000000..329077f --- /dev/null +++ b/vic20/fxtest.c02 @@ -0,0 +1,37 @@ +/* Test SoundFX Module */ + +/* To compile: ..\c02 -h vic3k -s vic fxtest.c02 * + * assemble: ..\a02.exe -p fxtest.asm fxtest.prg */ + +#include +#include "include/soundfx.h02" + +char key, effect; + +void putlin() {putstr(); newlin();} + +main: + clrscr(); + putlin("PRESS KEY FOR EFFECT"); + newlin(); + putlin(" 1 - INSERT COIN"); + putlin(" 2 - KLAXON"); + putlin(" 3 - FALLING"); + putlin(" 4 - POWER UP"); + putlin(" 5 - LASER CANNON"); + putlin(" 6 - SHIP CROSSING"); + putlin(" 7 - DROPPED"); + putlin(" 8 - EXPLOSION"); + newlin(); + putlin("PRESS STOP TO EXIT"); + + fxinit(); //Initilize SoundFX Engine + while() { + key = getchr(); + if (key == #ESCKEY) break; + effect = key - '1'; + if (effect < 8) fxplay(effect); + } + fxstop(); + goto exit; + \ No newline at end of file diff --git a/vic20/include/soundfx.a02 b/vic20/include/soundfx.a02 new file mode 100644 index 0000000..de29a06 --- /dev/null +++ b/vic20/include/soundfx.a02 @@ -0,0 +1,123 @@ +;SoundFX for VIC-20 by chysn +;Converted to A02 syntax by Curtis F Kaylor + + SUBROUTINE "SOUNDFX" + +;Available Sound Effect +FXCOIN EQU 0 ;Insert Coin +FXKLXN EQU 1 ;Klaxon +FXFALL EQU 2 ;Falling Into Something +FXPOWR EQU 3 ;Power Up +FXLASR EQU 4 ;Laser Cannon +FXCROS EQU 5 ;Command Ship Crossing +FXDROP EQU 6 ;Dropped Something +FXEXPL EQU 7 ;Explosion + +;SoundFX Constants +.VOICE EQU $900C ;$900C=high, $900B=mid, $900A=low, $900D=noise +.VOLUME EQU $900E + +;Internal Variables +.FREQ BYTE $00 ;Current effect frequency register +.LENGTH BYTE $00 ;Effect length for current effect +.COUNT BYTE $00 ;Effect countdown for current effect +.DIR BYTE $00 ;Effect direction ($00 if left, $80 is right) +.SPEED BYTE $00 ;Effect countdown reset value +.IADDR WORD $00 ;System Interrupt Routine Address + +;fxinit() - Start SoundFX Module +;Destroys: A +FXINIT JSR .CLEAR ;Clear Sound Registers + LDA #15 ;Set Volume to Max + STA .VOLUME + PHP ;Disable Interrupts + SEI + LDA $0314 ;Save Interrupt Routine Address + STA .IADDR + LDA $0315 + STA .IADDR+1 + LDA #<.FXSVC ;Install SoundFX Interrupt Routine + STA $0314 + LDA #>.FXSVC + STA $0315 + PLP ;Enable Interrupts + RTS + +;fxstop() - Stop SoundFX Module +FXSTOP PHP ;Disable Interrupts + SEI + LDA .IADDR ;Restore Interrupt Vector + STA $0314 + LDA .IADDR+1 + STA $0315 + PLP ;Enable Interrupts +.CLEAR LDA #0 ;Clear Sound Registers + LDX #5 +.LOOP STA $9009,X + DEX + BNE .LOOP + RTS + +;Sound Effects Service - Plays next sound effect, +;rotates the 8-bit sound effect register, and plays the pitch +.FXSVC LDA .LENGTH ;Has the sound been launched? + BEQ .DONE ;If unlaunched, kill voice and return + DEC .LENGTH ;Decrement both length + DEC .COUNT ; and countdown + BNE .RETURN ;If countdown has elapsed, + LDA .SPEED ; reset it with the current effect speed + STA .COUNT + BIT .DIR ;Rotate the register, based on the direction + BMI .RIGHT ; specified by the direction flag +.LEFT LDA #$00 + ASL .FREQ ;Rotate the register left if flag = $00 + ADC .FREQ ;If carry was set, set bit 0 + JMP .UPDATE ;Update and play the new frequency +.RIGHT LSR .FREQ ;Rotate the register right if flag = $80 + LDA .FREQ + BCC .PLAY ;If carry was set, set bit 7 + LDA #%10000000 + ORA .FREQ +.UPDATE STA .FREQ +.PLAY ORA #$80 ;Gate the high voice +.DONE STA .VOICE +.RETURN JMP (.IADDR) ;Execute System Interrupt Routine + +; Launch Sound Effect +; Args: A = The sound effect index +FXPLAY SEI ;Don't play anything while setting up + ASL ;Each effect has two bytes in the table + TAX + LDA .TABLE,X ;Get the register byte + STA .DIR ;Set the direction (only bit 7 will be used) + AND #$7F ;Mask away the direction bit to get the 7-bit + STA .FREQ ; frequency + LDA .TABLE+1,X ;Get the length byte + TAX ; and preserve it + AND #$F0 ;Length is in bits 4-7 of the length byte + STA .LENGTH + TXA + AND #$0F ;Speed (jiffies per rotation) is in the low + STA .SPEED ;nybble of the length byte + STA .COUNT + CLI ;Go! + RTS + +; Sound effects for the sound effects player +; Each effect has four parameters (DFFFFFFF LLLLSSSS) +; (1) Bit 7 (D) of the first byte is the direction +; * Unset=shift left, or a rising sound +; * Set=shift right, or a falling sound +; (2) Bits 0-6 (F) of the first byte is the frequency register +; (3) High nybble of the second byte (L) is the length in jiffies x 16 +; * Between approx. 1/4 sec and 4 sec in length +; (4) Low nybble of second byte (S) is speed in jiffies +.TABLE BYTE $7a,$13 ;0 - Insert Coin + BYTE $55,$68 ;1 - Klaxon + BYTE $f0,$26 ;2 - Falling Into Something + BYTE $07,$13 ;3 - Power Up + BYTE $3b,$31 ;4 - Laser Cannon + BYTE $6c,$74 ;5 - Command Ship Crossing + BYTE $95,$14 ;6 - Dropped Something + BYTE $92,$11 ;7 - Explosion + diff --git a/vic20/include/soundfx.h02 b/vic20/include/soundfx.h02 new file mode 100644 index 0000000..32ac74e --- /dev/null +++ b/vic20/include/soundfx.h02 @@ -0,0 +1,12 @@ +//SoundFX module for VIC-20 by chysn + +//Available Sound Effects +enum {FXCOIN, FXKLXN, FXFALL, FXPOWR, FXLASR, FXCROS, FXDROP, FXEXPL}; + +/* Initialize SoundFX Module * + * Installs Interrupt Routine */ +void fxinit(); + +/* Play Sound Effect * + * Args: char n - Effect */ + void fxplay();