Added basic game save function, doesn't save much yet, but implements version comparison of binary saves for compatibility

This commit is contained in:
2026-05-08 23:15:11 -04:00
parent 0bd1ae1df8
commit ff6b282112
5 changed files with 59 additions and 23 deletions

View File

@@ -4,6 +4,7 @@
#include <SDL3_ttf/SDL_ttf.h>
#include <stdio.h>
#include <akerror.h>
#include <semver.h>
#include <akgl/game.h>
#include <akgl/controller.h>
@@ -127,34 +128,61 @@ akerr_ErrorContext AKERR_NOIGNORE *akgl_game_save(char *fpath)
PREPARE_ERROR(errctx);
FAIL_ZERO_RETURN(errctx, fpath, AKERR_NULLPOINTER, "NULL file path");
fp = fopen(fpath, "rb");
fp = fopen(fpath, "wb");
FAIL_ZERO_RETURN(errctx, fp, errno, "%s", fpath);
fwrite(&game, 1, sizeof(akgl_Game), fp);
fclose(fp);
SUCCEED(errctx); // SUCCEED_NORETURN if in main().
SUCCEED_RETURN(errctx); // SUCCEED_NORETURN if in main().
}
akerr_ErrorContext AKERR_NOIGNORE *akgl_game_load(char *fpath)
{
FILE *fp = NULL;
char version[32];
char versionstr[32];
semver_t current_version = {};
semver_t compare_version = {};
PREPARE_ERROR(errctx);
FAIL_ZERO_RETURN(errctx, fpath, AKERR_NULLPOINTER, "NULL file path");
fp = fopen(fpath, "rb");
FAIL_ZERO_RETURN(
errctx,
(fread((void *)&version, 1, 32, fp) < 32),
AKERR_IO,
ATTEMPT {
FAIL_NONZERO_BREAK(
errctx,
semver_parse((const char *)&game.version, &current_version),
AKERR_VALUE,
"Invalid semantic version in current game: %s",
(char *)&current_version);
fp = fopen(fpath, "rb");
FAIL_NONZERO_BREAK(
errctx,
(fread((void *)&versionstr, 1, 32, fp) < 32),
AKERR_IO,
"Corrupt save file");
FAIL_NONZERO_BREAK(
errctx,
semver_parse((const char *)&versionstr, &compare_version),
AKERR_VALUE,
"Invalid semantic version in save game: %s",
(char *)&versionstr);
FAIL_ZERO_BREAK(
errctx,
semver_satisfies(compare_version, current_version, "^"),
AKERR_API,
"Incompatible save game version");
rewind(fp);
FAIL_NONZERO_BREAK(
errctx,
(fread((void *)&game, 1, sizeof(akgl_Game), fp) < sizeof(akgl_Game)),
AKERR_IO,
"Corrupt save file");
FAIL_ZERO_RETURN(
errctx,
strncmp((char *)&game.version, (char *)&version, 32),
AKERR_API,
"Save game can not be loaded, it is from an incompatible version");
rewind(fp);
FAIL_ZERO_RETURN(
errctx,
(fread((void *)&game, 1, sizeof(akgl_Game), fp) < sizeof(akgl_Game)),
AKERR_IO,
"Corrupt save file");
SUCCEED(errctx);
} CLEANUP {
if ( fp != NULL ) {
fclose(fp);
}
semver_free(&current_version);
semver_free(&compare_version);
} PROCESS(errctx) {
} FINISH(errctx, true);
SUCCEED_RETURN(errctx);
}