Skip to content

Commit 47dd350

Browse files
committed
Sound effects working and added throughout example. Filenames shortened.
1 parent 1e24d5b commit 47dd350

File tree

14 files changed

+442
-73
lines changed

14 files changed

+442
-73
lines changed

README.md

Lines changed: 23 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -125,25 +125,25 @@ If it finishes without errors, the game is built! Let's assume that zone 0 has 2
125125
* **SPRITES.BIN** - This is the binary version of **mygame_sprites.hex**, which contains the sprite frames for the game, as specified by the **sprites_hex** key. It will be loaded by the XCI program into VRAM (1:0000) prior to displaying the title screen.
126126
* **TTL.BM.BIN** - This is the background bitmap for the title screen, specified by the contents of **mygame_start.xci**, which will be explained later. It will be loaded into VRAM (0:0000) once the palette, tiles and sprites are all loaded. Unlike the background bitmaps of the game levels, this bitmap can take up the full screen (320x240). This will remain in VRAM and on screen until the player starts a new game or loads a saved game. It is never stored in base or banked RAM.
127127
* **TTL.MUS.BIN** - This is the music for the title screen, specified by the contents of **mygame_start.xci**. It will be loaded into bank 1 of banked RAM for only the duration of the start screen. Once the first game zone is loaded, it will not be in memory again.
128-
* **Z000L0.01.BIN** - This is the configuration data for level 0 of zone 0. This is the first level that will be loaded after starting a new game. It is defined by the contents of **mygame_zone0.xci**, as specified by the first instance of the **zone** key. It will be loaded into bank 1 of banked RAM whenever the game enters level 0 (as it does when starting a new game, but a saved game may have also left off in level 0).
129-
* **Z000L0.02.BIN** - This is the background bitmap for level 0 of zone 0, specified by the contents of **mygame_zone0.xci**, which will be explained later. It will be loaded into banks 2-5 of banked RAM whenever the game enters zone 0, and into VRAM when the game enters level 0. Because of the in-game screen layout, this bitmap will start 8 pixel9s from the top, and therefore starting at VRAM address 0:0500. From 0:0000 to 0:04FF will be zero-filled, as it lies behind the menu bar. From 0:7D00 to 0:95FF will be zero-filled, as it lies behind the text field/toolbar.
130-
* **Z000L0.06.BIN** - The music and sound effects for level 0 of zone 0. The length of the music and addresses for each sound effect are defined in the level configuration data. This file will be loaded into bank 6 when the game enters zone 0. They data will be played directly from banked RAM when the game enters level 0.
131-
* **Z000L1.07.BIN** - This is the configuration data for level 1 of zone 0. It will be loaded to bank 7 when the game enters zone 0.
132-
* **Z000L1.08.BIN** - This file contains the background bitmap for level 1 of zone 0. It will be loaded into banks 8-11 when the game enters zone 0, and into VRAM starting at 0:0500 when the game enters level 1.
133-
* **Z000L1.12.BIN** - The music and sound effects for level 1 of zone 0. It will be loaded to bank 12 when the game enters zone 0. It is also the last file to be loaded into banked RAM for zone 0, as it only contains two levels. When starting a new game, or loading a game that left off in zone 0, the rest of the files below will not be loaded from the file system at the beginning of game play.
134-
* **Z001L0.01.BIN, Z001L0.02.BIN, Z001L0.06.BIN** - All data for level 0 of zone 1. These will be loaded into banks 1-6 when the game enters zone 1.
135-
* **Z001L1.07.BIN, Z001L1.08.BIN, Z001L1.12.BIN** - All data for level 1 of zone 1. These will be loaded into banks 7-12 when the game enters zone 1.
136-
* **Z001L2.13.BIN, Z001L2.14.BIN, Z001L2.18.BIN** - All data for level 2 of zone 1. These will be loaded into banks 13-18 when the game enters zone 1. They are the last files to be loaded into banked RAM for zone 1.
137-
* **Z002L0.01.BIN, Z002L0.02.BIN, Z002L0.06.BIN** - Zone 2, level 0
138-
* **Z002L1.07.BIN, Z002L1.08.BIN, Z002L1.12.BIN** - Zone 2, level 1
139-
* **Z002L2.13.BIN, Z002L2.14.BIN, Z002L2.18.BIN** - Zone 2, level 2
140-
* **Z002L3.19.BIN, Z002L3.20.BIN, Z002L3.24.BIN** - Zone 2, level 3
141-
* **Z002L4.25.BIN, Z002L4.26.BIN, Z002L4.30.BIN** - Zone 2, level 4
142-
* **Z002L5.31.BIN, Z002L5.32.BIN, Z002L5.36.BIN** - Zone 2, level 5
143-
* **Z002L6.37.BIN, Z002L6.38.BIN, Z002L6.42.BIN** - Zone 2, level 6
144-
* **Z002L7.43.BIN, Z002L7.44.BIN, Z002L7.48.BIN** - Zone 2, level 7
145-
* **Z002L8.49.BIN, Z002L8.50.BIN, Z002L8.54.BIN** - Zone 2, level 8
146-
* **Z002L9.55.BIN, Z002L9.56.BIN, Z002L9.60.BIN** - Zone 2, level 9. These are loaded into banks 55-60, the highest RAM banks that can be populated by an XCI game, when the game enters zone 2.
128+
* **000L0.01.BIN** - This is the configuration data for level 0 of zone 0. This is the first level that will be loaded after starting a new game. It is defined by the contents of **mygame_zone0.xci**, as specified by the first instance of the **zone** key. It will be loaded into bank 1 of banked RAM whenever the game enters level 0 (as it does when starting a new game, but a saved game may have also left off in level 0).
129+
* **000L0.02.BIN** - This is the background bitmap for level 0 of zone 0, specified by the contents of **mygame_zone0.xci**, which will be explained later. It will be loaded into banks 2-5 of banked RAM whenever the game enters zone 0, and into VRAM when the game enters level 0. Because of the in-game screen layout, this bitmap will start 8 pixel9s from the top, and therefore starting at VRAM address 0:0500. From 0:0000 to 0:04FF will be zero-filled, as it lies behind the menu bar. From 0:7D00 to 0:95FF will be zero-filled, as it lies behind the text field/toolbar.
130+
* **000L0.06.BIN** - The music and sound effects for level 0 of zone 0. The length of the music and addresses for each sound effect are defined in the level configuration data. This file will be loaded into bank 6 when the game enters zone 0. They data will be played directly from banked RAM when the game enters level 0.
131+
* **000L1.07.BIN** - This is the configuration data for level 1 of zone 0. It will be loaded to bank 7 when the game enters zone 0.
132+
* **000L1.08.BIN** - This file contains the background bitmap for level 1 of zone 0. It will be loaded into banks 8-11 when the game enters zone 0, and into VRAM starting at 0:0500 when the game enters level 1.
133+
* **000L1.12.BIN** - The music and sound effects for level 1 of zone 0. It will be loaded to bank 12 when the game enters zone 0. It is also the last file to be loaded into banked RAM for zone 0, as it only contains two levels. When starting a new game, or loading a game that left off in zone 0, the rest of the files below will not be loaded from the file system at the beginning of game play.
134+
* **001L0.01.BIN, 001L0.02.BIN, 001L0.06.BIN** - All data for level 0 of zone 1. These will be loaded into banks 1-6 when the game enters zone 1.
135+
* **001L1.07.BIN, 001L1.08.BIN, 001L1.12.BIN** - All data for level 1 of zone 1. These will be loaded into banks 7-12 when the game enters zone 1.
136+
* **001L2.13.BIN, 001L2.14.BIN, 001L2.18.BIN** - All data for level 2 of zone 1. These will be loaded into banks 13-18 when the game enters zone 1. They are the last files to be loaded into banked RAM for zone 1.
137+
* **002L0.01.BIN, 002L0.02.BIN, 002L0.06.BIN** - Zone 2, level 0
138+
* **002L1.07.BIN, 002L1.08.BIN, 002L1.12.BIN** - Zone 2, level 1
139+
* **002L2.13.BIN, 002L2.14.BIN, 002L2.18.BIN** - Zone 2, level 2
140+
* **002L3.19.BIN, 002L3.20.BIN, 002L3.24.BIN** - Zone 2, level 3
141+
* **002L4.25.BIN, 002L4.26.BIN, 002L4.30.BIN** - Zone 2, level 4
142+
* **002L5.31.BIN, 002L5.32.BIN, 002L5.36.BIN** - Zone 2, level 5
143+
* **002L6.37.BIN, 002L6.38.BIN, 002L6.42.BIN** - Zone 2, level 6
144+
* **002L7.43.BIN, 002L7.44.BIN, 002L7.48.BIN** - Zone 2, level 7
145+
* **002L8.49.BIN, 002L8.50.BIN, 002L8.54.BIN** - Zone 2, level 8
146+
* **002L9.55.BIN, 002L9.56.BIN, 002L9.60.BIN** - Zone 2, level 9. These are loaded into banks 55-60, the highest RAM banks that can be populated by an XCI game, when the game enters zone 2.
147147

