lsnes/ui/tools/state-manager.cpp
2013-05-03 17:47:34 +03:00

155 lines
4.3 KiB
C++
Executable file

StateManager *stateManager = nullptr;
StateManager::StateManager() {
setTitle("State Manager");
setGeometry({ 128, 128, 600, 360 });
windowManager->append(this, "StateManager");
stateList.setHeaderText("Slot", "Description");
stateList.setHeaderVisible();
descLabel.setText("Description:");
loadButton.setText("Load");
saveButton.setText("Save");
eraseButton.setText("Erase");
append(layout);
layout.setMargin(5);
layout.append(stateList, { ~0, ~0 }, 5);
layout.append(descLayout, { ~0, 0 }, 5);
descLayout.append(descLabel, { 0, 0 }, 5);
descLayout.append(descEdit, { ~0, 0 }, 0);
layout.append(controlLayout, { ~0, 0 }, 0);
controlLayout.append(spacer, { ~0, 0 }, 0);
controlLayout.append(loadButton, { 80, 0 }, 5);
controlLayout.append(saveButton, { 80, 0 }, 5);
controlLayout.append(eraseButton, { 80, 0 }, 0);
for(unsigned n = 0; n < 32; n++) stateList.append(decimal<2>(n + 1), "(empty)");
stateList.autoSizeColumns();
synchronize();
stateList.onActivate = { &StateManager::slotLoad, this };
stateList.onChange = { &StateManager::synchronize, this };
descEdit.onChange = { &StateManager::slotSaveDescription, this };
loadButton.onActivate = { &StateManager::slotLoad, this };
saveButton.onActivate = { &StateManager::slotSave, this };
eraseButton.onActivate = { &StateManager::slotErase, this };
}
void StateManager::synchronize() {
layout.setEnabled(interface->cartridgeLoaded());
descEdit.setText("");
descEdit.setEnabled(false);
controlLayout.setEnabled(stateList.selected());
if(stateList.selected() == false) return;
if(slot[stateList.selection()].capacity() > 0) {
descEdit.setText(slotLoadDescription(stateList.selection()));
descEdit.setEnabled(true);
}
}
void StateManager::refresh() {
for(unsigned n = 0; n < 32; n++) {
stateList.modify(n, decimal<2>(n + 1), slotLoadDescription(n));
}
stateList.autoSizeColumns();
}
void StateManager::reset() {
for(unsigned n = 0; n < 32; n++) slot[n] = serializer();
synchronize();
refresh();
}
bool StateManager::load(const string &filename, unsigned revision) {
for(unsigned n = 0; n < 32; n++) slot[n] = serializer();
synchronize();
file fp;
if(fp.open(filename, file::mode::read) == false) return false;
if(fp.readl(4) == 0x31415342) {
if(fp.readl(4) == revision) { //'BSA1'
for(unsigned n = 0; n < 32; n++) {
if(fp.read() == false) continue;
unsigned size = fp.readl(4);
uint8_t *data = new uint8_t[size];
fp.read(data, size);
slot[n] = serializer(data, size);
delete[] data;
}
}
}
refresh();
return true;
}
bool StateManager::save(const string &filename, unsigned revision) {
bool hasSave = false;
for(unsigned n = 0; n < 32; n++) {
if(slot[n].capacity() > 0) hasSave = true;
}
if(hasSave == false) {
unlink(filename);
return true;
}
file fp;
if(fp.open(filename, file::mode::write) == false) return false;
fp.writel(0x31415342, 4); //'BSA1'
fp.writel(revision, 4);
for(unsigned n = 0; n < 32; n++) {
if(slot[n].capacity() == 0) {
fp.write(false);
} else {
fp.write(true);
fp.writel(slot[n].size(), 4);
fp.write(slot[n].data(), slot[n].size());
}
}
}
void StateManager::slotLoad() {
if(stateList.selected() == false) return;
serializer s(slot[stateList.selection()].data(), slot[stateList.selection()].capacity());
interface->unserialize(s);
}
void StateManager::slotSave() {
if(stateList.selected()) {
slot[stateList.selection()] = interface->serialize();
}
refresh();
synchronize();
descEdit.setFocused();
}
void StateManager::slotErase() {
if(stateList.selected()) {
slot[stateList.selection()] = serializer();
}
refresh();
synchronize();
}
string StateManager::slotLoadDescription(unsigned n) {
if(slot[n].capacity() == 0) return "(empty)";
char text[DescriptionLength];
strlcpy(text, (const char*)slot[n].data() + HeaderLength, DescriptionLength);
return text;
}
void StateManager::slotSaveDescription() {
if(stateList.selected() == false) return;
string text = descEdit.text();
if(slot[stateList.selection()].capacity() > 0) {
strlcpy((char*)slot[stateList.selection()].data() + HeaderLength, (const char*)text, DescriptionLength);
}
refresh();
}