2018-06-27 01:56:27 +00:00
|
|
|
auto Program::managedStates() -> string_vector {
|
|
|
|
if(!emulator->loaded()) return {};
|
|
|
|
|
|
|
|
if(gamePath().endsWith("/")) {
|
|
|
|
return directory::ifiles({statePath(), "managed/"}, "*.bst");
|
|
|
|
} else {
|
|
|
|
Decode::ZIP input;
|
|
|
|
if(input.open(statePath())) {
|
|
|
|
string_vector filenames;
|
|
|
|
for(auto& file : input.file) {
|
|
|
|
if(file.name.match("managed/*.bst")) filenames.append(file.name);
|
|
|
|
}
|
|
|
|
filenames.isort();
|
|
|
|
return filenames;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return {};
|
|
|
|
}
|
|
|
|
|
2018-06-11 04:50:18 +00:00
|
|
|
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"};
|
|
|
|
|
2018-06-27 01:56:27 +00:00
|
|
|
struct State { string name; vector<uint8_t> memory; };
|
2018-06-11 04:50:18 +00:00
|
|
|
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 {
|
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;
|
|
|
|
saveState("quick/recovery");
|
|
|
|
this->statusTime = statusTime;
|
|
|
|
this->statusMessage = statusMessage;
|
2018-06-11 04:50:18 +00:00
|
|
|
}
|
2018-06-27 01:56:27 +00:00
|
|
|
|
|
|
|
auto Program::removeState(string filename) -> bool {
|
|
|
|
if(!emulator->loaded()) return false;
|
|
|
|
|
|
|
|
if(gamePath().endsWith("/")) {
|
|
|
|
string location = {statePath(), filename, ".bst"};
|
|
|
|
return file::remove(location);
|
|
|
|
} else {
|
|
|
|
bool found = false;
|
|
|
|
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 == location) { found = true; continue; }
|
|
|
|
states.append({file.name, input.extract(file)});
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if(states) {
|
|
|
|
Encode::ZIP output{statePath()};
|
|
|
|
for(auto& state : states) {
|
|
|
|
output.append(state.name, state.memory.data(), state.memory.size());
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
//remove .bsz file if there are no states left in the archive
|
|
|
|
file::remove(statePath());
|
|
|
|
}
|
|
|
|
|
|
|
|
return found;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
auto Program::renameState(string from, string to) -> bool {
|
|
|
|
if(!emulator->loaded()) return false;
|
|
|
|
|
|
|
|
if(gamePath().endsWith("/")) {
|
|
|
|
from = {statePath(), from, ".bst"};
|
|
|
|
to = {statePath(), to, ".bst."};
|
|
|
|
return file::rename(from, to);
|
|
|
|
} else {
|
|
|
|
bool found = false;
|
|
|
|
from = {from, ".bst"};
|
|
|
|
to = {to, ".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 == from) { found = true; file.name = to; }
|
|
|
|
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());
|
|
|
|
}
|
|
|
|
|
|
|
|
return found;
|
|
|
|
}
|
|
|
|
}
|