mirror of https://github.com/bsnes-emu/bsnes.git
Update to v086r02 release.
byuu says: Fixed Super Game Boy RAM saving and loading. It plainly wasn't hooked up at all. Was apparently hard-coded before it became a multi-emulator. I also fixed a crashing issue when loading Satellaview-slotted or Satellaview games without specifying the sub-cart, wasn't setting has_bsx_slot = true, so the raw memory wasn't being allocated internally when it wasn't mapped in. Of course a better fix would be to just not physically map the ranges if the things aren't present. Kind of a lazy hack to map blank cartridges there, but oh well. Oh, fixed title displays as well; and did the best I could for now with regards to multi-file path saving.
This commit is contained in:
parent
a37ce1cb2f
commit
6cfb9e89e7
|
@ -1,7 +1,7 @@
|
|||
#ifndef BASE_HPP
|
||||
#define BASE_HPP
|
||||
|
||||
const char Version[] = "086.01";
|
||||
const char Version[] = "086.02";
|
||||
|
||||
#include <nall/platform.hpp>
|
||||
#include <nall/algorithm.hpp>
|
||||
|
|
|
@ -34,7 +34,7 @@ void Cartridge::load(Mode cartridge_mode, const char *markup) {
|
|||
nvram.reset();
|
||||
|
||||
parse_markup(markup);
|
||||
//print(markup, "\n\n");
|
||||
print(markup, "\n\n");
|
||||
|
||||
if(ram_size > 0) {
|
||||
ram.map(allocate<uint8>(ram_size, 0xff), ram_size);
|
||||
|
|
|
@ -334,6 +334,7 @@ void Cartridge::parse_markup_hitachidsp(XML::Node &root) {
|
|||
void Cartridge::parse_markup_bsx(XML::Node &root) {
|
||||
if(root.exists() == false) return;
|
||||
if(mode != Mode::BsxSlotted && mode != Mode::Bsx) return;
|
||||
has_bsx_slot = true;
|
||||
|
||||
for(auto &node : root["slot"]) {
|
||||
if(node.name != "map") continue;
|
||||
|
|
|
@ -16,11 +16,13 @@ bool InterfaceGameBoy::loadCartridge(GameBoy::System::Revision revision, const s
|
|||
interface->base = { true, filename };
|
||||
} else {
|
||||
if(file::read(filename, data, size) == false) return false;
|
||||
interface->base.name = { false, nall::basename(filename) };
|
||||
interface->base = { false, nall::basename(filename) };
|
||||
}
|
||||
|
||||
interface->unloadCartridge();
|
||||
//interface->applyPatch(interface->baseName, data, size);
|
||||
interface->game = interface->base;
|
||||
interface->cartridgeTitle = interface->base.title();
|
||||
interface->applyPatch(interface->base, data, size);
|
||||
|
||||
string markup;
|
||||
markup.readfile(interface->base.filename("manifest.xml", ".xml"));
|
||||
|
|
|
@ -28,6 +28,17 @@ string CartridgePath::filename(const string &folderName, const string &fileName)
|
|||
return { name, fileName };
|
||||
}
|
||||
|
||||
string CartridgePath::title() const {
|
||||
if(name.empty()) return "";
|
||||
if(folder) {
|
||||
string title = name;
|
||||
title.rtrim<1>("/");
|
||||
title = notdir(nall::basename(title));
|
||||
return title;
|
||||
}
|
||||
return notdir(nall::basename(name));
|
||||
}
|
||||
|
||||
void Interface::bindControllers() {
|
||||
switch(mode()) {
|
||||
case Mode::NES:
|
||||
|
@ -85,10 +96,10 @@ void Interface::loadCartridge(Mode mode) {
|
|||
}
|
||||
|
||||
bindControllers();
|
||||
cheatEditor->load(base.filename("cheats.xml", ".cht"));
|
||||
stateManager->load(base.filename("states.bsa", ".bsa"), 0u);
|
||||
cheatEditor->load(game.filename("cheats.xml", ".cht"));
|
||||
stateManager->load(game.filename("states.bsa", ".bsa"), 0u);
|
||||
dipSwitches->load();
|
||||
utility->showMessage({ "Loaded ", notdir(baseName) });
|
||||
utility->showMessage({ "Loaded ", cartridgeTitle });
|
||||
}
|
||||
|
||||
bool Interface::loadCartridge(const string &filename) {
|
||||
|
@ -103,8 +114,8 @@ bool Interface::loadCartridge(const string &filename) {
|
|||
void Interface::unloadCartridge() {
|
||||
if(cartridgeLoaded() == false) return;
|
||||
cheatDatabase->setVisible(false);
|
||||
cheatEditor->save(base.filename("cheats.xml", ".cht"));
|
||||
stateManager->save(base.filename("states.bsa", ".bsa"), 0u);
|
||||
cheatEditor->save(game.filename("cheats.xml", ".cht"));
|
||||
stateManager->save(game.filename("states.bsa", ".bsa"), 0u);
|
||||
setCheatCodes();
|
||||
|
||||
switch(mode()) {
|
||||
|
@ -113,7 +124,7 @@ void Interface::unloadCartridge() {
|
|||
case Mode::GameBoy: gameBoy.unloadCartridge(); break;
|
||||
}
|
||||
|
||||
interface->baseName = "";
|
||||
cartridgeTitle = "";
|
||||
utility->setMode(mode = Mode::None);
|
||||
}
|
||||
|
||||
|
@ -145,7 +156,7 @@ bool Interface::unserialize(serializer &s) {
|
|||
}
|
||||
|
||||
bool Interface::saveState(unsigned slot) {
|
||||
string filename = base.filename({ "state-", slot, ".bst" }, { "-", slot, ".bst" });
|
||||
string filename = game.filename({ "state-", slot, ".bst" }, { "-", slot, ".bst" });
|
||||
serializer s = serialize();
|
||||
bool result = file::write(filename, s.data(), s.size());
|
||||
utility->showMessage(result == true ? string{ "Saved state ", slot } : "Failed to save state");
|
||||
|
@ -153,7 +164,7 @@ bool Interface::saveState(unsigned slot) {
|
|||
}
|
||||
|
||||
bool Interface::loadState(unsigned slot) {
|
||||
string filename = base.filename({ "state-", slot, ".bst" }, { "-", slot, ".bst" });
|
||||
string filename = game.filename({ "state-", slot, ".bst" }, { "-", slot, ".bst" });
|
||||
uint8_t *data;
|
||||
unsigned size;
|
||||
if(file::read(filename, data, size) == false) {
|
||||
|
@ -193,8 +204,8 @@ Interface::Interface() : core(nullptr) {
|
|||
|
||||
//internal
|
||||
|
||||
bool Interface::applyPatch(const string &filename, uint8_t *&data, unsigned &size) {
|
||||
string patchname = { nall::basename(filename), ".bps" };
|
||||
bool Interface::applyPatch(CartridgePath &filepath, uint8_t *&data, unsigned &size) {
|
||||
string patchname = filepath.filename("patch.bps", ".bps");
|
||||
if(file::exists(patchname) == false) return false;
|
||||
|
||||
bpspatch bps;
|
||||
|
|
|
@ -13,6 +13,7 @@ struct CartridgePath {
|
|||
bool folder;
|
||||
string name;
|
||||
string filename(const string &folderName, const string &fileName) const;
|
||||
string title() const;
|
||||
};
|
||||
|
||||
#include "nes/nes.hpp"
|
||||
|
@ -61,14 +62,13 @@ struct Interface : property<Interface> {
|
|||
|
||||
Interface();
|
||||
|
||||
bool applyPatch(const string &filename, uint8_t *&data, unsigned &size);
|
||||
bool applyPatch(CartridgePath &filepath, uint8_t *&data, unsigned &size);
|
||||
void videoRefresh(const uint32_t *input, unsigned inputPitch, unsigned width, unsigned height);
|
||||
|
||||
CartridgePath base;
|
||||
vector<CartridgePath> slot;
|
||||
|
||||
//deprecated
|
||||
string baseName; // = "/path/to/cartridge" (no extension)
|
||||
CartridgePath base; //base cartridge connected to emulated system
|
||||
CartridgePath slot[2]; //slot cartridges connected to base cartridge
|
||||
CartridgePath game; //where to store resources (cheats.xml, states.bsa, ...)
|
||||
string cartridgeTitle; //combined name of game ([base] + [slot ...])
|
||||
|
||||
InterfaceCore *core;
|
||||
InterfaceNES nes;
|
||||
|
|
|
@ -48,7 +48,9 @@ bool InterfaceNES::loadCartridge(const string &filename) {
|
|||
}
|
||||
|
||||
interface->unloadCartridge();
|
||||
//interface->applyPatch(interface->base.filename("patch.bps", ".bps"), data, size);
|
||||
interface->game = interface->base;
|
||||
interface->cartridgeTitle = interface->base.title();
|
||||
interface->applyPatch(interface->base, data, size);
|
||||
|
||||
string markup;
|
||||
markup.readfile(interface->base.filename("manifest.xml", ".xml"));
|
||||
|
|
|
@ -31,6 +31,7 @@ bool InterfaceSNES::cartridgeLoaded() {
|
|||
}
|
||||
|
||||
bool InterfaceSNES::loadCartridge(const string &filename, CartridgePath &cartridge, uint8_t *&data, unsigned &size) {
|
||||
data = nullptr, size = 0u;
|
||||
auto backup = cartridge;
|
||||
string suffix;
|
||||
if(filename.endswith("/")) {
|
||||
|
@ -43,7 +44,7 @@ bool InterfaceSNES::loadCartridge(const string &filename, CartridgePath &cartrid
|
|||
cartridge = backup;
|
||||
return false;
|
||||
}
|
||||
//interface->applyPatch(filename, data, size);
|
||||
interface->applyPatch(cartridge, data, size);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -51,7 +52,10 @@ bool InterfaceSNES::loadCartridge(string basename) {
|
|||
uint8_t *data;
|
||||
unsigned size;
|
||||
if(loadCartridge(basename, interface->base, data, size) == false) return false;
|
||||
|
||||
interface->unloadCartridge();
|
||||
interface->game = interface->base;
|
||||
interface->cartridgeTitle = interface->base.title();
|
||||
|
||||
string markup;
|
||||
markup.readfile(interface->base.filename("manifest.xml", ".xml"));
|
||||
|
@ -73,8 +77,12 @@ bool InterfaceSNES::loadSatellaviewSlottedCartridge(string basename, string slot
|
|||
uint8_t *data[2];
|
||||
unsigned size[2];
|
||||
if(loadCartridge(basename, interface->base, data[0], size[0]) == false) return false;
|
||||
loadCartridge(slotname, interface->slot(0), data[1], size[1]);
|
||||
loadCartridge(slotname, interface->slot[0], data[1], size[1]);
|
||||
|
||||
interface->unloadCartridge();
|
||||
interface->game = !data[1] ? interface->base : interface->slot[0]; //TODO: subfolder for folders; concatenation for files
|
||||
interface->cartridgeTitle = interface->base.title();
|
||||
if(data[1]) interface->cartridgeTitle.append(" + ", interface->slot[0].title());
|
||||
|
||||
string markup;
|
||||
markup.readfile(interface->base.filename("manifest.xml", ".xml"));
|
||||
|
@ -98,8 +106,12 @@ bool InterfaceSNES::loadSatellaviewCartridge(string basename, string slotname) {
|
|||
uint8_t *data[2];
|
||||
unsigned size[2];
|
||||
if(loadCartridge(basename, interface->base, data[0], size[0]) == false) return false;
|
||||
loadCartridge(slotname, interface->slot(0), data[1], size[1]);
|
||||
loadCartridge(slotname, interface->slot[0], data[1], size[1]);
|
||||
|
||||
interface->unloadCartridge();
|
||||
interface->game = !data[1] ? interface->base : interface->slot[0];
|
||||
interface->cartridgeTitle = interface->base.title();
|
||||
if(data[1]) interface->cartridgeTitle = interface->slot[0].title();
|
||||
|
||||
string markup;
|
||||
markup.readfile(interface->base.filename("manifest.xml", ".xml"));
|
||||
|
@ -123,9 +135,17 @@ bool InterfaceSNES::loadSufamiTurboCartridge(string basename, string slotAname,
|
|||
uint8_t *data[3];
|
||||
unsigned size[3];
|
||||
if(loadCartridge(basename, interface->base, data[0], size[0]) == false) return false;
|
||||
loadCartridge(slotAname, interface->slot(0), data[1], size[1]);
|
||||
loadCartridge(slotBname, interface->slot(1), data[2], size[2]);
|
||||
loadCartridge(slotAname, interface->slot[0], data[1], size[1]);
|
||||
loadCartridge(slotBname, interface->slot[1], data[2], size[2]);
|
||||
|
||||
interface->unloadCartridge();
|
||||
interface->game = !data[1] ? interface->base : interface->slot[0]; //TODO: subfolder for folders; concatenation for files
|
||||
interface->cartridgeTitle = interface->base.title();
|
||||
if( data[1] && !data[2]) interface->cartridgeTitle = interface->slot[0].title();
|
||||
if(!data[1] && data[2]) interface->cartridgeTitle = interface->slot[1].title();
|
||||
if( data[1] && data[2]) interface->cartridgeTitle = {
|
||||
interface->slot[0].title(), " + ", interface->slot[1].title()
|
||||
};
|
||||
|
||||
string markup;
|
||||
markup.readfile(interface->base.filename("manifest.xml", ".xml"));
|
||||
|
@ -151,8 +171,12 @@ bool InterfaceSNES::loadSuperGameBoyCartridge(string basename, string slotname)
|
|||
uint8_t *data[2];
|
||||
unsigned size[2];
|
||||
if(loadCartridge(basename, interface->base, data[0], size[0]) == false) return false;
|
||||
loadCartridge(slotname, interface->slot(0), data[1], size[1]);
|
||||
loadCartridge(slotname, interface->slot[0], data[1], size[1]);
|
||||
|
||||
interface->unloadCartridge();
|
||||
interface->game = !data[1] ? interface->base : interface->slot[0];
|
||||
interface->cartridgeTitle = interface->base.title();
|
||||
if(data[1]) interface->cartridgeTitle = interface->slot[0].title();
|
||||
|
||||
string markup;
|
||||
markup.readfile(interface->base.filename("manifest.xml", ".xml"));
|
||||
|
@ -179,8 +203,6 @@ bool InterfaceSNES::loadSuperGameBoyCartridge(string basename, string slotname)
|
|||
void InterfaceSNES::unloadCartridge() {
|
||||
saveMemory();
|
||||
SNES::cartridge.unload();
|
||||
interface->base.name = "";
|
||||
interface->slot.reset();
|
||||
}
|
||||
|
||||
void InterfaceSNES::power() {
|
||||
|
@ -225,6 +247,17 @@ void InterfaceSNES::loadMemory() {
|
|||
delete[] data;
|
||||
}
|
||||
}
|
||||
|
||||
if(SNES::cartridge.mode() == SNES::Cartridge::Mode::SuperGameBoy) {
|
||||
if(GameBoy::cartridge.ramsize) {
|
||||
uint8_t *data;
|
||||
unsigned size;
|
||||
if(file::read(interface->slot[0].filename("program.ram", ".sav"), data, size)) {
|
||||
memcpy(GameBoy::cartridge.ramdata, data, min(GameBoy::cartridge.ramsize, size));
|
||||
delete[] data;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void InterfaceSNES::saveMemory() {
|
||||
|
@ -236,6 +269,14 @@ void InterfaceSNES::saveMemory() {
|
|||
|
||||
file::write(filename, memory.data, memory.size);
|
||||
}
|
||||
|
||||
if(SNES::cartridge.mode() == SNES::Cartridge::Mode::SuperGameBoy) {
|
||||
if(GameBoy::cartridge.ramsize) {
|
||||
file::write(interface->slot[0].filename("program.ram", ".sav"),
|
||||
GameBoy::cartridge.ramdata, GameBoy::cartridge.ramsize
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
serializer InterfaceSNES::serialize() {
|
||||
|
|
|
@ -17,13 +17,13 @@ void Utility::setMode(Interface::Mode mode) {
|
|||
}
|
||||
|
||||
else if(mode == Interface::Mode::NES) {
|
||||
mainWindow->setTitle(notdir(interface->baseName));
|
||||
mainWindow->setTitle(interface->cartridgeTitle);
|
||||
mainWindow->nesMenu.setVisible(true);
|
||||
dspaudio.setChannels(1);
|
||||
}
|
||||
|
||||
else if(mode == Interface::Mode::SNES) {
|
||||
mainWindow->setTitle(notdir(interface->baseName));
|
||||
mainWindow->setTitle(interface->cartridgeTitle);
|
||||
mainWindow->snesMenu.setVisible(true);
|
||||
dspaudio.setChannels(2);
|
||||
}
|
||||
|
@ -32,7 +32,7 @@ void Utility::setMode(Interface::Mode mode) {
|
|||
mainWindow->gameBoyMenu.setText(
|
||||
GameBoy::system.cgb() == false ? "Game Boy" : "Game Boy Color"
|
||||
);
|
||||
mainWindow->setTitle(notdir(interface->baseName));
|
||||
mainWindow->setTitle(interface->cartridgeTitle);
|
||||
mainWindow->gameBoyMenu.setVisible(true);
|
||||
dspaudio.setChannels(2);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue