Added Audio

Added UI, engine and sfx audio
This commit is contained in:
StewBC 2020-01-15 14:33:49 -08:00
parent 17c546baef
commit d34e0fabfc
10 changed files with 235 additions and 9 deletions

112
src/apple2/audio.inc Normal file
View File

@ -0,0 +1,112 @@
;-----------------------------------------------------------------------------
; audio.inc
; Part of penetrator, the zx spectrum game, made for Apple II
;
; Stefan Wessels, 2020
; This is free and unencumbered software released into the public domain.
;-----------------------------------------------------------------------------
.segment "CODE"
.proc serviceAudio
lda audioMask ; get the active channels
and audioFrame ; see if any channel needs to play this frame
bne makeSounds ; make a sound if a channel needs audio
rts
makeSounds:
bit Bit7Mask ; AUDIO_EXPLOSION
bne bombDrop
bit Bit6Mask ; AUDIO_FIRE
bne fire
bit Bit5Mask ; AUDIO_EXPLOSION
bne explosion
bit Bit8432Mask ; AUDIO_ENGINE - Not that bit 8 is erroneusly checked
bne engine ; only because I didn't want to make a new constant
bit Bit1Mask ; AUDIO_UI_TICK
bne ui
rts
explosion:
ldy audioExplFrame ; use the frame as an index
lda explDelay, y
tax
ldy #$6
jsr playNote
inc audioExplFrame
lda audioExplFrame
cmp #%00000011
bcc :+
stx audioFrame ; turn off the explosion
rts
:
lda #AUDIO_EXPLOSION
sta audioFrame
rts
bombDrop:
ldy #$50
ldx #$10
jmp playNote
fire:
ldy #$20
ldx #$10
jmp playNote
engine:
bit Bit4Mask ; AUDIO_MOTOR_FWD
beq :+
ldy #$25
ldx #$08
jmp playNote
:
bit Bit3Mask ; AUDIO_MOTOR_REW
beq :+
ldy #$35
ldx #$08
jmp playNote
:
ldy #$30
ldx #$08
jmp playNote
ui:
ldy #$80
ldx #$10
jmp playNote
.endproc
;-----------------------------------------------------------------------------
.proc playNote
delay = tempBlock + 21
sty delay
loop:
lda speaker_toggle
ldy delay
:
nop
nop
nop
nop
dey
bne :- ; hold for the duration in y
dex
bne loop ; retrigger
lda #AUDIO_EXPLOSION ; reset the audio frame (serviced)
and audioFrame ; but keep explosion if it was set
sta audioFrame
rts
.endproc

View File

@ -11,6 +11,7 @@
ram_layer0 = $2000 ; HGR Pages
ram_layer1 = $4000
speaker_toggle = $C030
;-----------------------------------------------------------------------------
; self-modifying address marker
@ -56,6 +57,15 @@ DANGER_FONT = 4 ; Number of font characters that
DANGER_LENGTH = ((textEnd-1)-textDangerBar) ; how many characters in the danger column (skip trailing 0)
DANGER_TICKS = ((((worldDataEnd-worldDataStart) / 3) / DANGER_LENGTH) / DANGER_FONT)
; audio constants
AUDIO_BOMB_DROP = %01000000 ; Releasing a bomb
AUDIO_FIRE = %00100000 ; Firing the gun
AUDIO_EXPLOSION = %00010000 ; An enemy exploding
AUDIO_MOTOR_FWD = %00001000 ; Speeding up
AUDIO_MOTOR_REW = %00000100 ; slowing down
AUDIO_MOTOR_PLAY = %00000010 ; flying at a constant speed
AUDIO_UI_TICK = %00000001 ; UI selection
; The enemyBuffer is filled with these values, which break down as:
;
; Bits 1 & 2 - Type. 0 - monster, 1 - missile, 2 - radar & 3 - nuke

View File

@ -352,7 +352,12 @@ explode:
stx explFrame
:
lda #3 ; set a nonsense width to make the explosio
stx audioExplFrame
lda audioFrame
ora #AUDIO_EXPLOSION
sta audioFrame
lda #3 ; set a nonsense width to make the explosion
sta zaDataWidth ; not so recognizable
lda #3 ; set the dimensions of the explosion

View File

@ -41,6 +41,19 @@ preamble: ; bring terrain on-screen with n
wait #$40 ; give the user a moment to get ready
loop:
lda runAudio
eor #1
sta runAudio
bne :+
jsr serviceAudio
lda audioFrame
ora #AUDIO_MOTOR_PLAY
sta audioFrame
beq loop
:
lda playerDead
bne skip
jsr inputGame ; read joystick and move player, check for pause key
cmp #$9b ; check for ESC
bne skip ; if not, check for pause
@ -85,7 +98,7 @@ delay:
died:
dec playerDead ; the counter holds the explosion state
bne skip ; don't get user input
bne loop ; don't get user input
jsr gameNextPlayer ; switch players if a 2p game
jmp outerloop
@ -146,6 +159,7 @@ win:
sta flipFlop
sta pause
sta fireCoolDown
sta audioFrame
tax ; clear the buffers for tracking objects
:
@ -1122,6 +1136,13 @@ continue:
and #%00000011 ; mask column (or strip of the sprite)
sta zaSprColumn ; save it
lda audioFrame
ora #AUDIO_EXPLOSION ; Add explosion to audio frame
sta audioFrame
lda #0 ; start the explosion at frame 0
sta audioExplFrame
lda zaEnemyColLocal ; see where the sprite starts
sec ; by subtracting the strip number (index)
sbc zaSprColumn ; from the current world column

View File

@ -142,7 +142,10 @@ left:
dex ; move left one column
bmi preBomb ; if off-screen to the left, ignore
stx playerShipX ; save the movement
bpl preBomb
lda audioFrame
ora #AUDIO_MOTOR_REW
sta audioFrame
bne preBomb
right:
bit Bit1Mask ; bit set when right joystick active
@ -153,6 +156,9 @@ right:
cpx #(((XSIZE/3)*2) - SHIP_WIDTH - 1) ; limit to two-thirds toward the right
bcs preBomb ; if over limit, ignore
stx playerShipX ; save movement
lda audioFrame
ora #AUDIO_MOTOR_FWD
sta audioFrame
preBomb:
lda zaRawInput
@ -184,6 +190,9 @@ drop:
sta bombY, x
lda #BOMB_FRWRD_FRMS ; set it to fly forward
sta bombDir, x
lda audioFrame
ora #AUDIO_BOMB_DROP
sta audioFrame
nobomb:
lda zaRawInput
@ -208,6 +217,9 @@ fire:
sta bulletsBuffer, x ; put height into 3 columns
lda #3
sta fireCoolDown
lda audioFrame
ora #AUDIO_FIRE
sta audioFrame
joyDone:
lda zaRawInput ; remember the key-state for next time
@ -380,10 +392,17 @@ joyDone:
bne :-
:
txa
rts
; rts
done:
and #$7f
beq :+
pha
lda #AUDIO_UI_TICK
sta audioFrame
jsr serviceAudio
pla
:
rts ; upon return 0 means no interaction, anything else is a user input
.endproc

View File

