mirror of https://git.sr.ht/~kikoodx/momento
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).
This commit is contained in:
parent
d0adef01e4
commit
25d928cef1
|
@ -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"
|
||||
|
|
|
@ -0,0 +1,3 @@
|
|||
*.kble:
|
||||
type: binary
|
||||
name_regex: (.*)\.kble kble_\1
|
|
@ -0,0 +1,3 @@
|
|||
*.kble:
|
||||
type: binary
|
||||
name_regex: (.*)\.kble kble_\1
|
|
@ -0,0 +1,3 @@
|
|||
*.kble:
|
||||
type: binary
|
||||
name_regex: (.*)\.kble kble_\1
|
|
@ -0,0 +1,5 @@
|
|||
/* SPDX-License-Identifier: GPL-3.0-or-later */
|
||||
/* Copyright (C) 2021 KikooDX */
|
||||
#pragma once
|
||||
|
||||
void init_level_binaries(void);
|
|
@ -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);
|
||||
|
|
|
@ -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 <stdint.h>\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 <stdint.h>\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
|
||||
|
|
|
@ -2,7 +2,6 @@
|
|||
/* Copyright (C) 2021 KikooDX */
|
||||
|
||||
#include "conf.h"
|
||||
#include "filepaths.h"
|
||||
#include "level.h"
|
||||
#include "tiles.h"
|
||||
#include <gint/bfile.h>
|
||||
|
@ -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) {
|
||||
|
|
|
@ -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 <gint/display.h>
|
||||
|
|
|
@ -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. */
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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"
|
||||
|
||||
|
|
|
@ -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 <gint/display.h>
|
||||
|
||||
extern struct Level level;
|
||||
extern char *const level_names[];
|
||||
|
||||
void
|
||||
player_draw(struct Player player)
|
||||
|
|
Loading…
Reference in New Issue