From 25d928cef10ba70d60ec756d2b9ae342c01f3c92 Mon Sep 17 00:00:00 2001 From: KikooDX Date: Sat, 8 May 2021 00:33:55 +0200 Subject: [PATCH] level loading: bundle levels in binary This doesn't replace the BFile loading system. This method is safer, faster and doesn't use gint_switch. The BFile system can be reused for additionnal features, such as custom user levels (definitly NOT coming in the first public release). --- CMakeLists.txt | 45 ++++++++++----- assets/levels/00/fxconv-metadata.txt | 3 + assets/levels/01/fxconv-metadata.txt | 3 + assets/levels/02/fxconv-metadata.txt | 3 + include/filepaths.h | 5 ++ include/level.h | 4 +- make_filepaths.sh | 45 +++++++++------ src/level/load.c | 85 +++++++++++++++++++--------- src/levelselection/draw.c | 2 +- src/levelselection/update.c | 2 +- src/main.c | 7 ++- src/mainmenu/update.c | 1 - src/player/draw.c | 2 +- 13 files changed, 143 insertions(+), 64 deletions(-) create mode 100644 assets/levels/00/fxconv-metadata.txt create mode 100644 assets/levels/01/fxconv-metadata.txt create mode 100644 assets/levels/02/fxconv-metadata.txt create mode 100644 include/filepaths.h diff --git a/CMakeLists.txt b/CMakeLists.txt index ca99be4..fa3df90 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -10,19 +10,7 @@ include(Fxconv) find_package(Gint 2.4.0 REQUIRED) find_package(LibImg 2.4.0 REQUIRED) -add_custom_target(filepaths - WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} - DEPENDS generated/filepaths.h - COMMENT "generated/filepaths.h target") - -add_custom_command(OUTPUT "${CMAKE_CURRENT_LIST_DIR}/generated/filepaths.h" - COMMENT "Generate genereated/filepaths.h." - COMMAND mkdir -p generated && - ./make_filepaths.sh > generated/filepaths.h - WORKING_DIRECTORY ${CMAKE_CURRENT_LIST_DIR} - DEPENDS make_filepaths.sh) - -include_directories(include generated) +include_directories(include generated/include) set(SOURCES src/main.c @@ -59,8 +47,37 @@ set(SOURCES src/pause/init.c src/pause/update.c src/pause/draw.c + generated/filepaths.c ) +set(LEVELS + assets/levels/00/0pillars.kble + assets/levels/00/1breach.kble + assets/levels/00/2human.kble + assets/levels/00/3amas.kble + assets/levels/01/0qujna.kble + assets/levels/01/1greed.kble + assets/levels/01/2dos.kble + assets/levels/01/3secrets.kble + assets/levels/02/0martha.kble +) + +add_custom_target(filepaths + WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} + DEPENDS ${LEVELS} make_filepaths.sh + COMMENT "filepaths.c & pack_count.h target") + +add_custom_command( + OUTPUT "${CMAKE_CURRENT_LIST_DIR}/generated/filepaths.c" + "${CMAKE_CURRENT_LIST_DIR}/generated/include/pack_count.h" + COMMENT "Generate genereated/filepaths.c & " + "generated/include/pack_count.h" + COMMAND mkdir -p generated && + ./make_filepaths.sh > generated/filepaths.c + WORKING_DIRECTORY ${CMAKE_CURRENT_LIST_DIR} + DEPENDS ${LEVELS} make_filepaths.sh) + + set(ASSETS assets/graphics/tileset.png assets/graphics/trail.png @@ -76,6 +93,7 @@ set(ASSETS assets/graphics/player/idle.png assets/graphics/player/jump.png assets/graphics/player/walk.png + ${LEVELS} ) set(FLAGS @@ -91,6 +109,7 @@ add_dependencies(${PROJECT_NAME} filepaths) target_compile_options(${PROJECT_NAME} PRIVATE ${FLAGS}) target_link_libraries(${PROJECT_NAME} Gint::Gint) target_link_libraries(${PROJECT_NAME} LibImg::LibImg) +target_link_options(${PROJECT_NAME} PRIVATE -Wl,-Map=map) generate_g3a(TARGET ${PROJECT_NAME} OUTPUT "${PROJECT_NAME}.g3a" diff --git a/assets/levels/00/fxconv-metadata.txt b/assets/levels/00/fxconv-metadata.txt new file mode 100644 index 0000000..1e3fa88 --- /dev/null +++ b/assets/levels/00/fxconv-metadata.txt @@ -0,0 +1,3 @@ +*.kble: + type: binary + name_regex: (.*)\.kble kble_\1 diff --git a/assets/levels/01/fxconv-metadata.txt b/assets/levels/01/fxconv-metadata.txt new file mode 100644 index 0000000..1e3fa88 --- /dev/null +++ b/assets/levels/01/fxconv-metadata.txt @@ -0,0 +1,3 @@ +*.kble: + type: binary + name_regex: (.*)\.kble kble_\1 diff --git a/assets/levels/02/fxconv-metadata.txt b/assets/levels/02/fxconv-metadata.txt new file mode 100644 index 0000000..1e3fa88 --- /dev/null +++ b/assets/levels/02/fxconv-metadata.txt @@ -0,0 +1,3 @@ +*.kble: + type: binary + name_regex: (.*)\.kble kble_\1 diff --git a/include/filepaths.h b/include/filepaths.h new file mode 100644 index 0000000..738d7da --- /dev/null +++ b/include/filepaths.h @@ -0,0 +1,5 @@ +/* SPDX-License-Identifier: GPL-3.0-or-later */ +/* Copyright (C) 2021 KikooDX */ +#pragma once + +void init_level_binaries(void); diff --git a/include/level.h b/include/level.h index 7018f5b..0aa27c2 100644 --- a/include/level.h +++ b/include/level.h @@ -4,6 +4,7 @@ #define LEVEL_WIDTH 25 #define LEVEL_HEIGHT 14 +#define LEVEL_SIZE (LEVEL_WIDTH * LEVEL_HEIGHT) #define KBLE_FORMAT_VERSION 0 #define KBLE_HEADER_LEN 6 @@ -28,6 +29,7 @@ struct Level { }; /* need to set global before call: level_id */ -void level_load(void); +void level_load_bfile(void); +void level_load_binary(void); void level_draw(void); Tile level_get_tile(int x, int y); diff --git a/make_filepaths.sh b/make_filepaths.sh index 70d9a73..80e2077 100755 --- a/make_filepaths.sh +++ b/make_filepaths.sh @@ -2,20 +2,22 @@ # SPDX-License-Identifier: GPL-3.0-or-later # Copyright (C) 2021 KikooDX -printf '/* SPDX-License-Identifier: GPL-3.0-or-later */\n' -printf '#pragma once\n' -printf '#include \n\n' -printf 'static const uint16_t filepaths[][64] = {\n' - +START_POS="$PWD" LEVEL_COUNT=0 -cd assets/levels +cd assets/levels || exit for PACK in *; do - PACK_NAME="$(basename $PACK)" - cd "$PACK" + PACK_NAME="$(basename "$PACK")" + cd "$PACK" || exit for LEVEL in *; do - LEVEL_COUNT="$(($LEVEL_COUNT + 1))" - LEVEL_NAME="$(basename $LEVEL | cut -c2- | + [ "$(basename $LEVEL)" == fxconv-metadata.txt ] && continue + LEVEL_ARRAY="$(printf '%s\n\tlevel_binaries[%s] = %s;' \ + "$LEVEL_ARRAY" "$LEVEL_COUNT" \ + "kble_$(basename "$LEVEL" .kble)")" + EXTERN_LEVEL="$(printf '%s\nextern uint8_t %s[];' "$EXTERN_LEVEL" \ + "kble_$(basename "$LEVEL" .kble)")" + LEVEL_COUNT="$((LEVEL_COUNT + 1))" + LEVEL_NAME="$(basename "$LEVEL" | cut -c2- | awk -F '.' '{print $1}' | tr '[:lower:]' '[:upper:]')" [ -z "$LEVEL_NAMES" ] && @@ -23,15 +25,26 @@ for PACK in *; do \"$LEVEL_NAME\"" || LEVEL_NAMES="$LEVEL_NAMES, \"$LEVEL_NAME\"" - printf '\tu"\\\\\\\\fls0\\\\mtem\\\\%s\\\\' "$PACK_NAME" - printf '%s",\n' "$LEVEL" done cd .. done -printf '};\n\n' -printf 'static const char level_names[][32] = {%s\n};\n\n' "$LEVEL_NAMES" +printf '/* SPDX-License-Identifier: GPL-3.0-or-later */\n' +printf '/* This code was generated with `make_filepaths.sh` */\n' +printf '#include "filepaths.h"\n' +printf '#include \n' -[ "$(($LEVEL_COUNT % 4))" != 0 ] && LEVEL_COUNT="$(($LEVEL_COUNT + 4 - $LEVEL_COUNT % 4))" +printf '%s\n\n' "$EXTERN_LEVEL" +printf 'uint8_t *level_binaries[%s];\n\n' "$LEVEL_COUNT" -printf '#define PACK_COUNT %s\n' "$(($LEVEL_COUNT / 4))" +printf 'char *const level_names[%s] = {%s\n};\n\n' "$LEVEL_COUNT" "$LEVEL_NAMES" + +# init_level_binaries +printf 'void\ninit_level_binaries(void)\n{' +printf '%s\n}\n' "$LEVEL_ARRAY" + +# Create headers +cd "$START_POS" +mkdir -p generated/include +[ "$((LEVEL_COUNT % 4))" != 0 ] && LEVEL_COUNT="$((LEVEL_COUNT + 4 - LEVEL_COUNT % 4))" +printf '#define PACK_COUNT %s\n' "$((LEVEL_COUNT / 4))" >> generated/include/pack_count.h diff --git a/src/level/load.c b/src/level/load.c index 7293978..5e386c4 100644 --- a/src/level/load.c +++ b/src/level/load.c @@ -2,7 +2,6 @@ /* Copyright (C) 2021 KikooDX */ #include "conf.h" -#include "filepaths.h" #include "level.h" #include "tiles.h" #include @@ -23,26 +22,27 @@ int fatal_error = 0; char *fatal_error_msg = "no error, happy kikoo :D"; int debug_value = 0; +static uint16_t *filepath = u"none"; + +static void level_load_post(void); static int read_byte(int file); static Tile read_merge_bytes(int file, int size); static int autotile_value(int x, int y); /* Load level from storage memory. */ void -level_load(void) +level_load_bfile(void) { int file; int tile_size; int level_size; int file_size; int i; - int x; - int y; - char byte; + uint8_t byte; Tile tile; /* open file read only */ - file = BFile_Open(filepaths[level_id], BFile_ReadOnly); + file = BFile_Open(filepath, BFile_ReadOnly); assert(file >= 0, "can't open file"); /* assert KBLE format version */ @@ -71,35 +71,68 @@ level_load(void) "file size doesn't make sense"); /* read file content */ - level.gold = 0; - level.exit_locked = 0; for (i = 0; i < level_size; i += 1) { tile = read_merge_bytes(file, tile_size); assert(tile != (Tile)-1, "can't read tile"); level.data[i] = tile; - /* special tiles */ - switch (tile) { - case TILE_GOLD: - level.gold += 1; - break; - case TILE_SWITCH: - level.exit_locked = 1; - break; - default: - break; - } } + level_load_post(); + + /* close file */ + file = BFile_Close(file); + assert(file >= 0, "file closure failed miserably"); +} + +/* Load level bundled in game binary. */ +void +level_load_binary(void) +{ + extern uint8_t *level_binaries[]; + uint8_t *level_binary = level_binaries[level_id]; + int i; + + i = LEVEL_SIZE; + while (i-- > 0) + level.data[i] = level_binary[KBLE_HEADER_LEN + i]; + + level.width = LEVEL_WIDTH; + level.height = LEVEL_HEIGHT; + + level_load_post(); +} + +/* Shared post processing between BFile and binary level load. */ +static void +level_load_post(void) +{ + Tile tile; + int x; + int y; + + level.gold = 0; + level.exit_locked = 0; + /* set level id for display */ level.id = level_id; - /* compute visuals */ y = level.height; - i = 0; while (y-- > 0) { x = level.width; while (x-- > 0) { tile = level.data[x + y * level.width]; + /* special tiles */ + switch (tile) { + case TILE_GOLD: + level.gold += 1; + break; + case TILE_SWITCH: + level.exit_locked = 1; + break; + default: + break; + } + /* compute visuals */ struct VisualTile visual_data; visual_data.x = x * TILE_WIDTH; visual_data.y = y * TILE_HEIGHT; @@ -120,18 +153,14 @@ level_load(void) level.visual_data[x + y * level.width] = visual_data; } } - - /* close file */ - file = BFile_Close(file); - assert(file >= 0, "file closure failed miserably"); } /* Read a single byte. Negative value is BFile error code. */ static int read_byte(int file) { - char byte; - const int error = BFile_Read(file, &byte, sizeof(char), -1); + uint8_t byte; + const int error = BFile_Read(file, &byte, sizeof(uint8_t), -1); if (error < 0) return error; else @@ -145,7 +174,7 @@ read_merge_bytes(int file, int size) { Tile merged = 0; int byte = 0; - char *byte_ptr = (char *)&merged; + uint8_t *byte_ptr = (uint8_t *)&merged; int i = 0; byte_ptr += sizeof(Tile) - size; for (i = 0; i < size; i += 1) { diff --git a/src/levelselection/draw.c b/src/levelselection/draw.c index 5624eba..795fb15 100644 --- a/src/levelselection/draw.c +++ b/src/levelselection/draw.c @@ -2,8 +2,8 @@ /* Copyright (C) 2021 KikooDX */ #include "conf.h" -#include "filepaths.h" #include "levelselection.h" +#include "pack_count.h" #include "util.h" #include "zxcolors.h" #include diff --git a/src/levelselection/update.c b/src/levelselection/update.c index c374b97..82fbd73 100644 --- a/src/levelselection/update.c +++ b/src/levelselection/update.c @@ -1,9 +1,9 @@ /* SPDX-License-Identifier: GPL-3.0-or-later */ /* Copyright (C) 2021 KikooDX */ -#include "filepaths.h" #include "input.h" #include "levelselection.h" +#include "pack_count.h" #include "util.h" /* Return 1 if game state should change. */ diff --git a/src/main.c b/src/main.c index 18414c1..acf68ba 100644 --- a/src/main.c +++ b/src/main.c @@ -2,6 +2,7 @@ /* Copyright (C) 2021 KikooDX */ #include "conf.h" +#include "filepaths.h" #include "game_state.h" #include "input.h" #include "level.h" @@ -31,7 +32,7 @@ } while (0); #define LOAD_LEVEL() \ do { \ - gint_world_switch(GINT_CALL(level_load)); \ + gint_world_switch(GINT_CALL(level_load_binary)); \ if (fatal_error == -1) \ PANIC(fatal_error_msg); \ particles_init(); \ @@ -73,9 +74,11 @@ main(void) /* set font */ dfont(&font_main); + init_level_binaries(); + /* load level */ level_id = 0; - gint_world_switch(GINT_CALL(level_load)); + gint_world_switch(GINT_CALL(level_load_binary)); if (fatal_error == -1) PANIC(fatal_error_msg); /* timer setup */ diff --git a/src/mainmenu/update.c b/src/mainmenu/update.c index 1c7b930..e1ec516 100644 --- a/src/mainmenu/update.c +++ b/src/mainmenu/update.c @@ -1,7 +1,6 @@ /* SPDX-License-Identifier: GPL-3.0-or-later */ /* Copyright (C) 2021 KikooDX */ -#include "filepaths.h" #include "input.h" #include "mainmenu.h" diff --git a/src/player/draw.c b/src/player/draw.c index d374d1d..bbb49fb 100644 --- a/src/player/draw.c +++ b/src/player/draw.c @@ -2,7 +2,6 @@ /* Copyright (C) 2021 KikooDX */ #include "conf.h" -#include "filepaths.h" #include "level.h" #include "particles.h" #include "player.h" @@ -10,6 +9,7 @@ #include extern struct Level level; +extern char *const level_names[]; void player_draw(struct Player player)