Add replay loading

This commit is contained in:
Miloslav Ciz 2025-01-15 23:08:31 +01:00
parent 9485a7cd95
commit 8040d6755f
3 changed files with 85 additions and 13 deletions

14
game.h
View file

@ -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 Helper subroutine, handles user input during main loop frame, EXCEPT for the
driving input (that is handled in the loop itself). driving input (that is handled in the loop itself).
@ -791,8 +796,8 @@ void LCR_gameHandleInput(void)
case LCR_GAME_STATE_RUN_FINISHED: case LCR_GAME_STATE_RUN_FINISHED:
if (LCR_game.keyStates[LCR_KEY_A] == 1) if (LCR_game.keyStates[LCR_KEY_A] == 1)
//LCR_gameResetRun(LCR_racing.playingReplay); // LCR_gameResetRun(LCR_racing.playingReplay);
LCR_gameResetRun(1); LCR_gameResetRun(1);
break; break;
@ -858,11 +863,6 @@ void LCR_gameHandleInput(void)
LCR_game.menu.selectedTab == 1 ? 'M' : 'R'); LCR_game.menu.selectedTab == 1 ? 'M' : 'R');
} }
void _LCR_gameResourceCharWrite(char c)
{
printf("%c",c);
}
uint8_t LCR_gameStep(uint32_t time) uint8_t LCR_gameStep(uint32_t time)
{ {
uint32_t sleep = 0; uint32_t sleep = 0;

View file

@ -53,4 +53,15 @@ char _LCR_hexDigit(int i)
return i < 10 ? '0' + i : ('a' - 10 + 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 #endif // guard

View file

@ -16,11 +16,12 @@
- Replay text format: first there is the name of the map terminated by ';', - Replay text format: first there is the name of the map terminated by ';',
then hexadecimal hash of the map follows (exactly 8 characters), then then hexadecimal hash of the map follows (exactly 8 characters), then
blank character follows, then achieved time as a series of decimal digits blank character follows, then achieved time as a series of decimal digits
expressing the number of milliseconds, then a non-decimal character follows, expressing the number of milliseconds, then the replay data, i.e. the series
then the replay data, i.e. the series of 16 bit words in hexadecimal. The of 16 bit words in hexadecimal, each preceded by ':'. The events (but
blocks (but nothing else) may be preceeded or followed by blank characters. nothing else) may otherwise be preceeded or followed by other characters
All hexadecimal letters must be lowercase. The word 00000000 may optinally (possible comments). All hexadecimal letters must be lowercase. The word
be used to terminate the replay, the rest of the string will be ignored. 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 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) for (int i = 0; i < LCR_replay.eventCount; ++i)
{ {
uint16_t e = LCR_replay.events[i]; uint16_t e = LCR_replay.events[i];
printChar(' '); printChar(':');
for (int j = 0; j < 4; ++j) for (int j = 0; j < 4; ++j)
{ {
@ -201,6 +202,66 @@ void LCR_replayOutputStr(void (*printChar)(char))
printChar('\n'); 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. During playing of a replay returns the next input and shifts to next frame.
*/ */