Update to v106r20 release.

byuu says:
Changelog:

  - Super Famicom: fixed loading of BS Memory and Sufami Turbo
    cartridges
  - Super Famicom: renamed NSS to DIP; as that's really all it is, it's
    not true NSS emulation
  - Super Famicom: slot loading now happens inside of board parsing
    instead of generically in loadCartridge()
  - Super Famicom: BS-X cartridges with flash memory now serialize their
    data and write it out to disk¹
  - icarus: fixed Famicom game importing (hopefully) and set file import
    title to “Load ROM File”

¹: there's no emulation of write commands yet, so the data is never
going to change anyway. This is just in preparation for more advanced
emulation of BS Memory cartridges.
This commit is contained in:
Tim Allen 2018-05-14 23:53:18 +10:00
parent 6847058210
commit 210306e661
19 changed files with 269 additions and 200 deletions

View File

@ -12,7 +12,7 @@ using namespace nall;
namespace Emulator {
static const string Name = "higan";
static const string Version = "106.19";
static const string Version = "106.20";
static const string Author = "byuu";
static const string License = "GPLv3";
static const string Website = "https://byuu.org/";

View File

@ -4,7 +4,7 @@ objects += sfc-interface sfc-system sfc-controller
objects += sfc-cartridge sfc-memory
objects += sfc-cpu sfc-smp sfc-dsp sfc-ppu
objects += sfc-expansion sfc-satellaview sfc-21fx
objects += sfc-icd sfc-mcc sfc-nss sfc-event
objects += sfc-icd sfc-mcc sfc-dip sfc-event
objects += sfc-sa1 sfc-superfx
objects += sfc-armdsp sfc-hitachidsp sfc-necdsp
objects += sfc-epsonrtc sfc-sharprtc
@ -29,7 +29,7 @@ obj/sfc-21fx.o: sfc/expansion/21fx/21fx.cpp $(call rwildcard,sfc/expansio
obj/sfc-icd.o: sfc/coprocessor/icd/icd.cpp $(call rwildcard,sfc/coprocessor/icd/)
obj/sfc-mcc.o: sfc/coprocessor/mcc/mcc.cpp $(call rwildcard,sfc/coprocessor/mcc/)
obj/sfc-nss.o: sfc/coprocessor/nss/nss.cpp $(call rwildcard,sfc/coprocessor/nss/)
obj/sfc-dip.o: sfc/coprocessor/dip/dip.cpp $(call rwildcard,sfc/coprocessor/dip/)
obj/sfc-event.o: sfc/coprocessor/event/event.cpp $(call rwildcard,sfc/coprocessor/event/)
obj/sfc-sa1.o: sfc/coprocessor/sa1/sa1.cpp $(call rwildcard,sfc/coprocessor/sa1/)

View File

@ -56,10 +56,10 @@ auto Cartridge::load() -> bool {
}
//Sufami Turbo
else if(cartridge.has.SufamiTurboSlots) {
else if(cartridge.has.SufamiTurboSlotA || cartridge.has.SufamiTurboSlotB) {
Hash::SHA256 sha;
sha.input(sufamiturboA.rom.data(), sufamiturboA.rom.size());
sha.input(sufamiturboB.rom.data(), sufamiturboB.rom.size());
if(cartridge.has.SufamiTurboSlotA) sha.input(sufamiturboA.rom.data(), sufamiturboA.rom.size());
if(cartridge.has.SufamiTurboSlotB) sha.input(sufamiturboB.rom.data(), sufamiturboB.rom.size());
information.sha256 = sha.digest();
}
@ -97,7 +97,7 @@ auto Cartridge::loadGameBoy() -> bool {
//invoked from ICD::load()
information.sha256 = GameBoy::cartridge.sha256();
slotGameBoy.load(GameBoy::cartridge.manifest());
loadGameBoy(slotGameBoy.document);
loadCartridgeGameBoy(slotGameBoy.document);
return true;
#endif
return false;
@ -107,7 +107,7 @@ auto Cartridge::loadBSMemory() -> bool {
if(auto fp = platform->open(bsmemory.pathID, "manifest.bml", File::Read, File::Required)) {
slotBSMemory.load(fp->reads());
} else return false;
loadBSMemory(slotBSMemory.document);
loadCartridgeBSMemory(slotBSMemory.document);
return true;
}
@ -115,7 +115,7 @@ auto Cartridge::loadSufamiTurboA() -> bool {
if(auto fp = platform->open(sufamiturboA.pathID, "manifest.bml", File::Read, File::Required)) {
slotSufamiTurboA.load(fp->reads());
} else return false;
loadSufamiTurboA(slotSufamiTurboA.document);
loadCartridgeSufamiTurboA(slotSufamiTurboA.document);
return true;
}
@ -123,21 +123,23 @@ auto Cartridge::loadSufamiTurboB() -> bool {
if(auto fp = platform->open(sufamiturboB.pathID, "manifest.bml", File::Read, File::Required)) {
slotSufamiTurboB.load(fp->reads());
} else return false;
loadSufamiTurboB(slotSufamiTurboB.document);
loadCartridgeSufamiTurboB(slotSufamiTurboB.document);
return true;
}
auto Cartridge::save() -> void {
saveCartridge(game.document);
if(has.GameBoySlot) {
saveGameBoy(slotGameBoy.document);
saveCartridgeGameBoy(slotGameBoy.document);
}
if(has.BSMemorySlot) {
saveBSMemory(slotBSMemory.document);
saveCartridgeBSMemory(slotBSMemory.document);
}
if(has.SufamiTurboSlots) {
saveSufamiTurboA(slotSufamiTurboA.document);
saveSufamiTurboB(slotSufamiTurboB.document);
if(has.SufamiTurboSlotA) {
saveCartridgeSufamiTurboA(slotSufamiTurboA.document);
}
if(has.SufamiTurboSlotB) {
saveCartridgeSufamiTurboB(slotSufamiTurboB.document);
}
}

View File

@ -23,7 +23,7 @@ struct Cartridge {
struct Has {
boolean ICD;
boolean MCC;
boolean NSSDIP;
boolean DIP;
boolean Event;
boolean SA1;
boolean SuperFX;
@ -39,7 +39,8 @@ struct Cartridge {
boolean GameBoySlot;
boolean BSMemorySlot;
boolean SufamiTurboSlots;
boolean SufamiTurboSlotA;
boolean SufamiTurboSlotB;
} has;
private:
@ -59,17 +60,23 @@ private:
//load.cpp
auto loadBoard(string) -> Markup::Node;
auto loadCartridge(Markup::Node) -> void;
auto loadGameBoy(Markup::Node) -> void;
auto loadBSMemory(Markup::Node) -> void;
auto loadSufamiTurboA(Markup::Node) -> void;
auto loadSufamiTurboB(Markup::Node) -> void;
auto loadCartridgeGameBoy(Markup::Node) -> void;
auto loadCartridgeBSMemory(Markup::Node) -> void;
auto loadCartridgeSufamiTurboA(Markup::Node) -> void;
auto loadCartridgeSufamiTurboB(Markup::Node) -> void;
auto loadMemory(MappedRAM&, Markup::Node, bool required) -> void;
auto loadMap(Markup::Node, SuperFamicom::Memory&) -> void;
auto loadMap(Markup::Node, const function<uint8 (uint24, uint8)>&, const function<void (uint24, uint8)>&) -> void;
auto loadROM(Markup::Node) -> void;
auto loadRAM(Markup::Node) -> void;
auto loadICD(Markup::Node) -> void;
auto loadMCC(Markup::Node) -> void;
auto loadSufamiTurbo(Markup::Node, bool slot) -> void;
auto loadNSS(Markup::Node) -> void;
auto loadBSMemory(Markup::Node) -> void;
auto loadSufamiTurboA(Markup::Node) -> void;
auto loadSufamiTurboB(Markup::Node) -> void;
auto loadDIP(Markup::Node) -> void;
auto loadEvent(Markup::Node) -> void;
auto loadSA1(Markup::Node) -> void;
auto loadSuperFX(Markup::Node) -> void;
@ -84,16 +91,14 @@ private:
auto loadOBC1(Markup::Node) -> void;
auto loadMSU1(Markup::Node) -> void;
auto loadMemory(MappedRAM&, Markup::Node, bool required, maybe<uint> id = nothing) -> void;
auto loadMap(Markup::Node, SuperFamicom::Memory&) -> void;
auto loadMap(Markup::Node, const function<uint8 (uint24, uint8)>&, const function<void (uint24, uint8)>&) -> void;
//save.cpp
auto saveCartridge(Markup::Node) -> void;
auto saveGameBoy(Markup::Node) -> void;
auto saveBSMemory(Markup::Node) -> void;
auto saveSufamiTurboA(Markup::Node) -> void;
auto saveSufamiTurboB(Markup::Node) -> void;
auto saveCartridgeGameBoy(Markup::Node) -> void;
auto saveCartridgeBSMemory(Markup::Node) -> void;
auto saveCartridgeSufamiTurboA(Markup::Node) -> void;
auto saveCartridgeSufamiTurboB(Markup::Node) -> void;
auto saveMemory(MappedRAM&, Markup::Node) -> void;
auto saveRAM(Markup::Node) -> void;
auto saveMCC(Markup::Node) -> void;
@ -108,8 +113,6 @@ private:
auto saveSPC7110(Markup::Node) -> void;
auto saveOBC1(Markup::Node) -> void;
auto saveMemory(MappedRAM&, Markup::Node, maybe<uint> = nothing) -> void;
friend class Interface;
friend class ICD;
};

View File

@ -45,30 +45,14 @@ auto Cartridge::loadCartridge(Markup::Node node) -> void {
}
}
if(board["slot(type=BSMemory)"]
|| board["processor(identifier=MCC)/mcu/slot(type=BSMemory)"]
|| board["processor(architecture=W65C816S)/mcu/slot(type=BSMemory)"]
) {
if(auto loaded = platform->load(ID::BSMemory, "BS Memory", "bs")) {
bsmemory.pathID = loaded.pathID();
loadBSMemory();
}
}
if(board["slot(type=SufamiTurbo)"]) {
if(auto loaded = platform->load(ID::SufamiTurboA, "Sufami Turbo", "st")) {
sufamiturboA.pathID = loaded.pathID();
loadSufamiTurboA();
}
}
if(auto node = board["memory(type=ROM,content=Program)"]) loadROM(node);
if(auto node = board["memory(type=RAM,content=Save)"]) loadRAM(node);
if(auto node = board["processor(identifier=ICD)"]) loadICD(node);
if(auto node = board["processor(identifier=MCC)"]) loadMCC(node);
if(auto node = board.find("slot(type=SufamiTurbo)")) if(node(0)) loadSufamiTurbo(node(0), 0);
if(auto node = board.find("slot(type=SufamiTurbo)")) if(node(1)) loadSufamiTurbo(node(1), 1);
if(auto node = board["nss"]) loadNSS(node);
if(auto node = board["slot(type=BSMemory)"]) loadBSMemory(node);
if(auto node = board["slot(type=SufamiTurbo)[0]"]) loadSufamiTurboA(node);
if(auto node = board["slot(type=SufamiTurbo)[1]"]) loadSufamiTurboB(node);
if(auto node = board["dip"]) loadDIP(node);
if(auto node = board["event"]) loadEvent(node);
if(auto node = board["processor(architecture=W65C816S)"]) loadSA1(node);
if(auto node = board["processor(architecture=GSU)"]) loadSuperFX(node);
@ -84,54 +68,86 @@ auto Cartridge::loadCartridge(Markup::Node node) -> void {
if(auto node = board["processor(identifier=MSU1)"]) loadMSU1(node);
}
auto Cartridge::loadGameBoy(Markup::Node node) -> void {
auto Cartridge::loadCartridgeGameBoy(Markup::Node node) -> void {
}
auto Cartridge::loadBSMemory(Markup::Node node) -> void {
has.BSMemorySlot = true;
if(auto memory = node["game/board/memory(type=ROM)"]) {
bsmemory.readonly = true;
loadMemory(bsmemory.memory, memory, File::Required, bsmemory.pathID);
} else if(auto memory = node["game/board/memory(type=Flash)"]) {
bsmemory.readonly = false;
loadMemory(bsmemory.memory, memory, File::Required, bsmemory.pathID);
}
for(auto map : node.find("map")) {
if(bsmemory.memory.size()) {
loadMap(map, bsmemory);
auto Cartridge::loadCartridgeBSMemory(Markup::Node node) -> void {
if(auto memory = Emulator::Game::Memory{node["game/board/memory(content=Program)"]}) {
bsmemory.readonly = memory.type == "ROM";
bsmemory.memory.allocate(memory.size);
if(auto fp = platform->open(bsmemory.pathID, memory.name(), File::Read, File::Required)) {
fp->read(bsmemory.memory.data(), memory.size);
}
}
}
auto Cartridge::loadSufamiTurboA(Markup::Node node) -> void {
if(auto memory = node["game/board/memory(type=ROM)"]) {
loadMemory(sufamiturboA.rom, memory, File::Required, sufamiturboA.pathID);
auto Cartridge::loadCartridgeSufamiTurboA(Markup::Node node) -> void {
if(auto memory = Emulator::Game::Memory{node["game/board/memory(type=ROM,content=Program)"]}) {
sufamiturboA.rom.allocate(memory.size);
if(auto fp = platform->open(sufamiturboA.pathID, memory.name(), File::Read, File::Required)) {
fp->read(sufamiturboA.rom.data(), memory.size);
}
}
if(auto memory = node["game/board/memory(type=RAM)"]) {
loadMemory(sufamiturboA.ram, memory, File::Optional, sufamiturboA.pathID);
}
if(auto loaded = platform->load(ID::SufamiTurboB, "Sufami Turbo", "st")) {
sufamiturboB.pathID = loaded.pathID();
loadSufamiTurboB();
if(auto memory = Emulator::Game::Memory{node["game/board/memory(type=RAM,content=Save)"]}) {
sufamiturboA.ram.allocate(memory.size);
if(auto fp = platform->open(sufamiturboA.pathID, memory.name(), File::Read)) {
fp->read(sufamiturboA.ram.data(), memory.size);
}
}
}
auto Cartridge::loadSufamiTurboB(Markup::Node node) -> void {
if(auto memory = node["game/board/memory(type=ROM)"]) {
loadMemory(sufamiturboB.rom, memory, File::Required, sufamiturboB.pathID);
auto Cartridge::loadCartridgeSufamiTurboB(Markup::Node node) -> void {
if(auto memory = Emulator::Game::Memory{node["game/board/memory(type=ROM,content=Program)"]}) {
sufamiturboB.rom.allocate(memory.size);
if(auto fp = platform->open(sufamiturboB.pathID, memory.name(), File::Read, File::Required)) {
fp->read(sufamiturboB.rom.data(), memory.size);
}
}
if(auto memory = node["game/board/memory(type=RAM)"]) {
loadMemory(sufamiturboB.ram, memory, File::Optional, sufamiturboB.pathID);
if(auto memory = Emulator::Game::Memory{node["game/board/memory(type=RAM,content=Save)"]}) {
sufamiturboB.ram.allocate(memory.size);
if(auto fp = platform->open(sufamiturboB.pathID, memory.name(), File::Read)) {
fp->read(sufamiturboB.ram.data(), memory.size);
}
}
}
//
auto Cartridge::loadMemory(MappedRAM& ram, Markup::Node node, bool required) -> void {
if(auto memory = game.memory(node)) {
ram.allocate(memory->size);
if(memory->type == "RAM" && !memory->nonVolatile) return;
if(memory->type == "RTC" && !memory->nonVolatile) return;
if(auto fp = platform->open(pathID(), memory->name(), File::Read, required)) {
fp->read(ram.data(), ram.size());
}
}
}
auto Cartridge::loadMap(Markup::Node map, SuperFamicom::Memory& memory) -> void {
auto addr = map["address"].text();
auto size = map["size"].natural();
auto base = map["base"].natural();
auto mask = map["mask"].natural();
if(size == 0) size = memory.size();
if(size == 0) return;
bus.map({&SuperFamicom::Memory::read, &memory}, {&SuperFamicom::Memory::write, &memory}, addr, size, base, mask);
}
auto Cartridge::loadMap(
Markup::Node map,
const function<uint8 (uint24, uint8)>& reader,
const function<void (uint24, uint8)>& writer
) -> void {
auto addr = map["address"].text();
auto size = map["size"].natural();
auto base = map["base"].natural();
auto mask = map["mask"].natural();
bus.map(reader, writer, addr, size, base, mask);
}
//memory(type=ROM,content=Program)
auto Cartridge::loadROM(Markup::Node node) -> void {
loadMemory(rom, node, File::Required);
@ -177,6 +193,9 @@ auto Cartridge::loadMCC(Markup::Node node) -> void {
if(auto memory = mcu["memory(type=ROM,content=Program)"]) {
loadMemory(mcc.rom, memory, File::Required);
}
if(auto slot = mcu["slot(type=BSMemory)"]) {
loadBSMemory(slot);
}
}
if(auto memory = node["memory(type=RAM,content=Download)"]) {
@ -187,28 +206,63 @@ auto Cartridge::loadMCC(Markup::Node node) -> void {
}
}
//slot(type=SufamiTurbo)[0,1]
auto Cartridge::loadSufamiTurbo(Markup::Node node, bool slot) -> void {
has.SufamiTurboSlots = true;
//slot(type=BSMemory)
auto Cartridge::loadBSMemory(Markup::Node node) -> void {
has.BSMemorySlot = true;
for(auto map : node.find("rom/map")) {
auto& cartridge = slot == 0 ? sufamiturboA : sufamiturboB;
if(cartridge.rom.size() == 0) continue;
loadMap(map, cartridge.rom);
}
if(auto loaded = platform->load(ID::BSMemory, "BS Memory", "bs")) {
bsmemory.pathID = loaded.pathID();
loadBSMemory();
for(auto map : node.find("ram/map")) {
auto& cartridge = slot == 0 ? sufamiturboA : sufamiturboB;
if(cartridge.ram.size() == 0) continue;
loadMap(map, cartridge.ram);
for(auto map : node.find("map")) {
loadMap(map, bsmemory);
}
}
}
auto Cartridge::loadNSS(Markup::Node node) -> void {
has.NSSDIP = true;
nss.dip = platform->dipSettings(node);
//slot(type=SufamiTurbo)[0]
auto Cartridge::loadSufamiTurboA(Markup::Node node) -> void {
has.SufamiTurboSlotA = true;
for(auto leaf : node.find("map")) loadMap(leaf, {&NSS::read, &nss}, {&NSS::write, &nss});
if(auto loaded = platform->load(ID::SufamiTurboA, "Sufami Turbo", "st")) {
sufamiturboA.pathID = loaded.pathID();
loadSufamiTurboA();
for(auto map : node.find("rom/map")) {
loadMap(map, sufamiturboA.rom);
}
for(auto map : node.find("ram/map")) {
loadMap(map, sufamiturboA.ram);
}
}
}
//slot(type=SufamiTurbo)[1]
auto Cartridge::loadSufamiTurboB(Markup::Node node) -> void {
has.SufamiTurboSlotB = true;
if(auto loaded = platform->load(ID::SufamiTurboB, "Sufami Turbo", "st")) {
sufamiturboB.pathID = loaded.pathID();
loadSufamiTurboB();
for(auto map : node.find("rom/map")) {
loadMap(map, sufamiturboB.rom);
}
for(auto map : node.find("ram/map")) {
loadMap(map, sufamiturboB.ram);
}
}
}
auto Cartridge::loadDIP(Markup::Node node) -> void {
has.DIP = true;
dip.value = platform->dipSettings(node);
for(auto map : node.find("map")) {
loadMap(map, {&DIP::read, &dip}, {&DIP::write, &dip});
}
}
auto Cartridge::loadEvent(Markup::Node node) -> void {
@ -244,6 +298,9 @@ auto Cartridge::loadSA1(Markup::Node node) -> void {
if(auto memory = mcu["memory(type=ROM,content=Program)"]) {
loadMemory(sa1.rom, memory, File::Required);
}
if(auto slot = mcu["slot(type=BSMemory)"]) {
loadBSMemory(slot);
}
}
if(auto memory = node["memory(type=RAM,content=Save)"]) {
@ -582,39 +639,3 @@ auto Cartridge::loadMSU1(Markup::Node node) -> void {
loadMap(map, {&MSU1::readIO, &msu1}, {&MSU1::writeIO, &msu1});
}
}
//
auto Cartridge::loadMemory(MappedRAM& ram, Markup::Node node, bool required, maybe<uint> id) -> void {
if(!id) id = pathID();
if(auto memory = game.memory(node)) {
ram.allocate(memory->size);
if(memory->type == "RAM" && !memory->nonVolatile) return;
if(memory->type == "RTC" && !memory->nonVolatile) return;
if(auto fp = platform->open(id(), memory->name(), File::Read, required)) {
fp->read(ram.data(), ram.size());
}
}
}
auto Cartridge::loadMap(Markup::Node map, SuperFamicom::Memory& memory) -> void {
auto addr = map["address"].text();
auto size = map["size"].natural();
auto base = map["base"].natural();
auto mask = map["mask"].natural();
if(size == 0) size = memory.size();
if(size == 0) return;
bus.map({&SuperFamicom::Memory::read, &memory}, {&SuperFamicom::Memory::write, &memory}, addr, size, base, mask);
}
auto Cartridge::loadMap(
Markup::Node map,
const function<uint8 (uint24, uint8)>& reader,
const function<void (uint24, uint8)>& writer
) -> void {
auto addr = map["address"].text();
auto size = map["size"].natural();
auto base = map["base"].natural();
auto mask = map["mask"].natural();
bus.map(reader, writer, addr, size, base, mask);
}

View File

@ -13,22 +13,49 @@ auto Cartridge::saveCartridge(Markup::Node node) -> void {
if(auto node = board["processor(identifier=OBC1)"]) saveOBC1(node);
}
auto Cartridge::saveGameBoy(Markup::Node node) -> void {
auto Cartridge::saveCartridgeGameBoy(Markup::Node node) -> void {
}
auto Cartridge::saveBSMemory(Markup::Node node) -> void {
auto Cartridge::saveCartridgeBSMemory(Markup::Node node) -> void {
if(auto memory = Emulator::Game::Memory{node["game/board/memory(type=Flash,content=Program)"]}) {
if(auto fp = platform->open(bsmemory.pathID, memory.name(), File::Write)) {
fp->write(bsmemory.memory.data(), memory.size);
}
}
}
auto Cartridge::saveSufamiTurboA(Markup::Node node) -> void {
saveMemory(sufamiturboA.ram, node["game/board/memory(type=RAM)"], sufamiturboA.pathID);
auto Cartridge::saveCartridgeSufamiTurboA(Markup::Node node) -> void {
if(auto memory = Emulator::Game::Memory{node["game/board/memory(type=RAM,content=Save)"]}) {
if(memory.nonVolatile) {
if(auto fp = platform->open(sufamiturboA.pathID, memory.name(), File::Write)) {
fp->write(sufamiturboA.ram.data(), memory.size);
}
}
}
}
auto Cartridge::saveSufamiTurboB(Markup::Node node) -> void {
saveMemory(sufamiturboB.ram, node["game/board/memory(type=RAM)"], sufamiturboB.pathID);
auto Cartridge::saveCartridgeSufamiTurboB(Markup::Node node) -> void {
if(auto memory = Emulator::Game::Memory{node["game/board/memory(type=RAM,content=Save)"]}) {
if(memory.nonVolatile) {
if(auto fp = platform->open(sufamiturboB.pathID, memory.name(), File::Write)) {
fp->write(sufamiturboB.ram.data(), memory.size);
}
}
}
}
//
auto Cartridge::saveMemory(MappedRAM& ram, Markup::Node node) -> void {
if(auto memory = game.memory(node)) {
if(memory->type == "RAM" && !memory->nonVolatile) return;
if(memory->type == "RTC" && !memory->nonVolatile) return;
if(auto fp = platform->open(pathID(), memory->name(), File::Write)) {
fp->write(ram.data(), ram.size());
}
}
}
//memory(type=RAM,content=Save)
auto Cartridge::saveRAM(Markup::Node node) -> void {
saveMemory(ram, node);
@ -160,16 +187,3 @@ auto Cartridge::saveOBC1(Markup::Node node) -> void {
saveMemory(obc1.ram, memory);
}
}
//
auto Cartridge::saveMemory(MappedRAM& ram, Markup::Node node, maybe<uint> id) -> void {
if(!id) id = pathID();
if(auto memory = game.memory(node)) {
if(memory->type == "RAM" && !memory->nonVolatile) return;
if(memory->type == "RTC" && !memory->nonVolatile) return;
if(auto fp = platform->open(id(), memory->name(), File::Write)) {
fp->write(ram.data(), ram.size());
}
}
}

View File

@ -1,6 +1,6 @@
#include <sfc/coprocessor/icd/icd.hpp>
#include <sfc/coprocessor/mcc/mcc.hpp>
#include <sfc/coprocessor/nss/nss.hpp>
#include <sfc/coprocessor/dip/dip.hpp>
#include <sfc/coprocessor/event/event.hpp>
#include <sfc/coprocessor/sa1/sa1.hpp>

View File

@ -0,0 +1,21 @@
//DIP switch
//used for Nintendo Super System emulation
#include <sfc/sfc.hpp>
namespace SuperFamicom {
#include "serialization.cpp"
DIP dip;
auto DIP::power() -> void {
}
auto DIP::read(uint24, uint8) -> uint8 {
return value;
}
auto DIP::write(uint24, uint8) -> void {
}
}

View File

@ -0,0 +1,14 @@
struct DIP {
//dip.cpp
auto power() -> void;
auto read(uint24 addr, uint8 data) -> uint8;
auto write(uint24 addr, uint8 data) -> void;
//serialization.cpp
auto serialize(serializer&) -> void;
uint8 value = 0x00;
};
extern DIP dip;

View File

@ -0,0 +1,3 @@
auto DIP::serialize(serializer& s) -> void {
s.integer(value);
}

View File

@ -1,21 +0,0 @@
#include <sfc/sfc.hpp>
namespace SuperFamicom {
NSS nss;
auto NSS::power() -> void {
}
auto NSS::setDip(uint16 dip) -> void {
this->dip = dip;
}
auto NSS::read(uint24, uint8) -> uint8 {
return dip;
}
auto NSS::write(uint24, uint8) -> void {
}
}

View File

@ -1,11 +0,0 @@
struct NSS {
auto power() -> void;
auto setDip(uint16 dip) -> void;
auto read(uint24 addr, uint8 data) -> uint8;
auto write(uint24 addr, uint8 data) -> void;
uint8 dip = 0x00;
};
extern NSS nss;

View File

@ -2,6 +2,7 @@
namespace SuperFamicom {
#include "serialization.cpp"
BSMemory bsmemory;
auto BSMemory::load() -> void {

View File

@ -1,4 +1,5 @@
struct BSMemory : Memory {
//bsmemory.cpp
auto load() -> void;
auto unload() -> void;
auto power() -> void;
@ -7,6 +8,9 @@ struct BSMemory : Memory {
auto read(uint24 addr, uint8) -> uint8;
auto write(uint24 addr, uint8 data) -> void;
//serialization.cpp
auto serialize(serializer&) -> void;
uint pathID = 0;
MappedRAM memory;
bool readonly;

View File

@ -0,0 +1,3 @@
auto BSMemory::serialize(serializer& s) -> void {
if(!readonly) s.array(memory.data(), memory.size());
}

View File

@ -52,6 +52,7 @@ auto System::serializeAll(serializer& s) -> void {
if(cartridge.has.ICD) icd.serialize(s);
if(cartridge.has.MCC) mcc.serialize(s);
if(cartridge.has.DIP) dip.serialize(s);
if(cartridge.has.Event) event.serialize(s);
if(cartridge.has.SA1) sa1.serialize(s);
if(cartridge.has.SuperFX) superfx.serialize(s);
@ -65,7 +66,9 @@ auto System::serializeAll(serializer& s) -> void {
if(cartridge.has.OBC1) obc1.serialize(s);
if(cartridge.has.MSU1) msu1.serialize(s);
if(cartridge.has.SufamiTurboSlots) sufamiturboA.serialize(s), sufamiturboB.serialize(s);
if(cartridge.has.BSMemorySlot) bsmemory.serialize(s);
if(cartridge.has.SufamiTurboSlotA) sufamiturboA.serialize(s);
if(cartridge.has.SufamiTurboSlotB) sufamiturboB.serialize(s);
controllerPort1.serialize(s);
controllerPort2.serialize(s);

View File

@ -81,7 +81,8 @@ auto System::unload() -> void {
if(cartridge.has.OBC1) obc1.unload();
if(cartridge.has.MSU1) msu1.unload();
if(cartridge.has.BSMemorySlot) bsmemory.unload();
if(cartridge.has.SufamiTurboSlots) sufamiturboA.unload(), sufamiturboB.unload();
if(cartridge.has.SufamiTurboSlotA) sufamiturboA.unload();
if(cartridge.has.SufamiTurboSlotB) sufamiturboB.unload();
cartridge.unload();
information.loaded = false;
@ -106,7 +107,7 @@ auto System::power(bool reset) -> void {
if(cartridge.has.ICD) icd.power();
if(cartridge.has.MCC) mcc.power();
if(cartridge.has.NSSDIP) nss.power();
if(cartridge.has.DIP) dip.power();
if(cartridge.has.Event) event.power();
if(cartridge.has.SA1) sa1.power();
if(cartridge.has.SuperFX) superfx.power();
@ -120,7 +121,8 @@ auto System::power(bool reset) -> void {
if(cartridge.has.OBC1) obc1.power();
if(cartridge.has.MSU1) msu1.power();
if(cartridge.has.BSMemorySlot) bsmemory.power();
if(cartridge.has.SufamiTurboSlots) sufamiturboA.power(), sufamiturboB.power();
if(cartridge.has.SufamiTurboSlotA) sufamiturboA.power();
if(cartridge.has.SufamiTurboSlotB) sufamiturboB.power();
if(cartridge.has.ICD) cpu.coprocessors.append(&icd);
if(cartridge.has.Event) cpu.coprocessors.append(&event);

View File

@ -30,19 +30,29 @@ auto Icarus::famicomImport(vector<uint8_t>& buffer, string location) -> string {
auto manifest = famicomManifest(buffer, location);
if(!manifest) return failure("failed to parse ROM image");
auto document = BML::unserialize(manifest);
uint prgrom = document["game/memory[name=program.rom]"]["size"].natural();
uint chrrom = document["game/memory[name=character.rom]"]["size"].natural();
if(!create(target)) return failure("library path unwritable");
if(exists({source, name, ".sav"}) && !exists({target, "save.ram"})) {
copy({source, name, ".sav"}, {target, "save.ram"});
}
if(settings["icarus/CreateManifests"].boolean()) write({target, "manifest.bml"}, manifest);
write({target, "ines.rom"}, &buffer[0], 16);
write({target, "program.rom"}, &buffer[16], prgrom);
if(!chrrom) return success(target);
write({target, "character.rom"}, &buffer[16 + prgrom], chrrom);
auto document = BML::unserialize(manifest);
uint offset = 0;
if(true) {
//todo: support images without iNES headers (via database lookup)
uint size = 16;
write({target, "ines.rom"}, &buffer[offset], size);
offset += size;
}
if(auto program = document["game/memory(type=ROM,content=Program)"]) {
uint size = program["size"].natural();
write({target, "program.rom"}, &buffer[offset], size);
offset += size;
}
if(auto character = document["game/memory(type=ROM,content=Character)"]) {
uint size = character["size"].natural();
write({target, "character.rom"}, &buffer[offset], size);
offset += size;
}
return success(target);
}

View File

@ -78,7 +78,7 @@ auto nall::main(string_vector args) -> void {
if(args.size() == 2 && args[1] == "--import") {
if(string source = BrowserDialog()
.setTitle("Load ROM Image")
.setTitle("Load ROM File")
.setPath(settings["icarus/Path"].text())
.setFilters("ROM Files|"
"*.fc:*.nes:"