taisei/src/replay/replay.c
2023-06-17 21:53:24 +02:00

154 lines
3.4 KiB
C

/*
* This software is licensed under the terms of the MIT License.
* See COPYING for further information.
* ---
* Copyright (c) 2011-2019, Lukas Weber <laochailan@web.de>.
* Copyright (c) 2012-2019, Andrei Alexeyev <akari@taisei-project.org>.
*/
#include "taisei.h"
#include "replay.h"
#include "struct.h"
#include "stage.h"
#include "state.h"
void replay_destroy_events(Replay *rpy) {
dynarray_foreach_elem(&rpy->stages, ReplayStage *stg, {
replay_stage_destroy_events(stg);
});
}
void replay_reset(Replay *rpy) {
replay_destroy_events(rpy);
dynarray_free_data(&rpy->stages);
mem_free(rpy->playername);
memset(rpy, 0, sizeof(Replay));
}
static char *replay_getpath(const char *name, bool ext) {
return ext ?
strfmt("storage/replays/%s.%s", name, REPLAY_EXTENSION) :
strfmt("storage/replays/%s", name);
}
bool replay_save(Replay *rpy, const char *name) {
char *p = replay_getpath(name, !strendswith(name, REPLAY_EXTENSION));
char *sp = vfs_repr(p, true);
log_info("Saving %s", sp);
mem_free(sp);
SDL_RWops *file = vfs_open(p, VFS_MODE_WRITE);
mem_free(p);
if(!file) {
log_error("VFS error: %s", vfs_get_error());
return false;
}
bool result = replay_write(rpy, file, REPLAY_STRUCT_VERSION_WRITE);
SDL_RWclose(file);
vfs_sync(VFS_SYNC_STORE, NO_CALLCHAIN);
return result;
}
static const char *replay_mode_string(ReplayReadMode mode) {
if((mode & REPLAY_READ_ALL) == REPLAY_READ_ALL) {
return "full";
}
if(mode & REPLAY_READ_META) {
return "meta";
}
if(mode & REPLAY_READ_EVENTS) {
return "events";
}
log_fatal("Bad mode %i", mode);
}
bool replay_load_vfspath(Replay *rpy, const char *path, ReplayReadMode mode) {
char *sp = vfs_repr(path, true);
log_info("Loading %s (%s)", sp, replay_mode_string(mode));
SDL_RWops *file = vfs_open(path, VFS_MODE_READ);
if(!file) {
log_error("VFS error: %s", vfs_get_error());
mem_free(sp);
return false;
}
bool result = replay_read(rpy, file, mode, sp);
mem_free(sp);
SDL_RWclose(file);
return result;
}
bool replay_load(Replay *rpy, const char *name, ReplayReadMode mode) {
char *p = replay_getpath(name, !strendswith(name, REPLAY_EXTENSION));
bool result = replay_load_vfspath(rpy, p, mode);
mem_free(p);
return result;
}
bool replay_load_syspath(Replay *rpy, const char *path, ReplayReadMode mode) {
log_info("Loading %s (%s)", path, replay_mode_string(mode));
SDL_RWops *file;
if(!strcmp(path, "-")) {
file = SDL_RWFromFP(stdin, false);
if(!file) {
log_sdl_error(LOG_ERROR, "SDL_RWFromFP");
return false;
}
} else {
file = SDL_RWFromFile(path, "rb");
if(!file) {
log_sdl_error(LOG_ERROR, "SDL_RWFromFile");
return false;
}
}
bool result = replay_read(rpy, file, mode, path);
SDL_RWclose(file);
return result;
}
bool replay_save_syspath(Replay *rpy, const char *path, uint16_t version) {
log_info("Saving %s", path);
SDL_RWops *file;
if(!strcmp(path, "-")) {
file = SDL_RWFromFP(stdout, false);
if(!file) {
log_sdl_error(LOG_ERROR, "SDL_RWFromFP");
return false;
}
} else {
file = SDL_RWFromFile(path, "wb");
if(!file) {
log_sdl_error(LOG_ERROR, "SDL_RWFromFile");
return false;
}
}
bool result = replay_write(rpy, file, version);
SDL_RWclose(file);
return result;
}
int replay_find_stage_idx(Replay *rpy, uint8_t stageid) {
dynarray_foreach(&rpy->stages, int i, ReplayStage *stg, {
if(stg->stage == stageid) {
return i;
}
});
log_warn("Stage %X was not found in the replay", stageid);
return -1;
}