@ -21,6 +21,7 @@ jmp main ; This ends up at $080d (sys 206
.include "defs.inc" ; constants
.include "macros.inc" ; vpoke, vpeek, print* & wait.
.include "zpvars.inc" ; Zero Page usage (variables)
.include "audio.inc" ; Play notes fro audio events
.include "input.inc" ; Keyboard/Joystick routines
.include "ui.inc" ; The front-end code
.include "edit.inc" ; In-game editor
@ -34,7 +35,7 @@ jmp main ; This ends up at $080d (sys 206
.include "fontdata.inc" ; The ZA Spectrum font as 2bpp, 2 bytes/char
.include "logodata.inc" ; Lines to spell Penetrator and intro graphic
.include "rodata.inc" ; Read Only (RODATA segment sprites, etc)
.include "logo.inc"
.include "logo.inc" ; The include to include the HGR image
;-----------------------------------------------------------------------------
.segment "CODE"
@ -67,12 +68,16 @@ store:
ldx #((highScoresEnd-highScores) - 1) ; set high score table scores to 0
lda #$0
sta backLayer ; set back layer to 0
sta audioFrame ; set all audio channels to off (0)
:
sta highScores, x
dex
bpl :-
sta backLayer ; set back layer to 0
ldx #(AUDIO_EXPLOSION | AUDIO_BOMB_DROP | AUDIO_FIRE | AUDIO_UI_TICK)
stx audioMask ; set the mask to all channels on ($ff)
ldx #((BitMasksEnd - BitMasks) - 1)
:

View File

@ -181,6 +181,11 @@ BitMasks:
.byte %11110000
BitMasksEnd:
;-----------------------------------------------------------------------------
; Audio delay values
explDelay:
.byte $04, $08, $06, $04
;-----------------------------------------------------------------------------
; Sprite Information
; Images to the right in human form, not Apple II form (i.e. bytes don't

View File

@ -37,7 +37,12 @@ textOneTwo: .asciiz "\"1\" OR \"2\" FOR NUMBER OF PLAYERS"
textTrain: .asciiz "\"T\" FOR TRAINING CONTROL CENTER"
textEdit: .asciiz "\"E\" FOR THE LANDSCAPE EDITOR"
textLoad: .asciiz "\"L\" TO LOAD ANOTHER LANDSCAPE"
textSirens: .asciiz "\"S\" TO DISABLE SIRENS"
textSirens: .asciiz "\"S\" SET AUDIO: "
; main menu audio options
textAudio1: .asciiz "ENGINE, SFX"
textAudio2: .asciiz "SFX "
textAudio3: .asciiz "NONE "
; training mode menu
textTrainingMode: .asciiz "TRAINING MODE"

View File

@ -83,7 +83,7 @@ loop:
jmp loop
done:
rts
rts
.endproc
@ -348,6 +348,7 @@ plot:
jsr drawClearScreen
redraw:
print textInstructions, #(10), #(8*04)
print textPress , #(13), #(8*08)
print textUnderline , #(13), #(8*09)
@ -357,6 +358,22 @@ plot:
print textLoad , #(01), #(8*14)
print textSirens , #(05), #(8*15)
lda audioMask
beq none
bit Bit8432Mask
bne :+
print textAudio2 , #(20), #(8*15)
jmp present
:
print textAudio1 , #(20), #(8*15)
jmp present
none:
print textAudio3 , #(20), #(8*15)
present:
jsr drawPresent
lda #GAME_MODE_PLAY ; assume the player will play (play is 0)
@ -400,7 +417,21 @@ load:
jmp uiMainMenu
sirens:
jmp loop ; siren code instead of this
lda audioMask
beq audioSetAll
bit Bit8432Mask
bne :+
lda #0
beq :++
:
lda #(AUDIO_EXPLOSION | AUDIO_BOMB_DROP | AUDIO_FIRE | AUDIO_UI_TICK)
bne :+
audioSetAll:
lda #%01111111
:
sta audioMask
jmp redraw ; siren code instead of this
options: .byte "12TELS"
@ -1030,6 +1061,13 @@ loop:
bit Bit8Mask
beq loop
bit KBDSTRB
pha
lda #AUDIO_UI_TICK
sta audioFrame
jsr serviceAudio
pla
and #$7F
cmp #$0D ; enter key then done
beq enter

View File

@ -57,6 +57,7 @@ dangerTickCount: .res 1 ; how often a dot is added to th
dangerTickIdx: .res 1 ; the index into the text that holds the danger line of dots
moveHorz: .res 1 ; keeps track of horizontal movement - only moves every 2nd frame
moveVert: .res 1 ; keeps track of vertical movement - moves 4 rows but over 2 frames
runAudio: .res 1 ; flip-flop for service audio or run a game frame
; helper variables
updateHUD: .res 1 ; 0 - don't draw, 1+ - clean and redraw
@ -67,3 +68,8 @@ enemyHitType: .res 1 ; 0 = nuke, 1 = missile, 2 = mon
lastInput: .res 1 ; holds the value of the prev joystick frame
pause: .res 1 ; <> 0 when the game is paused
fireCoolDown: .res 1
; audio variables
audioMask: .res 1 ; which audio "channels" are active (and with audioFrame)
audioFrame: .res 1 ; prioritized mask for sounds to make (msb to lsb)
audioExplFrame: .res 1 ; explosion frame index, for sound