#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; }