From 2dfad249ad1d2d0d998bb5909177502cb1a000ea Mon Sep 17 00:00:00 2001 From: Miloslav Ciz Date: Tue, 14 Jan 2025 13:40:22 +0100 Subject: [PATCH] Output replays --- game.h | 55 ++++++++++++++++++++++++++++++++++++++----------------- map.h | 17 ++++++++++++++++- racing.h | 46 ++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 100 insertions(+), 18 deletions(-) diff --git a/game.h b/game.h index 63b4e1a..6851851 100644 --- a/game.h +++ b/game.h @@ -357,8 +357,8 @@ char LCR_gameGetNextResourceStrChar(void) } /** - 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. + Seeks to the Nth resource string in the global resource file, after the magic + number, so that the name is now available for reading. */ void LCR_seekResourceByIndex(unsigned int index, char magicNumber) { @@ -368,31 +368,45 @@ void LCR_seekResourceByIndex(unsigned int index, char magicNumber) LCR_gameRewindResourceFile(); - while (index) + do { c = LCR_gameGetNextResourceFileChar(); - if (c == 0) - return; - if (c == magicNumber) - index--; - - do + { + if (index) + index--; + else + return; + } + + while (c != 0 && c != LCR_RESOURCE_FILE_SEPARATOR) c = LCR_gameGetNextResourceFileChar(); - while (c != LCR_RESOURCE_FILE_SEPARATOR && c != 0); - } - - do // skip magic number and name - c = LCR_gameGetNextResourceFileChar(); - while (c != LCR_RESOURCE_FILE_SEPARATOR2 && - c != LCR_RESOURCE_FILE_SEPARATOR && c != 0); + + } while (c); } void LCR_gameStartRun(unsigned int mapIndex) { + char mapName[LCR_MAP_NAME_MAX_LEN]; + LCR_seekResourceByIndex(mapIndex,'M'); - LCR_mapLoadFromStr(LCR_gameGetNextResourceStrChar); + + mapName[0] = 0; + + for (int i = 0; i < LCR_MAP_NAME_MAX_LEN; ++i) + { + char c = LCR_gameGetNextResourceFileChar(); + + if (c == LCR_RESOURCE_FILE_SEPARATOR2 || + c == LCR_RESOURCE_FILE_SEPARATOR || c == 0) + break; + + mapName[i] = c; + mapName[i + 1] = 0; + } + + LCR_mapLoadFromStr(LCR_gameGetNextResourceStrChar,mapName); LCR_gameSetState(LCR_GAME_STATE_LOADING_MAP); } @@ -821,6 +835,11 @@ void LCR_gameHandleInput(void) LCR_game.menu.selectedTab == 1 ? 'M' : 'R'); } +void _LCR_gameResourceCharWrite(char c) +{ + printf("%c",c); +} + uint8_t LCR_gameStep(uint32_t time) { uint32_t sleep = 0; @@ -871,6 +890,8 @@ uint8_t LCR_gameStep(uint32_t time) LCR_game.state != LCR_GAME_STATE_RUN_FINISHED) { LCR_LOG1("finished"); +LCR_replayOutputStr(_LCR_gameResourceCharWrite); + LCR_audioPlaySound(LCR_SOUND_CLICK); LCR_gameSetState(LCR_GAME_STATE_RUN_FINISHED); } diff --git a/map.h b/map.h index 96f3806..f656ce3 100644 --- a/map.h +++ b/map.h @@ -56,6 +56,8 @@ - last if C7 is set, the block is flipped vertically */ +#define LCR_MAP_NAME_MAX_LEN 15 /**< Maximum map name length (without + terminating zero. */ #define LCR_BLOCK_START_CHAR ':' #define LCR_BLOCK_TRANSFORM_FLIP_H 0x10 @@ -153,6 +155,8 @@ struct uint8_t checkpointCount; uint32_t hash; ///< Hash of the processed binary map. + + char name[LCR_MAP_NAME_MAX_LEN + 1]; } LCR_currentMap; void LCR_makeMapBlock(uint8_t type, uint8_t x, uint8_t y, uint8_t z, @@ -373,10 +377,21 @@ void _LCR_mapComputeHash(void) (LCR_currentMap.hash >> 13)) * 113; } -uint8_t LCR_mapLoadFromStr(char (*getNextCharFunc)(void)) +uint8_t LCR_mapLoadFromStr(char (*getNextCharFunc)(void), const char *name) { LCR_LOG0("loading map string"); + for (int i = 0; i < LCR_MAP_NAME_MAX_LEN; ++i) + { + LCR_currentMap.name[i] = *name; + LCR_currentMap.name[i + 1] = 0; + + if (*name == 0) + break; + + name++; + } + char c; uint8_t prevBlock[LCR_BLOCK_SIZE]; diff --git a/racing.h b/racing.h index cec6ead..82bff8d 100644 --- a/racing.h +++ b/racing.h @@ -145,6 +145,52 @@ void LCR_replayInitPlaying(void) LCR_replay.currentFrame = 0; } +char _LCR_hexDigit(int i) +{ + return i < 10 ? '0' + i : ('a' - 10 + i); +} + +/** + Outputs current replay using provided character printing function. The string + will be zero terminated. +*/ +void LCR_replayOutputStr(void (*printChar)(char)) +{ + LCR_LOG1("outputting replay"); + + const char *s = LCR_currentMap.name; + + while (*s) + { + printChar(*s); + s++; + } + + printChar(';'); + + uint32_t hash = LCR_currentMap.hash; + + for (int i = 0; i < 8; ++i) + { + printChar(_LCR_hexDigit(hash % 16)); + hash /= 16; + } + + for (int i = 0; i < LCR_replay.eventCount; ++i) + { + uint16_t e = LCR_replay.events[i]; + printChar(' '); + + for (int j = 0; j < 4; ++j) + { + printChar(_LCR_hexDigit(e % 16)); + e /= 16; + } + } + + printChar('\n'); +} + /** During playing of a replay returns the next input and shifts to next frame. */