Hmm, I think there are probably many ways you can approach this. My first approach would be to have some per-frame information about input, perhaps in a form like this:
| typedef struct Input
{
b32 key_down[KEY_MAX];
b32 key_pressed[KEY_MAX];
b32 left_mouse_down;
f32 mouse_x;
f32 mouse_y;
// etc.
// If you want event-driven input, have that stuff in here as well?
}
Input;
|
Then, recording input is as easy as saving this memory for each frame, and then when playing it back, instead of filling out this struct with SDL's events, you could just fill it out with the saved input history that you are playing back.
I don't use SDL so I don't know, but alternatively you might be able to pipe events back through SDL if you save them to disk and reload them?
On your point about your
GameState struct not being able to be saved to disk, from what it sounds like, it very much sounds like you could just write that entire block of memory to disk, load it back up during a different instance of the program, and run with it, unless you are keeping pointers to further allocations in that storage (these pointers would no longer be valid if you loaded this memory at a different runtime).
From my understanding,
malloc will just call either
VirtualAlloc (what Casey uses to allocate his memory block at startup time) or
HeapAlloc (which calls
VirtualAlloc as necessary, as it will manage a heap within pages allocated by
VirtualAlloc) under the hood. There isn't really much difference between the memory you allocate for your
GameState struct and the memory Casey allocates. What you need to be careful about is when your memory contains pointers that reference memory that is allocated separately.