148148
Wow, that's a lot of files! But most of them are 32kB or smaller. Each zone would easily fit on a single double-density 3.5" floppy, to put it in perspective. In this case, the whole game maxes out at 870kB (and that's assuming very complicated title screen and levels, and all available sprite frames and tiles defined), which would fit on a single high-density floppy, 2 double-density 3.5" floppies, or 3 double-density 5.25" floppies. The biggest XCI game possible would be 125MB, or 87 high-density 3.5" floppies. A CD-ROM could hold at least 5 XCI games. A 2GB SD Card could hold at least 16. Of course, it is highly unlikely that even the most prolific storyteller could come up with 2560 levels for a single game, so most games should clock in at around 5MB, which means that an X16 user could play hundreds of XCI games without changing their SD card. Because of filename conflicts, each game would need to be in a separate directory.
149149

@@ -740,8 +740,8 @@ Technically, levels don't have any specifically required keys. Not even a bitmap
740740

741741
##### Level File: Keys
742742

743-
* **bitmap** - Filename of the level background bitmap, which should be an indexed 16-color 320x200 raw image file. It should have a raw 24-bit palette file that has the same filename appended with ```.pal```. If that file is not available, the bitmap will use the default palette, offset 0. It will be converted to X16 format and stored across 4 banks of banked RAM when that level's zone is loaded. The starting bank is based on the level number. Using N for the level number, it will be stored in banks 6N+2 through 6N+5. So, that would be banks 2-5 for level 0 (loaded from **Z000L0.02.BIN** for zone 0, for example), banks 8-11 for level 1 and so on up to banks 56-59 for level 9. The palette for this bitmap will be written to palette offset N+1 (e.g. level 0 = palette offset 1) when the level's zone is loaded.
744-
* **music** - Filename of the level music VGM file. It is converted into a more X16-friendly format and stored in bank that it shares with sound effects in banked RAM. Using N for the level number, that bank number will be 6N+6. So, level 0 of zone 0 music and sound effects would be loaded from **Z000L0.06.BIN** and stored in bank 6.
743+
* **bitmap** - Filename of the level background bitmap, which should be an indexed 16-color 320x200 raw image file. It should have a raw 24-bit palette file that has the same filename appended with ```.pal```. If that file is not available, the bitmap will use the default palette, offset 0. It will be converted to X16 format and stored across 4 banks of banked RAM when that level's zone is loaded. The starting bank is based on the level number. Using N for the level number, it will be stored in banks 6N+2 through 6N+5. So, that would be banks 2-5 for level 0 (loaded from **000L0.02.BIN** for zone 0, for example), banks 8-11 for level 1 and so on up to banks 56-59 for level 9. The palette for this bitmap will be written to palette offset N+1 (e.g. level 0 = palette offset 1) when the level's zone is loaded.
744+
* **music** - Filename of the level music VGM file. It is converted into a more X16-friendly format and stored in bank that it shares with sound effects in banked RAM. Using N for the level number, that bank number will be 6N+6. So, level 0 of zone 0 music and sound effects would be loaded from **000L0.06.BIN** and stored in bank 6.
745745
* **sound** - Defines a sound effect. The first value is the identifier that will be used by the **play** key, and the second is the filename of the 4578 Hz signed 8-bit raw PCM file to play. As the music and sound effects are in the same bank for each level, the total number of sound effects used in each level must not exceed 8 kB when added to the size of the music file and a few extra bytes for a header. The header size will be 3 + 2(N+1) bytes where N is the number of sound files specified. In theory, up to 127 sound effects could be added to a level, but with only 8 kB available in total, even without music there would be room for only 1.79 seconds of sound effects.
746746
* **init** - This key is placed at the beginning of the level initialization sequence. It has no values. It will always be the first sequence run when the level is loaded. It must appear before any other sequences.
747747
* **first** - This key is placed at the beginning of the sequence that is run after initialization the very first time the level is loaded. It has no values. This is good for exposition, explaining what the level is supposed to be. This sequence will not be run when the level is re-visited. Must appear after the **init** sequence (if defined) and before any others.
@@ -982,7 +982,7 @@ Ok, so there's a lot to unpack here. This is more typical of how most game level
982982
| *Zone 0: Level 1 Background* |
983983

984984

985-
First are the bitmap and music source files, which is no different that the last level or the title screen. In fact, you can see that we are simply recycling the music that was used for the last level, called **zone0.vgm** because it's the music for all of zone 0.
985+
First are the bitmap and music source files, which is no different that the last level or the title screen. In fact, you can see that we are simply recycling the music that was used for the last level, called **zone0.vgm** because it's the music for all of zone 0. This level also has a sound effect, as specified by the **sound** key. The identifier for the sound is ```coffee``` and it comes from ```coffee.raw```, which is a 4578 Hz raw 8-bit PCM file. As it is only 3329 bytes (0.727 seconds) and the converted VGM music amounts to less than 2 kB, there is plenty of room for both in the music bank.
986986

987987
The **init** sequence places a coffee maker on the counter between the refrigerator and the stove, using the tiles that make it appear empty. Then, a frame sequence is defined for sprite 2, which will be some animated steam. With no **sprite** keys yet, the sprite won't be shown at the beginning.
988988

@@ -1005,7 +1005,7 @@ In other words, we know the cup is empty, so we nudge the player to fill it. Oth
10051005

10061006
![making coffee](example/coffee.gif)
10071007

1008-
Stepping back a bit, if ```holding_carafe``` is still true, that means the player is ready to pour the coffee, but hasn't done so yet. So, we don't need to check for ```coffee_poured``` in this sub-sub-sequence because it must still be false. Instead, we go right ahead and pour the coffee into the cup. This means swapping the empyt carfe tiles back in, then setting ```holding_carafe``` to false and ```coffee_poured``` to true. Also, the steam is instantly moved from above the coffee maker to above the cup. This is done with a **sprite** specifying the news position, and a fresh **sprite_move** to keep the steam going another 30 seconds. This will effectively cancel the previous **sprite_move**. Now the game state is ready for the cup to be "used" again to add it to the inventory, as described above.
1008+
Stepping back a bit, if ```holding_carafe``` is still true, that means the player is ready to pour the coffee, but hasn't done so yet. So, we don't need to check for ```coffee_poured``` in this sub-sub-sequence because it must still be false. Instead, we go right ahead and pour the coffee into the cup. This means playing the ```coffee``` sound effect, waiting for it to complete and then swapping the empty carafe tiles back in, then setting ```holding_carafe``` to false and ```coffee_poured``` to true. Also, the steam is instantly moved from above the coffee maker to above the cup. This is done with a **sprite** specifying the news position, and a fresh **sprite_move** to keep the steam going another 30 seconds. This will effectively cancel the previous **sprite_move**. Now the game state is ready for the cup to be "used" again to add it to the inventory, as described above.
10091009

