1 #include "../ui-base.hpp" 2 State state; 3 save(unsigned slot)4bool State::save(unsigned slot) { 5 if(!allowed()) return false; 6 7 SNES::system.runtosave(); 8 serializer state = SNES::system.serialize(); 9 10 file fp; 11 bool result = false; 12 if(fp.open(name(slot), file::mode_write)) { 13 fp.write(state.data(), state.size()); 14 fp.close(); 15 result = true; 16 } 17 18 if(result) { 19 utility.showMessage(string() << "State " << (slot + 1) << " saved."); 20 } else { 21 utility.showMessage(string() << "Failed to save state " << (slot + 1) << "."); 22 } 23 return result; 24 } 25 load(unsigned slot)26bool State::load(unsigned slot) { 27 if(!allowed()) return false; 28 29 file fp; 30 bool result = false; 31 if(fp.open(name(slot), file::mode_read)) { 32 unsigned size = fp.size(); 33 uint8_t *data = new uint8_t[size]; 34 fp.read(data, size); 35 fp.close(); 36 serializer state(data, size); 37 delete[] data; 38 result = SNES::system.unserialize(state); 39 } 40 41 if(result) { 42 utility.showMessage(string() << "State " << (slot + 1) << " loaded."); 43 resetHistory(); 44 } else { 45 utility.showMessage(string() << "Failed to load state " << (slot + 1) << "."); 46 } 47 return result; 48 } 49 frame()50void State::frame() { 51 if(!allowed()) return; 52 if(!config().system.rewindEnabled) return; 53 54 //if a full second has passed, automatically capture state 55 if(++frameCounter >= (SNES::system.region() == SNES::System::NTSC ? 60 : 50)) { 56 frameCounter = 0; 57 historyIndex = (historyIndex + 1) % historySize; 58 historyCount = min(historyCount + 1, historySize); 59 SNES::system.runtosave(); 60 history[historyIndex] = SNES::system.serialize(); 61 } 62 } 63 resetHistory()64void State::resetHistory() { 65 historyIndex = 0; 66 historyCount = 0; 67 frameCounter = 0; 68 } 69 rewind()70bool State::rewind() { 71 if(!allowed()) return false; 72 if(!config().system.rewindEnabled) return false; 73 74 if(historyCount == 0) return false; 75 serializer state(history[historyIndex].data(), history[historyIndex].size()); 76 bool result = SNES::system.unserialize(state); 77 historyIndex = (historyIndex + historySize - 1) % historySize; //add historySize to prevent underflow 78 historyCount--; 79 return true; 80 } 81 State()82State::State() { 83 historySize = 120; 84 history = new serializer[historySize]; 85 for(unsigned i = 0; i < historySize; i++) history[i] = 0; 86 } 87 ~State()88State::~State() { 89 delete[] history; 90 } 91 92 // 93 allowed() const94bool State::allowed() const { 95 if(!SNES::cartridge.loaded() || !application.power) return false; 96 if(movie.state != Movie::Inactive) return false; 97 return cartridge.saveStatesSupported(); 98 } 99 name(unsigned slot) const100string State::name(unsigned slot) const { 101 string name = filepath(nall::basename(cartridge.fileName), config().path.state); 102 name << "-" << (slot + 1) << ".bst"; 103 return name; 104 } 105