From 2682bc5d1d864341aaeb42a449db73c3ecd16d70 Mon Sep 17 00:00:00 2001 From: "Juan J. Martinez" Date: Wed, 30 Dec 2020 19:07:31 +0000 Subject: Initial import --- game/src/Makefile | 48 +++ game/src/akm.z80 | 15 + game/src/aux.c | 27 ++ game/src/aux.h | 13 + game/src/crt0.z80 | 82 +++++ game/src/data.c | 9 + game/src/effects.asm | 249 +++++++++++++++ game/src/effects_playerconfig.asm | 14 + game/src/game.c | 437 +++++++++++++++++++++++++ game/src/game.h | 130 ++++++++ game/src/main.c | 143 +++++++++ game/src/main.h | 50 +++ game/src/song.asm | 650 ++++++++++++++++++++++++++++++++++++++ game/src/song_playerconfig.asm | 17 + 14 files changed, 1884 insertions(+) create mode 100644 game/src/Makefile create mode 100644 game/src/akm.z80 create mode 100644 game/src/aux.c create mode 100644 game/src/aux.h create mode 100644 game/src/crt0.z80 create mode 100644 game/src/data.c create mode 100644 game/src/effects.asm create mode 100644 game/src/effects_playerconfig.asm create mode 100644 game/src/game.c create mode 100644 game/src/game.h create mode 100644 game/src/main.c create mode 100644 game/src/main.h create mode 100644 game/src/song.asm create mode 100644 game/src/song_playerconfig.asm (limited to 'game/src') 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 + +#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 + +/** + * 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 +#include + +#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 + +#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 + +#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 -- cgit v1.2.3