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

233 lines
7.3 KiB
C++
Raw Normal View History

const uint Program::State::Signature = 0x5a22'0000;
auto Program::availableStates(string type) -> vector<State> {
vector<State> result;
if(!emulator->loaded()) return result;
if(gamePath().endsWith("/")) {
for(auto& file : directory::ifiles({statePath(), type}, "*.bst")) {
auto timestamp = file::timestamp({statePath(), type, file}, file::time::modify);
result.append({{type, file.trimRight(".bst", 1L)}, timestamp});
}
} else {
Decode::ZIP input;
if(input.open(statePath())) {
for(auto& file : input.file) {
if(!file.name.match({type, "*.bst"})) continue;
result.append({file.name.trimRight(".bst", 1L), (uint64_t)file.timestamp});
}
}
}
return result;
}
auto Program::hasState(string filename) -> bool {
if(!emulator->loaded()) return false;
if(gamePath().endsWith("/")) {
return file::exists({statePath(), filename, ".bst"});
} else {
auto type = string{filename.split("/").first(), "/"};
return (bool)availableStates(type).find([&](auto& state) { return state.name == filename; });
}
}
auto Program::loadStateData(string filename) -> vector<uint8_t> {
if(!emulator->loaded()) return {};
vector<uint8_t> memory;
if(gamePath().endsWith("/")) {
string location = {statePath(), filename, ".bst"};
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.size() < 3 * sizeof(uint)) return {}; //too small to be a valid state file
if(memory::readl<sizeof(uint)>(memory.data()) != State::Signature) return {}; //wrong format or version
return memory;
}
auto Program::loadState(string filename) -> bool {
string prefix = Location::file(filename);
if(auto memory = loadStateData(filename)) {
if(filename != "Quick/Undo") saveUndoState();
if(filename == "Quick/Undo") saveRedoState();
auto serializerRLE = Decode::RLE<1>({memory.data() + 3 * sizeof(uint), memory.size() - 3 * sizeof(uint)});
serializer s{serializerRLE.data(), serializerRLE.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;
auto serializerRLE = Encode::RLE<1>({s.data(), s.size()});
vector<uint8_t> previewRLE;
//this can be null if a state is captured before the first frame of video output after power/reset
if(screenshot.data) {
image preview;
preview.copy(screenshot.data, screenshot.pitch, screenshot.width, screenshot.height);
if(preview.width() != 256 || preview.height() != 240) preview.scale(256, 240, true);
preview.transform(0, 15, 0x8000, 0x7c00, 0x03e0, 0x001f);
previewRLE = Encode::RLE<2>({preview.data(), preview.size()});
}
vector<uint8_t> saveState;
saveState.resize(3 * sizeof(uint));
memory::writel<sizeof(uint)>(saveState.data() + 0 * sizeof(uint), State::Signature);
memory::writel<sizeof(uint)>(saveState.data() + 1 * sizeof(uint), serializerRLE.size());
memory::writel<sizeof(uint)>(saveState.data() + 2 * sizeof(uint), previewRLE.size());
saveState.append(serializerRLE);
saveState.append(previewRLE);
if(gamePath().endsWith("/")) {
string location = {statePath(), filename, ".bst"};
directory::create(Location::path(location));
if(!file::write(location, saveState)) {
return showMessage({"Unable to write [", prefix, "] to disk"}), false;
}
} else {
string location = {filename, ".bst"};
struct State { string name; time_t timestamp; 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, file.timestamp, input.extract(file)});
}
}
Update to v106r44 release. byuu says: Changelog: - hiro/Windows: use `WS_CLIPSIBLINGS` on Label to prevent resize drawing issues - bsnes: correct viewport resizing - bsnes: speed up window resizing a little bit - bsnes: fix the cheat editor list enable checkbox - bsnes: fix the state manager filename display in game ROM mode - bsnes: fix the state manager save/rename/remove functionality in game ROM mode - bsnes: correct path searching for IPS and BPS patches in game ROM mode - bsnes: patch BS-X town cartridge to disable play limits - bsnes: do not load (program,data,expansion).(rom,flash) from disk in game pak mode - this is required to support soft-patching and ROM hacks - bsnes: added speed mode selection (50%, 75%, 100%, 150%, 200%); maintains proper pitch - bsnes: added icons to the menubar - this is particularly useful to tell game ROMs from game paks in the load recent game menu - bsnes: added emblem at bottom left of status bar to indicate if a game is verified or not - verified means it is in the icarus verified game dump database - the verified diamond is orange; the unverified diamond is blue - bsnes: added an option (which defaults to off) to warn when loading unverified games - working around a bug in GTK, I have to use the uglier MessageWindow instead of MessageDialog - bsnes: added (non-functional) link to <https://doc.byuu.org/bsnes/> to the help menu - bsnes: added GUI setting to toggle memory auto-save feature - bsnes: added GUI setting to toggle capturing a backup save state when closing the emulator - bsnes: made auto-saving states on exit an option - bsnes: added an option to auto-load the auto-saved state on load - basically, the two combined implements auto-resume - bsnes: when firmware is missing, offer to take the user to the online help documentation - bsnes: added fast PPU option to disable the sprite limit - increase from 32 items/line + 34 tiles/line to 128 items/line + 128 tiles/line - technically, 1024 tiles/line are possible with 128 sprites at 64-width - but this is just a waste of cache locality and worst-case performance; it'll never happen Errata: - hiro/Windows: fallthrough on Canvas `WM_ERASEBKGND` to prevent startup flicker
2018-06-28 06:28:27 +00:00
input.close();
Encode::ZIP output{statePath()};
for(auto& state : states) {
output.append(state.name, state.memory.data(), state.memory.size(), state.timestamp);
}
output.append(location, saveState.data(), saveState.size());
}
if(filename.beginsWith("Quick/")) presentation.updateStateMenus();
stateManager.stateEvent(filename);
return showMessage({"Saved [", prefix, "]"}), true;
}
auto Program::saveUndoState() -> bool {
Update to v106r42 release. byuu says: Changelog: - emulator: added `Thread::setHandle(cothread_t)` - icarus: added special heuristics support for the Tengai Maykou Zero fan translation - board identifier is: EXSPC7110-RAM-EPSONRTC (match on SPC7110 + ROM size=56mbit) - board ROM contents are: 8mbit program, 40mbit data, 8mbit expansion (sizes are fixed) - bsnes: show messages on game load, unload, and reset - bsnes: added support for BS Memory and Sufami Turbo games - bsnes: added support for region selection (Auto [default], NTSC, PAL) - bsnes: correct presentation window size from 223/239 to 224/240 - bsnes: add SA-1 internal RAM on cartridges with BS Memory slot - bsnes: fixed recovery state to store inside .bsz archive - bsnes: added support for custom manifests in both game pak and game ROM modes - bsnes: added icarus game database support (manifest → database → heuristics) - bsnes: added flexible SuperFX overclocking - bsnes: added IPS and BPS soft-patching support to all ROM types (sfc,smc,gb,gbc,bs,st) - can load patches inside of ZIP archives (matches first “.ips” or “.bps” file) - bsnes/ppu: cache interlace/overscan/vdisp (277 → 291fps with fast PPU) - hiro/Windows: faster painting of Label widget on expose - hiro/Windows: immediately apply LineEdit::setBackgroundColor changes - hiro/Qt: inherit Window backgroundColor when one is not assigned to Label Errata: - sfc/ppu-fast: remove `renderMode7Hires()` function (the body isn't in the codebase) - bsnes: advanced note label should probably use a lighter text color and/or smaller font size instead of italics I didn't test the soft-patching at all, as I don't have any patches on my dev box. If anyone wants to test, that'd be great. The Tengai Makyou Zero fan translation would be a great test case.
2018-06-26 03:17:26 +00:00
auto statusTime = this->statusTime;
auto statusMessage = this->statusMessage;
auto result = saveState("Quick/Undo");
Update to v106r42 release. byuu says: Changelog: - emulator: added `Thread::setHandle(cothread_t)` - icarus: added special heuristics support for the Tengai Maykou Zero fan translation - board identifier is: EXSPC7110-RAM-EPSONRTC (match on SPC7110 + ROM size=56mbit) - board ROM contents are: 8mbit program, 40mbit data, 8mbit expansion (sizes are fixed) - bsnes: show messages on game load, unload, and reset - bsnes: added support for BS Memory and Sufami Turbo games - bsnes: added support for region selection (Auto [default], NTSC, PAL) - bsnes: correct presentation window size from 223/239 to 224/240 - bsnes: add SA-1 internal RAM on cartridges with BS Memory slot - bsnes: fixed recovery state to store inside .bsz archive - bsnes: added support for custom manifests in both game pak and game ROM modes - bsnes: added icarus game database support (manifest → database → heuristics) - bsnes: added flexible SuperFX overclocking - bsnes: added IPS and BPS soft-patching support to all ROM types (sfc,smc,gb,gbc,bs,st) - can load patches inside of ZIP archives (matches first “.ips” or “.bps” file) - bsnes/ppu: cache interlace/overscan/vdisp (277 → 291fps with fast PPU) - hiro/Windows: faster painting of Label widget on expose - hiro/Windows: immediately apply LineEdit::setBackgroundColor changes - hiro/Qt: inherit Window backgroundColor when one is not assigned to Label Errata: - sfc/ppu-fast: remove `renderMode7Hires()` function (the body isn't in the codebase) - bsnes: advanced note label should probably use a lighter text color and/or smaller font size instead of italics I didn't test the soft-patching at all, as I don't have any patches on my dev box. If anyone wants to test, that'd be great. The Tengai Makyou Zero fan translation would be a great test case.
2018-06-26 03:17:26 +00:00
this->statusTime = statusTime;
this->statusMessage = statusMessage;
return result;
}
auto Program::saveRedoState() -> bool {
auto statusTime = this->statusTime;
auto statusMessage = this->statusMessage;
auto result = saveState("Quick/Redo");
this->statusTime = statusTime;
this->statusMessage = statusMessage;
return result;
}
auto Program::removeState(string filename) -> bool {
if(!emulator->loaded()) return false;
bool result = false;
if(gamePath().endsWith("/")) {
string location = {statePath(), filename, ".bst"};
result = file::remove(location);
} else {
bool found = false;
string location = {filename, ".bst"};
struct State { string name; time_t timestamp; vector<uint8_t> memory; };
vector<State> states;
Decode::ZIP input;
if(input.open(statePath())) {
for(auto& file : input.file) {
if(file.name == location) { found = true; continue; }
states.append({file.name, file.timestamp, input.extract(file)});
}
}
Update to v106r44 release. byuu says: Changelog: - hiro/Windows: use `WS_CLIPSIBLINGS` on Label to prevent resize drawing issues - bsnes: correct viewport resizing - bsnes: speed up window resizing a little bit - bsnes: fix the cheat editor list enable checkbox - bsnes: fix the state manager filename display in game ROM mode - bsnes: fix the state manager save/rename/remove functionality in game ROM mode - bsnes: correct path searching for IPS and BPS patches in game ROM mode - bsnes: patch BS-X town cartridge to disable play limits - bsnes: do not load (program,data,expansion).(rom,flash) from disk in game pak mode - this is required to support soft-patching and ROM hacks - bsnes: added speed mode selection (50%, 75%, 100%, 150%, 200%); maintains proper pitch - bsnes: added icons to the menubar - this is particularly useful to tell game ROMs from game paks in the load recent game menu - bsnes: added emblem at bottom left of status bar to indicate if a game is verified or not - verified means it is in the icarus verified game dump database - the verified diamond is orange; the unverified diamond is blue - bsnes: added an option (which defaults to off) to warn when loading unverified games - working around a bug in GTK, I have to use the uglier MessageWindow instead of MessageDialog - bsnes: added (non-functional) link to <https://doc.byuu.org/bsnes/> to the help menu - bsnes: added GUI setting to toggle memory auto-save feature - bsnes: added GUI setting to toggle capturing a backup save state when closing the emulator - bsnes: made auto-saving states on exit an option - bsnes: added an option to auto-load the auto-saved state on load - basically, the two combined implements auto-resume - bsnes: when firmware is missing, offer to take the user to the online help documentation - bsnes: added fast PPU option to disable the sprite limit - increase from 32 items/line + 34 tiles/line to 128 items/line + 128 tiles/line - technically, 1024 tiles/line are possible with 128 sprites at 64-width - but this is just a waste of cache locality and worst-case performance; it'll never happen Errata: - hiro/Windows: fallthrough on Canvas `WM_ERASEBKGND` to prevent startup flicker
2018-06-28 06:28:27 +00:00
input.close();
if(states) {
Encode::ZIP output{statePath()};
for(auto& state : states) {
output.append(state.name, state.memory.data(), state.memory.size(), state.timestamp);
}
} else {
//remove .bsz file if there are no states left in the archive
file::remove(statePath());
}
result = found;
}
if(result) {
presentation.updateStateMenus();
stateManager.stateEvent(filename);
}
return result;
}
auto Program::renameState(string from_, string to_) -> bool {
if(!emulator->loaded()) return false;
bool result = false;
if(gamePath().endsWith("/")) {
string from = {statePath(), from_, ".bst"};
string to = {statePath(), to_, ".bst"};
result = file::rename(from, to);
} else {
bool found = false;
string from = {from_, ".bst"};
string to = {to_, ".bst"};
struct State { string name; time_t timestamp; vector<uint8_t> memory; };
vector<State> states;
Decode::ZIP input;
if(input.open(statePath())) {
for(auto& file : input.file) {
if(file.name == from) { found = true; file.name = to; }
states.append({file.name, file.timestamp, input.extract(file)});
}
}
Update to v106r44 release. byuu says: Changelog: - hiro/Windows: use `WS_CLIPSIBLINGS` on Label to prevent resize drawing issues - bsnes: correct viewport resizing - bsnes: speed up window resizing a little bit - bsnes: fix the cheat editor list enable checkbox - bsnes: fix the state manager filename display in game ROM mode - bsnes: fix the state manager save/rename/remove functionality in game ROM mode - bsnes: correct path searching for IPS and BPS patches in game ROM mode - bsnes: patch BS-X town cartridge to disable play limits - bsnes: do not load (program,data,expansion).(rom,flash) from disk in game pak mode - this is required to support soft-patching and ROM hacks - bsnes: added speed mode selection (50%, 75%, 100%, 150%, 200%); maintains proper pitch - bsnes: added icons to the menubar - this is particularly useful to tell game ROMs from game paks in the load recent game menu - bsnes: added emblem at bottom left of status bar to indicate if a game is verified or not - verified means it is in the icarus verified game dump database - the verified diamond is orange; the unverified diamond is blue - bsnes: added an option (which defaults to off) to warn when loading unverified games - working around a bug in GTK, I have to use the uglier MessageWindow instead of MessageDialog - bsnes: added (non-functional) link to <https://doc.byuu.org/bsnes/> to the help menu - bsnes: added GUI setting to toggle memory auto-save feature - bsnes: added GUI setting to toggle capturing a backup save state when closing the emulator - bsnes: made auto-saving states on exit an option - bsnes: added an option to auto-load the auto-saved state on load - basically, the two combined implements auto-resume - bsnes: when firmware is missing, offer to take the user to the online help documentation - bsnes: added fast PPU option to disable the sprite limit - increase from 32 items/line + 34 tiles/line to 128 items/line + 128 tiles/line - technically, 1024 tiles/line are possible with 128 sprites at 64-width - but this is just a waste of cache locality and worst-case performance; it'll never happen Errata: - hiro/Windows: fallthrough on Canvas `WM_ERASEBKGND` to prevent startup flicker
2018-06-28 06:28:27 +00:00
input.close();
Encode::ZIP output{statePath()};
for(auto& state : states) {
output.append(state.name, state.memory.data(), state.memory.size(), state.timestamp);
}
result = found;
}
if(result) {
stateManager.stateEvent(to_);
}
return result;
}