10101010
The other trigger for the coffee cup is for the ```look``` tool, which gives a different message based on the states, guiding the player toward what their next step should be. If ```cup_taken``` is true, then the trigger will do nothing, as the cup should not be visible in the level.
10111011

engine/globals.asm

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -142,6 +142,7 @@ START_TEXT_Y = 26
142142

143143
; --------- Global Variables ---------
144144
vsync_trig: .byte 0
145+
aflow_trig: .byte 0
145146
frame_num: .byte 0
146147
def_cursor: .word 0
147148
num_zones: .byte 0

engine/irq.asm

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,9 +26,15 @@ handle_irq:
2626
sta vsync_trig
2727
; clear vera irq flag
2828
sta VERA_isr
29-
3029
@done_vsync:
3130

31+
; check for AFLOW
32+
lda VERA_isr
33+
and #$08
34+
beq @done_aflow
35+
sta aflow_trig
36+
@done_aflow:
37+
3238
; TODO check other IRQs
3339

3440
jmp (def_irq)

engine/music.asm

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,7 @@ disable_music:
6262
rts
6363

6464
start_music:
65+
jsr stop_music
6566
lda music_enabled
6667
beq @return
6768
lda music_bank

engine/sfx.asm

Lines changed: 67 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,11 @@
11
.ifndef SFX_INC
22
SFX_INC = 1
33

4-
__sfx_playing: .byte 0
5-
__sfx_end: .word 0
4+
__sfx_playing: .byte 0
5+
__sfx_end: .word 0
66

77
SOUND_0_PTR = RAM_WIN+3
8+
PCM_RATE = 12 ; 4578 Hz
89

910
enable_sfx:
1011
lda #1
@@ -13,9 +14,17 @@ enable_sfx:
1314

