/* * This software is licensed under the terms of the MIT License. * See COPYING for further information. * --- * Copyright (c) 2011-2019, Lukas Weber . * Copyright (c) 2012-2019, Andrei Alexeyev . */ #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; }