First implementation of sound
Sounds are packed into a bank, loaded, copied to Ensoniq RAM, and can be played through oscillators. The most basic form of GS sound system.
This commit is contained in:
parent
b289166038
commit
50b1e71521
|
@ -25,9 +25,12 @@
|
|||
7088096D1F2ECE8D00D4C950 /* GenerateRenderSpans.py */ = {isa = PBXFileReference; lastKnownFileType = text.script.python; path = GenerateRenderSpans.py; sourceTree = "<group>"; };
|
||||
708D1B1E27B9A1A600909AFC /* crosshair.s */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.asm; path = crosshair.s; sourceTree = "<group>"; };
|
||||
709175C01F60D263008FAFAB /* GenerateCircles.py */ = {isa = PBXFileReference; lastKnownFileType = text.script.python; path = GenerateCircles.py; sourceTree = "<group>"; };
|
||||
709816A32A53B21800108D9C /* GenerateSoundBank.sh */ = {isa = PBXFileReference; lastKnownFileType = text.script.sh; path = GenerateSoundBank.sh; sourceTree = "<group>"; };
|
||||
709816A42A54E19F00108D9C /* ReadMe.md */ = {isa = PBXFileReference; lastKnownFileType = net.daringfireball.markdown; path = ReadMe.md; sourceTree = "<group>"; };
|
||||
7099E3841F41022100182A82 /* gameobject.s */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.asm; path = gameobject.s; sourceTree = "<group>"; };
|
||||
7099E3851F4107B100182A82 /* GenerateVRAMYOffset.py */ = {isa = PBXFileReference; lastKnownFileType = text.script.python; path = GenerateVRAMYOffset.py; sourceTree = "<group>"; };
|
||||
70A80FB01F43D7F200BD34C9 /* gamemanager.s */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.asm; path = gamemanager.s; sourceTree = "<group>"; };
|
||||
70BCB0CE2A4FC92D00B19803 /* sound.s */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.asm; path = sound.s; sourceTree = "<group>"; };
|
||||
70BDCBC92006AD5F00CB51F1 /* linkerConfig */ = {isa = PBXFileReference; lastKnownFileType = text; path = linkerConfig; sourceTree = "<group>"; };
|
||||
70BDCBCA200A99F200CB51F1 /* ParseMapFile.py */ = {isa = PBXFileReference; lastKnownFileType = text.script.python; path = ParseMapFile.py; sourceTree = "<group>"; };
|
||||
70C073091F5BAA3E009844A9 /* collision.s */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.asm; path = collision.s; sourceTree = "<group>"; };
|
||||
|
@ -66,6 +69,8 @@
|
|||
700C39C51F2E5CA800C24F9C /* tables.s */,
|
||||
70E266E31F6F262D005AC7E4 /* circleTable.s */,
|
||||
70F0869F1F413A89002446C3 /* player.s */,
|
||||
70BCB0CE2A4FC92D00B19803 /* sound.s */,
|
||||
709816A32A53B21800108D9C /* GenerateSoundBank.sh */,
|
||||
705456882A4D336200A2B866 /* animation.s */,
|
||||
700B5E6F2069831000B31C00 /* inventory.s */,
|
||||
700F21DF1F4A364600D7007D /* projectile.s */,
|
||||
|
@ -85,6 +90,7 @@
|
|||
705456862A43E03B00A2B866 /* GeneratePixelCircle.py */,
|
||||
709175C01F60D263008FAFAB /* GenerateCircles.py */,
|
||||
70BDCBCA200A99F200CB51F1 /* ParseMapFile.py */,
|
||||
709816A42A54E19F00108D9C /* ReadMe.md */,
|
||||
);
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
|
|
|
@ -0,0 +1,61 @@
|
|||
#!/bin/bash
|
||||
|
||||
############################################
|
||||
# Takes a list of WAV files for the sound effects,
|
||||
# downsamples them to GS-friendly rates,
|
||||
# and packs them into a 64k block that can
|
||||
# be loaded into Ensoniq RAM
|
||||
#
|
||||
# IMPORTANT: This depends on sox, which MacOS doesn't have natively.
|
||||
# You can get it from Homebrew ("brew install sox")
|
||||
#
|
||||
# Big thanks to Jeremy Rand, from whom this approach
|
||||
# borrows heavily
|
||||
# https://github.com/jeremysrand/BuGS/blob/master/BuGS/sound/sources/createRaw
|
||||
|
||||
rm -f "SoundBank#060000"
|
||||
rm -f "Sound/SoundMap.txt"
|
||||
|
||||
currAddr=0
|
||||
|
||||
for (( index=1; index<="$#"; index+=2 )); do
|
||||
waveFilePath=${!index}
|
||||
|
||||
# Downsample and convert to 8-bit unsigned raw waveform
|
||||
rateIndex=$((index+1))
|
||||
rate=${!rateIndex}
|
||||
sox "$waveFilePath" -c 1 -r "$rate" --bits 8 --encoding unsigned tempSound.raw
|
||||
|
||||
waveFile=$(basename -- "$waveFilePath")
|
||||
rawFile="Sound/Generated/${waveFile%.wav}.raw"
|
||||
|
||||
# Replace any 00 bytes with 01 because 00 is the terminator for Ensoniq
|
||||
LC_ALL=C tr < tempSound.raw '\000' '\001' > "$rawFile"
|
||||
rm tempSound.raw
|
||||
|
||||
# Null-terminate the waveform
|
||||
rawSize=`stat -f '%z' "$rawFile"`
|
||||
dd if=/dev/zero bs=1 count=1 >> "$rawFile"
|
||||
|
||||
# Pad the file out to a wavetable page boundary
|
||||
rawSize=`stat -f '%z' "$rawFile"`
|
||||
pageSize=`echo "a=$rawSize; b=4096; if ( a%b ) (a/b+1)*4096 else a/b*4096" | bc`
|
||||
let "padding = $pageSize - $rawSize"
|
||||
dd if=/dev/zero bs=1 count="$padding" >> "$rawFile"
|
||||
|
||||
# Concatenate to our soundbank
|
||||
cat "$rawFile" >> "SoundBank#060000"
|
||||
|
||||
# Update the human-readable sound map (so human can modify loading code as needed)
|
||||
soundName="${waveFile%.wav}"
|
||||
printf "$%04x\t%s\t%d bytes\t%d Hz\n" "$currAddr" "$soundName" "$pageSize" "$rate" >> "Sound/SoundMap.txt"
|
||||
|
||||
# Increment address for next sound in bank
|
||||
currAddr=$((currAddr+pageSize))
|
||||
|
||||
done
|
||||
|
||||
echo
|
||||
echo "Sound RAM mapping:"
|
||||
cat "Sound/SoundMap.txt"
|
||||
|
13
Makefile
13
Makefile
|
@ -4,8 +4,7 @@
|
|||
#
|
||||
# Created by Quinn Dunki on 7/14/15.
|
||||
# One Girl, One Laptop Productions
|
||||
# http://www.quinndunki.com
|
||||
# http://www.quinndunki.com/blondihacks
|
||||
# http://www.blondihacks.com
|
||||
#
|
||||
|
||||
|
||||
|
@ -18,10 +17,12 @@ ADDR=0800
|
|||
CODEBANK=CODEBANK\#060000
|
||||
CODEBANKE1=CODEBANKE1\#060800
|
||||
EXEC=$(PGM)\#06$(ADDR)
|
||||
SOUNDBANK=SOUNDBANK\#060000
|
||||
|
||||
PGM=gscats
|
||||
MRSPRITE=../MrSprite/mrsprite
|
||||
GENART=Art/Generated
|
||||
GENSOUND=Sound/Generated
|
||||
CHROMA=a4dffb
|
||||
PALETTE=a4dffb a4dffb 008800 886611 cc9933 eebb44 dd6666 ff99aa 777777 ff0000 b7b7b7 dddddd 0077bb ffff00 000000 ffffff
|
||||
SPRITES=SpriteBank
|
||||
|
@ -47,6 +48,8 @@ $(PGM):
|
|||
@PATH=$(PATH):/usr/local/bin; $(CL65) -t apple2enh -C linkerConfig --cpu 65816 --start-addr 0000 -l$(PGM).lst $(REMOTESYMBOLS) $(PGM).s -o $(CODEBANK)
|
||||
$(CAD) ADDFILE $(PGM).2mg /$(VOLNAME) $(CODEBANK)
|
||||
$(CAD) ADDFILE $(PGM).2mg /$(VOLNAME) $(SPRITEBANK)
|
||||
$(CAD) ADDFILE $(PGM).2mg /$(VOLNAME) $(SOUNDBANK)
|
||||
|
||||
rm -f $(CODEBANK)
|
||||
rm -f $(PGM).o
|
||||
rm -f terrain_e1.map
|
||||
|
@ -87,3 +90,9 @@ art:
|
|||
./MerlinToCA65.sh $(GENART)/$(SPRITES)Src.txt > spritebank.s
|
||||
rm $(GENART)/*.txt
|
||||
rm -f Art/*m.gif
|
||||
|
||||
.PHONY: sound
|
||||
sound:
|
||||
rm -f $(GENSOUND)/*
|
||||
./GenerateSoundBank.sh Sound/CatHowl.wav 11264 Sound/Meow1.wav 5513
|
||||
rm -f $(GENSOUND)/*
|
||||
|
|
|
@ -0,0 +1,24 @@
|
|||
# GSCats
|
||||
|
||||
## Introduction
|
||||
|
||||
This is a simple game in the style of Apple II Artilley, Scorched Earth, or Worms– but with cats and nobody gets hurt.
|
||||
|
||||
This was written as an exercise for me to learn the fundamentals of Apple IIgs game programming, and I certainly won't claim there's anything special here technically. The neatest part is probably the terrain, which is deformable and scrolls at 60fps on stock hardware. Well, sometimes it does, anyway, depending on how you hold your nose. The GS is hard.
|
||||
|
||||
## Acknowledgements
|
||||
|
||||
I'm writing this game now because I'm learning all the things I wished I could know when I was a teenager and playing all the amazing GS games. Games like Rastan, Task Force, Alien Mind, The Immortal, and Sword of Sodan that did things that people said the GS shouldn't be capable of. I was never able to acquire the knowledge of how these things were done back then, but thanks to an amazing modern retro community, I can! In that spirit, thanks to:
|
||||
|
||||
- John Brooks, who has forgotten more about the GS than I will ever know.
|
||||
- Rebecca Heineman, who wrote every good game on the platform that you probably played except the ones John wrote
|
||||
- Jeremy Rand, who is inspiring to me with his prolific retro programming endeavours and humble spirit. Not to mention I learned a lot from reading his code for BuGS.
|
||||
- Brutal Deluxe, who have made so many great GS tools, including [Mr. Sprite](http://www.brutaldeluxe.fr/products/crossdevtools/mrsprite/index.html) and Cadius, upon which this game depends. I doubt you could find anyone more consistently devoted to the platform than these guys. Mr. Sprite's Tech Page is probably the greatest single treatise ever written on how to do fast Apple IIgs graphics.
|
||||
- Dagen Brock, for tirelessly maintaining the last remaining (as of this writing) good GS emulator, GSPlus. Without good emulators, retro-development dies, so thank you for fighting the good fight, Dagen. Emulating the GS is a thankless job for a platform almost nobody cares about.
|
||||
- All of the KansasFest and Apple II community on Slack and elsewhere
|
||||
|
||||
|
||||
### Sound Credits:
|
||||
|
||||
- Cat noise compilation, by Counter-gamer. Used with permission under CC3.0 license. [https://freesound.org/s/213889/](url)
|
||||
- Cat Howl, by InspectorJ. Used with permission under CC4.0 license. [https://freesound.org/s/415209/](url)
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
@ -0,0 +1,2 @@
|
|||
$0000 CatHowl 8192 bytes 11264 Hz
|
||||
$2000 Meow1 8192 bytes 5513 Hz
|
Binary file not shown.
|
@ -14,6 +14,12 @@ SHADOWVRAMBANK = $010000
|
|||
PRODOS = $bf00 ; MLI entry point
|
||||
PRODOSRETURN = $300 ; Indirect jump to get back to ProDOS from any bank
|
||||
|
||||
ENSONIQ_CONTROL = $e1c03c ; Ensoniq-related registers/locations
|
||||
ENSONIQ_DATA = $e1c03d
|
||||
ENSONIQ_ADDRL = $e1c03e
|
||||
ENSONIQ_ADDRH = $e1c03f
|
||||
SYSTEM_VOLUME = $e100ca
|
||||
|
||||
; Zero page locations we use (unused by Monitor, Applesoft, or ProDOS)
|
||||
PARAM0 = $06
|
||||
PARAM1 = $07
|
||||
|
|
|
@ -37,6 +37,9 @@ beginGameplay:
|
|||
sta SpriteBankBank00+3 ; Tell compiled sprites what bank they are in
|
||||
BITS16
|
||||
|
||||
; Set up audio
|
||||
jsr initSoundSystem
|
||||
|
||||
; Erase the screen
|
||||
ldx #$0000
|
||||
ldy #200
|
||||
|
|
1
gscats.s
1
gscats.s
|
@ -37,6 +37,7 @@ quitGame:
|
|||
|
||||
.include "random.s"
|
||||
.include "graphics.s"
|
||||
.include "sound.s"
|
||||
.include "font.s"
|
||||
.include "smallNumbers.s"
|
||||
.include "animation.s"
|
||||
|
|
36
loader.s
36
loader.s
|
@ -138,6 +138,33 @@ loadData:
|
|||
ldy #0
|
||||
jsr copyBytes
|
||||
|
||||
EMULATION
|
||||
|
||||
; Open the sound file
|
||||
jsr PRODOS
|
||||
.byte $c8
|
||||
.addr fileOpenSound
|
||||
bne ioError
|
||||
|
||||
; Load the sound data into bank 0
|
||||
jsr PRODOS
|
||||
.byte $ca
|
||||
.addr fileRead
|
||||
bne ioError
|
||||
|
||||
; Close the file
|
||||
jsr PRODOS
|
||||
.byte $cc
|
||||
.addr fileClose
|
||||
|
||||
NATIVE
|
||||
|
||||
; Copy sound data into bank 4
|
||||
ldx fileReadLen
|
||||
lda #4
|
||||
ldy #0
|
||||
jsr copyBytes
|
||||
|
||||
; Set up a long jump into bank 2, and
|
||||
; a way for game code to get back here to exit
|
||||
; properly to ProDOS 8
|
||||
|
@ -259,9 +286,18 @@ fileOpenSprites:
|
|||
.byte 0 ; Result (file handle)
|
||||
.byte 0 ; Padding
|
||||
|
||||
fileOpenSound:
|
||||
.byte 3
|
||||
.addr soundPath
|
||||
.addr $9200 ; 1k below BASIC.SYSTEM
|
||||
.byte 0 ; Result (file handle)
|
||||
.byte 0 ; Padding
|
||||
|
||||
codePath:
|
||||
pstring "/GSAPP/CODEBANK"
|
||||
codePathE1:
|
||||
pstring "/GSAPP/CODEBANKE1"
|
||||
spritePath:
|
||||
pstring "/GSAPP/SPRITEBANK"
|
||||
soundPath:
|
||||
pstring "/GSAPP/SOUNDBANK"
|
||||
|
|
7
player.s
7
player.s
|
@ -335,6 +335,13 @@ unrenderPlayers:
|
|||
;
|
||||
renderHitAnimation:
|
||||
SAVE_AXY
|
||||
|
||||
; Play hit sound
|
||||
phy
|
||||
ldy #SOUND_HOWL
|
||||
jsr playSound
|
||||
ply
|
||||
|
||||
PLAYERPTR_Y
|
||||
|
||||
jsr unrenderPlayers
|
||||
|
|
|
@ -0,0 +1,312 @@
|
|||
;
|
||||
; sound
|
||||
; Code and data structures for playing sound effects
|
||||
;
|
||||
; Created by Quinn Dunki on 6/30/23
|
||||
;
|
||||
|
||||
|
||||
NUM_SOUNDS = 2
|
||||
|
||||
SOUND_HOWL=0
|
||||
SOUND_MEOW1=2
|
||||
|
||||
soundTable:
|
||||
; Sound Ram Address, Wave Size, Low Frequency
|
||||
.byte $00,WAVE_SIZE_8192,200 ; SOUND_HOWL
|
||||
.byte $20,WAVE_SIZE_8192,100 ; SOUND_MEOW1
|
||||
|
||||
|
||||
; Ensoniq Control Register bit patterns
|
||||
DOC_RAMACCESS = $40 ; or
|
||||
DOC_DOCACCESS = $bf ; and
|
||||
DOC_AUTOINC = $20 ; or
|
||||
DOC_NOINC = $df ; and
|
||||
|
||||
; Oscillator Control Register bit patterns
|
||||
OSC_MODE_FREE = $00
|
||||
OSC_MODE_ONESHOT = $02
|
||||
OSC_MODE_SYNC = $04
|
||||
OSC_MODE_SWAP = $06
|
||||
|
||||
OSC_CHANNEL_ALL = $70
|
||||
OSC_CHANNEL_RIGHT = $00
|
||||
OSC_CHANNEL_LEFT = $10
|
||||
|
||||
; Internal oscillator-related registers (additional per-oscillator registers per the big table on page 110 of Apple IIGS Hardware Reference Manual)
|
||||
OSC_REG_INTERRUPT = $e0
|
||||
OSC_REG_ENABLE = $e1
|
||||
OSC_REG_DIGITIZE = $e2
|
||||
|
||||
; Wave table page size bit patterns
|
||||
WAVE_SIZE_256 = $07
|
||||
WAVE_SIZE_512 = $0f
|
||||
WAVE_SIZE_1024 = $17
|
||||
WAVE_SIZE_2048 = $1f
|
||||
WAVE_SIZE_4096 = $27
|
||||
WAVE_SIZE_8192 = $2f
|
||||
WAVE_SIZE_16384 = $37
|
||||
WAVE_SIZE_32768 = $3f
|
||||
|
||||
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
; ENSONIQ_WAIT
|
||||
;
|
||||
; Polls the high bit of the Sound Control Register, which tells us when we're allowed
|
||||
; to talk to the DOC
|
||||
;
|
||||
.macro ENSONIQ_WAIT
|
||||
.local busyLoop
|
||||
BITS8A
|
||||
busyLoop:
|
||||
lda ENSONIQ_CONTROL
|
||||
bmi busyLoop
|
||||
BITS16
|
||||
.endmacro
|
||||
|
||||
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
; writeInternalRegister - Call in 8 BIT MODE ONLY (also why it's a macro)
|
||||
;
|
||||
; Writes to the internal registers of the Ensoniq
|
||||
;
|
||||
; A = Data to write (8 bits)
|
||||
; X = Register number to write to (8 bits)
|
||||
;
|
||||
; Trashes A
|
||||
;
|
||||
.macro writeInternalRegister
|
||||
pha
|
||||
txa
|
||||
sta ENSONIQ_ADDRL
|
||||
pla
|
||||
sta ENSONIQ_DATA
|
||||
.endmacro
|
||||
|
||||
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
; writeInternalRegisterPair - Call in 8 BIT MODE ONLY (also why it's a macro)
|
||||
;
|
||||
; Writes to the internal registers of the Ensoniq for a pair of oscillators
|
||||
;
|
||||
; A = Data to write (8 bits)
|
||||
; X = Register number to write to (8 bits). X+1 will also be written
|
||||
;
|
||||
; Trashes A
|
||||
;
|
||||
.macro writeInternalRegisterPair
|
||||
pha
|
||||
txa
|
||||
sta ENSONIQ_ADDRL
|
||||
pla
|
||||
sta ENSONIQ_DATA
|
||||
pha
|
||||
inx
|
||||
txa
|
||||
sta ENSONIQ_ADDRL
|
||||
pla
|
||||
sta ENSONIQ_DATA
|
||||
.endmacro
|
||||
|
||||
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
; initSoundSystem
|
||||
;
|
||||
; Trashes SCRATCHL
|
||||
;
|
||||
initSoundSystem:
|
||||
SAVE_AXY
|
||||
|
||||
ENSONIQ_WAIT
|
||||
|
||||
; Load sound file bank into Ensoniq RAM
|
||||
lda #$0000 ; Sound location in bank 4
|
||||
sta PARAML0
|
||||
ldx #$04
|
||||
ldy #11749
|
||||
jsr copyToSoundRAM
|
||||
|
||||
; Configure all our oscillators
|
||||
lda #0
|
||||
sta SCRATCHL
|
||||
|
||||
ldy #0
|
||||
|
||||
initSoundSystemLoop:
|
||||
BITS8A
|
||||
lda soundTable,y
|
||||
sta PARAM0
|
||||
iny
|
||||
lda soundTable,y
|
||||
sta PARAM1
|
||||
iny
|
||||
lda soundTable,y
|
||||
sta PARAM2
|
||||
iny
|
||||
BITS16
|
||||
|
||||
phy
|
||||
ldy SCRATCHL
|
||||
jsr configureOscillatorPair
|
||||
|
||||
iny
|
||||
iny
|
||||
cpy #NUM_SOUNDS*2
|
||||
beq initSoundSystemReady
|
||||
sty SCRATCHL
|
||||
ply
|
||||
bra initSoundSystemLoop
|
||||
|
||||
initSoundSystemReady:
|
||||
ply
|
||||
|
||||
; Enable oscillators (see page 108 of Apple IIGS Hardware Reference Manual)
|
||||
BITS8
|
||||
lda #(NUM_SOUNDS*2)<<1 ; Two oscillators per sound and leaving low bit untouched
|
||||
ldx #OSC_REG_ENABLE
|
||||
writeInternalRegister
|
||||
BITS16
|
||||
|
||||
RESTORE_AXY
|
||||
rts
|
||||
|
||||
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
; playSound
|
||||
;
|
||||
; Y = Oscillator to start (+1 also starts)
|
||||
;
|
||||
playSound:
|
||||
SAVE_AX
|
||||
|
||||
ENSONIQ_WAIT
|
||||
|
||||
BITS8
|
||||
|
||||
; Configure run mode for our oscillators
|
||||
lda #OSC_CHANNEL_RIGHT | OSC_MODE_ONESHOT
|
||||
ldx docRegisterTableControl,y
|
||||
writeInternalRegister
|
||||
|
||||
lda #OSC_CHANNEL_LEFT | OSC_MODE_ONESHOT
|
||||
ldx docRegisterTableControl+1,y
|
||||
writeInternalRegister
|
||||
|
||||
BITS16
|
||||
RESTORE_AX
|
||||
rts
|
||||
|
||||
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
; configureOscillatorPair
|
||||
;
|
||||
; Y = Oscillator number (+1 will also be configured)
|
||||
; PARAM0 = Wave table address (one byte)
|
||||
; PARAM1 = Wave table page size (must use WAVE_SIZE constants)
|
||||
; PARAM2 = Low frequency (high frequency is always 0)
|
||||
;
|
||||
configureOscillatorPair:
|
||||
SAVE_AXY
|
||||
ENSONIQ_WAIT
|
||||
BITS8
|
||||
|
||||
; Configure low frequency
|
||||
lda PARAM2
|
||||
ldx docRegisterTableLowFreq,y
|
||||
writeInternalRegisterPair
|
||||
|
||||
; Configure high frequency
|
||||
lda #0
|
||||
ldx docRegisterTableHighFreq,y
|
||||
writeInternalRegisterPair
|
||||
|
||||
; Configure volume
|
||||
lda #$ff ; This is relative to system volume, so set it to max
|
||||
ldx docRegisterTableVolume,y
|
||||
writeInternalRegisterPair
|
||||
|
||||
; Configure sound RAM pointer
|
||||
lda PARAM0
|
||||
ldx docRegisterTableWavePointer,y
|
||||
writeInternalRegisterPair
|
||||
|
||||
; Configure sound RAM size
|
||||
; Format of this register is tricky. See page 114 of Apple IIGS Hardware Reference Manual
|
||||
lda PARAM1
|
||||
ldx docRegisterTableWaveSize,y
|
||||
writeInternalRegisterPair
|
||||
|
||||
BITS16
|
||||
RESTORE_AXY
|
||||
rts
|
||||
|
||||
; DOC register locations for each oscillator
|
||||
docRegisterTableLowFreq:
|
||||
.byte $00,$01,$02,$03,$04,$05,$06,$07,$08,$09,$0a,$0b,$0c,$0d,$0e,$0f,$10,$11,$12,$13,$14,$15,$16,$17,$18,$19,$1a,$1b,$1c,$1d,$1e,$1f
|
||||
docRegisterTableHighFreq:
|
||||
.byte $20,$21,$22,$23,$24,$25,$26,$27,$28,$29,$2a,$2b,$2c,$2d,$2e,$2f,$30,$31,$32,$33,$34,$35,$36,$37,$38,$39,$3a,$3b,$3c,$3d,$3e,$3f
|
||||
docRegisterTableVolume:
|
||||
.byte $40,$41,$42,$43,$44,$45,$46,$47,$48,$49,$4a,$4b,$4c,$4d,$4e,$4f,$50,$51,$52,$53,$54,$55,$56,$57,$58,$59,$5a,$5b,$5c,$5d,$5e,$5f
|
||||
docRegisterTableData:
|
||||
.byte $60,$61,$62,$63,$64,$65,$66,$67,$68,$69,$6a,$6b,$6c,$6d,$6e,$6f,$70,$71,$72,$73,$74,$75,$76,$77,$78,$79,$7a,$7b,$7c,$7d,$7e,$7f
|
||||
docRegisterTableWavePointer:
|
||||
.byte $80,$81,$82,$83,$84,$85,$86,$87,$88,$89,$8a,$8b,$8c,$8d,$8e,$8f,$90,$91,$92,$93,$94,$95,$96,$97,$98,$99,$9a,$9b,$9c,$9d,$9e,$9f
|
||||
docRegisterTableControl:
|
||||
.byte $a0,$a1,$a2,$a3,$a4,$a5,$a6,$a7,$a8,$a9,$aa,$ab,$ac,$ad,$ae,$af,$b0,$b1,$b2,$b3,$b4,$b5,$b6,$b7,$b8,$b9,$ba,$bb,$bc,$bd,$be,$bf
|
||||
docRegisterTableWaveSize:
|
||||
.byte $c0,$c1,$c2,$c3,$c4,$c5,$c6,$c7,$c8,$c9,$ca,$cb,$cc,$cd,$ce,$cf,$d0,$d1,$d2,$d3,$d4,$d5,$d6,$d7,$d8,$d9,$da,$db,$dc,$dd,$de,$df
|
||||
|
||||
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
; copyToSoundRAM
|
||||
;
|
||||
; Copies data from main RAM to sound RAM
|
||||
;
|
||||
; PARAML0 = Pointer to sound data in main RAM
|
||||
; X = Bank number of sound data in main RAM
|
||||
; Y = Size of sound bank in bytes
|
||||
;
|
||||
; Trashes SCRATCHL
|
||||
;
|
||||
copyToSoundRAM:
|
||||
SAVE_AXY
|
||||
sty SCRATCHL
|
||||
|
||||
ENSONIQ_WAIT
|
||||
|
||||
lda #0
|
||||
BITS8
|
||||
stx copyToSoundRAMLoop+3 ; Self modifying code. Don't panic
|
||||
|
||||
; Enable sound RAM access and auto-increment mode
|
||||
lda ENSONIQ_CONTROL
|
||||
ora #DOC_RAMACCESS | DOC_AUTOINC
|
||||
sta ENSONIQ_CONTROL
|
||||
BITS16
|
||||
|
||||
; Prepare start address in sound RAM
|
||||
lda #$0000
|
||||
sta ENSONIQ_ADDRL
|
||||
|
||||
; Copy all the data
|
||||
lda #0
|
||||
BITS8A
|
||||
ldx #0
|
||||
|
||||
copyToSoundRAMLoop:
|
||||
lda $ff0000,x ; Note: 8 bit accumulator! DOC takes one byte at a time
|
||||
sta ENSONIQ_DATA ; Do not use indexed addressing here- see page 107 of Apple IIGS Hardware Reference Manual
|
||||
inx
|
||||
cpx SCRATCHL
|
||||
bne copyToSoundRAMLoop
|
||||
|
||||
; Enable DOC access and disable auto-increment mode
|
||||
; This is a nicer mode to leave the Ensoniq in for normal usage once loading is complete
|
||||
lda ENSONIQ_CONTROL
|
||||
and #DOC_DOCACCESS & DOC_NOINC
|
||||
sta ENSONIQ_CONTROL
|
||||
|
||||
BITS16
|
||||
RESTORE_AXY
|
||||
rts
|
||||
|
Loading…
Reference in New Issue