87 lines
3.4 KiB
C
87 lines
3.4 KiB
C
#include "kknd.h"
|
|
|
|
/* =========================================================================
|
|
* save.c - Binary save / load of skirmish state.
|
|
* ========================================================================= */
|
|
|
|
static void w32(FILE *f, uint32_t v) { fwrite(&v, 4, 1, f); }
|
|
static void wf(FILE *f, float v) { fwrite(&v, 4, 1, f); }
|
|
static void wi(FILE *f, int v) { fwrite(&v, 4, 1, f); }
|
|
static uint32_t r32(FILE *f) { uint32_t v = 0; fread(&v, 4, 1, f); return v; }
|
|
static float rf(FILE *f) { float v = 0; fread(&v, 4, 1, f); return v; }
|
|
static int ri(FILE *f) { int v = 0; fread(&v, 4, 1, f); return v; }
|
|
|
|
int save_game(Game *g, const char *path) {
|
|
FILE *f = fopen(path, "wb");
|
|
if (!f) return 0;
|
|
w32(f, SAVE_MAGIC);
|
|
w32(f, SAVE_VERSION);
|
|
wi(f, g->map.w); wi(f, g->map.h);
|
|
size_t n = (size_t)g->map.w * g->map.h;
|
|
for (size_t i = 0; i < n; i++) {
|
|
Tile *t = &g->map.tiles[i];
|
|
uint8_t buf[4] = { t->terrain, t->walkable, t->scrap, t->occupied };
|
|
fwrite(buf, 1, 4, f);
|
|
}
|
|
for (int i = 0; i < MAX_FACTIONS; i++) wf(f, (float)g->scrap[i]);
|
|
wf(f, g->time);
|
|
wi(f, g->unit_count); wi(f, g->unit_next_id);
|
|
fwrite(g->units, sizeof(Unit), (size_t)g->unit_count, f);
|
|
wi(f, g->bld_count); wi(f, g->bld_next_id);
|
|
fwrite(g->buildings, sizeof(Building), (size_t)g->bld_count, f);
|
|
wf(f, g->cam.x); wf(f, g->cam.y);
|
|
/* upgrades / research / mission */
|
|
wi(f, g->mission_id); wi(f, g->objective);
|
|
wi(f, (int)g->human); wi(f, (int)g->enemy);
|
|
for (int i = 0; i < MAX_FACTIONS; i++) {
|
|
for (int u = 0; u < UP_COUNT; u++) wi(f, g->upg[i].lvl[u]);
|
|
wi(f, g->research_lab[i]);
|
|
wi(f, g->research_cur[i]);
|
|
wf(f, g->research_prog[i]);
|
|
}
|
|
fclose(f);
|
|
engine_log("Game saved to %s", path);
|
|
return 1;
|
|
}
|
|
|
|
int load_game(Game *g, const char *path) {
|
|
FILE *f = fopen(path, "rb");
|
|
if (!f) return 0;
|
|
if (r32(f) != SAVE_MAGIC) { fclose(f); return 0; }
|
|
if (r32(f) != SAVE_VERSION) { fclose(f); return 0; }
|
|
int w = ri(f), h = ri(f);
|
|
map_free(&g->map);
|
|
g->map.w = w; g->map.h = h;
|
|
g->map.tiles = (Tile *)calloc((size_t)w*h, sizeof(Tile));
|
|
size_t n = (size_t)w*h;
|
|
for (size_t i = 0; i < n; i++) {
|
|
uint8_t buf[4];
|
|
if (fread(buf, 1, 4, f) != 4) break;
|
|
g->map.tiles[i].terrain = buf[0];
|
|
g->map.tiles[i].walkable = buf[1];
|
|
g->map.tiles[i].scrap = buf[2];
|
|
g->map.tiles[i].occupied = buf[3];
|
|
}
|
|
for (int i = 0; i < MAX_FACTIONS; i++) g->scrap[i] = (int)rf(f);
|
|
g->time = rf(f);
|
|
g->unit_count = ri(f); g->unit_next_id = ri(f);
|
|
if (g->unit_count > MAX_UNITS) g->unit_count = MAX_UNITS;
|
|
fread(g->units, sizeof(Unit), (size_t)g->unit_count, f);
|
|
g->bld_count = ri(f); g->bld_next_id = ri(f);
|
|
if (g->bld_count > MAX_BUILDINGS) g->bld_count = MAX_BUILDINGS;
|
|
fread(g->buildings, sizeof(Building), (size_t)g->bld_count, f);
|
|
g->cam.x = rf(f); g->cam.y = rf(f);
|
|
g->mission_id = ri(f); g->objective = ri(f);
|
|
g->human = (Faction)ri(f); g->enemy = (Faction)ri(f);
|
|
for (int i = 0; i < MAX_FACTIONS; i++) {
|
|
for (int u = 0; u < UP_COUNT; u++) g->upg[i].lvl[u] = ri(f);
|
|
g->research_lab[i] = ri(f);
|
|
g->research_cur[i] = ri(f);
|
|
g->research_prog[i] = rf(f);
|
|
}
|
|
g->sel_count = 0; g->placing = 0;
|
|
g->state = GAME_PLAYING;
|
|
fclose(f);
|
|
engine_log("Game loaded from %s", path);
|
|
return 1;
|
|
}
|