From 8040d6755f2a32fac85227865c2787147ebf941d Mon Sep 17 00:00:00 2001 From: Miloslav Ciz Date: Wed, 15 Jan 2025 23:08:31 +0100 Subject: [PATCH] Add replay loading --- game.h | 14 +++++------ general.h | 11 +++++++++ racing.h | 73 ++++++++++++++++++++++++++++++++++++++++++++++++++----- 3 files changed, 85 insertions(+), 13 deletions(-) diff --git a/game.h b/game.h index 20b2fc7..2cc9661 100644 --- a/game.h +++ b/game.h @@ -666,6 +666,11 @@ void LCR_gameDraw3DView(void) } } +void _LCR_gameResourceCharWrite(char c) +{ // TODO + printf("%c",c); +} + /** Helper subroutine, handles user input during main loop frame, EXCEPT for the driving input (that is handled in the loop itself). @@ -791,8 +796,8 @@ void LCR_gameHandleInput(void) case LCR_GAME_STATE_RUN_FINISHED: if (LCR_game.keyStates[LCR_KEY_A] == 1) - //LCR_gameResetRun(LCR_racing.playingReplay); - LCR_gameResetRun(1); +// LCR_gameResetRun(LCR_racing.playingReplay); + LCR_gameResetRun(1); break; @@ -858,11 +863,6 @@ 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; diff --git a/general.h b/general.h index 8cce340..cf3987e 100644 --- a/general.h +++ b/general.h @@ -53,4 +53,15 @@ char _LCR_hexDigit(int i) return i < 10 ? '0' + i : ('a' - 10 + i); } +int _LCR_hexDigitVal(char c) +{ + if (c >= '0' && c <= '9') + return c - '0'; + + if (c >= 'a' && c <= 'f') + return c - 'a' + 10; + + return -1; +} + #endif // guard diff --git a/racing.h b/racing.h index 549d243..8f0b85f 100644 --- a/racing.h +++ b/racing.h @@ -16,11 +16,12 @@ - Replay text format: first there is the name of the map terminated by ';', then hexadecimal hash of the map follows (exactly 8 characters), then blank character follows, then achieved time as a series of decimal digits - expressing the number of milliseconds, then a non-decimal character follows, - then the replay data, i.e. the series of 16 bit words in hexadecimal. The - blocks (but nothing else) may be preceeded or followed by blank characters. - All hexadecimal letters must be lowercase. The word 00000000 may optinally - be used to terminate the replay, the rest of the string will be ignored. + expressing the number of milliseconds, then the replay data, i.e. the series + of 16 bit words in hexadecimal, each preceded by ':'. The events (but + nothing else) may otherwise be preceeded or followed by other characters + (possible comments). All hexadecimal letters must be lowercase. The word + 00000000 may optinally be used to terminate the replay, the rest of the + string will be ignored. */ typedef int32_t LCR_GameUnit; ///< abstract game unit @@ -189,7 +190,7 @@ void LCR_replayOutputStr(void (*printChar)(char)) for (int i = 0; i < LCR_replay.eventCount; ++i) { uint16_t e = LCR_replay.events[i]; - printChar(' '); + printChar(':'); for (int j = 0; j < 4; ++j) { @@ -201,6 +202,66 @@ void LCR_replayOutputStr(void (*printChar)(char)) printChar('\n'); } +/** + Reads replay from string using provided function that returns next character + in the string. Returns 1 on success, else 0. +*/ +int LCR_replayLoadFromStr(char (*nextChar)(void)) +{ + char c = ' '; + + LCR_replay.eventCount = 0; + LCR_replay.achievedTime = 0; + + do // map name + { + c = nextChar(); + + if (c == 0) + return 0; + } while (c != ';'); + + for (int i = 0; i < 8; ++i) // hash + if (_LCR_hexDigitVal(nextChar()) < 0) + return 0; + + nextChar(); + + while (1) // time + { + c = nextChar(); + + if (c < '0' || c > '9') + break; + + LCR_replay.achievedTime = LCR_replay.achievedTime * 10 + c - '0'; + } + + while (c != 0) // events + { + if (c == ':') + { + uint16_t e = 0; + + for (int i = 0; i < 4; ++i) + e = (e << 4) | _LCR_hexDigitVal(nextChar()); + + if (e == 0) + break; + + if (LCR_replay.eventCount >= LCR_SETTING_REPLAY_MAX_SIZE) + return 0; + + LCR_replay.events[LCR_replay.eventCount] = e; + LCR_replay.eventCount++; + } + + c = nextChar(); + } + + return 1; +} + /** During playing of a replay returns the next input and shifts to next frame. */