bsnes/higan/target-bsnes/program/states.cpp

81 lines
2.5 KiB
C++

auto Program::loadState(string filename) -> bool {
if(!emulator->loaded()) return false;
string prefix = Location::file(filename);
vector<uint8_t> memory;
if(gamePath().endsWith("/")) {
string location = {statePath(), filename, ".bst"};
if(!file::exists(location)) return showMessage({"[", prefix, "] not found"}), false;
if(filename != "quick/recovery") saveRecoveryState();
memory = file::read(location);
} else {
string location = {filename, ".bst"};
Decode::ZIP input;
if(input.open(statePath())) {
for(auto& file : input.file) {
if(file.name != location) continue;
memory = input.extract(file);
break;
}
}
}
if(memory) {
serializer s{memory.data(), memory.size()};
if(!emulator->unserialize(s)) return showMessage({"[", prefix, "] is in incompatible format"}), false;
return showMessage({"Loaded [", prefix, "]"}), true;
} else {
return showMessage({"[", prefix, "] not found"}), false;
}
}
auto Program::saveState(string filename) -> bool {
if(!emulator->loaded()) return false;
string prefix = Location::file(filename);
serializer s = emulator->serialize();
if(!s.size()) return showMessage({"Failed to save [", prefix, "]"}), false;
if(gamePath().endsWith("/")) {
string location = {statePath(), filename, ".bst"};
directory::create(Location::path(location));
if(!file::write(location, s.data(), s.size())) return showMessage({"Unable to write [", prefix, "] to disk"}), false;
} else {
string location = {filename, ".bst"};
struct State {
string name;
vector<uint8_t> memory;
};
vector<State> states;
Decode::ZIP input;
if(input.open(statePath())) {
for(auto& file : input.file) {
if(!file.name.endsWith(".bst")) continue;
if(file.name == location) continue;
states.append({file.name, input.extract(file)});
}
}
Encode::ZIP output{statePath()};
for(auto& state : states) {
output.append(state.name, state.memory.data(), state.memory.size());
}
output.append(location, s.data(), s.size());
}
return showMessage({"Saved [", prefix, "]"}), true;
}
auto Program::saveRecoveryState() -> bool {
if(!emulator->loaded()) return false;
string location = {statePath(), "quick/recovery.bst"};
directory::create(Location::path(location));
serializer s = emulator->serialize();
if(!s.size()) return false;
if(!file::write(location, s.data(), s.size())) return false;
return true;
}