mirror of
https://github.com/StewBC/penetrator-apple2.git
synced 2025-01-14 02:32:35 +00:00
Added Audio
Added UI, engine and sfx audio
This commit is contained in:
parent
17c546baef
commit
d34e0fabfc
112
src/apple2/audio.inc
Normal file
112
src/apple2/audio.inc
Normal 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
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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)
|
||||
:
|
||||
|
@ -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
|
||||
|
@ -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"
|
||||
|
@ -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
|
||||
|
@ -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
|
Loading…
x
Reference in New Issue
Block a user