From da49dbeb2ba1d4437e25d3ba4f1b84760dd60edb Mon Sep 17 00:00:00 2001 From: Zack Buhman Date: Wed, 26 Jul 2023 18:17:45 +0000 Subject: [PATCH] Makefile: improve build rules slightly I'm still not satisfied with the Makefile, but this at least makes it converge in a single make invocation again. This also removes the enum value arrays. --- Makefile | 37 +++-- main.cpp | 64 +++----- maps.hpp | 255 -------------------------------- sprites.hpp | 77 ---------- tools/generate/__main__.py | 19 +-- tools/generate/connections.py | 32 ++++ tools/generate/files.py | 11 ++ tools/generate/maps.py | 10 +- tools/generate/sprites.py | 5 +- tools/generate_list/__main__.py | 8 + tools/parse/__main__.py | 2 +- tools/parse/map_header.py | 36 ++++- 12 files changed, 148 insertions(+), 408 deletions(-) delete mode 100644 maps.hpp delete mode 100644 sprites.hpp create mode 100644 tools/generate/connections.py create mode 100644 tools/generate/files.py create mode 100644 tools/generate_list/__main__.py diff --git a/Makefile b/Makefile index 0af42b8..29bbbeb 100644 --- a/Makefile +++ b/Makefile @@ -3,11 +3,19 @@ CFLAGS = -Isaturn OPT ?= -Og LIB = ./saturn -SRC = main.o input.o -SRC += gen/maps.o -SRC += gen/map_objects.o -SRC += gen/sprites.o -DEP = $(patsubst %.o,%.d,$(SRC)) +GEN_PYTHON_SOURCE = $(wildcard tools/source/*.py) $(wildcard tools/generate/*.py) + +GEN_SRC = +GEN_SRC += gen/maps.cpp +GEN_SRC += gen/map_objects.cpp +GEN_SRC += gen/sprites.cpp + +SRC = +SRC += $(GEN_SRC) +SRC += main.cpp +SRC += input.cpp + +DEP = $(patsubst %.cpp,%.cpp.d,$(SRC)) res = $(subst pokered/,res/,$(patsubst %.$(1),%.$(1).o,$(wildcard $(2)*.$(1)))) res_png = $(subst pokered/,res/,$(patsubst %.png,%.$(1).o,$(wildcard $(2)*.png))) @@ -17,8 +25,9 @@ GFX_BLOCKSETS = $(call res,bst,pokered/gfx/blocksets/) GFX_SPRITES = $(call res_png,2bpp,pokered/gfx/sprites/) MAPS_BLOCKS = $(call res,blk,pokered/maps/) -GENERATED = $(GFX_TILESETS) $(GFX_BLOCKSETS) $(GFX_SPRITES) $(MAPS_BLOCKS) -OBJ = $(SRC) $(GENERATED) +GENERATED = $(GFX_TILESETS) $(GFX_BLOCKSETS) $(GFX_SPRITES) $(MAPS_BLOCKS) $(GEN_SRC) + +OBJ = $(patsubst %.cpp,%.o,$(SRC) $(GENERATED)) all: main.cue @@ -30,20 +39,16 @@ define LINK_BINARY ln -sf $(shell realpath --relative-to="$(dir $@)" $<) $@ endef -GEN_PYTHON_SOURCE = $(wildcard tools/source/*.py) $(wildcard tools/generate/*.py) - define RUN_GENERATE @mkdir -p ./gen PYTHONPATH=./tools python -m generate ./pokered ./gen ./res endef -gen/%.cpp: $(GEN_PYTHON_SOURCE) - $(RUN_GENERATE) - gen/%.hpp: $(GEN_PYTHON_SOURCE) - $(RUN_GENERATE) + $(RUN_GENERATE) $@ -generated: $(GENERATED) +gen/%.cpp: gen/%.hpp $(GEN_PYTHON_SOURCE) + $(RUN_GENERATE) $@ res/%.2bpp: pokered/%.png @mkdir -p $(dir $@) @@ -85,4 +90,6 @@ clean: clean-sh clean-sh: rm -rf res gen -PHONY: generated-headers +generated: $(GENERATED) + +PHONY: generated diff --git a/main.cpp b/main.cpp index 364405d..a6108fe 100644 --- a/main.cpp +++ b/main.cpp @@ -15,8 +15,6 @@ #include "gen/maps.hpp" #include "gen/sprites.hpp" #include "map_objects.hpp" -#include "maps.hpp" // hack? -#include "sprites.hpp" constexpr inline uint16_t rgb15(int32_t r, int32_t g, int32_t b) { @@ -88,8 +86,8 @@ constexpr inline void render_block(const uint32_t base_pattern, const int32_t block_ix = 4 * block_y + block_x; const uint8_t tile_ix = tileset.blockset.start[block * 4 * 4 + block_ix]; - const int32_t cell_y = map_y * 4 + block_y; - const int32_t cell_x = map_x * 4 + block_x; + const uint32_t cell_y = map_y * 4 + block_y; + const uint32_t cell_x = map_x * 4 + block_x; // assumes NBG0 map plane_a is at offset 0 vdp2.vram.u16[64 * (cell_y % 64) + (cell_x % 64)] = (base_pattern & 0xfff) + tile_ix; //vdp2.vram.u32[64 * cell_y + cell_x] = base_pattern + tile_ix; @@ -101,25 +99,25 @@ constexpr int32_t last_map = map_t::wardens_house; struct draw_t { struct { - uint16_t tilesets[tilesets_ix_last]; // div 32 - uint16_t spritesheets[spritesheets_ix_last]; // div 128 + uint16_t tilesets[tileset_t::count]; // div 32 + uint16_t spritesheets[spritesheet_t::count]; // div 128 } base_pattern; }; struct player_t { struct { - int16_t x; - int16_t y; + int32_t x; + int32_t y; }; }; struct state_t { - int32_t map_ix; + enum map_t::map map; draw_t draw; player_t player; }; -static state_t state = { 0 }; +static state_t state = { map_t::pallet_town, 0 }; uint32_t load_tileset(uint32_t top, enum tileset_t::tileset tileset) { @@ -146,8 +144,8 @@ void load_vram() vdp2.reg.CYCB1 = 0xeeee'eeee; uint32_t vdp2_top = (sizeof (union vdp2_vram)); - for (uint32_t i = 0; i < tilesets_ix_last; i++) - vdp2_top = load_tileset(vdp2_top, tilesets_ix[i]); + for (uint32_t i = 0; i < tileset_t::count; i++) + vdp2_top = load_tileset(vdp2_top, static_cast(i)); vdp2.reg.CYCA0 = 0x0121'ffff; vdp2.reg.CYCA1 = 0x0121'ffff; @@ -155,8 +153,8 @@ void load_vram() vdp2.reg.CYCB1 = 0x4565'ffff; uint32_t vdp1_top = (sizeof (union vdp1_vram)); - for (uint32_t i = 0; i < spritesheets_ix_last; i++) - vdp1_top = load_sprite(vdp1_top, spritesheets_ix[i]); + for (uint32_t i = 0; i < spritesheet_t::count; i++) + vdp1_top = load_sprite(vdp1_top, static_cast(i)); } // screen space @@ -244,16 +242,18 @@ static uint16_t scroll = 0; */ +// there are 16 pixels per block + void render_map() { - if (++scroll > 64) { + if (++scroll > 4) { scroll = 0; state.player.x += 1; state.player.y += 1; } - vdp2.reg.SCXIN0 = (state.player.x - 1) * 16 + (scroll / 4); - vdp2.reg.SCYIN0 = (state.player.y - 1) * 16 + (scroll / 4); + vdp2.reg.SCXIN0 = state.player.x - 16; + vdp2.reg.SCYIN0 = state.player.y - 16; /* vdp2.reg.WPSX0 = 80 << 1; vdp2.reg.WPSY0 = 48; @@ -262,20 +262,18 @@ void render_map() vdp2.reg.WCTLA = WCTLA__N0W0E | WCTLA__N0W0A__OUTSIDE; */ - const map_t& map = maps[maps_ix[state.map_ix]]; - const uint8_t border_block = map_objects[maps_ix[state.map_ix]].border_block; + const map_t& map = maps[state.map]; + const uint8_t border_block = map_objects[state.map].border_block; const uint32_t base_pattern = state.draw.base_pattern.tilesets[map.tileset]; vdp2.reg.PNCN0 = PNCN0__N0PNB__1WORD | PNCN0__N0CNSM | PNCN0__N0SCN((base_pattern >> 10) & 0x1f); - int32_t origin_x = state.player.x / 2; - int32_t origin_y = state.player.y / 2; - int32_t offset_x = state.player.x & 1; - int32_t offset_y = state.player.y & 1; + int32_t origin_x = state.player.x / 32; + int32_t origin_y = state.player.y / 32; fill(vdp2.vram.u32, 0, 64 * 64 * 2); - for (int32_t y = origin_y - 3 + offset_x; y <= (origin_y + 2 + offset_x); y++) { - for (int32_t x = origin_x - 3 + offset_y; x <= (origin_x + 3 + offset_y); x++) { + for (int32_t y = origin_y - 3; y <= (origin_y + 3); y++) { + for (int32_t x = origin_x - 3; x <= (origin_x + 3); x++) { const uint8_t block = ( (x < static_cast(map.width)) && (y < static_cast(map.height)) && (x >= 0) @@ -301,19 +299,6 @@ void render() render_sprites(); } -void update() -{ - if (event::cursor_right()) { - state.map_ix++; - if (state.map_ix >= map_ix_last) - state.map_ix = 0; - } - if (event::cursor_left()) { - state.map_ix--; - if (state.map_ix < 0) state.map_ix = last_map; - } -} - extern "C" void v_blank_in_int(void) __attribute__ ((interrupt_handler)); void v_blank_in_int() @@ -326,7 +311,6 @@ void v_blank_in_int() sh2.reg.FTCSR = 0; // clear flags render(); - update(); // wait at least 300us, as specified in the SMPC manual. // It appears reading FRC.H is mandatory and *must* occur before FRC.L on real @@ -462,7 +446,7 @@ void init_vdp2() void main() { - state.map_ix = map_t::pallet_town; + state.map = map_t::pallet_town; load_vram(); diff --git a/maps.hpp b/maps.hpp deleted file mode 100644 index f316d1a..0000000 --- a/maps.hpp +++ /dev/null @@ -1,255 +0,0 @@ -enum map_t::map maps_ix[] = { - map_t::agathas_room, - map_t::bike_shop, - map_t::bills_house, - map_t::blues_house, - map_t::brunos_room, - map_t::celadon_chief_house, - map_t::celadon_city, - map_t::celadon_diner, - map_t::celadon_gym, - map_t::celadon_hotel, - map_t::celadon_mansion_1f, - map_t::celadon_mansion_2f, - map_t::celadon_mansion_3f, - map_t::celadon_mansion_roof, - map_t::celadon_mansion_roof_house, - map_t::celadon_mart_1f, - map_t::celadon_mart_2f, - map_t::celadon_mart_3f, - map_t::celadon_mart_4f, - map_t::celadon_mart_5f, - map_t::celadon_mart_elevator, - map_t::celadon_mart_roof, - map_t::celadon_pokecenter, - map_t::cerulean_badge_house, - map_t::cerulean_cave_1f, - map_t::cerulean_cave_2f, - map_t::cerulean_cave_b1f, - map_t::cerulean_city, - map_t::cerulean_gym, - map_t::cerulean_mart, - map_t::cerulean_pokecenter, - map_t::cerulean_trade_house, - map_t::cerulean_trashed_house, - map_t::champions_room, - map_t::cinnabar_gym, - map_t::cinnabar_island, - map_t::cinnabar_lab, - map_t::cinnabar_lab_fossil_room, - map_t::cinnabar_lab_metronome_room, - map_t::cinnabar_lab_trade_room, - map_t::cinnabar_mart, - map_t::cinnabar_pokecenter, - map_t::colosseum, - map_t::copycats_house_1f, - map_t::copycats_house_2f, - map_t::daycare, - map_t::digletts_cave, - map_t::digletts_cave_route_11, - map_t::digletts_cave_route_2, - map_t::fighting_dojo, - map_t::fuchsia_bills_grandpas_house, - map_t::fuchsia_city, - map_t::fuchsia_good_rod_house, - map_t::fuchsia_gym, - map_t::fuchsia_mart, - map_t::fuchsia_meeting_room, - map_t::fuchsia_pokecenter, - map_t::game_corner, - map_t::game_corner_prize_room, - map_t::hall_of_fame, - map_t::indigo_plateau, - map_t::indigo_plateau_lobby, - map_t::lances_room, - map_t::lavender_cubone_house, - map_t::lavender_mart, - map_t::lavender_pokecenter, - map_t::lavender_town, - map_t::loreleis_room, - map_t::mr_fujis_house, - map_t::mr_psychics_house, - map_t::mt_moon_1f, - map_t::mt_moon_b1f, - map_t::mt_moon_b2f, - map_t::mt_moon_pokecenter, - map_t::museum_1f, - map_t::museum_2f, - map_t::name_raters_house, - map_t::oaks_lab, - map_t::pallet_town, - map_t::pewter_city, - map_t::pewter_gym, - map_t::pewter_mart, - map_t::pewter_nidoran_house, - map_t::pewter_pokecenter, - map_t::pewter_speech_house, - map_t::pokemon_fan_club, - map_t::pokemon_mansion_1f, - map_t::pokemon_mansion_2f, - map_t::pokemon_mansion_3f, - map_t::pokemon_mansion_b1f, - map_t::pokemon_tower_1f, - map_t::pokemon_tower_2f, - map_t::pokemon_tower_3f, - map_t::pokemon_tower_4f, - map_t::pokemon_tower_5f, - map_t::pokemon_tower_6f, - map_t::pokemon_tower_7f, - map_t::power_plant, - map_t::reds_house_1f, - map_t::reds_house_2f, - map_t::rocket_hideout_b1f, - map_t::rocket_hideout_b2f, - map_t::rocket_hideout_b3f, - map_t::rocket_hideout_b4f, - map_t::rocket_hideout_elevator, - map_t::rock_tunnel_1f, - map_t::rock_tunnel_b1f, - map_t::rock_tunnel_pokecenter, - map_t::route_1, - map_t::route_10, - map_t::route_11, - map_t::route_11_gate_1f, - map_t::route_11_gate_2f, - map_t::route_12, - map_t::route_12_gate_1f, - map_t::route_12_gate_2f, - map_t::route_12_super_rod_house, - map_t::route_13, - map_t::route_14, - map_t::route_15, - map_t::route_15_gate_1f, - map_t::route_15_gate_2f, - map_t::route_16, - map_t::route_16_fly_house, - map_t::route_16_gate_1f, - map_t::route_16_gate_2f, - map_t::route_17, - map_t::route_18, - map_t::route_18_gate_1f, - map_t::route_18_gate_2f, - map_t::route_19, - map_t::route_2, - map_t::route_20, - map_t::route_21, - map_t::route_22, - map_t::route_22_gate, - map_t::route_23, - map_t::route_24, - map_t::route_25, - map_t::route_2_gate, - map_t::route_2_trade_house, - map_t::route_3, - map_t::route_4, - map_t::route_5, - map_t::route_5_gate, - map_t::route_6, - map_t::route_6_gate, - map_t::route_7, - map_t::route_7_gate, - map_t::route_8, - map_t::route_8_gate, - map_t::route_9, - map_t::safari_zone_center, - map_t::safari_zone_center_rest_house, - map_t::safari_zone_east, - map_t::safari_zone_east_rest_house, - map_t::safari_zone_gate, - map_t::safari_zone_north, - map_t::safari_zone_north_rest_house, - map_t::safari_zone_secret_house, - map_t::safari_zone_west, - map_t::safari_zone_west_rest_house, - map_t::saffron_city, - map_t::saffron_gym, - map_t::saffron_mart, - map_t::saffron_pidgey_house, - map_t::saffron_pokecenter, - map_t::seafoam_islands_1f, - map_t::seafoam_islands_b1f, - map_t::seafoam_islands_b2f, - map_t::seafoam_islands_b3f, - map_t::seafoam_islands_b4f, - map_t::silph_co_10f, - map_t::silph_co_11f, - map_t::silph_co_1f, - map_t::silph_co_2f, - map_t::silph_co_3f, - map_t::silph_co_4f, - map_t::silph_co_5f, - map_t::silph_co_6f, - map_t::silph_co_7f, - map_t::silph_co_8f, - map_t::silph_co_9f, - map_t::silph_co_elevator, - map_t::ss_anne_1f, - map_t::ss_anne_1f_rooms, - map_t::ss_anne_2f, - map_t::ss_anne_2f_rooms, - map_t::ss_anne_3f, - map_t::ss_anne_b1f, - map_t::ss_anne_b1f_rooms, - map_t::ss_anne_bow, - map_t::ss_anne_captains_room, - map_t::ss_anne_kitchen, - map_t::trade_center, - map_t::underground_path_north_south, - map_t::underground_path_route_5, - map_t::underground_path_route_6, - map_t::underground_path_route_7, - map_t::underground_path_route_8, - map_t::underground_path_west_east, - map_t::vermilion_city, - map_t::vermilion_dock, - map_t::vermilion_gym, - map_t::vermilion_mart, - map_t::vermilion_old_rod_house, - map_t::vermilion_pidgey_house, - map_t::vermilion_pokecenter, - map_t::vermilion_trade_house, - map_t::victory_road_1f, - map_t::victory_road_2f, - map_t::victory_road_3f, - map_t::viridian_city, - map_t::viridian_forest, - map_t::viridian_forest_north_gate, - map_t::viridian_forest_south_gate, - map_t::viridian_gym, - map_t::viridian_mart, - map_t::viridian_nickname_house, - map_t::viridian_pokecenter, - map_t::viridian_school_house, - map_t::wardens_house, -}; - -constexpr int map_ix_last = (sizeof (maps_ix)) / (sizeof (enum map_t::map)); - -enum tileset_t::tileset tilesets_ix[] = { - tileset_t::cavern, - tileset_t::cemetery, - tileset_t::club, - tileset_t::dojo, - tileset_t::facility, - tileset_t::forest, - tileset_t::forest_gate, - tileset_t::gate, - tileset_t::gym, - tileset_t::house, - tileset_t::interior, - tileset_t::lab, - tileset_t::lobby, - tileset_t::mansion, - tileset_t::mart, - tileset_t::museum, - tileset_t::overworld, - tileset_t::plateau, - tileset_t::pokecenter, - tileset_t::reds_house_1, - tileset_t::reds_house_2, - tileset_t::ship, - tileset_t::ship_port, - tileset_t::underground, -}; - -constexpr int tilesets_ix_last = (sizeof (tilesets_ix)) / (sizeof (enum tileset_t::tileset)); diff --git a/sprites.hpp b/sprites.hpp deleted file mode 100644 index 6af16a9..0000000 --- a/sprites.hpp +++ /dev/null @@ -1,77 +0,0 @@ -enum spritesheet_t::spritesheet spritesheets_ix[] = { - spritesheet_t::agatha, - spritesheet_t::balding_guy, - spritesheet_t::beauty, - spritesheet_t::biker, - spritesheet_t::bike_shop_clerk, - spritesheet_t::bird, - spritesheet_t::blue, - spritesheet_t::boulder, - spritesheet_t::brunette_girl, - spritesheet_t::bruno, - spritesheet_t::captain, - spritesheet_t::channeler, - spritesheet_t::clerk, - spritesheet_t::clipboard, - spritesheet_t::cook, - spritesheet_t::cooltrainer_f, - spritesheet_t::cooltrainer_m, - spritesheet_t::daisy, - spritesheet_t::fairy, - spritesheet_t::fisher, - spritesheet_t::fishing_guru, - spritesheet_t::fossil, - spritesheet_t::gambler, - spritesheet_t::gambler_asleep, - spritesheet_t::gameboy_kid, - spritesheet_t::gentleman, - spritesheet_t::giovanni, - spritesheet_t::girl, - spritesheet_t::gramps, - spritesheet_t::granny, - spritesheet_t::guard, - spritesheet_t::gym_guide, - spritesheet_t::hiker, - spritesheet_t::koga, - spritesheet_t::lance, - spritesheet_t::link_receptionist, - spritesheet_t::little_boy, - spritesheet_t::little_girl, - spritesheet_t::lorelei, - spritesheet_t::middle_aged_man, - spritesheet_t::middle_aged_woman, - spritesheet_t::mom, - spritesheet_t::monster, - spritesheet_t::mr_fuji, - spritesheet_t::none, - spritesheet_t::nurse, - spritesheet_t::oak, - spritesheet_t::old_amber, - spritesheet_t::paper, - spritesheet_t::pokedex, - spritesheet_t::poke_ball, - spritesheet_t::red, - spritesheet_t::rocker, - spritesheet_t::rocket, - spritesheet_t::safari_zone_worker, - spritesheet_t::sailor, - spritesheet_t::scientist, - spritesheet_t::seel, - spritesheet_t::silph_president, - spritesheet_t::silph_worker_f, - spritesheet_t::silph_worker_m, - spritesheet_t::snorlax, - spritesheet_t::super_nerd, - spritesheet_t::swimmer, - spritesheet_t::unused_gambler_asleep_1, - spritesheet_t::unused_gambler_asleep_2, - spritesheet_t::unused_gameboy_kid, - spritesheet_t::unused_guard, - spritesheet_t::unused_old_amber, - spritesheet_t::unused_scientist, - spritesheet_t::waiter, - spritesheet_t::warden, - spritesheet_t::youngster, -}; - -constexpr int spritesheets_ix_last = (sizeof (spritesheets_ix)) / (sizeof (enum spritesheet_t::spritesheet)); diff --git a/tools/generate/__main__.py b/tools/generate/__main__.py index fdba7ef..79d7322 100644 --- a/tools/generate/__main__.py +++ b/tools/generate/__main__.py @@ -2,24 +2,17 @@ from pathlib import Path from pprint import pprint import sys -from generate import maps -from generate import map_objects -from generate import sprites +from generate.files import files -files = [ - (maps.generate_maps_header, "maps.hpp"), - (maps.generate_maps_source, "maps.cpp"), - (map_objects.generate_map_objects_source, "map_objects.cpp"), - (sprites.generate_sprites_header, "sprites.hpp"), - (sprites.generate_sprites_source, "sprites.cpp"), -] - -def generate(base_path): +def generate(base_path, target_path): for func, filename in files: path = base_path / filename + if path != target_path: + continue with open(path, 'w') as f: f.write(func().getvalue()) # sys.argv[1] is secretly used in parse base_path = Path(sys.argv[2]) -generate(base_path) +target_path = Path(sys.argv[4]) +generate(base_path, target_path) diff --git a/tools/generate/connections.py b/tools/generate/connections.py new file mode 100644 index 0000000..5f3b250 --- /dev/null +++ b/tools/generate/connections.py @@ -0,0 +1,32 @@ +from itertools import chain + +from generate.maps import sorted_map_headers + +def includes_header(): + yield "#pragma once" + yield "" + yield '#include "maps.hpp"' + yield "" + +def directions(): + return set( + # fixme: improve the connection parser + # add dataclass fields + connection[0] + for map_header in sorted_map_headers() + for connection in map_header.connections + ) + +def struct_connection_t(): + struct connection_t { + enum direction { + # directions for lulz + }; + + enum direction direction; + map_t::map map; + uint8_t offset; + }; + + +def (): diff --git a/tools/generate/files.py b/tools/generate/files.py new file mode 100644 index 0000000..bbe1937 --- /dev/null +++ b/tools/generate/files.py @@ -0,0 +1,11 @@ +from generate import maps +from generate import map_objects +from generate import sprites + +files = [ + (maps.generate_maps_header, "maps.hpp"), + (maps.generate_maps_source, "maps.cpp"), + (map_objects.generate_map_objects_source, "map_objects.cpp"), + (sprites.generate_sprites_header, "sprites.hpp"), + (sprites.generate_sprites_source, "sprites.cpp"), +] diff --git a/tools/generate/maps.py b/tools/generate/maps.py index 6f190d5..5dca7c4 100644 --- a/tools/generate/maps.py +++ b/tools/generate/maps.py @@ -57,9 +57,10 @@ def includes_header(): yield "" def struct_tileset_t(): + _sorted_tilesets_constants_list = list(sorted_tilesets_constants_list()) tileset_names = ( f"{name.lower()}," - for name, _ in sorted_tilesets_constants_list() + for name, _ in _sorted_tilesets_constants_list ) return [ "struct tileset_t {", @@ -69,13 +70,16 @@ def struct_tileset_t(): "enum tileset {", *tileset_names, "};", + "", + f"static constexpr int32_t count = {len(_sorted_tilesets_constants_list)};" "};", ] def struct_map_t(): + _sorted_map_headers = list(sorted_map_headers()) map_names = ( f"{map_header.name2.lower()}," - for map_header in sorted_map_headers() + for map_header in _sorted_map_headers ) return [ "struct map_t {", @@ -89,6 +93,8 @@ def struct_map_t(): "last_map,", # special map name "unused_map_ed,", # special silph co elevator map name "};", + "", + f"static constexpr int32_t count = {len(_sorted_map_headers)};", "};", ] diff --git a/tools/generate/sprites.py b/tools/generate/sprites.py index 4a1234e..9df6493 100644 --- a/tools/generate/sprites.py +++ b/tools/generate/sprites.py @@ -40,9 +40,10 @@ def sprite_name(name): return name.removeprefix('SPRITE_').lower() def struct_spritesheet_t(): + _sorted_sprite_constants_list = list(sorted_sprite_constants_list()) sprite_names = ( f"{sprite_name(name)}," - for name, _ in sorted_sprite_constants_list() + for name, _ in _sorted_sprite_constants_list ) return [ "struct spritesheet_t {", @@ -52,6 +53,8 @@ def struct_spritesheet_t(): "enum spritesheet {", *sprite_names, "};", + "", + f"static constexpr int32_t count = {len(_sorted_sprite_constants_list)};", "};", ] diff --git a/tools/generate_list/__main__.py b/tools/generate_list/__main__.py new file mode 100644 index 0000000..8f7201f --- /dev/null +++ b/tools/generate_list/__main__.py @@ -0,0 +1,8 @@ +import sys +from pathlib import Path + +from generate.files import files + +base_path = Path(sys.argv[1]) +for _, filename in files: + print(base_path / filename) diff --git a/tools/parse/__main__.py b/tools/parse/__main__.py index 77213b9..41e45b4 100644 --- a/tools/parse/__main__.py +++ b/tools/parse/__main__.py @@ -1,5 +1,5 @@ from pprint import pprint from parse import parse -for i in parse.sprite_constants_list: +for i in parse.map_headers: pprint(i) diff --git a/tools/parse/map_header.py b/tools/parse/map_header.py index 5b0b6c8..878514e 100644 --- a/tools/parse/map_header.py +++ b/tools/parse/map_header.py @@ -49,6 +49,16 @@ class MapHeader: def height(self): return f"{self.name2}_HEIGHT" +@dataclass +class Connection: + name: str + map_name1: str + map_name2: str + offset: int + +def parse_connection(): + return + def flatten(tokens): # expects tokens from a single file @@ -63,14 +73,32 @@ def flatten(tokens): map_headers = [s for s in tokens if s[0] == 'map_header'] assert len(map_headers) == 1 map_header, = map_headers - _, (name1, name2, tileset, connection_mask) = map_header - connections = [s for s in tokens if s[0] == 'connection'] + _, (name1, name2, tileset, connection_mask0) = map_header + connections = [s[1] for s in tokens if s[0] == 'connection'] + + connection_mask = connection_mask0 if type(connection_mask0) is list else [connection_mask0] + null_mask = lambda m: ( + len(m) == 1 and any(m[0] == n for n in {'0', '$0', '$00'}) + ) + connection_names = ( + [] if null_mask(connection_mask) else connection_mask + ) return MapHeader( name1 = name1, name2 = name2, tileset = tileset, - connection_names = [] if connection_mask == '0' else connection_mask, - connections = [tuple(c[1]) for c in connections] + connection_names = sorted(connection_names), + connections = list(sorted( + ( + Connection( + name, + map_name1, + map_name2, + int(offset) + ) + for name, map_name1, map_name2, offset in connections + ), + key=lambda c: c.name)) ) def parse(path):