bsnes-plus/bsnes/ui-qt/state/state.cpp
2014-11-26 18:35:12 -05:00

111 lines
2.7 KiB
C++

#include "../ui-base.hpp"
State state;
bool State::save(unsigned slot) {
if(!allowed()) {
utility.showMessage("Cannot save state.");
return false;
}
SNES::system.runtosave();
serializer state = SNES::system.serialize();
file fp;
bool result = false;
if(fp.open(name(slot), file::mode::write)) {
fp.write(state.data(), state.size());
fp.close();
result = true;
}
if(result) {
utility.showMessage(string() << "State " << (slot + 1) << " saved.");
} else {
utility.showMessage(string() << "Failed to save state " << (slot + 1) << ".");
}
return result;
}
bool State::load(unsigned slot) {
if(!allowed()) {
utility.showMessage("Cannot load state.");
return false;
}
file fp;
bool result = false;
if(fp.open(name(slot), file::mode::read)) {
unsigned size = fp.size();
uint8_t *data = new uint8_t[size];
fp.read(data, size);
fp.close();
serializer state(data, size);
delete[] data;
result = SNES::system.unserialize(state);
}
if(result) {
utility.showMessage(string() << "State " << (slot + 1) << " loaded.");
resetHistory();
} else {
utility.showMessage(string() << "Failed to load state " << (slot + 1) << ".");
}
return result;
}
void State::frame() {
if(!allowed()) return;
if(!config().system.rewindEnabled) return;
//if a full second has passed, automatically capture state
if(++frameCounter >= (SNES::system.region() == SNES::System::Region::NTSC ? 60 : 50)) {
frameCounter = 0;
historyIndex = (historyIndex + 1) % historySize;
historyCount = min(historyCount + 1, historySize);
SNES::system.runtosave();
history[historyIndex] = SNES::system.serialize();
}
}
void State::resetHistory() {
historyIndex = 0;
historyCount = 0;
frameCounter = 0;
}
bool State::rewind() {
if(!allowed()) return false;
if(!config().system.rewindEnabled) return false;
if(historyCount == 0) return false;
serializer state(history[historyIndex].data(), history[historyIndex].size());
bool result = SNES::system.unserialize(state);
historyIndex = (historyIndex + historySize - 1) % historySize; //add historySize to prevent underflow
historyCount--;
return true;
}
State::State() {
active = 0;
historySize = 120;
history = new serializer[historySize];
for(unsigned i = 0; i < historySize; i++) history[i] = 0;
}
State::~State() {
delete[] history;
}
//
bool State::allowed() const {
if(!SNES::cartridge.loaded() || !application.power) return false;
if(movie.state != Movie::Inactive) return false;
return cartridge.saveStatesSupported();
}
string State::name(unsigned slot) const {
string name = filepath(nall::basename(cartridge.fileName), config().path.state);
name << "-" << (slot + 1) << ".bst";
return name;
}