1415
disable_sfx:
1516
stz sfx_enabled
17+
stz VERA_audio_rate
1618
rts
1719

1820
play_sfx: ; A: sound index
21+
; check for sfx enabled
22+
ldx sfx_enabled
23+
beq @return
24+
; initialize PCM
25+
stz VERA_audio_rate
26+
ldx #$8F ; reset to 8-bit mono, max volume
27+
stx VERA_audio_ctrl
1928
; get address of sound start pointer
2029
asl
2130
tay
@@ -44,9 +53,13 @@ play_sfx: ; A: sound index
4453
lda (ZP_PTR_1),y
4554
adc #>RAM_WIN
4655
sta __sfx_end+1
47-
; start playing at next tick
56+
; start playing
4857
lda #1
4958
sta __sfx_playing
59+
jsr sfx_fill_fifo
60+
lda #PCM_RATE
61+
sta VERA_audio_rate
62+
@return:
5063
rts
5164

5265
sfx_tick:
@@ -55,11 +68,58 @@ sfx_tick:
5568
jmp @return
5669
@check_playing:
5770
lda __sfx_playing
58-
bne @play
71+
bne @check_fifo
72+
jmp @return
73+
@check_fifo:
74+
lda aflow_trig
75+
beq @return
76+
stz aflow_trig
77+
jsr sfx_fill_fifo
78+
@return:
79+
rts
80+
81+
sfx_fill_fifo:
82+
bra @start
83+
@remaining: .word 0
84+
@start:
85+
lda music_bank
86+
sta RAM_BANK
87+
stz @remaining
88+
lda #08
89+
sta @remaining+1 ; 2048 bytes remaining to write
90+
@data_loop:
91+
lda @remaining+1
92+
bne @more
93+
lda @remaining
94+
bne @more
5995
jmp @return
60-
@play:
61-
; TODO - play sound effects
62-
nop
96+
@more:
97+
lda SFX_PTR+1
98+
cmp __sfx_end+1
99+
bne @write_data
100+
lda SFX_PTR
101+
cmp __sfx_end
102+
bne @write_data
103+
stz __sfx_playing
104+
bra @return
105+
@write_data:
106+
lda (SFX_PTR)
107+
sta VERA_audio_data
108+
lda SFX_PTR
109+
clc
110+
adc #1
111+
sta SFX_PTR
112+
lda SFX_PTR+1
113+
adc #0
114+
sta SFX_PTR+1
115+
lda @remaining
116+
sec
117+
sbc #1
118+
sta @remaining
119+
lda @remaining+1
120+
sbc #0
121+
sta @remaining+1
122+
bra @data_loop
63123
@return:
64124
rts
65125

engine/zone.asm

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ ZONE_INC = 1
88
.include "bin2dec.asm"
99
.include "level.asm"
1010

11-
__zone_filename: .asciiz "Z000.L0.00.BIN"
11+
__zone_filename: .asciiz "000L0.00.BIN"
1212
__zone_bank: .byte 0
1313
ZONE_FN_LENGTH = __zone_bank - __zone_filename - 1
1414

@@ -73,9 +73,9 @@ load_zone:
7373
ldx #DISK_DEVICE
7474
ldy #0
7575
jsr SETLFS ; SetFileParams(LogNum=1,DevNum=DISK_DEVICE,SA=0)
76-
lda #<(__zone_filename+1) ; overwrite zone number in filename
76+
lda #<(__zone_filename) ; overwrite zone number in filename
7777
sta ZP_PTR_2
78-
lda #>(__zone_filename+1)
78+
lda #>(__zone_filename)
7979
sta ZP_PTR_2+1
8080
lda zone
8181
jsr byte2ascii
@@ -90,7 +90,7 @@ load_zone:
9090
jsr byte2ascii
9191
plx
9292
lda __zone_num_string+2
93-
sta __zone_filename+6
93+
sta __zone_filename+4
9494
ldy #6
9595
phx
9696
jsr byte_mult
@@ -150,9 +150,9 @@ __zone_load_file:
150150
lda __zone_bank
151151
jsr byte2ascii
152152
lda __zone_num_string+1
153-
sta __zone_filename+8
153+
sta __zone_filename+6
154154
lda __zone_num_string+2
155-
sta __zone_filename+9
155+
sta __zone_filename+7
156156
lda #ZONE_FN_LENGTH
157157
ldx #<__zone_filename
158158
ldy #>__zone_filename

0 commit comments

Comments
 (0)