From c3dcd1ff0f596b489127069d187dd900bc641bbd Mon Sep 17 00:00:00 2001 From: Miloslav Ciz Date: Mon, 30 Dec 2024 00:49:41 +0100 Subject: [PATCH] Start resource files --- TODO.txt | 17 +++++++ assets.h | 11 +++-- constants.h | 3 ++ frontend_sdl.c | 10 +++++ game.h | 119 +++++++++++++++++++++++++++++++++++++++++++++---- settings.h | 5 +++ 6 files changed, 154 insertions(+), 11 deletions(-) diff --git a/TODO.txt b/TODO.txt index 5fe6400..4aa8c10 100644 --- a/TODO.txt +++ b/TODO.txt @@ -1,10 +1,27 @@ =========== GENERAL ============== +- prevent time overflow! stop incrementing level frame once it's at maximum - asset system: - assets are to be loaded from one BIG string consisting of substrings, each substring adds a map, replay, setting etc. - part of the substring will be hardcoded (default maps) - optionally a frontend can extend this from a file + - details: + - strings separated by '#' + - each string has format: + - magic number: + - map: LM + - replay: LR + - record time: LT + - name + - ';' + - string content + - map: see map.h + - replay: + - map name + - map hash + - data: frame, input state + - record time: decimal time in ms - make the racing module usable by itself, e.g. to allow making tools for verifying replays etc., i.e. make the module measure time, count checkpoints etc. diff --git a/assets.h b/assets.h index 72a5ea1..902ea68 100644 --- a/assets.h +++ b/assets.h @@ -16,8 +16,8 @@ #include #include "map.h" -static const char *LCR_maps[] = -{ +static const char *LCR_internalResourceFile = + "testmap;" "0 :*H1k0J" ":=s0s0 :fd190" // big concrete @@ -58,7 +58,12 @@ static const char *LCR_maps[] = ":}l0k0L :|l1k0L :|l3k0L- :]l4k0L- :=k0k0 :f1510" ":]l0j0L :|l1j0L :|l3j0L- :]l4j0L- :=k0j0 :f1510" ":-k5k0 :f5120" -}; + " map end " + + "#map2;1 :*H1k0J :,s0s0 :fd190 " + +; + #define LCR_IMAGE_SIZE 64 ///< one-dimension resolution of bitmap image #define LCR_IMAGE_STORE_SIZE (LCR_IMAGE_SIZE * LCR_IMAGE_SIZE + 256 * 2) diff --git a/constants.h b/constants.h index a2fd24a..c1d144b 100644 --- a/constants.h +++ b/constants.h @@ -33,4 +33,7 @@ #define LCR_FONT_PIXEL_SIZE (1 + LCR_EFFECTIVE_RESOLUTION_X / 512) +#define LCR_RESOURCE_FILE_SEPARATOR '#' +#define LCR_RESOURCE_FILE_SEPARATOR2 ';' + #endif diff --git a/frontend_sdl.c b/frontend_sdl.c index 3b38ce0..743b99f 100644 --- a/frontend_sdl.c +++ b/frontend_sdl.c @@ -14,6 +14,16 @@ uint16_t screen[LCR_SETTING_RESOLUTION_X * LCR_SETTING_RESOLUTION_Y]; FILE *musicFile = 0; +char LCR_getNextResourceFileChar(void) +{ + return 0; +} + +void LCR_appendResourceStr(const char *str) +{ + return; +} + void audioFillCallback(void *userdata, uint8_t *s, int l) { if (musicFile) diff --git a/game.h b/game.h index 53f4aba..ff1ca20 100644 --- a/game.h +++ b/game.h @@ -79,6 +79,26 @@ void LCR_drawPixel(unsigned long index, uint16_t color); */ void LCR_log(const char *str); +/** + Implement this in your frontend. This function serves for loading optional + resource file that allows to add more maps, replays etc. If your frontend + won't support this, just make the function return 0. Otherwise it must return + characters from the resource file one by one; after reaching the end of file + 0 must be returned and the reading position will be reset to start again. +*/ +char LCR_getNextResourceFileChar(void); + +/** + Implement this in your frontend. This serves to store data in the optional + resource file, e.g. replays. If your frontend doesn't support this (e.g. + because the file is read only), the function may ignore the append, but if + the file is otherwise supported, a rewind of the read position must still be + done. If appending is supported, the function must append the provided string + to the resource file AND then reset the resource file reading position back to + the start. +*/ +void LCR_appendResourceStr(const char *str); + /** Call this function in your frontend at the start of the program. */ @@ -142,11 +162,13 @@ struct uint8_t state; uint32_t stateStartTime; uint32_t time; + uint32_t frame; uint32_t nextRenderFrameTime; uint32_t nextRacingTickTime; uint8_t controlMode; uint8_t debugDraw; uint8_t musicVolume; + int resourceFileState; ///< -1 if reading external res. f., else pos. } LCR_game; uint8_t LCR_gameGetMusicVolume(void) @@ -224,26 +246,103 @@ void LCR_gameResetRun(void) LCR_gameSetState(LCR_GAME_STATE_RUN_STARTING); } - - -int aaaa = 0; // tmp -char aaa(void) +void LCR_gameRewindResourceFile(void) { - return LCR_maps[0][aaaa++]; + LCR_appendResourceStr(""); + LCR_game.resourceFileState = 0; } +/** + Reads the next resource file character while merging the internal resource + file with the optional user file. First the internal file will be read, + immediately followed by the user file, then zero char will return and + reading will start over. +*/ +char LCR_gameGetNextResourceFileChar(void) +{ +#if LCR_SETTING_ENABLE_RESOURCE_FILE + char c; + if (LCR_game.resourceFileState < 0) // external file? + { + c = LCR_getNextResourceFileChar(); + + if (c == 0) + LCR_game.resourceFileState = 0; // move to internal file next + } + else // internal file + { + c = LCR_internalResourceFile[LCR_game.resourceFileState]; + LCR_game.resourceFileState++; + + if (c == 0) + { + c = LCR_getNextResourceFileChar(); + LCR_game.resourceFileState = c ? -1 : 0; // trust this + } + } + + return c; +#else + if (LCR_internalResourceFile[LCR_game.resourceFileState] == 0) + { + LCR_game.resourceFileState = 0; + return 0; + } + + return LCR_internalResourceFile[LCR_game.resourceFileState++]; +#endif +} + +/** + Similar to LCR_gameGetNextResourceFileChar, but returns 0 instead of the + resource string separator character. This function is means to be used by + functions that load something from a string while expecting a zero terminated + string. +*/ +char LCR_gameGetNextResourceStrChar(void) +{ + char c = LCR_gameGetNextResourceFileChar(); + return c != LCR_RESOURCE_FILE_SEPARATOR ? c : 0; +} + +/** + Seeks to the Nth resource string in the global resource file, after its name, + so that the pure resource string will now be available for reading. +*/ +void LCR_seekResourceByIndex(unsigned int index) +{ + char c; + + LCR_LOG0("seeking resource string"); + + LCR_gameRewindResourceFile(); + + while (index) + { + do + c = LCR_gameGetNextResourceFileChar(); + while (c != LCR_RESOURCE_FILE_SEPARATOR && c != 0); + + index--; + } + + do // skip the name + c = LCR_gameGetNextResourceFileChar(); + while (c != LCR_RESOURCE_FILE_SEPARATOR2 && + c != LCR_RESOURCE_FILE_SEPARATOR && c != 0); +} void LCR_gameStartRun(void) { - LCR_mapLoadFromStr(aaa); +LCR_seekResourceByIndex(0); // TODO + + LCR_mapLoadFromStr(LCR_gameGetNextResourceStrChar); LCR_rendererLoadMap(); LCR_gameResetRun(); LCR_racingRestart(); } - - void LCR_gameInit(void) { LCR_LOG0("initializing"); @@ -255,6 +354,9 @@ void LCR_gameInit(void) LCR_racingInit(); LCR_audioInit(); + LCR_game.resourceFileState = 0; + + LCR_game.frame = 0; LCR_game.musicVolume = 255; LCR_game.nextRenderFrameTime = 0; LCR_game.nextRacingTickTime = 0; @@ -444,6 +546,7 @@ LCR_audioSetEngineIntensity((2 * val) < 256 ? (2 * val) : 255); LCR_LOG1("can't sleep, frames take too long!"); } + LCR_game.frame++; LCR_LOG2("game step end"); return 1; diff --git a/settings.h b/settings.h index 5b8b987..813ee3d 100644 --- a/settings.h +++ b/settings.h @@ -177,4 +177,9 @@ #define LCR_SETTING_MUSIC 1 #endif +#ifndef LCR_SETTING_ENABLE_RESOURCE_FILE + /** May be used to disable using the user resource file. */ + #define LCR_SETTING_ENABLE_RESOURCE_FILE 1 +#endif + #endif // guard