diff options
author | Juan J. Martinez <jjm@usebox.net> | 2020-12-30 19:07:31 +0000 |
---|---|---|
committer | Juan J. Martinez <jjm@usebox.net> | 2020-12-30 19:23:41 +0000 |
commit | 2682bc5d1d864341aaeb42a449db73c3ecd16d70 (patch) | |
tree | 9116764364b4ee0ce7f6037305077807b57776de /game | |
download | ubox-msx-lib-ca9b663c147340e92804979a96eee4113ab0b27f.tar.gz ubox-msx-lib-ca9b663c147340e92804979a96eee4113ab0b27f.zip |
Initial import1.0
Diffstat (limited to 'game')
-rw-r--r-- | game/Makefile | 12 | ||||
-rw-r--r-- | game/README.md | 37 | ||||
-rw-r--r-- | game/data/Makefile | 21 | ||||
-rw-r--r-- | game/data/effects.aks | bin | 0 -> 1614 bytes | |||
-rw-r--r-- | game/data/enemy.png | bin | 0 -> 5448 bytes | |||
-rw-r--r-- | game/data/map.json | 159 | ||||
-rw-r--r-- | game/data/map_conf.json | 19 | ||||
-rw-r--r-- | game/data/player.png | bin | 0 -> 5447 bytes | |||
-rw-r--r-- | game/data/song.aks | bin | 0 -> 2019 bytes | |||
-rw-r--r-- | game/data/tiles.png | bin | 0 -> 6932 bytes | |||
-rw-r--r-- | game/src/Makefile | 48 | ||||
-rw-r--r-- | game/src/akm.z80 | 15 | ||||
-rw-r--r-- | game/src/aux.c | 27 | ||||
-rw-r--r-- | game/src/aux.h | 13 | ||||
-rw-r--r-- | game/src/crt0.z80 | 82 | ||||
-rw-r--r-- | game/src/data.c | 9 | ||||
-rw-r--r-- | game/src/effects.asm | 249 | ||||
-rw-r--r-- | game/src/effects_playerconfig.asm | 14 | ||||
-rw-r--r-- | game/src/game.c | 437 | ||||
-rw-r--r-- | game/src/game.h | 130 | ||||
-rw-r--r-- | game/src/main.c | 143 | ||||
-rw-r--r-- | game/src/main.h | 50 | ||||
-rw-r--r-- | game/src/song.asm | 650 | ||||
-rw-r--r-- | game/src/song_playerconfig.asm | 17 |
24 files changed, 2132 insertions, 0 deletions
diff --git a/game/Makefile b/game/Makefile new file mode 100644 index 0000000..da7d699 --- /dev/null +++ b/game/Makefile @@ -0,0 +1,12 @@ +all: + mkdir -p ./generated ./bin ./build + make -C data + cd src && rm -f Makefile.deps && touch Makefile.deps && find . -name "*.c" | xargs -n1 sdcc -I../generated -I../../include -MM | sed -r 's/([^:]+):/..\/build\/\1:/' >> Makefile.deps + make -C src + +.PHONY: all clean +clean: + rm -rf ./generated ./bin ./build + make -C src clean + make -C data clean + diff --git a/game/README.md b/game/README.md new file mode 100644 index 0000000..36437f2 --- /dev/null +++ b/game/README.md @@ -0,0 +1,37 @@ +# GREEN + +This is a example game to demo and test functionality of ubox MSX lib. + +It has only one screen is not too exciting! + +In the menu press fire on any joystick or space to play with cursors. + +Use space to activate the elevators and ESC to exit the game. + +This game is meant to be a demo, and because of that, it is simple and not +specially optimised; but you can see that it moves the player and 7 enemies +just fine and **it is a good example on how to write a game in C for the MSX**. + + GREEN, a demo for ubox MSX lib + Copyright (C) 2020 by Juan J. Martinez <jjm@usebox.net> + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + THE SOFTWARE. + +The graphics, music and sound are CC BY NC SA 4.0 (basically: no commercial). + diff --git a/game/data/Makefile b/game/data/Makefile new file mode 100644 index 0000000..f79ae33 --- /dev/null +++ b/game/data/Makefile @@ -0,0 +1,21 @@ +OUTPUT=../generated +GENERATED=$(OUTPUT)/tiles.h $(OUTPUT)/player.h $(OUTPUT)/enemy.h $(OUTPUT)/map.h + +all: $(GENERATED) + +$(OUTPUT)/tiles.h: tiles.png + ../../tools/png2tiles.py -i tiles $< > $@ + +$(OUTPUT)/player.h: player.png + ../../tools/png2sprites.py -i player_sprite $< > $@ + +$(OUTPUT)/enemy.h: enemy.png + ../../tools/png2sprites.py -i enemy_sprite $< > $@ + +$(OUTPUT)/map.h: map.json map_conf.json + ../../tools/map.py --max-ents 11 --room-height 21 map.json map > $@ + +.PHONY: all clean +clean: + rm -f $(OUTPUT)/* + diff --git a/game/data/effects.aks b/game/data/effects.aks Binary files differnew file mode 100644 index 0000000..9b21571 --- /dev/null +++ b/game/data/effects.aks diff --git a/game/data/enemy.png b/game/data/enemy.png Binary files differnew file mode 100644 index 0000000..728d9f5 --- /dev/null +++ b/game/data/enemy.png diff --git a/game/data/map.json b/game/data/map.json new file mode 100644 index 0000000..a5df88c --- /dev/null +++ b/game/data/map.json @@ -0,0 +1,159 @@ +{ "compressionlevel":-1, + "editorsettings": + { + "export": + { + "target":"." + } + }, + "height":21, + "infinite":false, + "layers":[ + { + "data":[6, 7, 6, 7, 6, 7, 6, 7, 6, 7, 6, 7, 6, 7, 6, 7, 6, 7, 6, 7, 6, 7, 6, 7, 6, 7, 6, 7, 6, 7, 6, 7, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 8, 9, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 13, 14, 13, 14, 13, 14, 13, 14, 13, 14, 13, 14, 193, 14, 8, 9, 13, 193, 13, 14, 13, 14, 13, 14, 13, 14, 13, 14, 13, 14, 13, 14, 13, 14, 13, 14, 13, 14, 13, 14, 13, 14, 13, 14, 225, 14, 8, 9, 13, 225, 13, 14, 13, 14, 13, 14, 13, 14, 13, 14, 13, 14, 13, 14, 6, 7, 6, 7, 10, 11, 6, 7, 6, 7, 6, 7, 6, 7, 8, 9, 6, 7, 6, 7, 6, 7, 10, 11, 6, 7, 6, 7, 6, 7, 6, 7, 130, 130, 130, 130, 15, 16, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 15, 16, 130, 130, 130, 130, 130, 130, 130, 130, 13, 14, 13, 14, 15, 16, 13, 14, 13, 14, 13, 14, 13, 14, 13, 14, 13, 14, 13, 14, 13, 14, 15, 16, 13, 14, 13, 14, 13, 14, 13, 14, 13, 14, 13, 14, 15, 16, 13, 14, 13, 14, 13, 14, 13, 14, 13, 14, 13, 14, 13, 14, 13, 14, 15, 16, 13, 14, 13, 14, 13, 14, 13, 14, 6, 7, 6, 7, 10, 11, 6, 7, 6, 7, 10, 11, 6, 7, 6, 7, 6, 7, 6, 7, 6, 7, 10, 11, 6, 7, 6, 7, 6, 7, 6, 7, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 15, 16, 130, 130, 130, 130, 130, 130, 8, 9, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 13, 14, 13, 14, 13, 14, 13, 14, 13, 14, 15, 16, 13, 14, 13, 14, 193, 14, 8, 9, 13, 193, 13, 14, 13, 14, 13, 14, 13, 14, 13, 14, 13, 14, 13, 14, 13, 14, 13, 14, 13, 14, 15, 16, 13, 14, 13, 14, 225, 14, 8, 9, 13, 225, 13, 14, 13, 14, 13, 14, 13, 14, 13, 14, 6, 7, 6, 7, 6, 7, 6, 7, 6, 7, 10, 11, 6, 7, 6, 7, 6, 7, 8, 9, 6, 7, 6, 7, 6, 7, 10, 11, 6, 7, 6, 7, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 15, 16, 130, 130, 130, 130, 13, 14, 13, 14, 13, 14, 13, 14, 13, 14, 13, 14, 13, 14, 13, 14, 13, 14, 13, 14, 13, 14, 13, 14, 13, 14, 15, 16, 13, 14, 13, 14, 13, 14, 13, 14, 13, 14, 13, 14, 13, 14, 13, 14, 13, 14, 13, 14, 13, 14, 13, 14, 13, 14, 13, 14, 13, 14, 15, 16, 13, 14, 13, 14, 6, 7, 6, 7, 10, 11, 6, 7, 6, 7, 6, 7, 6, 7, 6, 7, 6, 7, 6, 7, 10, 11, 6, 7, 6, 7, 10, 11, 6, 7, 6, 7, 130, 130, 130, 130, 15, 16, 130, 130, 130, 130, 8, 9, 130, 130, 130, 130, 130, 130, 130, 130, 15, 16, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 13, 14, 13, 14, 15, 16, 13, 14, 193, 14, 8, 9, 13, 193, 13, 14, 13, 14, 13, 14, 15, 16, 13, 14, 13, 14, 13, 14, 13, 14, 193, 14, 13, 14, 13, 14, 15, 16, 13, 14, 225, 14, 8, 9, 13, 225, 13, 14, 13, 14, 13, 14, 15, 16, 13, 14, 13, 14, 13, 14, 13, 14, 225, 14, 6, 7, 6, 7, 10, 11, 6, 7, 6, 7, 8, 9, 6, 7, 6, 7, 6, 7, 6, 7, 10, 11, 6, 7, 6, 7, 6, 7, 6, 7, 6, 7], + "height":21, + "id":1, + "name":"Map", + "opacity":1, + "type":"tilelayer", + "visible":true, + "width":32, + "x":0, + "y":0 + }, + { + "draworder":"topdown", + "id":2, + "name":"Entities", + "objects":[ + { + "height":16, + "id":10, + "name":"player", + "rotation":0, + "type":"", + "visible":true, + "width":16, + "x":8, + "y":16 + }, + { + "height":16, + "id":11, + "name":"enemy", + "rotation":0, + "type":"", + "visible":true, + "width":16, + "x":168, + "y":16 + }, + { + "height":16, + "id":12, + "name":"enemy", + "rotation":0, + "type":"", + "visible":true, + "width":16, + "x":64, + "y":48 + }, + { + "height":16, + "id":13, + "name":"enemy", + "properties":[ + { + "name":"param", + "type":"int", + "value":1 + }], + "rotation":0, + "type":"", + "visible":true, + "width":16, + "x":232, + "y":48 + }, + { + "height":16, + "id":14, + "name":"enemy", + "rotation":0, + "type":"", + "visible":true, + "width":16, + "x":104, + "y":80 + }, + { + "height":16, + "id":15, + "name":"enemy", + "rotation":0, + "type":"", + "visible":true, + "width":16, + "x":32, + "y":112 + }, + { + "height":16, + "id":16, + "name":"enemy", + "rotation":0, + "type":"", + "visible":true, + "width":16, + "x":128, + "y":144 + }, + { + "height":16, + "id":18, + "name":"enemy", + "properties":[ + { + "name":"param", + "type":"int", + "value":1 + }], + "rotation":0, + "type":"", + "visible":true, + "width":16, + "x":144, + "y":48 + }], + "opacity":1, + "type":"objectgroup", + "visible":true, + "x":0, + "y":0 + }], + "nextlayerid":3, + "nextobjectid":19, + "orientation":"orthogonal", + "renderorder":"right-down", + "tiledversion":"1.3.1", + "tileheight":8, + "tilesets":[ + { + "columns":32, + "firstgid":1, + "image":"tiles.png", + "imageheight":64, + "imagewidth":256, + "margin":0, + "name":"default", + "spacing":0, + "tilecount":256, + "tileheight":8, + "tilewidth":8 + }], + "tilewidth":8, + "type":"map", + "version":1.2, + "width":32 +}
\ No newline at end of file diff --git a/game/data/map_conf.json b/game/data/map_conf.json new file mode 100644 index 0000000..79a7a29 --- /dev/null +++ b/game/data/map_conf.json @@ -0,0 +1,19 @@ +{ + "entities": [ + { + "bytes": 0, + "name": "unused", + "w": 1 + }, + { + "bytes": 0, + "name": "player", + "w": 1 + }, + { + "bytes": 0, + "name": "enemy", + "w": 1 + } + ] +} diff --git a/game/data/player.png b/game/data/player.png Binary files differnew file mode 100644 index 0000000..fe6b254 --- /dev/null +++ b/game/data/player.png diff --git a/game/data/song.aks b/game/data/song.aks Binary files differnew file mode 100644 index 0000000..59b94e1 --- /dev/null +++ b/game/data/song.aks diff --git a/game/data/tiles.png b/game/data/tiles.png Binary files differnew file mode 100644 index 0000000..82fbb6c --- /dev/null +++ b/game/data/tiles.png diff --git a/game/src/Makefile b/game/src/Makefile new file mode 100644 index 0000000..7fa9f2f --- /dev/null +++ b/game/src/Makefile @@ -0,0 +1,48 @@ +TARGET=game + +CODE=0x4000 +# leaves 199 bytes for AKM player buffer +DATA=0xc0de + +# HEX, will fill with 0 +ROM_MAX=8000 + +OUTPUT=../build +OBJS = $(patsubst %.c,$(OUTPUT)/%.rel,$(wildcard *.c)) $(OUTPUT)/akm.rel +LIBS = -lubox -lspman -lmplayer + +CC=sdcc +AS=sdasz80 +AR=sdcclib +CFLAGS=-mz80 --Werror -I../../include -I../generated --fsigned-char --std-sdcc99 --opt-code-speed +LDFLAGS=-L../../lib -L. --no-std-crt0 --fomit-frame-pointer + +all: $(OUTPUT)/$(TARGET).rom + @../../tools/chksize 8000 4000 $(OUTPUT)/$(TARGET).map + cp ../bin/$(TARGET).rom ../../bin + +openmsx: all + openmsx -carta $(OUTPUT)/$(TARGET).rom -machine msx1 + +$(OUTPUT)/%.rel: %.c + $(CC) $(CFLAGS) $(LDFLAGS) -c $< -o $@ + +$(OUTPUT)/%.rel: %.z80 + $(AS) -g -o $@ $< + +$(OUTPUT)/akm.rel: akm.z80 song.asm effects.asm + ../../bin/rasm akm.z80 -o $(OUTPUT)/akm -s -sl -sq + Disark --sourceProfile sdcc --symbolFile $(OUTPUT)/akm.sym --src16bitsValuesInHex --src8bitsValuesInHex --undocumentedOpcodesToBytes $(OUTPUT)/akm.bin $(OUTPUT)/akm_sdcc.asm + $(AS) -g -o $@ $(OUTPUT)/akm_sdcc.asm + +$(OUTPUT)/$(TARGET).rom: $(OBJS) $(OUTPUT)/crt0.rel ../../lib/*.lib + $(CC) $(CFLAGS) $(LDFLAGS) $(LIBS) --code-loc $(CODE) --data-loc $(DATA) $(OUTPUT)/crt0.rel $(OBJS) -o $(OUTPUT)/$(TARGET).ihx + ../../bin/hex2bin -e bin -p 00 -l $(ROM_MAX) $(OUTPUT)/$(TARGET).ihx + mv $(OUTPUT)/$(TARGET).bin ../bin/$(TARGET).rom + +clean: + rm -f $(OUTPUT)/* + +.PHONY: all clean + +include Makefile.deps diff --git a/game/src/akm.z80 b/game/src/akm.z80 new file mode 100644 index 0000000..97c8498 --- /dev/null +++ b/game/src/akm.z80 @@ -0,0 +1,15 @@ +; +; to build the custom AKM player with song + effects +; + +include "song_playerconfig.asm" +include "effects_playerconfig.asm" + +include "../../src/mplayer/akm/akm_ubox.asm" + +songDisarkGenerateExternalLabel: +include "song.asm" + +effectsDisarkGenerateExternalLabel: +include "effects.asm" + diff --git a/game/src/aux.c b/game/src/aux.c new file mode 100644 index 0000000..15fc2a4 --- /dev/null +++ b/game/src/aux.c @@ -0,0 +1,27 @@ +#include <stdint.h> + +#include "ubox.h" + +#include "aux.h" + +/** + * Put a zero terminated string on the screen using tiles. + * + * The font starts on the tileset on tile 128 and the fist char in our has + * ASCII value 31, so it is adjusted so we can use ASCII *uppercase* directly + * in our C code. + */ +void put_text(uint8_t x, uint8_t y, const uint8_t *text) +{ + while (*text) + ubox_put_tile(x++, y, *text++ + 128 - 31); +} + +/** + * Wait for `frames` frames. + */ +void wait_for(uint8_t frames) +{ + while (frames--) + ubox_wait(); +} diff --git a/game/src/aux.h b/game/src/aux.h new file mode 100644 index 0000000..bf62d1a --- /dev/null +++ b/game/src/aux.h @@ -0,0 +1,13 @@ +#ifndef _AUX_H +#define _AUX_H + +#include <stdint.h> + +/** + * Auxiliary functions. + */ + +void put_text(uint8_t x, uint8_t y, const uint8_t *text); +void wait_for(uint8_t frames); + +#endif // _AUX_H diff --git a/game/src/crt0.z80 b/game/src/crt0.z80 new file mode 100644 index 0000000..81763d0 --- /dev/null +++ b/game/src/crt0.z80 @@ -0,0 +1,82 @@ +.module crt0 +.globl _main + +.area _HOME +.area _CODE +.area _INITIALIZER +.area _GSINIT +.area _GSFINAL + +.area _DATA +.area _INITIALIZED +.area _BSEG +.area _BSS +.area _HEAP + +.area _CODE + +ENASLT = 0x0024 +RSLREG = 0x0138 +CLIKSW = 0xf3db + + ; ROM header + .str "AB" + .dw _main_init + .db 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 + +_main_init:: + + ; init the stack + di + ld sp, #0xf380 + ei + + ; setup memory + ; ref: https://www.msx.org/forum/msx-talk/development/memory-pages-again + + call RSLREG + rrca + rrca + and #3 + ld c, a + add a, #0xc1 + ld l, a + ld h, #0xfc + ld a, (hl) + and #0x80 + or c + ld c, a + inc l + inc l + inc l + inc l + ld a, (hl) + and #0x0c + or c + ld h, #0x80 + call ENASLT + + ; disable key click sound + xor a + ld (CLIKSW), a + + call gsinit + call _main + +halt0: + halt + jr halt0 + +.area _GSINIT +gsinit:: + ld bc, #l__INITIALIZER + ld a, b + or a, c + jr Z, gsinit_next + ld de, #s__INITIALIZED + ld hl, #s__INITIALIZER + ldir +gsinit_next: + +.area _GSFINAL + ret diff --git a/game/src/data.c b/game/src/data.c new file mode 100644 index 0000000..67bec4e --- /dev/null +++ b/game/src/data.c @@ -0,0 +1,9 @@ +/** + * Module storing the generated data. + */ + +#define LOCAL +#include "tiles.h" +#include "player.h" +#include "enemy.h" +#include "map.h" diff --git a/game/src/effects.asm b/game/src/effects.asm new file mode 100644 index 0000000..0ff8465 --- /dev/null +++ b/game/src/effects.asm @@ -0,0 +1,249 @@ +; Sound Effects for song Green, version 2.0, generated by Arkos Tracker 2.
+
+Green_SoundEffects
+Green_SoundEffectsDisarkGenerateExternalLabel
+
+; The sound effects, starting at 1.
+Green_SoundEffectsDisarkPointerRegionStart0
+ dw Green_SoundEffects_Sound1 ; Sound effect 1.
+ dw Green_SoundEffects_Sound2 ; Sound effect 2.
+ dw Green_SoundEffects_Sound3 ; Sound effect 3.
+ dw Green_SoundEffects_Sound4 ; Sound effect 4.
+ dw Green_SoundEffects_Sound5 ; Sound effect 5.
+Green_SoundEffectsDisarkPointerRegionEnd0
+
+Green_SoundEffectsDisarkByteRegionStart1
+; Sound effect 1.
+Green_SoundEffects_Sound1
+ db 0 ; Speed
+
+Green_SoundEffects_Sound1_Loop db 57 ; Soft only. Volume: 14.
+ dw 96 ; Software period.
+
+ db 57 ; Soft only. Volume: 14.
+ dw 96 ; Software period.
+
+ db 53 ; Soft only. Volume: 13.
+ dw 128 ; Software period.
+
+ db 53 ; Soft only. Volume: 13.
+ dw 128 ; Software period.
+
+ db 41 ; Soft only. Volume: 10.
+ dw 256 ; Software period.
+
+ db 41 ; Soft only. Volume: 10.
+ dw 256 ; Software period.
+
+ db 37 ; Soft only. Volume: 9.
+ dw 128 ; Software period.
+
+ db 37 ; Soft only. Volume: 9.
+ dw 128 ; Software period.
+
+ db 29 ; Soft only. Volume: 7.
+ dw 128 ; Software period.
+
+ db 29 ; Soft only. Volume: 7.
+ dw 128 ; Software period.
+
+ db 4 ; End of the sound effect.
+
+; Sound effect 2.
+Green_SoundEffects_Sound2
+ db 0 ; Speed
+
+ db 57 ; Soft only. Volume: 14.
+ dw 96 ; Software period.
+
+ db 57 ; Soft only. Volume: 14.
+ dw 96 ; Software period.
+
+ db 53 ; Soft only. Volume: 13.
+ dw 112 ; Software period.
+
+ db 53 ; Soft only. Volume: 13.
+ dw 112 ; Software period.
+
+ db 41 ; Soft only. Volume: 10.
+ dw 128 ; Software period.
+
+ db 41 ; Soft only. Volume: 10.
+ dw 128 ; Software period.
+
+ db 41 ; Soft only. Volume: 10.
+ dw 128 ; Software period.
+
+ db 41 ; Soft only. Volume: 10.
+ dw 128 ; Software period.
+
+ db 1 ; Soft only. Volume: 0.
+ dw 128 ; Software period.
+
+ db 1 ; Soft only. Volume: 0.
+ dw 128 ; Software period.
+
+ db 33 ; Soft only. Volume: 8.
+ dw 96 ; Software period.
+
+ db 33 ; Soft only. Volume: 8.
+ dw 96 ; Software period.
+
+Green_SoundEffects_Sound2_Loop db 1 ; Soft only. Volume: 0.
+ dw 96 ; Software period.
+
+ db 1 ; Soft only. Volume: 0.
+ dw 96 ; Software period.
+
+ db 25 ; Soft only. Volume: 6.
+ dw 128 ; Software period.
+
+ db 25 ; Soft only. Volume: 6.
+ dw 128 ; Software period.
+
+ db 4 ; End of the sound effect.
+
+; Sound effect 3.
+Green_SoundEffects_Sound3
+ db 0 ; Speed
+
+ db 177 ; Soft only. Volume: 12.
+ db 1 ; Noise: 1.
+ dw 128 ; Software period.
+
+ db 177 ; Soft only. Volume: 12.
+ db 1 ; Noise: 1.
+ dw 128 ; Software period.
+
+ db 177 ; Soft only. Volume: 12.
+ db 1 ; Noise: 1.
+ dw 128 ; Software period.
+
+ db 177 ; Soft only. Volume: 12.
+ db 1 ; Noise: 1.
+ dw 128 ; Software period.
+
+ db 49 ; Soft only. Volume: 12.
+ dw 128 ; Software period.
+
+ db 49 ; Soft only. Volume: 12.
+ dw 96 ; Software period.
+
+ db 49 ; Soft only. Volume: 12.
+ dw 96 ; Software period.
+
+ db 49 ; Soft only. Volume: 12.
+ dw 256 ; Software period.
+
+Green_SoundEffects_Sound3_Loop db 49 ; Soft only. Volume: 12.
+ dw 256 ; Software period.
+
+ db 4 ; End of the sound effect.
+
+; Sound effect 4.
+Green_SoundEffects_Sound4
+ db 0 ; Speed
+
+ db 185 ; Soft only. Volume: 14.
+ db 1 ; Noise: 1.
+ dw 256 ; Software period.
+
+ db 185 ; Soft only. Volume: 14.
+ db 1 ; Noise: 1.
+ dw 256 ; Software period.
+
+ db 185 ; Soft only. Volume: 14.
+ db 1 ; Noise: 1.
+ dw 512 ; Software period.
+
+ db 185 ; Soft only. Volume: 14.
+ db 1 ; Noise: 1.
+ dw 512 ; Software period.
+
+ db 53 ; Soft only. Volume: 13.
+ dw 640 ; Software period.
+
+ db 53 ; Soft only. Volume: 13.
+ dw 640 ; Software period.
+
+ db 45 ; Soft only. Volume: 11.
+ dw 608 ; Software period.
+
+ db 45 ; Soft only. Volume: 11.
+ dw 608 ; Software period.
+
+ db 41 ; Soft only. Volume: 10.
+ dw 768 ; Software period.
+
+ db 41 ; Soft only. Volume: 10.
+ dw 768 ; Software period.
+
+ db 33 ; Soft only. Volume: 8.
+ dw 1024 ; Software period.
+
+Green_SoundEffects_Sound4_Loop db 33 ; Soft only. Volume: 8.
+ dw 1024 ; Software period.
+
+ db 4 ; End of the sound effect.
+
+; Sound effect 5.
+Green_SoundEffects_Sound5
+ db 0 ; Speed
+
+ db 57 ; Soft only. Volume: 14.
+ dw 512 ; Software period.
+
+ db 57 ; Soft only. Volume: 14.
+ dw 512 ; Software period.
+
+ db 57 ; Soft only. Volume: 14.
+ dw 608 ; Software period.
+
+ db 57 ; Soft only. Volume: 14.
+ dw 608 ; Software period.
+
+ db 57 ; Soft only. Volume: 14.
+ dw 800 ; Software period.
+
+ db 57 ; Soft only. Volume: 14.
+ dw 800 ; Software period.
+
+ db 53 ; Soft only. Volume: 13.
+ dw 768 ; Software period.
+
+ db 53 ; Soft only. Volume: 13.
+ dw 1024 ; Software period.
+
+ db 45 ; Soft only. Volume: 11.
+ dw 1280 ; Software period.
+
+ db 45 ; Soft only. Volume: 11.
+ dw 1536 ; Software period.
+
+ db 41 ; Soft only. Volume: 10.
+ dw 2048 ; Software period.
+
+ db 41 ; Soft only. Volume: 10.
+ dw 2048 ; Software period.
+
+ db 33 ; Soft only. Volume: 8.
+ dw 2048 ; Software period.
+
+ db 33 ; Soft only. Volume: 8.
+ dw 2048 ; Software period.
+
+ db 33 ; Soft only. Volume: 8.
+ dw 2048 ; Software period.
+
+ db 33 ; Soft only. Volume: 8.
+ dw 2048 ; Software period.
+
+ db 25 ; Soft only. Volume: 6.
+ dw 2048 ; Software period.
+
+Green_SoundEffects_Sound5_Loop db 25 ; Soft only. Volume: 6.
+ dw 2048 ; Software period.
+
+ db 4 ; End of the sound effect.
+
+Green_SoundEffectsDisarkByteRegionEnd1
diff --git a/game/src/effects_playerconfig.asm b/game/src/effects_playerconfig.asm new file mode 100644 index 0000000..f9d189c --- /dev/null +++ b/game/src/effects_playerconfig.asm @@ -0,0 +1,14 @@ +; Configuration that can be included to Arkos Tracker 2 players.
+; It indicates what parts of code are useful to the song/sound effects, to save both memory and CPU.
+; The players may or may not take advantage of these flags, it is up to them.
+
+; You can either:
+; - Include this to the source that also includes the player (BEFORE the player is included) (recommended solution).
+; - Include this at the beginning of the player code.
+; - Copy/paste this directly in the player.
+; If you use one player but several songs, don't worry, these declarations will stack up.
+; If no configuration is used, the player will use default values (full code used).
+
+ PLY_CFG_SFX_ConfigurationIsPresent = 1
+ PLY_CFG_SFX_SoftOnly = 1
+ PLY_CFG_SFX_SoftOnly_Noise = 1
diff --git a/game/src/game.c b/game/src/game.c new file mode 100644 index 0000000..bc52b2a --- /dev/null +++ b/game/src/game.c @@ -0,0 +1,437 @@ +#include <stdint.h> +#include <string.h> + +#include "ubox.h" +#include "spman.h" +#include "mplayer.h" + +#include "aux.h" +#include "main.h" + +#define LOCAL +#include "game.h" + +// generated +#include "map.h" +#include "player.h" +#include "enemy.h" + +void init_map_entities() +{ + const uint8_t *m = cur_map; + uint8_t typ, last = 0; + uint16_t i; + + // init sprite and patterns + spman_init(); + + // this sets everything to 0, which is useful as + // entity ET_UNUSED is 0 + memset(entities, 0, sizeof(struct entity) * MAX_ENTITIES); + + // get to the beginning of the entities: + // map size + 3 bytes of header (the map size and the entities size) + m += (uint16_t)(m[0] | m[1] << 8) + 3; + + // the entity list ends with 255 + while (*m != 0xff) + { + // first byte is type + direction flag on MSB + // remove MSB + typ = m[0] & (~DIR_FLAG); + + entities[last].type = typ; + entities[last].x = m[1]; + entities[last].y = m[2]; + // in the map: param is 1 (int) to look left + entities[last].dir = m[0] & DIR_FLAG ? 1 : 0; + + switch (typ) + { + // can be only one; always first entity + // because our entities are sorted by type! + case ET_PLAYER: + // 3 frames x 2 sprites = 6 + entities[last].pat = spman_alloc_pat(PAT_PLAYER, player_sprite[0], 6, 0); + spman_alloc_pat(PAT_PLAYER_FLIP, player_sprite[0], 6, 1); + entities[last].update = update_player; + break; + + case ET_ENEMY: + // 3 frames + entities[last].pat = spman_alloc_pat(PAT_ENEMY, enemy_sprite[0], 3, 0); + spman_alloc_pat(PAT_ENEMY_FLIP, enemy_sprite[0], 3, 1); + entities[last].update = update_enemy; + break; + } + + // next entity + last++; + + // all our entities are 3 bytes + m += 3; + } + + // count how many batteries are in the map + batteries = 0; + for (i = 0; i < MAP_W * MAP_H; ++i) + if (cur_map_data[i] == BATTERY_TILE) + batteries++; + +} + +void draw_map() +{ + // draw the map! + // + // - is not compressed (which limits how many maps we can store) + // - our map is just the tile numbers + // + // so we do it in one call by coping our map to the backtround tile map + // addr in the VDP VRAM + ubox_wait_vsync(); + ubox_write_vm((uint8_t *)0x1800, MAP_W * MAP_H, cur_map_data); +} + +void draw_hud() +{ + uint8_t i; + + put_text(0, 21, "LIVES"); + + for (i = 0; i < MAX_LIVES; ++i) + if (i < lives) + // our hearts tile + ubox_put_tile(1 + i, 22, 193); + else + ubox_put_tile(1 + i, 22, WHITESPACE_TILE); +} + +// x and y in pixels +void erase_battery(uint8_t x, uint8_t y) +{ + uint8_t t; + int8_t mod; + + // find out the bg tile to use + + // border of the map + if ((x >> 3) == 0) + mod = 1; + else + mod = -1; + + switch (cur_map_data[mod + (x >> 3) + (y >> 3) * MAP_W]) + { + case 12: + t = 13; + break; + case 13: + t = 12; + break; + default: + // this is next to a wall + if (mod == 1) + t = 13; + else + t = 12; + break; + } + + // change the map data so we don't pick it up again + cur_map_data[(x >> 3) + (y >> 3) * MAP_W] = t; + + // erase on the screen + ubox_put_tile(x >> 3, y >> 3, t); + ubox_put_tile(x >> 3, (y >> 3) - 1, t); +} + +// x and y in pixels +uint8_t is_map_blocked(uint8_t x, uint8_t y) +{ + return cur_map_data[(x >> 3) + (y >> 3) * MAP_W] < LAST_SOLID_TILE + 1; +} + +// x and y in pixels +uint8_t is_map_battery(uint8_t x, uint8_t y) +{ + return cur_map_data[(x >> 3) + (y >> 3) * MAP_W] == BATTERY_TILE; +} + +// x and y in pixels; always check the bottom tile! +uint8_t is_map_elevator_down(uint8_t x, uint8_t y) +{ + uint8_t t = cur_map_data[(x >> 3) + (y >> 3) * MAP_W]; + + // first check the elevator platform comparing tiles + if (t != 9 && t != 10) + return 0; + + // then check the elevator tube comparing tiles + t = cur_map_data[(x >> 3) + ((y >> 3) - 1) * MAP_W]; + return (t != 14 && t != 15); +} + +// x and y in pixels; always check the bottom tile! +uint8_t is_map_elevator_up(uint8_t x, uint8_t y) +{ + uint8_t t = cur_map_data[(x >> 3) + (y >> 3) * MAP_W]; + + // first check the elevator platform comparing tiles + if (t != 9 && t != 10) + return 0; + + // then check the elevator tube comparing tiles + t = cur_map_data[(x >> 3) + ((y >> 3) - 1) * MAP_W]; + return (t == 14 || t == 15); +} + +void update_enemy() +{ + // check for the player; if alive and not invulnerable! + // we use small hit boxes + if (lives && !invuln + && entities[0].x + 6 < self->x + 10 && self->x + 6 < entities[0].x + 10 + && self->y == entities[0].y) + { + // change direction + self->dir ^= 1; + + // remove one life (is more like "hits") + lives--; + draw_hud(); + invuln = INVUL_TIME; + + if (!lives) + { + // different sound effects if is game over + mplayer_init(SONG, SONG_SILENCE); + mplayer_play_effect_p(EFX_DEAD, EFX_CHAN_NO, 0); + gameover_delay = GAMEOVER_DELAY; + } + else + mplayer_play_effect_p(EFX_HIT, EFX_CHAN_NO, 0); + } + + // left or right? + if (self->dir) + { + // change direction + if (self->x == 2 || is_map_blocked(self->x, self->y + 15)) + self->dir ^= 1; + else + self->x -= 1; + } + else + { + // change direction + if (self->x == 255 - 16 || is_map_blocked(self->x + 15, self->y + 15)) + self->dir ^= 1; + else + self->x += 1; + } + + // update the walking animation + if (self->delay++ == FRAME_WAIT) + { + self->delay = 0; + if (++self->frame == WALK_CYCLE) + self->frame = 0; + } + + // allocate the sprites + sp.x = self->x; + // y on the screen starts in 255 + sp.y = self->y - 1; + // find which pattern to show + sp.pattern = self->pat + (walk_frames[self->frame] + self->dir * 3) * 4; + // red + sp.attr = 9; + spman_alloc_sprite(&sp); +} + +void update_player() +{ + // to know if we need to update the walk animation + uint8_t moved = 0; + + // player is dead + if (!lives) + return; + + // decrease counter if set + if (invuln) + invuln--; + + if (control & UBOX_MSX_CTL_RIGHT) + { + self->dir = DIR_RIGHT; + moved = 1; + + // wrap horizontally + if (self->x == 255 - 16) + self->x = 0; + // check if not solid, using bottom right + else if (!is_map_blocked(self->x + 15, self->y + 15)) + self->x += 2; + } + + if (control & UBOX_MSX_CTL_LEFT) + { + self->dir = DIR_LEFT; + moved = 1; + + // wrap horizontally + if (self->x == 2) + self->x = (uint8_t)(255 - 16); + // check if not solid, using bottom left + else if (!is_map_blocked(self->x, self->y + 15)) + self->x -= 2; + } + + // are we touching a battery? + // use bottom center + if (is_map_battery(self->x + 8, self->y + 15)) + { + mplayer_play_effect_p(EFX_BATTERY, EFX_CHAN_NO, 0); + batteries--; + erase_battery(self->x + 8, self->y + 15); + } + + if (control & UBOX_MSX_CTL_FIRE1) + { + // use flags to prevent repeat: the player will + // have to release fire to use the elevator again + if (!self->flags) + { + self->flags = 1; + + // check elevator down; using bottom middle + if (is_map_elevator_down(self->x + 8, self->y + 16)) + { + mplayer_play_effect_p(EFX_ELEVATOR, EFX_CHAN_NO, 0); + self->y += 8 * 4; + } + // then elevator up; using bottom middle + else if (is_map_elevator_up(self->x + 8, self->y + 16)) + { + mplayer_play_effect_p(EFX_ELEVATOR, EFX_CHAN_NO, 0); + self->y -= 8 * 4; + } + } + } + else + { + if (self->flags) + self->flags = 0; + } + + // it moved, or at least pushed against a wall + if (moved) + { + // update the walking animation + if (self->delay++ == FRAME_WAIT) + { + self->delay = 0; + if (++self->frame == WALK_CYCLE) + self->frame = 0; + } + } + else + { + // just stand + if (self->frame) + { + self->frame = 0; + self->delay = 0; + } + } + + // if we are invulnerable, don't draw odd frames + // and we get a nice blinking effect + if (invuln & 1) + return; + + // allocate the player sprites; fixed so they never flicker + sp.x = self->x; + // y on the screen starts in 255 + sp.y = self->y - 1; + // find which pattern to show + sp.pattern = self->pat + (walk_frames[self->frame] + self->dir * 3) * 8; + // green + sp.attr = 12; + spman_alloc_fixed_sprite(&sp); + // second one is 4 patterns away (16x16 sprites) + sp.pattern += 4; + // white + sp.attr = 15; + spman_alloc_fixed_sprite(&sp); +} + +void run_game() +{ + // init some variables; look at game.h for description + lives = MAX_LIVES; + invuln = 0; + gameover_delay = 0; + + ubox_disable_screen(); + + ubox_fill_screen(WHITESPACE_TILE); + + // we only have one map, select it + cur_map = map[0]; + // copy map data into RAM, we will modify it + // map data starts on byte 3 (skip map data size and entities size) + memcpy(cur_map_data, cur_map + 3, MAP_W * MAP_H); + + // init entities before drawing + init_map_entities(); + draw_map(); + + draw_hud(); + + ubox_enable_screen(); + + mplayer_init(SONG, SONG_IN_GAME); + + // our game loop + while (1) + { + // exit the game + if (ubox_read_keys(7) == UBOX_MSX_KEY_ESC) + break; + + // game completed! + if (!batteries) + break; + + // we are in the gameover delay + if (gameover_delay) + { + // if finished, exit + if (--gameover_delay == 0) + break; + } + + // read the selected control + control = ubox_read_ctl(ctl); + + // update all the entities: + // - self is a pointer to THIS entity + // - because we don't create/destroy entities dynamically + // when we found one that is unused we are done + for (self = entities; self->type; self++) + self->update(); + + // ensure we wait to our desired update rate + ubox_wait(); + // update sprites on screen + spman_update(); + } + + // stop the in game music + mplayer_init(SONG, SONG_IN_GAME); + // hide all the sprites before going back to the menu + spman_hide_all_sprites(); +} diff --git a/game/src/game.h b/game/src/game.h new file mode 100644 index 0000000..9227987 --- /dev/null +++ b/game/src/game.h @@ -0,0 +1,130 @@ +#ifndef _GAME_H +#define _GAME_H + +#ifndef LOCAL +#define LOCAL extern +#else + +#define WALK_CYCLE 4 + +// walk animation frames, private +const uint8_t walk_frames[WALK_CYCLE] = { 0, 1, 0, 2 }; + +#endif + +/** + * Game implementation and helpers. + */ + +// map size in tiles +#define MAP_W 32 +#define MAP_H 21 + +// some useful tiles +#define LAST_SOLID_TILE 10 +#define BATTERY_TILE 224 + +#define MAX_LIVES 3 + +// player + other entities +#define MAX_ENTITIES 11 + +// MSB in our entity data +#define DIR_FLAG 128 + +// sprite direction +#define DIR_LEFT 1 +#define DIR_RIGHT 0 + +// how long we wait between animation frames +#define FRAME_WAIT 3 + +// how long the player is invulnerable after death +// time in frames +#define INVUL_TIME 64 + +// show some game frames before jumping to the game over +// screen; this helps the player to know what happened +#define GAMEOVER_DELAY 72 + +// types for our pattern groups +// used by spman +enum pattern_type +{ + PAT_PLAYER = 0, + PAT_PLAYER_FLIP, + PAT_ENEMY, + PAT_ENEMY_FLIP, +}; + +// entity types in the same order +// used in the map (see map_conf.json) +enum entity_type +{ + ET_UNUSED = 0, + ET_PLAYER, + ET_ENEMY, +}; + +// notes: +// +// - x, y are the logic position on the map +// - sp.x, sp.y are the position on screen +struct entity +{ + uint8_t type; + uint8_t x; + uint8_t y; + uint8_t dir; + uint8_t pat; + uint8_t flags; + uint8_t delay; + uint8_t frame; + void (*update)(); +}; + +void run_game(); + +void update_player(); +void update_enemy(); + +void draw_map(); +void draw_hud(); + +void erase_battery(uint8_t x, uint8_t y); + +uint8_t is_map_blocked(uint8_t x, uint8_t y); +uint8_t is_map_elevator_up(uint8_t x, uint8_t y); +uint8_t is_map_elevator_down(uint8_t x, uint8_t y); + +// our entities; the player is 0 +LOCAL struct entity entities[MAX_ENTITIES]; + +// used to read our control method +LOCAL uint8_t control; + +// current map; we don't use ROM because we will modify it +LOCAL const uint8_t *cur_map; +// current map tile map (map data, not entities) +LOCAL uint8_t cur_map_data[MAP_W * MAP_H]; + +// player lives +LOCAL uint8_t lives; +// invulnerability time after death +LOCAL uint8_t invuln; +// batteries left +LOCAL uint8_t batteries; +// show dome delay once the lives run out +LOCAL uint8_t gameover_delay; + +// used by all entities +LOCAL struct sprite_attr sp; + +// current entity +LOCAL struct entity *self; + +#ifdef LOCAL +#undef LOCAL +#endif + +#endif // _GAME_H diff --git a/game/src/main.c b/game/src/main.c new file mode 100644 index 0000000..1405356 --- /dev/null +++ b/game/src/main.c @@ -0,0 +1,143 @@ +#include <stdint.h> + +#include "ubox.h" +#include "mplayer.h" + +#include "aux.h" +#include "game.h" + +#define LOCAL +#include "main.h" + +// generated +#include "tiles.h" + +void draw_menu() +{ + uint8_t i; + + ubox_disable_screen(); + + ubox_fill_screen(WHITESPACE_TILE); + + // game logo; starts in tile 32 and it is 10 x 3 tiles + for (i = 0; i < 10; ++i) + { + ubox_put_tile(11 + i, 6, 32 + i); + ubox_put_tile(11 + i, 7, 64 + i); + ubox_put_tile(11 + i, 8, 96 + i); + } + + put_text(11, 11, "PRESS FIRE"); + + put_text(7, 2, "UBOX MSX LIB DEMO!"); + put_text(4, 16, "CODE, GRAPHICS AND SOUND"); + put_text(8, 17, "JUAN J. MARTINEZ"); + // 037 is ASCII 31 in octal, our Copyright sign + put_text(8, 21, "\0372020 USEBOX.NET"); + + ubox_enable_screen(); +} + +void draw_end_game() +{ + ubox_disable_screen(); + + ubox_fill_screen(WHITESPACE_TILE); + + put_text(3, 9, "WELL DONE!"); + put_text(3, 10, "YOU HAVE FINISHED THE DEMO."); + put_text(3, 12, "NOW GO AND MAKE GAMES :)"); + + put_text(3, 14, "(PRESS ESC)"); + + ubox_enable_screen(); + + // wait until ESC is pressed + while (1) + { + if (ubox_read_keys(7) == UBOX_MSX_KEY_ESC) + break; + + ubox_wait(); + } +} + +void draw_game_over() +{ + ubox_disable_screen(); + + ubox_fill_screen(WHITESPACE_TILE); + put_text(11, 10, "GAME OVER"); + + ubox_enable_screen(); + + // play game over music + mplayer_init(SONG, SONG_GAME_OVER); + + wait_for(128); +} + +void main() +{ + // PAL: 50/2 = 25 FPS + // NTSC: 60/2 = 30 FPS + ubox_init_isr(2); + + // set screen 2 + ubox_set_mode(2); + // all black + ubox_set_colors(1, 1, 1); + + // avoid showing garbage on the screen + // while setting up the tiles + ubox_disable_screen(); + + // upload our tileset + ubox_set_tiles(tiles); + // and the colour information + ubox_set_tiles_colors(tiles_colors); + + // clear the screen + ubox_fill_screen(WHITESPACE_TILE); + + ubox_enable_screen(); + + // reg 1: activate sprites, v-blank int on, 16x16 sprites + ubox_wvdp(1, 0xe2); + + // init the player + mplayer_init(SONG, SONG_SILENCE); + mplayer_init_effects(EFFECTS); + + // we don't need anything in our ISR + // other than the play function, so we + // use that! + ubox_set_user_isr(mplayer_play); + +redraw_menu: + draw_menu(); + + // whait until fire is pressed + // can be space (control will be cursors), or any fire button on a joystick + while (1) + { + ctl = ubox_select_ctl(); + if (ctl != UBOX_MSX_CTL_NONE) + { + mplayer_play_effect_p(EFX_START, EFX_CHAN_NO, 0); + wait_for(16); + + // play the game + run_game(); + + if (!lives) + draw_game_over(); + else if (!batteries) + draw_end_game(); + + goto redraw_menu; + } + ubox_wait(); + } +} diff --git a/game/src/main.h b/game/src/main.h new file mode 100644 index 0000000..f8d5d77 --- /dev/null +++ b/game/src/main.h @@ -0,0 +1,50 @@ +#ifndef _MAIN_H +#define _MAIN_H + +#include <stdint.h> + +#ifndef LOCAL +#define LOCAL extern +#endif + +#define WHITESPACE_TILE 129 + +// sub-songs matching our Arkos song +// configure the song to use MSX AY +enum songs +{ + SONG_SILENCE = 0, + SONG_IN_GAME, + SONG_GAME_OVER, +}; + +// we will use 0 and 1 for the music +#define EFX_CHAN_NO 2 + +// sound effects matching our Arkos efc song +// configure the song to use MSX AY +enum effects +{ + EFX_NONE = 0, + EFX_START, + EFX_BATTERY, + EFX_ELEVATOR, + EFX_HIT, + EFX_DEAD, +}; + +void draw_end_game(); +void draw_menu(); + +// store the selected control +LOCAL uint8_t ctl; + +// Arkos data +extern uint8_t SONG[]; +extern uint8_t EFFECTS[]; + +#ifdef LOCAL +#undef LOCAL +#endif + +#endif // _MAIN_H diff --git a/game/src/song.asm b/game/src/song.asm new file mode 100644 index 0000000..de3ca50 --- /dev/null +++ b/game/src/song.asm @@ -0,0 +1,650 @@ +; Green, Song part, encoded in the AKM (minimalist) format V0.
+
+
+Green_Start
+Green_StartDisarkGenerateExternalLabel
+
+Green_DisarkPointerRegionStart0
+ dw Green_InstrumentIndexes ; Index table for the Instruments.
+Green_DisarkForceNonReferenceDuring2_1
+ dw 0 ; Index table for the Arpeggios.
+Green_DisarkForceNonReferenceDuring2_2
+ dw 0 ; Index table for the Pitches.
+
+; The subsongs references.
+ dw Green_Subsong0
+ dw Green_Subsong1
+ dw Green_Subsong2
+Green_DisarkPointerRegionEnd0
+
+; The Instrument indexes.
+Green_InstrumentIndexes
+Green_DisarkPointerRegionStart3
+ dw Green_Instrument0
+ dw Green_Instrument1
+ dw Green_Instrument2
+ dw Green_Instrument3
+ dw Green_Instrument4
+Green_DisarkPointerRegionEnd3
+
+; The Instrument.
+Green_DisarkByteRegionStart4
+Green_Instrument0
+ db 255 ; Speed.
+
+Green_Instrument0Loop db 0 ; Volume: 0.
+
+ db 4 ; End the instrument.
+Green_DisarkPointerRegionStart5
+ dw Green_Instrument0Loop ; Loops.
+Green_DisarkPointerRegionEnd5
+
+Green_Instrument1
+ db 0 ; Speed.
+
+ db 173 ; Volume: 11.
+ db 232 ; Arpeggio: -12.
+
+ db 45 ; Volume: 11.
+
+ db 45 ; Volume: 11.
+
+ db 45 ; Volume: 11.
+
+ db 45 ; Volume: 11.
+
+ db 4 ; End the instrument.
+Green_DisarkPointerRegionStart6
+ dw Green_Instrument0Loop ; Loop to silence.
+Green_DisarkPointerRegionEnd6
+
+Green_Instrument2
+ db 0 ; Speed.
+
+ db 173 ; Volume: 11.
+ db 232 ; Arpeggio: -12.
+
+ db 45 ; Volume: 11.
+
+ db 173 ; Volume: 11.
+ db 232 ; Arpeggio: -12.
+
+ db 45 ; Volume: 11.
+
+ db 4 ; End the instrument.
+Green_DisarkPointerRegionStart7
+ dw Green_Instrument0Loop ; Loop to silence.
+Green_DisarkPointerRegionEnd7
+
+Green_Instrument3
+ db 0 ; Speed.
+
+ db 177 ; Volume: 12.
+ db 27 ; Arpeggio: 13.
+ db 9 ; Noise: 9.
+
+ db 173 ; Volume: 11.
+ db 18 ; Arpeggio: 9.
+
+ db 169 ; Volume: 10.
+ db 12 ; Arpeggio: 6.
+
+ db 165 ; Volume: 9.
+ db 9 ; Arpeggio: 4.
+ db 5 ; Noise: 5.
+
+ db 4 ; End the instrument.
+Green_DisarkPointerRegionStart8
+ dw Green_Instrument0Loop ; Loop to silence.
+Green_DisarkPointerRegionEnd8
+
+Green_Instrument4
+ db 0 ; Speed.
+
+ db 113 ; Volume: 12.
+ dw 2 ; Pitch: 2.
+
+ db 45 ; Volume: 11.
+
+ db 41 ; Volume: 10.
+
+ db 37 ; Volume: 9.
+
+ db 33 ; Volume: 8.
+
+ db 29 ; Volume: 7.
+
+ db 25 ; Volume: 6.
+
+ db 21 ; Volume: 5.
+
+ db 4 ; End the instrument.
+Green_DisarkPointerRegionStart9
+ dw Green_Instrument0Loop ; Loop to silence.
+Green_DisarkPointerRegionEnd9
+
+Green_DisarkByteRegionEnd4
+Green_ArpeggioIndexes
+Green_DisarkPointerRegionStart10
+Green_DisarkPointerRegionEnd10
+
+Green_DisarkByteRegionStart11
+Green_DisarkByteRegionEnd11
+
+Green_PitchIndexes
+Green_DisarkPointerRegionStart12
+Green_DisarkPointerRegionEnd12
+
+Green_DisarkByteRegionStart13
+Green_DisarkByteRegionEnd13
+
+; Green, Subsong 0.
+; ----------------------------------
+
+Green_Subsong0
+Green_Subsong0DisarkPointerRegionStart0
+ dw Green_Subsong0_NoteIndexes ; Index table for the notes.
+ dw Green_Subsong0_TrackIndexes ; Index table for the Tracks.
+Green_Subsong0DisarkPointerRegionEnd0
+
+Green_Subsong0DisarkByteRegionStart1
+ db 6 ; Initial speed.
+
+ db 2 ; Most used instrument.
+ db 4 ; Second most used instrument.
+
+ db 1 ; Most used wait.
+ db 3 ; Second most used wait.
+
+ db 0 ; Default start note in tracks.
+ db 0 ; Default start instrument in tracks.
+ db 0 ; Default start wait in tracks.
+
+ db 13 ; Are there effects? 12 if yes, 13 if not. Don't ask.
+Green_Subsong0DisarkByteRegionEnd1
+
+; The Linker.
+Green_Subsong0DisarkByteRegionStart2
+; Pattern 0
+Green_Subsong0_Loop
+ db 170 ; State byte.
+ db 63 ; New height.
+ db 128 ; New track (0) for channel 1, as a reference (index 0).
+ db 128 ; New track (0) for channel 2, as a reference (index 0).
+ db 128 ; New track (0) for channel 3, as a reference (index 0).
+
+ db 1 ; End of the Song.
+ db 0 ; Speed to 0, meaning "end of song".
+Green_Subsong0DisarkByteRegionEnd2
+Green_Subsong0DisarkPointerRegionStart3
+ dw Green_Subsong0_Loop
+
+Green_Subsong0DisarkPointerRegionEnd3
+; The indexes of the tracks.
+Green_Subsong0_TrackIndexes
+Green_Subsong0DisarkPointerRegionStart4
+ dw Green_Subsong0_Track0 ; Track 0, index 0.
+Green_Subsong0DisarkPointerRegionEnd4
+
+Green_Subsong0DisarkByteRegionStart5
+Green_Subsong0_Track0
+ db 205 ; New wait (127).
+ db 127 ; Escape wait value.
+
+Green_Subsong0DisarkByteRegionEnd5
+; The note indexes.
+Green_Subsong0_NoteIndexes
+Green_Subsong0DisarkByteRegionStart6
+Green_Subsong0DisarkByteRegionEnd6
+
+; Green, Subsong 1.
+; ----------------------------------
+
+Green_Subsong1
+Green_Subsong1DisarkPointerRegionStart0
+ dw Green_Subsong1_NoteIndexes ; Index table for the notes.
+ dw Green_Subsong1_TrackIndexes ; Index table for the Tracks.
+Green_Subsong1DisarkPointerRegionEnd0
+
+Green_Subsong1DisarkByteRegionStart1
+ db 6 ; Initial speed.
+
+ db 2 ; Most used instrument.
+ db 4 ; Second most used instrument.
+
+ db 1 ; Most used wait.
+ db 3 ; Second most used wait.
+
+ db 57 ; Default start note in tracks.
+ db 0 ; Default start instrument in tracks.
+ db 0 ; Default start wait in tracks.
+
+ db 13 ; Are there effects? 12 if yes, 13 if not. Don't ask.
+Green_Subsong1DisarkByteRegionEnd1
+
+; The Linker.
+Green_Subsong1DisarkByteRegionStart2
+; Pattern 0
+Green_Subsong1_Loop
+ db 170 ; State byte.
+ db 63 ; New height.
+ db ((Green_Subsong1_Track0 - ($ + 2)) & #ff00) / 256 ; New track (0) for channel 1, as an offset. Offset MSB, then LSB.
+ db ((Green_Subsong1_Track0 - ($ + 1)) & 255)
+ db ((Green_Subsong1_Track1 - ($ + 2)) & #ff00) / 256 ; New track (1) for channel 2, as an offset. Offset MSB, then LSB.
+ db ((Green_Subsong1_Track1 - ($ + 1)) & 255)
+ db 128 ; New track (2) for channel 3, as a reference (index 0).
+
+; Pattern 1
+ db 32 ; State byte.
+ db ((Green_Subsong1_Track3 - ($ + 2)) & #ff00) / 256 ; New track (3) for channel 2, as an offset. Offset MSB, then LSB.
+ db ((Green_Subsong1_Track3 - ($ + 1)) & 255)
+
+; Pattern 2
+ db 40 ; State byte.
+ db ((Green_Subsong1_Track4 - ($ + 2)) & #ff00) / 256 ; New track (4) for channel 1, as an offset. Offset MSB, then LSB.
+ db ((Green_Subsong1_Track4 - ($ + 1)) & 255)
+ db ((Green_Subsong1_Track1 - ($ + 2)) & #ff00) / 256 ; New track (1) for channel 2, as an offset. Offset MSB, then LSB.
+ db ((Green_Subsong1_Track1 - ($ + 1)) & 255)
+
+; Pattern 3
+ db 40 ; State byte.
+ db ((Green_Subsong1_Track5 - ($ + 2)) & #ff00) / 256 ; New track (5) for channel 1, as an offset. Offset MSB, then LSB.
+ db ((Green_Subsong1_Track5 - ($ + 1)) & 255)
+ db ((Green_Subsong1_Track3 - ($ + 2)) & #ff00) / 256 ; New track (3) for channel 2, as an offset. Offset MSB, then LSB.
+ db ((Green_Subsong1_Track3 - ($ + 1)) & 255)
+
+ db 1 ; End of the Song.
+ db 0 ; Speed to 0, meaning "end of song".
+Green_Subsong1DisarkByteRegionEnd2
+Green_Subsong1DisarkPointerRegionStart3
+ dw Green_Subsong1_Loop
+
+Green_Subsong1DisarkPointerRegionEnd3
+; The indexes of the tracks.
+Green_Subsong1_TrackIndexes
+Green_Subsong1DisarkPointerRegionStart4
+ dw Green_Subsong1_Track2 ; Track 2, index 0.
+Green_Subsong1DisarkPointerRegionEnd4
+
+Green_Subsong1DisarkByteRegionStart5
+Green_Subsong1_Track0
+ db 222 ; Primary instrument (2). New escaped note: 69. New wait (11).
+ db 69 ; Escape note value.
+ db 11 ; Escape wait value.
+ db 95 ; Primary instrument (2). Same escaped note: 69. Primary wait (1).
+ db 94 ; Primary instrument (2). New escaped note: 60. Primary wait (1).
+ db 60 ; Escape note value.
+ db 30 ; Primary instrument (2). New escaped note: 62.
+ db 62 ; Escape note value.
+ db 94 ; Primary instrument (2). New escaped note: 69. Primary wait (1).
+ db 69 ; Escape note value.
+ db 94 ; Primary instrument (2). New escaped note: 62. Primary wait (1).
+ db 62 ; Escape note value.
+ db 222 ; Primary instrument (2). New escaped note: 67. New wait (15).
+ db 67 ; Escape note value.
+ db 15 ; Escape wait value.
+ db 95 ; Primary instrument (2). Same escaped note: 67. Primary wait (1).
+ db 95 ; Primary instrument (2). Same escaped note: 67. Primary wait (1).
+ db 95 ; Primary instrument (2). Same escaped note: 67. Primary wait (1).
+ db 94 ; Primary instrument (2). New escaped note: 65. Primary wait (1).
+ db 65 ; Escape note value.
+ db 158 ; Primary instrument (2). New escaped note: 62. Secondary wait (3).
+ db 62 ; Escape note value.
+ db 222 ; Primary instrument (2). New escaped note: 60. New wait (127).
+ db 60 ; Escape note value.
+ db 127 ; Escape wait value.
+
+Green_Subsong1_Track1
+ db 94 ; Primary instrument (2). New escaped note: 38. Primary wait (1).
+ db 38 ; Escape note value.
+ db 190 ; New instrument (1). New escaped note: 26. Secondary wait (3).
+ db 26 ; Escape note value.
+ db 1 ; Escape instrument value.
+ db 78 ; New escaped note: 24. Primary wait (1).
+ db 24 ; Escape note value.
+ db 126 ; New instrument (3). New escaped note: 36. Primary wait (1).
+ db 36 ; Escape note value.
+ db 3 ; Escape instrument value.
+ db 190 ; New instrument (1). New escaped note: 26. Secondary wait (3).
+ db 26 ; Escape note value.
+ db 1 ; Escape instrument value.
+ db 78 ; New escaped note: 24. Primary wait (1).
+ db 24 ; Escape note value.
+ db 94 ; Primary instrument (2). New escaped note: 38. Primary wait (1).
+ db 38 ; Escape note value.
+ db 142 ; New escaped note: 26. Secondary wait (3).
+ db 26 ; Escape note value.
+ db 78 ; New escaped note: 24. Primary wait (1).
+ db 24 ; Escape note value.
+ db 126 ; New instrument (3). New escaped note: 36. Primary wait (1).
+ db 36 ; Escape note value.
+ db 3 ; Escape instrument value.
+ db 190 ; New instrument (1). New escaped note: 26. Secondary wait (3).
+ db 26 ; Escape note value.
+ db 1 ; Escape instrument value.
+ db 78 ; New escaped note: 24. Primary wait (1).
+ db 24 ; Escape note value.
+ db 94 ; Primary instrument (2). New escaped note: 43. Primary wait (1).
+ db 43 ; Escape note value.
+ db 142 ; New escaped note: 31. Secondary wait (3).
+ db 31 ; Escape note value.
+ db 78 ; New escaped note: 29. Primary wait (1).
+ db 29 ; Escape note value.
+ db 126 ; New instrument (3). New escaped note: 36. Primary wait (1).
+ db 36 ; Escape note value.
+ db 3 ; Escape instrument value.
+ db 190 ; New instrument (1). New escaped note: 31. Secondary wait (3).
+ db 31 ; Escape note value.
+ db 1 ; Escape instrument value.
+ db 78 ; New escaped note: 29. Primary wait (1).
+ db 29 ; Escape note value.
+ db 94 ; Primary instrument (2). New escaped note: 43. Primary wait (1).
+ db 43 ; Escape note value.
+ db 142 ; New escaped note: 31. Secondary wait (3).
+ db 31 ; Escape note value.
+ db 78 ; New escaped note: 29. Primary wait (1).
+ db 29 ; Escape note value.
+ db 126 ; New instrument (3). New escaped note: 36. Primary wait (1).
+ db 36 ; Escape note value.
+ db 3 ; Escape instrument value.
+ db 126 ; New instrument (1). New escaped note: 31. Primary wait (1).
+ db 31 ; Escape note value.
+ db 1 ; Escape instrument value.
+ db 126 ; New instrument (3). New escaped note: 36. Primary wait (1).
+ db 36 ; Escape note value.
+ db 3 ; Escape instrument value.
+ db 254 ; New instrument (1). New escaped note: 27. New wait (127).
+ db 27 ; Escape note value.
+ db 1 ; Escape instrument value.
+ db 127 ; Escape wait value.
+
+Green_Subsong1_Track2
+ db 205 ; New wait (127).
+ db 127 ; Escape wait value.
+
+Green_Subsong1_Track3
+ db 94 ; Primary instrument (2). New escaped note: 38. Primary wait (1).
+ db 38 ; Escape note value.
+ db 190 ; New instrument (1). New escaped note: 26. Secondary wait (3).
+ db 26 ; Escape note value.
+ db 1 ; Escape instrument value.
+ db 78 ; New escaped note: 24. Primary wait (1).
+ db 24 ; Escape note value.
+ db 126 ; New instrument (3). New escaped note: 36. Primary wait (1).
+ db 36 ; Escape note value.
+ db 3 ; Escape instrument value.
+ db 190 ; New instrument (1). New escaped note: 26. Secondary wait (3).
+ db 26 ; Escape note value.
+ db 1 ; Escape instrument value.
+ db 78 ; New escaped note: 24. Primary wait (1).
+ db 24 ; Escape note value.
+ db 94 ; Primary instrument (2). New escaped note: 38. Primary wait (1).
+ db 38 ; Escape note value.
+ db 142 ; New escaped note: 26. Secondary wait (3).
+ db 26 ; Escape note value.
+ db 78 ; New escaped note: 24. Primary wait (1).
+ db 24 ; Escape note value.
+ db 126 ; New instrument (3). New escaped note: 36. Primary wait (1).
+ db 36 ; Escape note value.
+ db 3 ; Escape instrument value.
+ db 190 ; New instrument (1). New escaped note: 26. Secondary wait (3).
+ db 26 ; Escape note value.
+ db 1 ; Escape instrument value.
+ db 78 ; New escaped note: 24. Primary wait (1).
+ db 24 ; Escape note value.
+ db 94 ; Primary instrument (2). New escaped note: 43. Primary wait (1).
+ db 43 ; Escape note value.
+ db 142 ; New escaped note: 31. Secondary wait (3).
+ db 31 ; Escape note value.
+ db 78 ; New escaped note: 29. Primary wait (1).
+ db 29 ; Escape note value.
+ db 126 ; New instrument (3). New escaped note: 36. Primary wait (1).
+ db 36 ; Escape note value.
+ db 3 ; Escape instrument value.
+ db 190 ; New instrument (1). New escaped note: 31. Secondary wait (3).
+ db 31 ; Escape note value.
+ db 1 ; Escape instrument value.
+ db 78 ; New escaped note: 29. Primary wait (1).
+ db 29 ; Escape note value.
+ db 94 ; Primary instrument (2). New escaped note: 43. Primary wait (1).
+ db 43 ; Escape note value.
+ db 142 ; New escaped note: 31. Secondary wait (3).
+ db 31 ; Escape note value.
+ db 78 ; New escaped note: 29. Primary wait (1).
+ db 29 ; Escape note value.
+ db 126 ; New instrument (3). New escaped note: 36. Primary wait (1).
+ db 36 ; Escape note value.
+ db 3 ; Escape instrument value.
+ db 143 ; Same escaped note: 36. Secondary wait (3).
+ db 207 ; Same escaped note: 36. New wait (127).
+ db 127 ; Escape wait value.
+
+Green_Subsong1_Track4
+ db 111 ; Secondary instrument (4). Same escaped note: 57. Primary wait (1).
+ db 110 ; Secondary instrument (4). New escaped note: 50. Primary wait (1).
+ db 50 ; Escape note value.
+ db 110 ; Secondary instrument (4). New escaped note: 48. Primary wait (1).
+ db 48 ; Escape note value.
+ db 110 ; Secondary instrument (4). New escaped note: 50. Primary wait (1).
+ db 50 ; Escape note value.
+ db 110 ; Secondary instrument (4). New escaped note: 57. Primary wait (1).
+ db 57 ; Escape note value.
+ db 110 ; Secondary instrument (4). New escaped note: 50. Primary wait (1).
+ db 50 ; Escape note value.
+ db 110 ; Secondary instrument (4). New escaped note: 48. Primary wait (1).
+ db 48 ; Escape note value.
+ db 110 ; Secondary instrument (4). New escaped note: 50. Primary wait (1).
+ db 50 ; Escape note value.
+ db 94 ; Primary instrument (2). New escaped note: 69. Primary wait (1).
+ db 69 ; Escape note value.
+ db 94 ; Primary instrument (2). New escaped note: 70. Primary wait (1).
+ db 70 ; Escape note value.
+ db 94 ; Primary instrument (2). New escaped note: 69. Primary wait (1).
+ db 69 ; Escape note value.
+ db 94 ; Primary instrument (2). New escaped note: 67. Primary wait (1).
+ db 67 ; Escape note value.
+ db 158 ; Primary instrument (2). New escaped note: 69. Secondary wait (3).
+ db 69 ; Escape note value.
+ db 158 ; Primary instrument (2). New escaped note: 65. Secondary wait (3).
+ db 65 ; Escape note value.
+ db 110 ; Secondary instrument (4). New escaped note: 55. Primary wait (1).
+ db 55 ; Escape note value.
+ db 110 ; Secondary instrument (4). New escaped note: 53. Primary wait (1).
+ db 53 ; Escape note value.
+ db 110 ; Secondary instrument (4). New escaped note: 55. Primary wait (1).
+ db 55 ; Escape note value.
+ db 110 ; Secondary instrument (4). New escaped note: 57. Primary wait (1).
+ db 57 ; Escape note value.
+ db 110 ; Secondary instrument (4). New escaped note: 55. Primary wait (1).
+ db 55 ; Escape note value.
+ db 110 ; Secondary instrument (4). New escaped note: 53. Primary wait (1).
+ db 53 ; Escape note value.
+ db 110 ; Secondary instrument (4). New escaped note: 50. Primary wait (1).
+ db 50 ; Escape note value.
+ db 110 ; Secondary instrument (4). New escaped note: 48. Primary wait (1).
+ db 48 ; Escape note value.
+ db 158 ; Primary instrument (2). New escaped note: 62. Secondary wait (3).
+ db 62 ; Escape note value.
+ db 158 ; Primary instrument (2). New escaped note: 69. Secondary wait (3).
+ db 69 ; Escape note value.
+ db 95 ; Primary instrument (2). Same escaped note: 69. Primary wait (1).
+ db 94 ; Primary instrument (2). New escaped note: 67. Primary wait (1).
+ db 67 ; Escape note value.
+ db 94 ; Primary instrument (2). New escaped note: 65. Primary wait (1).
+ db 65 ; Escape note value.
+ db 222 ; Primary instrument (2). New escaped note: 64. New wait (127).
+ db 64 ; Escape note value.
+ db 127 ; Escape wait value.
+
+Green_Subsong1_Track5
+ db 111 ; Secondary instrument (4). Same escaped note: 57. Primary wait (1).
+ db 110 ; Secondary instrument (4). New escaped note: 50. Primary wait (1).
+ db 50 ; Escape note value.
+ db 110 ; Secondary instrument (4). New escaped note: 48. Primary wait (1).
+ db 48 ; Escape note value.
+ db 110 ; Secondary instrument (4). New escaped note: 50. Primary wait (1).
+ db 50 ; Escape note value.
+ db 110 ; Secondary instrument (4). New escaped note: 57. Primary wait (1).
+ db 57 ; Escape note value.
+ db 110 ; Secondary instrument (4). New escaped note: 50. Primary wait (1).
+ db 50 ; Escape note value.
+ db 110 ; Secondary instrument (4). New escaped note: 48. Primary wait (1).
+ db 48 ; Escape note value.
+ db 110 ; Secondary instrument (4). New escaped note: 50. Primary wait (1).
+ db 50 ; Escape note value.
+ db 94 ; Primary instrument (2). New escaped note: 69. Primary wait (1).
+ db 69 ; Escape note value.
+ db 94 ; Primary instrument (2). New escaped note: 70. Primary wait (1).
+ db 70 ; Escape note value.
+ db 94 ; Primary instrument (2). New escaped note: 69. Primary wait (1).
+ db 69 ; Escape note value.
+ db 94 ; Primary instrument (2). New escaped note: 67. Primary wait (1).
+ db 67 ; Escape note value.
+ db 158 ; Primary instrument (2). New escaped note: 69. Secondary wait (3).
+ db 69 ; Escape note value.
+ db 158 ; Primary instrument (2). New escaped note: 65. Secondary wait (3).
+ db 65 ; Escape note value.
+ db 110 ; Secondary instrument (4). New escaped note: 55. Primary wait (1).
+ db 55 ; Escape note value.
+ db 110 ; Secondary instrument (4). New escaped note: 53. Primary wait (1).
+ db 53 ; Escape note value.
+ db 110 ; Secondary instrument (4). New escaped note: 55. Primary wait (1).
+ db 55 ; Escape note value.
+ db 110 ; Secondary instrument (4). New escaped note: 57. Primary wait (1).
+ db 57 ; Escape note value.
+ db 110 ; Secondary instrument (4). New escaped note: 55. Primary wait (1).
+ db 55 ; Escape note value.
+ db 110 ; Secondary instrument (4). New escaped note: 53. Primary wait (1).
+ db 53 ; Escape note value.
+ db 110 ; Secondary instrument (4). New escaped note: 50. Primary wait (1).
+ db 50 ; Escape note value.
+ db 110 ; Secondary instrument (4). New escaped note: 48. Primary wait (1).
+ db 48 ; Escape note value.
+ db 222 ; Primary instrument (2). New escaped note: 62. New wait (5).
+ db 62 ; Escape note value.
+ db 5 ; Escape wait value.
+ db 94 ; Primary instrument (2). New escaped note: 65. Primary wait (1).
+ db 65 ; Escape note value.
+ db 94 ; Primary instrument (2). New escaped note: 67. Primary wait (1).
+ db 67 ; Escape note value.
+ db 159 ; Primary instrument (2). Same escaped note: 67. Secondary wait (3).
+ db 222 ; Primary instrument (2). New escaped note: 65. New wait (127).
+ db 65 ; Escape note value.
+ db 127 ; Escape wait value.
+
+Green_Subsong1DisarkByteRegionEnd5
+; The note indexes.
+Green_Subsong1_NoteIndexes
+Green_Subsong1DisarkByteRegionStart6
+Green_Subsong1DisarkByteRegionEnd6
+
+; Green, Subsong 2.
+; ----------------------------------
+
+Green_Subsong2
+Green_Subsong2DisarkPointerRegionStart0
+ dw Green_Subsong2_NoteIndexes ; Index table for the notes.
+ dw Green_Subsong2_TrackIndexes ; Index table for the Tracks.
+Green_Subsong2DisarkPointerRegionEnd0
+
+Green_Subsong2DisarkByteRegionStart1
+ db 6 ; Initial speed.
+
+ db 2 ; Most used instrument.
+ db 4 ; Second most used instrument.
+
+ db 1 ; Most used wait.
+ db 3 ; Second most used wait.
+
+ db 31 ; Default start note in tracks.
+ db 3 ; Default start instrument in tracks.
+ db 0 ; Default start wait in tracks.
+
+ db 13 ; Are there effects? 12 if yes, 13 if not. Don't ask.
+Green_Subsong2DisarkByteRegionEnd1
+
+; The Linker.
+Green_Subsong2DisarkByteRegionStart2
+; Pattern 0
+ db 170 ; State byte.
+ db 63 ; New height.
+ db ((Green_Subsong2_Track0 - ($ + 2)) & #ff00) / 256 ; New track (0) for channel 1, as an offset. Offset MSB, then LSB.
+ db ((Green_Subsong2_Track0 - ($ + 1)) & 255)
+ db ((Green_Subsong2_Track1 - ($ + 2)) & #ff00) / 256 ; New track (1) for channel 2, as an offset. Offset MSB, then LSB.
+ db ((Green_Subsong2_Track1 - ($ + 1)) & 255)
+ db 128 ; New track (2) for channel 3, as a reference (index 0).
+
+; Pattern 1
+Green_Subsong2_Loop
+ db 40 ; State byte.
+ db 128 ; New track (2) for channel 1, as a reference (index 0).
+ db 128 ; New track (2) for channel 2, as a reference (index 0).
+
+ db 1 ; End of the Song.
+ db 0 ; Speed to 0, meaning "end of song".
+Green_Subsong2DisarkByteRegionEnd2
+Green_Subsong2DisarkPointerRegionStart3
+ dw Green_Subsong2_Loop
+
+Green_Subsong2DisarkPointerRegionEnd3
+; The indexes of the tracks.
+Green_Subsong2_TrackIndexes
+Green_Subsong2DisarkPointerRegionStart4
+ dw Green_Subsong2_Track2 ; Track 2, index 0.
+Green_Subsong2DisarkPointerRegionEnd4
+
+Green_Subsong2DisarkByteRegionStart5
+Green_Subsong2_Track0
+ db 110 ; Secondary instrument (4). New escaped note: 55. Primary wait (1).
+ db 55 ; Escape note value.
+ db 110 ; Secondary instrument (4). New escaped note: 54. Primary wait (1).
+ db 54 ; Escape note value.
+ db 110 ; Secondary instrument (4). New escaped note: 53. Primary wait (1).
+ db 53 ; Escape note value.
+ db 46 ; Secondary instrument (4). New escaped note: 51.
+ db 51 ; Escape note value.
+ db 46 ; Secondary instrument (4). New escaped note: 49.
+ db 49 ; Escape note value.
+ db 174 ; Secondary instrument (4). New escaped note: 50. Secondary wait (3).
+ db 50 ; Escape note value.
+ db 175 ; Secondary instrument (4). Same escaped note: 50. Secondary wait (3).
+ db 238 ; Secondary instrument (4). New escaped note: 55. New wait (7).
+ db 55 ; Escape note value.
+ db 7 ; Escape wait value.
+ db 222 ; Primary instrument (2). New escaped note: 43. New wait (127).
+ db 43 ; Escape note value.
+ db 127 ; Escape wait value.
+
+Green_Subsong2_Track1
+ db 79 ; Same escaped note: 31. Primary wait (1).
+ db 126 ; New instrument (1). New escaped note: 30. Primary wait (1).
+ db 30 ; Escape note value.
+ db 1 ; Escape instrument value.
+ db 78 ; New escaped note: 29. Primary wait (1).
+ db 29 ; Escape note value.
+ db 78 ; New escaped note: 28. Primary wait (1).
+ db 28 ; Escape note value.
+ db 190 ; New instrument (3). New escaped note: 26. Secondary wait (3).
+ db 26 ; Escape note value.
+ db 3 ; Escape instrument value.
+ db 191 ; New instrument (1). Same escaped note: 26. Secondary wait (3).
+ db 1 ; Escape instrument value.
+ db 254 ; New instrument (3). New escaped note: 43. New wait (7).
+ db 43 ; Escape note value.
+ db 3 ; Escape instrument value.
+ db 7 ; Escape wait value.
+ db 254 ; New instrument (1). New escaped note: 31. New wait (127).
+ db 31 ; Escape note value.
+ db 1 ; Escape instrument value.
+ db 127 ; Escape wait value.
+
+Green_Subsong2_Track2
+ db 205 ; New wait (127).
+ db 127 ; Escape wait value.
+
+Green_Subsong2DisarkByteRegionEnd5
+; The note indexes.
+Green_Subsong2_NoteIndexes
+Green_Subsong2DisarkByteRegionStart6
+Green_Subsong2DisarkByteRegionEnd6
+
diff --git a/game/src/song_playerconfig.asm b/game/src/song_playerconfig.asm new file mode 100644 index 0000000..9e7821f --- /dev/null +++ b/game/src/song_playerconfig.asm @@ -0,0 +1,17 @@ +; Configuration that can be included to Arkos Tracker 2 players.
+; It indicates what parts of code are useful to the song/sound effects, to save both memory and CPU.
+; The players may or may not take advantage of these flags, it is up to them.
+
+; You can either:
+; - Include this to the source that also includes the player (BEFORE the player is included) (recommended solution).
+; - Include this at the beginning of the player code.
+; - Copy/paste this directly in the player.
+; If you use one player but several songs, don't worry, these declarations will stack up.
+; If no configuration is used, the player will use default values (full code used).
+
+ PLY_CFG_ConfigurationIsPresent = 1
+ PLY_CFG_NoSoftNoHard = 1
+ PLY_CFG_SoftOnly = 1
+ PLY_CFG_SoftOnly_Noise = 1
+ PLY_CFG_SoftOnly_SoftwareArpeggio = 1
+ PLY_CFG_SoftOnly_SoftwarePitch = 1
|