mirror of https://github.com/bsnes-emu/bsnes.git
Update to higan and icarus v095r15 release.
r13 and r14 weren't posted as individual releases, but their changelogs were posted. byuu says about r13: I'm not going to be posting WIPs for r13 and above for a while. The reason is that I'm working on the major manifest overhaul I've discussed previously on the icarus subforum. I'm recreating my boards database from scratch using the map files and the new map analyzer. The only games that will load are ones I've created board definitions for, and updated sfc/cartridge/markup.cpp to parse. Once I've finished all the boards, then I'll update the heuristics. Then finally, I'll sync the syntax changes over to the fc, gb, gba cores. Once that's done, I'll start posting WIPs again, along with a new build of icarus. But I'll still post changelogs as I work through things. Changelog (r13): - preservation: created new database-builder tool (merges region-specific databases with boards) - icarus: support new, external database format (~/.config/icarus/Database/(Super Famicom.bml, ...) - added 1A3B-(10,11,12); 1A3B-20 byuu says about r14: r14 work: I successfully created mappings for every board used in the US set. I also updated icarus' heuristics to use the new mappings, and created ones there for the boards that are only in the JP set. Then I patched icarus to support pulling games out of the database when it's used on a game folder to generate a manifest file. Then I updated a lot of code in higan/sfc to support the new mapping syntax. sfc/cartridge/markup.cpp is about half the size it used to be with the new mappings, and I was able to kill off both map/id and map/select entirely. Then I updated all four emulated systems (and both subsystems) to use "board" as the root node, and harmonized their syntax (made them all more consistent with each other.) Then I added a manifest viewer to the tools window+menu. It's kind of an advanced user feature, but oh well. No reason to coddle people when the feature is very useful for developers. The viewer will show all manifests in order when you load multi-cart games as well. Still not going to call any syntax 100% done right now, but thankfully with the new manifest-free folders, nobody will have to do anything to use the new format. Just download the new version and go. The Super Famicom Event stuff is currently broken (CC92/PF94 boards). That's gonna be fun to support. byuu says about r15: EDIT: small bug in icarus with heuristics. Edit core/super-famicom.cpp line 27: if(/*auto*/ markup = cartridge.markup) { Gotta remove that "auto" so that it returns valid markup. Resolved the final concerns I had with the new manifest format. Right now there are two things that are definitely broken: MCC (BS-X Town cart) and Event (CC '92 and PF'94). And there are a few things that are untested: SPC7110, EpsonRTC, SharpRTC, SDD1+RAM, SufamiTurbo, BS-X slotted carts.
This commit is contained in:
parent
2c53d5fbc0
commit
bd628de3cf
|
@ -7,7 +7,7 @@ using namespace nall;
|
|||
|
||||
namespace Emulator {
|
||||
static const string Name = "higan";
|
||||
static const string Version = "095.12";
|
||||
static const string Version = "095.15";
|
||||
static const string Author = "byuu";
|
||||
static const string License = "GPLv3";
|
||||
static const string Website = "http://byuu.org/";
|
||||
|
|
|
@ -75,6 +75,7 @@ struct Interface {
|
|||
template<typename... P> auto notify(P&&... p) -> void { return bind->notify({forward<P>(p)...}); }
|
||||
|
||||
//information
|
||||
virtual auto manifest() -> string = 0;
|
||||
virtual auto title() -> string = 0;
|
||||
virtual auto videoFrequency() -> double = 0;
|
||||
virtual auto audioFrequency() -> double = 0;
|
||||
|
|
|
@ -21,15 +21,15 @@
|
|||
|
||||
Board::Board(Markup::Node& document) {
|
||||
cartridge.board = this;
|
||||
auto cartridge = document["cartridge"];
|
||||
auto board = document["board"];
|
||||
|
||||
information.type = cartridge["board/type"].text();
|
||||
information.battery = (bool)cartridge["prg/ram/name"];
|
||||
information.type = board["id"].text();
|
||||
information.battery = (bool)board["prg/ram/name"];
|
||||
|
||||
auto prom = cartridge["prg/rom"];
|
||||
auto pram = cartridge["prg/ram"];
|
||||
auto crom = cartridge["chr/rom"];
|
||||
auto cram = cartridge["chr/ram"];
|
||||
auto prom = board["prg/rom"];
|
||||
auto pram = board["prg/ram"];
|
||||
auto crom = board["chr/rom"];
|
||||
auto cram = board["chr/ram"];
|
||||
|
||||
prgrom.size = prom["size"].natural();
|
||||
prgram.size = pram["size"].natural();
|
||||
|
@ -120,7 +120,7 @@ auto Board::load(string manifest) -> Board* {
|
|||
auto document = BML::unserialize(manifest);
|
||||
cartridge.information.title = document["information/title"].text();
|
||||
|
||||
string type = document["cartridge/board/type"].text();
|
||||
string type = document["board/id"].text();
|
||||
|
||||
if(type == "BANDAI-FCG" ) return new BandaiFCG(document);
|
||||
|
||||
|
|
|
@ -14,6 +14,10 @@ auto Cartridge::sha256() const -> string {
|
|||
return _sha256;
|
||||
}
|
||||
|
||||
auto Cartridge::manifest() const -> string {
|
||||
return information.markup;
|
||||
}
|
||||
|
||||
auto Cartridge::title() const -> string {
|
||||
return information.title;
|
||||
}
|
||||
|
|
|
@ -7,6 +7,7 @@ struct Cartridge : Thread {
|
|||
|
||||
auto loaded() const -> bool;
|
||||
auto sha256() const -> string;
|
||||
auto manifest() const -> string;
|
||||
auto title() const -> string;
|
||||
|
||||
auto load() -> void;
|
||||
|
|
|
@ -43,6 +43,10 @@ Interface::Interface() {
|
|||
}
|
||||
}
|
||||
|
||||
auto Interface::manifest() -> string {
|
||||
return cartridge.manifest();
|
||||
}
|
||||
|
||||
auto Interface::title() -> string {
|
||||
return cartridge.title();
|
||||
}
|
||||
|
|
|
@ -27,6 +27,7 @@ struct ID {
|
|||
struct Interface : Emulator::Interface {
|
||||
Interface();
|
||||
|
||||
auto manifest() -> string;
|
||||
auto title() -> string;
|
||||
auto videoFrequency() -> double;
|
||||
auto audioFrequency() -> double;
|
||||
|
|
|
@ -22,7 +22,11 @@ Cartridge::~Cartridge() {
|
|||
unload();
|
||||
}
|
||||
|
||||
auto Cartridge::title() -> string {
|
||||
auto Cartridge::manifest() const -> string {
|
||||
return information.markup;
|
||||
}
|
||||
|
||||
auto Cartridge::title() const -> string {
|
||||
return information.title;
|
||||
}
|
||||
|
||||
|
@ -58,7 +62,7 @@ auto Cartridge::load(System::Revision revision) -> void {
|
|||
auto document = BML::unserialize(information.markup);
|
||||
information.title = document["information/title"].text();
|
||||
|
||||
auto mapperid = document["cartridge/board/type"].text();
|
||||
auto mapperid = document["board/mapper"].text();
|
||||
if(mapperid == "none" ) information.mapper = Mapper::MBC0;
|
||||
if(mapperid == "MBC1" ) information.mapper = Mapper::MBC1;
|
||||
if(mapperid == "MBC2" ) information.mapper = Mapper::MBC2;
|
||||
|
@ -71,8 +75,8 @@ auto Cartridge::load(System::Revision revision) -> void {
|
|||
information.rtc = false;
|
||||
information.rumble = false;
|
||||
|
||||
auto rom = document["cartridge/rom"];
|
||||
auto ram = document["cartridge/ram"];
|
||||
auto rom = document["board/rom"];
|
||||
auto ram = document["board/ram"];
|
||||
|
||||
romsize = rom["size"].natural();
|
||||
romdata = allocate<uint8>(romsize, 0xff);
|
||||
|
|
|
@ -53,7 +53,8 @@ struct Cartridge : MMIO, property<Cartridge> {
|
|||
uint ramsize;
|
||||
} information;
|
||||
|
||||
string title();
|
||||
auto manifest() const -> string;
|
||||
auto title() const -> string;
|
||||
|
||||
struct Memory {
|
||||
uint id;
|
||||
|
|
|
@ -37,6 +37,10 @@ Interface::Interface() {
|
|||
port.append({0, "Device", {device[0]}});
|
||||
}
|
||||
|
||||
auto Interface::manifest() -> string {
|
||||
return cartridge.manifest();
|
||||
}
|
||||
|
||||
auto Interface::title() -> string {
|
||||
return cartridge.title();
|
||||
}
|
||||
|
|
|
@ -29,6 +29,7 @@ struct ID {
|
|||
struct Interface : Emulator::Interface {
|
||||
Interface();
|
||||
|
||||
auto manifest() -> string;
|
||||
auto title() -> string;
|
||||
auto videoFrequency() -> double;
|
||||
auto audioFrequency() -> double;
|
||||
|
|
|
@ -31,6 +31,10 @@ auto Cartridge::sha256() const -> string {
|
|||
return information.sha256;
|
||||
}
|
||||
|
||||
auto Cartridge::manifest() const -> string {
|
||||
return information.markup;
|
||||
}
|
||||
|
||||
auto Cartridge::title() const -> string {
|
||||
return information.title;
|
||||
}
|
||||
|
@ -45,48 +49,50 @@ auto Cartridge::load() -> void {
|
|||
hasEEPROM = false;
|
||||
hasFLASH = false;
|
||||
|
||||
if(auto info = document["cartridge/mrom"]) {
|
||||
if(auto info = document["board/rom"]) {
|
||||
mrom.size = min(32 * 1024 * 1024, info["size"].natural());
|
||||
|
||||
interface->loadRequest(ID::MROM, info["name"].text(), true);
|
||||
}
|
||||
|
||||
if(auto info = document["cartridge/sram"]) {
|
||||
hasSRAM = true;
|
||||
sram.size = min(32 * 1024, info["size"].natural());
|
||||
sram.mask = sram.size - 1;
|
||||
for(auto n : range(sram.size)) sram.data[n] = 0xff;
|
||||
if(auto info = document["board/ram"]) {
|
||||
if(info["type"].text() == "sram") {
|
||||
hasSRAM = true;
|
||||
sram.size = min(32 * 1024, info["size"].natural());
|
||||
sram.mask = sram.size - 1;
|
||||
for(auto n : range(sram.size)) sram.data[n] = 0xff;
|
||||
|
||||
interface->loadRequest(ID::SRAM, info["name"].text(), false);
|
||||
memory.append({ID::SRAM, info["name"].text()});
|
||||
}
|
||||
interface->loadRequest(ID::SRAM, info["name"].text(), false);
|
||||
memory.append({ID::SRAM, info["name"].text()});
|
||||
}
|
||||
|
||||
if(auto info = document["cartridge/eeprom"]) {
|
||||
hasEEPROM = true;
|
||||
eeprom.size = min(8 * 1024, info["size"].natural());
|
||||
eeprom.bits = eeprom.size <= 512 ? 6 : 14;
|
||||
if(eeprom.size == 0) eeprom.size = 8192, eeprom.bits = 0; //auto-detect size
|
||||
eeprom.mask = mrom.size > 16 * 1024 * 1024 ? 0x0fffff00 : 0x0f000000;
|
||||
eeprom.test = mrom.size > 16 * 1024 * 1024 ? 0x0dffff00 : 0x0d000000;
|
||||
for(auto n : range(eeprom.size)) eeprom.data[n] = 0xff;
|
||||
if(info["type"].text() == "eeprom") {
|
||||
hasEEPROM = true;
|
||||
eeprom.size = min(8 * 1024, info["size"].natural());
|
||||
eeprom.bits = eeprom.size <= 512 ? 6 : 14;
|
||||
if(eeprom.size == 0) eeprom.size = 8192, eeprom.bits = 0; //auto-detect size
|
||||
eeprom.mask = mrom.size > 16 * 1024 * 1024 ? 0x0fffff00 : 0x0f000000;
|
||||
eeprom.test = mrom.size > 16 * 1024 * 1024 ? 0x0dffff00 : 0x0d000000;
|
||||
for(auto n : range(eeprom.size)) eeprom.data[n] = 0xff;
|
||||
|
||||
interface->loadRequest(ID::EEPROM, info["name"].text(), false);
|
||||
memory.append({ID::EEPROM, info["name"].text()});
|
||||
}
|
||||
interface->loadRequest(ID::EEPROM, info["name"].text(), false);
|
||||
memory.append({ID::EEPROM, info["name"].text()});
|
||||
}
|
||||
|
||||
if(auto info = document["cartridge/flash"]) {
|
||||
hasFLASH = true;
|
||||
flash.id = info["id"].natural();
|
||||
flash.size = min(128 * 1024, info["size"].natural());
|
||||
for(auto n : range(flash.size)) flash.data[n] = 0xff;
|
||||
if(info["type"].text() == "flash") {
|
||||
hasFLASH = true;
|
||||
flash.id = info["id"].natural();
|
||||
flash.size = min(128 * 1024, info["size"].natural());
|
||||
for(auto n : range(flash.size)) flash.data[n] = 0xff;
|
||||
|
||||
//if flash ID not provided; guess that it's a Macronix chip
|
||||
//this will not work for all games; in which case, the ID must be specified manually
|
||||
if(!flash.id && flash.size == 64 * 1024) flash.id = 0x1cc2;
|
||||
if(!flash.id && flash.size == 128 * 1024) flash.id = 0x09c2;
|
||||
//if flash ID not provided; guess that it's a Macronix chip
|
||||
//this will not work for all games; in which case, the ID must be specified manually
|
||||
if(!flash.id && flash.size == 64 * 1024) flash.id = 0x1cc2;
|
||||
if(!flash.id && flash.size == 128 * 1024) flash.id = 0x09c2;
|
||||
|
||||
interface->loadRequest(ID::FLASH, info["name"].text(), false);
|
||||
memory.append({ID::FLASH, info["name"].text()});
|
||||
interface->loadRequest(ID::FLASH, info["name"].text(), false);
|
||||
memory.append({ID::FLASH, info["name"].text()});
|
||||
}
|
||||
}
|
||||
|
||||
information.sha256 = Hash::SHA256(mrom.data, mrom.size).digest();
|
||||
|
|
|
@ -3,6 +3,7 @@ struct Cartridge {
|
|||
|
||||
auto loaded() const -> bool;
|
||||
auto sha256() const -> string;
|
||||
auto manifest() const -> string;
|
||||
auto title() const -> string;
|
||||
|
||||
struct Information {
|
||||
|
|
|
@ -37,6 +37,10 @@ Interface::Interface() {
|
|||
port.append({0, "Device", {device[0]}});
|
||||
}
|
||||
|
||||
auto Interface::manifest() -> string {
|
||||
return cartridge.manifest();
|
||||
}
|
||||
|
||||
auto Interface::title() -> string {
|
||||
return cartridge.title();
|
||||
}
|
||||
|
|
|
@ -27,6 +27,7 @@ struct ID {
|
|||
struct Interface : Emulator::Interface {
|
||||
Interface();
|
||||
|
||||
auto manifest() -> string;
|
||||
auto title() -> string;
|
||||
auto videoFrequency() -> double;
|
||||
auto audioFrequency() -> double;
|
||||
|
|
|
@ -22,6 +22,7 @@ auto mMenuCheckItem::onToggle(const function<void ()>& callback) -> type& {
|
|||
auto mMenuCheckItem::setChecked(bool checked) -> type& {
|
||||
state.checked = checked;
|
||||
signal(setChecked, checked);
|
||||
return *this;
|
||||
}
|
||||
|
||||
auto mMenuCheckItem::setText(const string& text) -> type& {
|
||||
|
|
|
@ -9,7 +9,7 @@ Hotkey::Hotkey(const string& sequence) : state(new Hotkey::State) {
|
|||
}
|
||||
|
||||
Hotkey::operator bool() const {
|
||||
return state->sequence;
|
||||
return (bool)state->sequence;
|
||||
}
|
||||
|
||||
auto Hotkey::operator==(const Hotkey& source) const -> bool {
|
||||
|
|
|
@ -9,6 +9,7 @@ auto pSizable::destruct() -> void {
|
|||
}
|
||||
|
||||
auto pSizable::minimumSize() const -> Size {
|
||||
return {0, 0};
|
||||
}
|
||||
|
||||
auto pSizable::setGeometry(Geometry geometry) -> void {
|
||||
|
|
|
@ -1,13 +1,5 @@
|
|||
namespace Database {
|
||||
#include "../database/super-famicom.hpp"
|
||||
#include "../database/bsx-satellaview.hpp"
|
||||
#include "../database/sufami-turbo.hpp"
|
||||
}
|
||||
|
||||
Icarus::Icarus() {
|
||||
database.superFamicom = BML::unserialize(Database::SuperFamicom);
|
||||
database.bsxSatellaview = BML::unserialize(Database::BsxSatellaview);
|
||||
database.sufamiTurbo = BML::unserialize(Database::SufamiTurbo);
|
||||
database.superFamicom = BML::unserialize(string::read(locate({configpath(), "icarus/"}, "Database/Super Famicom.bml")));
|
||||
}
|
||||
|
||||
auto Icarus::error() const -> string {
|
||||
|
|
|
@ -19,8 +19,8 @@ struct Icarus {
|
|||
//super-famicom.cpp
|
||||
auto superFamicomManifest(const string& location) -> string;
|
||||
auto superFamicomManifest(vector<uint8_t>& buffer, const string& location) -> string;
|
||||
auto superFamicomManifestScan(vector<Markup::Node>& roms, Markup::Node node) -> void;
|
||||
auto superFamicomImport(vector<uint8_t>& buffer, const string& location) -> bool;
|
||||
auto superFamicomImportScanManifest(vector<Markup::Node>& roms, Markup::Node node) -> void;
|
||||
|
||||
//game-boy.cpp
|
||||
auto gameBoyManifest(const string& location) -> string;
|
||||
|
|
|
@ -10,16 +10,36 @@ auto Icarus::superFamicomManifest(const string& location) -> string {
|
|||
}
|
||||
|
||||
auto Icarus::superFamicomManifest(vector<uint8_t>& buffer, const string& location) -> string {
|
||||
SuperFamicomCartridge cartridge{buffer.data(), buffer.size()};
|
||||
if(auto markup = cartridge.markup) {
|
||||
markup.append("\n");
|
||||
markup.append("information\n");
|
||||
markup.append(" sha256: ", Hash::SHA256(buffer.data(), buffer.size()).digest(), "\n");
|
||||
markup.append(" title: ", prefixname(location), "\n");
|
||||
markup.append(" note: ", "heuristically generated by icarus\n");
|
||||
return markup;
|
||||
string markup;
|
||||
|
||||
if(settings["icarus/UseDatabase"].boolean() && !markup) {
|
||||
auto digest = Hash::SHA256(buffer.data(), buffer.size()).digest();
|
||||
for(auto node : database.superFamicom) {
|
||||
if(node["sha256"].text() == digest) {
|
||||
markup.append(node.text(), "\n sha256: ", digest, "\n");
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return "";
|
||||
|
||||
if(settings["icarus/UseHeuristics"].boolean() && !markup) {
|
||||
SuperFamicomCartridge cartridge{buffer.data(), buffer.size()};
|
||||
if(auto markup = cartridge.markup) {
|
||||
markup.append("\n");
|
||||
markup.append("information\n");
|
||||
markup.append(" region: ", cartridge.region == SuperFamicomCartridge::Region::NTSC ? "NTSC" : "PAL", "\n");
|
||||
markup.append(" title: ", prefixname(location), "\n");
|
||||
markup.append(" sha256: ", Hash::SHA256(buffer.data(), buffer.size()).digest(), "\n");
|
||||
markup.append(" note: ", "heuristically generated by icarus\n");
|
||||
}
|
||||
}
|
||||
|
||||
return markup;
|
||||
}
|
||||
|
||||
auto Icarus::superFamicomManifestScan(vector<Markup::Node>& roms, Markup::Node node) -> void {
|
||||
if(node["name"].text().endsWith(".rom")) roms.append(node);
|
||||
for(auto leaf : node) superFamicomManifestScan(roms, leaf);
|
||||
}
|
||||
|
||||
auto Icarus::superFamicomImport(vector<uint8_t>& buffer, const string& location) -> bool {
|
||||
|
@ -29,16 +49,13 @@ auto Icarus::superFamicomImport(vector<uint8_t>& buffer, const string& location)
|
|||
//if(directory::exists(target)) return failure("game already exists");
|
||||
|
||||
string markup;
|
||||
vector<Markup::Node> roms;
|
||||
bool firmwareAppended = true;
|
||||
|
||||
if(settings["icarus/UseDatabase"].boolean() && !markup) {
|
||||
auto digest = Hash::SHA256(buffer.data(), buffer.size()).digest();
|
||||
for(auto node : database.superFamicom) {
|
||||
if(node.name() != "release") continue;
|
||||
if(node["information/sha256"].text() == digest) {
|
||||
markup.append(BML::serialize(node["cartridge"]), "\n");
|
||||
markup.append(BML::serialize(node["information"]));
|
||||
if(node["sha256"].text() == digest) {
|
||||
markup.append(node.text(), "\n sha256: ", digest, "\n");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -50,13 +67,16 @@ auto Icarus::superFamicomImport(vector<uint8_t>& buffer, const string& location)
|
|||
firmwareAppended = cartridge.firmware_appended;
|
||||
markup.append("\n");
|
||||
markup.append("information\n");
|
||||
markup.append(" title: ", name, "\n");
|
||||
markup.append(" note: ", "heuristically generated by icarus\n");
|
||||
markup.append(" region: ", cartridge.region == SuperFamicomCartridge::Region::NTSC ? "NTSC" : "PAL", "\n");
|
||||
markup.append(" title: ", name, "\n");
|
||||
markup.append(" sha256: ", Hash::SHA256(buffer.data(), buffer.size()).digest(), "\n");
|
||||
markup.append(" note: ", "heuristically generated by icarus\n");
|
||||
}
|
||||
}
|
||||
|
||||
auto document = BML::unserialize(markup);
|
||||
superFamicomImportScanManifest(roms, document["cartridge"]);
|
||||
vector<Markup::Node> roms;
|
||||
superFamicomManifestScan(roms, document["board"]);
|
||||
for(auto rom : roms) {
|
||||
auto name = rom["name"].text();
|
||||
auto size = rom["size"].natural();
|
||||
|
@ -68,7 +88,7 @@ auto Icarus::superFamicomImport(vector<uint8_t>& buffer, const string& location)
|
|||
if(!directory::create(target)) return failure("library path unwritable");
|
||||
|
||||
if(settings["icarus/CreateManifests"].boolean()) file::write({target, "manifest.bml"}, markup);
|
||||
unsigned offset = (buffer.size() & 0x7fff) == 512 ? 512 : 0; //skip header if present
|
||||
uint offset = (buffer.size() & 0x7fff) == 512 ? 512 : 0; //skip header if present
|
||||
for(auto rom : roms) {
|
||||
auto name = rom["name"].text();
|
||||
auto size = rom["size"].natural();
|
||||
|
@ -83,8 +103,3 @@ auto Icarus::superFamicomImport(vector<uint8_t>& buffer, const string& location)
|
|||
}
|
||||
return success();
|
||||
}
|
||||
|
||||
auto Icarus::superFamicomImportScanManifest(vector<Markup::Node>& roms, Markup::Node node) -> void {
|
||||
if(node.name() == "rom") roms.append(node);
|
||||
for(auto leaf : node) superFamicomImportScanManifest(roms, leaf);
|
||||
}
|
||||
|
|
|
@ -1,19 +0,0 @@
|
|||
string BsxSatellaview = R"(
|
||||
|
||||
database revision=2013-01-22
|
||||
|
||||
release
|
||||
cartridge
|
||||
rom name=program.rom size=0x80000 type=MaskROM
|
||||
information
|
||||
title: 鮫亀 キャラカセット
|
||||
name: Same Game - Character Cassette
|
||||
region: JP
|
||||
revision: 1.0
|
||||
board: BSMC-CR-01
|
||||
serial: BSMC-ZS5J-JPN
|
||||
sha256: 80c34b50817d58820bc8c88d2d9fa462550b4a76372e19c6467cbfbc8cf5d9ef
|
||||
configuration
|
||||
rom name=program.rom size=0x80000 type=MaskROM
|
||||
|
||||
)";
|
|
@ -1,162 +0,0 @@
|
|||
string SufamiTurbo = R"(
|
||||
|
||||
database revision=2013-01-22
|
||||
|
||||
release
|
||||
cartridge linkable
|
||||
rom name=program.rom size=0x80000
|
||||
ram name=save.ram size=0x800
|
||||
information
|
||||
title: SDウルトラバトル ウルトラマン伝説
|
||||
name: SD Ultra Battle - Ultraman Densetsu
|
||||
region: JP
|
||||
revision: 1.0
|
||||
serial: SFT-0101-JPN
|
||||
sha256: 2bb55214fb668ca603d7b944b14f105dfb10b987a8902d420fe4ae1cb69c1d4a
|
||||
configuration
|
||||
rom name=program.rom size=0x80000
|
||||
ram name=save.ram size=0x800
|
||||
linkable
|
||||
|
||||
release
|
||||
cartridge linkable
|
||||
rom name=program.rom size=0x80000
|
||||
ram name=save.ram size=0x800
|
||||
information
|
||||
title: SDウルトラバトル セブン伝説
|
||||
name: SD Ultra Battle - Seven Densetsu
|
||||
region: JP
|
||||
revision: 1.0
|
||||
serial: SFT-0102-JPN
|
||||
sha256: 2fec5f2bc7dee010af10569a3d2bc18715a79a126940800c3eade5abbd625e3f
|
||||
configuration
|
||||
rom name=program.rom size=0x80000
|
||||
ram name=save.ram size=0x800
|
||||
linkable
|
||||
|
||||
release
|
||||
cartridge linkable
|
||||
rom name=program.rom size=0x80000
|
||||
ram name=save.ram size=0x800
|
||||
information
|
||||
title: ポイポイ忍者ワールド
|
||||
name: Poi Poi Ninja World
|
||||
region: JP
|
||||
revision: 1.0
|
||||
serial: SFT-0103-JPN
|
||||
sha256: 602b20b788640f5743487108a10f3f77bca5ce2d24208b25b1ca498a96eb0d69
|
||||
configuration
|
||||
rom name=program.rom size=0x80000
|
||||
ram name=save.ram size=0x800
|
||||
linkable
|
||||
|
||||
release
|
||||
cartridge linkable
|
||||
rom name=program.rom size=0x80000
|
||||
ram name=save.ram size=0x2000
|
||||
information
|
||||
title: SDガンダムジェネレーション 一年戦争記
|
||||
name: SD Gundam Generation - Ichinen Sensouki
|
||||
region: JP
|
||||
revision: 1.0
|
||||
serial: SFT-0104-JPN
|
||||
sha256: 3e82215bed08274874b30d461fc4a965c6bca932229da5d46d56e36f484d65eb
|
||||
configuration
|
||||
rom name=program.rom size=0x80000
|
||||
ram name=save.ram size=0x2000
|
||||
linkable
|
||||
|
||||
release
|
||||
cartridge linkable
|
||||
rom name=program.rom size=0x80000
|
||||
ram name=save.ram size=0x2000
|
||||
information
|
||||
title: SDガンダムジェネレーション グリプス戦記
|
||||
name: SD Gundam Generation - Grips Senki
|
||||
region: JP
|
||||
revision: 1.0
|
||||
serial: SFT-0105-JPN
|
||||
sha256: 8547a08ed11fe408eac282a90ac46654bd2e5f49bda3aec8e5edf166a0a4b9af
|
||||
configuration
|
||||
rom name=program.rom size=0x80000
|
||||
ram name=save.ram size=0x2000
|
||||
linkable
|
||||
|
||||
release
|
||||
cartridge
|
||||
rom name=program.rom size=0x80000
|
||||
information
|
||||
title: ゲゲゲの鬼太郎 妖怪ドンジャラ
|
||||
name: Gegege no Kitarou - Youkai Donjara
|
||||
region: JP
|
||||
revision: 1.0
|
||||
serial: SFT-0106-JPN
|
||||
sha256: d93b3a570e7cf343f680ab0768a50b77e3577f9c555007e2de3decd6bc4765c8
|
||||
configuration
|
||||
rom name=program.rom size=0x80000
|
||||
|
||||
release
|
||||
cartridge linkable
|
||||
rom name=program.rom size=0x80000
|
||||
ram name=save.ram size=0x2000
|
||||
information
|
||||
title: SDガンダムジェネレーション アクシズ戦記
|
||||
name: SD Gundam Generation - Axis Senki
|
||||
region: JP
|
||||
revision: 1.0
|
||||
serial: SFT-0107-JPN
|
||||
sha256: 2a9d7c9a61318861028a73ca03e32a48cff162d76cba36fbaab8690b212efe9b
|
||||
configuration
|
||||
rom name=program.rom size=0x80000
|
||||
ram name=save.ram size=0x2000
|
||||
linkable
|
||||
|
||||
release
|
||||
cartridge linkable
|
||||
rom name=program.rom size=0x80000
|
||||
ram name=save.ram size=0x2000
|
||||
information
|
||||
title: SDガンダムジェネレーション バビロニア建国戦記
|
||||
name: SD Gundam Generation - Babylonia Kenkoku Senki
|
||||
region: JP
|
||||
revision: 1.0
|
||||
serial: SFT-0108-JPN
|
||||
sha256: 60ac017c18f534e8cf24ca7f38e22ce92db95ea6c30b2d59d76f13c4f1c8a6e4
|
||||
configuration
|
||||
rom name=program.rom size=0x80000
|
||||
ram name=save.ram size=0x2000
|
||||
linkable
|
||||
|
||||
release
|
||||
cartridge linkable
|
||||
rom name=program.rom size=0x80000
|
||||
ram name=save.ram size=0x2000
|
||||
information
|
||||
title: SDガンダムジェネレーション ザンスカール戦記
|
||||
name: SD Gundam Generation - Zanscar Senki
|
||||
region: JP
|
||||
revision: 1.0
|
||||
serial: SFT-0110-JPN
|
||||
sha256: 5951a58a91d8e397d0a237ccc2b1248e17c7312cb9cc11cbc350200a97b4e021
|
||||
configuration
|
||||
rom name=program.rom size=0x80000
|
||||
ram name=save.ram size=0x2000
|
||||
linkable
|
||||
|
||||
release
|
||||
cartridge linkable
|
||||
rom name=program.rom size=0x80000
|
||||
ram name=save.ram size=0x800
|
||||
information
|
||||
title: SDガンダムジェネレーション コロニー格闘記
|
||||
name: SD Gundam Generation - Colony Kakutouki
|
||||
region: JP
|
||||
revision: 1.0
|
||||
serial: SFT-0111-JPN
|
||||
sha256: e639b5d5d722432b6809ccc6801dc584e1a3016379f34b335ed2dfa73b1ebf69
|
||||
configuration
|
||||
rom name=program.rom size=0x80000
|
||||
ram name=save.ram size=0x800
|
||||
linkable
|
||||
|
||||
)";
|
File diff suppressed because it is too large
Load Diff
|
@ -5,6 +5,6 @@ struct BsxSatellaviewCartridge {
|
|||
};
|
||||
|
||||
BsxSatellaviewCartridge::BsxSatellaviewCartridge(const uint8_t* data, unsigned size) {
|
||||
markup.append("cartridge\n");
|
||||
markup.append(" rom name=program.rom size=0x", hex(size), " type=FlashROM\n");
|
||||
markup.append("board\n");
|
||||
markup.append(" rom type=flash name=program.rom size=0x", hex(size), "\n");
|
||||
}
|
||||
|
|
|
@ -1,18 +1,18 @@
|
|||
struct FamicomCartridge {
|
||||
FamicomCartridge(const uint8_t* data, unsigned size);
|
||||
FamicomCartridge(const uint8* data, uint size);
|
||||
|
||||
string markup;
|
||||
|
||||
//private:
|
||||
unsigned mapper;
|
||||
unsigned mirror;
|
||||
unsigned prgrom;
|
||||
unsigned prgram;
|
||||
unsigned chrrom;
|
||||
unsigned chrram;
|
||||
uint mapper;
|
||||
uint mirror;
|
||||
uint prgrom;
|
||||
uint prgram;
|
||||
uint chrrom;
|
||||
uint chrram;
|
||||
};
|
||||
|
||||
FamicomCartridge::FamicomCartridge(const uint8_t* data, unsigned size) {
|
||||
FamicomCartridge::FamicomCartridge(const uint8* data, uint size) {
|
||||
if(size < 16) return;
|
||||
if(data[0] != 'N') return;
|
||||
if(data[1] != 'E') return;
|
||||
|
@ -26,65 +26,65 @@ FamicomCartridge::FamicomCartridge(const uint8_t* data, unsigned size) {
|
|||
prgram = 0u;
|
||||
chrram = chrrom == 0u ? 8192u : 0u;
|
||||
|
||||
markup.append("cartridge\n");
|
||||
markup.append("board ");
|
||||
|
||||
switch(mapper) {
|
||||
default:
|
||||
markup.append(" board type=NES-NROM-256\n");
|
||||
markup.append("id:NES-NROM-256\n");
|
||||
markup.append(" mirror mode=", mirror == 0 ? "horizontal" : "vertical", "\n");
|
||||
break;
|
||||
|
||||
case 1:
|
||||
markup.append(" board type=NES-SXROM\n");
|
||||
markup.append("id:NES-SXROM\n");
|
||||
markup.append(" chip type=MMC1B2\n");
|
||||
prgram = 8192;
|
||||
break;
|
||||
|
||||
case 2:
|
||||
markup.append(" board type=NES-UOROM\n");
|
||||
markup.append("id:NES-UOROM\n");
|
||||
markup.append(" mirror mode=", mirror == 0 ? "horizontal" : "vertical", "\n");
|
||||
break;
|
||||
|
||||
case 3:
|
||||
markup.append(" board type=NES-CNROM\n");
|
||||
markup.append("id:NES-CNROM\n");
|
||||
markup.append(" mirror mode=", mirror == 0 ? "horizontal" : "vertical", "\n");
|
||||
break;
|
||||
|
||||
case 4:
|
||||
//MMC3
|
||||
markup.append(" board type=NES-TLROM\n");
|
||||
markup.append("id:NES-TLROM\n");
|
||||
markup.append(" chip type=MMC3B\n");
|
||||
prgram = 8192;
|
||||
//MMC6
|
||||
//markup.append(" board type=NES-HKROM\n");
|
||||
//markup.append("id:NES-HKROM\n");
|
||||
//markup.append(" chip type=MMC6n");
|
||||
//prgram = 1024;
|
||||
break;
|
||||
|
||||
case 5:
|
||||
markup.append(" board type=NES-ELROM\n");
|
||||
markup.append("id:NES-ELROM\n");
|
||||
markup.append(" chip type=MMC5\n");
|
||||
prgram = 65536;
|
||||
break;
|
||||
|
||||
case 7:
|
||||
markup.append(" board type=NES-AOROM\n");
|
||||
markup.append("id:NES-AOROM\n");
|
||||
break;
|
||||
|
||||
case 9:
|
||||
markup.append(" board type=NES-PNROM\n");
|
||||
markup.append("id:NES-PNROM\n");
|
||||
markup.append(" chip type=MMC2\n");
|
||||
prgram = 8192;
|
||||
break;
|
||||
|
||||
case 10:
|
||||
markup.append(" board type=NES-FKROM\n");
|
||||
markup.append("id:NES-FKROM\n");
|
||||
markup.append(" chip type=MMC4\n");
|
||||
prgram = 8192;
|
||||
break;
|
||||
|
||||
case 16:
|
||||
markup.append(" board type=BANDAI-FCG\n");
|
||||
markup.append("id:BANDAI-FCG\n");
|
||||
markup.append(" chip type=LZ93D50\n");
|
||||
break;
|
||||
|
||||
|
@ -92,7 +92,7 @@ FamicomCartridge::FamicomCartridge(const uint8_t* data, unsigned size) {
|
|||
case 23:
|
||||
case 25:
|
||||
//VRC4
|
||||
markup.append(" board type=KONAMI-VRC-4\n");
|
||||
markup.append("id:KONAMI-VRC-4\n");
|
||||
markup.append(" chip type=VRC4\n");
|
||||
markup.append(" pinout a0=1 a1=0\n");
|
||||
prgram = 8192;
|
||||
|
@ -100,52 +100,52 @@ FamicomCartridge::FamicomCartridge(const uint8_t* data, unsigned size) {
|
|||
|
||||
case 22:
|
||||
//VRC2
|
||||
markup.append(" board type=KONAMI-VRC-2\n");
|
||||
markup.append("id:KONAMI-VRC-2\n");
|
||||
markup.append(" chip type=VRC2\n");
|
||||
markup.append(" pinout a0=0 a1=1\n");
|
||||
break;
|
||||
|
||||
case 24:
|
||||
markup.append(" board type=KONAMI-VRC-6\n");
|
||||
markup.append("id:KONAMI-VRC-6\n");
|
||||
markup.append(" chip type=VRC6\n");
|
||||
break;
|
||||
|
||||
case 26:
|
||||
markup.append(" board type=KONAMI-VRC-6\n");
|
||||
markup.append("id:KONAMI-VRC-6\n");
|
||||
markup.append(" chip type=VRC6\n");
|
||||
prgram = 8192;
|
||||
break;
|
||||
|
||||
case 34:
|
||||
markup.append(" board type=NES-BNROM\n");
|
||||
markup.append("id:NES-BNROM\n");
|
||||
markup.append(" mirror mode=", mirror == 0 ? "horizontal" : "vertical", "\n");
|
||||
break;
|
||||
|
||||
case 66:
|
||||
markup.append(" board type=NES-GNROM\n");
|
||||
markup.append("id:NES-GNROM\n");
|
||||
markup.append(" mirror mode=", mirror == 0 ? "horizontal" : "vertical", "\n");
|
||||
break;
|
||||
|
||||
case 69:
|
||||
markup.append(" board type=SUNSOFT-5B\n");
|
||||
markup.append("id:SUNSOFT-5B\n");
|
||||
markup.append(" chip type=5B\n");
|
||||
prgram = 8192;
|
||||
break;
|
||||
|
||||
case 73:
|
||||
markup.append(" board type=KONAMI-VRC-3\n");
|
||||
markup.append("id:KONAMI-VRC-3\n");
|
||||
markup.append(" chip type=VRC3\n");
|
||||
markup.append(" mirror mode=", mirror == 0 ? "horizontal" : "vertical", "\n");
|
||||
prgram = 8192;
|
||||
break;
|
||||
|
||||
case 75:
|
||||
markup.append(" board type=KONAMI-VRC-1\n");
|
||||
markup.append("id:KONAMI-VRC-1\n");
|
||||
markup.append(" chip type=VRC1\n");
|
||||
break;
|
||||
|
||||
case 85:
|
||||
markup.append(" board type=KONAMI-VRC-7\n");
|
||||
markup.append("id:KONAMI-VRC-7\n");
|
||||
markup.append(" chip type=VRC7\n");
|
||||
prgram = 8192;
|
||||
break;
|
||||
|
|
|
@ -37,14 +37,14 @@ GameBoyAdvanceCartridge::GameBoyAdvanceCartridge(const uint8_t *data, unsigned s
|
|||
}
|
||||
identifiers = list.merge(",");
|
||||
|
||||
markup.append("cartridge\n");
|
||||
markup.append(" mrom name=program.rom size=0x", hex(size), "\n");
|
||||
markup.append("board\n");
|
||||
markup.append(" rom type=mrom name=program.rom size=0x", hex(size), "\n");
|
||||
if(0);
|
||||
else if(identifiers.beginsWith("SRAM_V" )) markup.append(" sram name=save.ram size=0x8000\n");
|
||||
else if(identifiers.beginsWith("SRAM_F_V" )) markup.append(" sram name=save.ram size=0x8000\n");
|
||||
else if(identifiers.beginsWith("EEPROM_V" )) markup.append(" eeprom name=save.ram size=0x0\n");
|
||||
else if(identifiers.beginsWith("FLASH_V" )) markup.append(" flash name=save.ram size=0x10000\n");
|
||||
else if(identifiers.beginsWith("FLASH512_V")) markup.append(" flash name=save.ram size=0x10000\n");
|
||||
else if(identifiers.beginsWith("FLASH1M_V" )) markup.append(" flash name=save.ram size=0x20000\n");
|
||||
//if(identifiers.empty() == false) markup.append(" #detected: ", identifiers, "\n");
|
||||
else if(identifiers.beginsWith("SRAM_V" )) markup.append(" ram type=sram name=save.ram size=0x8000\n");
|
||||
else if(identifiers.beginsWith("SRAM_F_V" )) markup.append(" ram type=sram name=save.ram size=0x8000\n");
|
||||
else if(identifiers.beginsWith("EEPROM_V" )) markup.append(" ram type=eeprom name=save.ram size=0x0\n");
|
||||
else if(identifiers.beginsWith("FLASH_V" )) markup.append(" ram type=flash name=save.ram size=0x10000\n");
|
||||
else if(identifiers.beginsWith("FLASH512_V")) markup.append(" ram type=flash name=save.ram size=0x10000\n");
|
||||
else if(identifiers.beginsWith("FLASH1M_V" )) markup.append(" ram type=flash name=save.ram size=0x20000\n");
|
||||
//if(identifiers) markup.append(" #detected: ", identifiers, "\n");
|
||||
}
|
||||
|
|
|
@ -100,8 +100,7 @@ GameBoyCartridge::GameBoyCartridge(uint8_t *romdata, unsigned romsize) {
|
|||
|
||||
if(info.mapper == "MBC2") info.ramsize = 512; //512 x 4-bit
|
||||
|
||||
markup.append("cartridge\n");
|
||||
markup.append(" board type=", info.mapper, "\n");
|
||||
markup.append("board mapper=", info.mapper, "\n");
|
||||
markup.append(" rom name=program.rom size=0x", hex(romsize), "\n");
|
||||
if(info.ramsize > 0) markup.append(" ram name=save.ram size=0x", hex(info.ramsize), "\n");
|
||||
}
|
||||
|
|
|
@ -11,7 +11,7 @@ SufamiTurboCartridge::SufamiTurboCartridge(const uint8_t* data, unsigned size) {
|
|||
unsigned ramsize = data[0x37] * 0x800; //2KB
|
||||
bool linkable = data[0x35] != 0x00; //TODO: unconfirmed
|
||||
|
||||
markup.append("cartridge", linkable ? " linkable" : "", "\n");
|
||||
markup.append("board", linkable ? " linkable" : "", "\n");
|
||||
markup.append(" rom name=program.rom size=0x", hex(romsize), "\n");
|
||||
if(ramsize)
|
||||
markup.append(" ram name=save.ram size=0x", hex(ramsize), "\n");
|
||||
|
|
|
@ -1,14 +1,14 @@
|
|||
struct SuperFamicomCartridge {
|
||||
SuperFamicomCartridge(const uint8_t *data, unsigned size);
|
||||
SuperFamicomCartridge(const uint8* data, uint size);
|
||||
|
||||
string markup;
|
||||
|
||||
//private:
|
||||
auto readHeader(const uint8_t *data, unsigned size) -> void;
|
||||
auto findHeader(const uint8_t *data, unsigned size) -> unsigned;
|
||||
auto scoreHeader(const uint8_t *data, unsigned size, unsigned addr) -> unsigned;
|
||||
auto readHeader(const uint8* data, uint size) -> void;
|
||||
auto findHeader(const uint8* data, uint size) -> uint;
|
||||
auto scoreHeader(const uint8* data, uint size, uint addr) -> uint;
|
||||
|
||||
enum HeaderField : unsigned {
|
||||
enum HeaderField : uint {
|
||||
CartName = 0x00,
|
||||
Mapper = 0x15,
|
||||
RomType = 0x16,
|
||||
|
@ -22,7 +22,7 @@ struct SuperFamicomCartridge {
|
|||
ResetVector = 0x3c,
|
||||
};
|
||||
|
||||
enum Mode : unsigned {
|
||||
enum Mode : uint {
|
||||
ModeNormal,
|
||||
ModeBsxSlotted,
|
||||
ModeBsx,
|
||||
|
@ -30,7 +30,7 @@ struct SuperFamicomCartridge {
|
|||
ModeSuperGameBoy,
|
||||
};
|
||||
|
||||
enum Type : unsigned {
|
||||
enum Type : uint {
|
||||
TypeNormal,
|
||||
TypeBsxSlotted,
|
||||
TypeBsxBios,
|
||||
|
@ -43,12 +43,12 @@ struct SuperFamicomCartridge {
|
|||
TypeUnknown,
|
||||
};
|
||||
|
||||
enum Region : unsigned {
|
||||
enum Region : uint {
|
||||
NTSC,
|
||||
PAL,
|
||||
};
|
||||
|
||||
enum MemoryMapper : unsigned {
|
||||
enum MemoryMapper : uint {
|
||||
LoROM,
|
||||
HiROM,
|
||||
ExLoROM,
|
||||
|
@ -62,17 +62,17 @@ struct SuperFamicomCartridge {
|
|||
STROM,
|
||||
};
|
||||
|
||||
enum DSP1MemoryMapper : unsigned {
|
||||
enum DSP1MemoryMapper : uint {
|
||||
DSP1Unmapped,
|
||||
DSP1LoROM1MB,
|
||||
DSP1LoROM2MB,
|
||||
DSP1HiROM,
|
||||
};
|
||||
|
||||
bool loaded; //is a base cartridge inserted?
|
||||
unsigned crc32; //crc32 of all cartridges (base+slot(s))
|
||||
unsigned rom_size;
|
||||
unsigned ram_size;
|
||||
bool loaded; //is a base cartridge inserted?
|
||||
uint crc32; //crc32 of all cartridges (base+slot(s))
|
||||
uint rom_size;
|
||||
uint ram_size;
|
||||
bool firmware_required; //true if firmware is required for emulation
|
||||
bool firmware_appended; //true if firmware is present at end of data
|
||||
|
||||
|
@ -100,7 +100,7 @@ struct SuperFamicomCartridge {
|
|||
bool has_st018;
|
||||
};
|
||||
|
||||
SuperFamicomCartridge::SuperFamicomCartridge(const uint8_t *data, unsigned size) {
|
||||
SuperFamicomCartridge::SuperFamicomCartridge(const uint8* data, uint size) {
|
||||
firmware_required = false;
|
||||
firmware_appended = false;
|
||||
|
||||
|
@ -116,7 +116,7 @@ SuperFamicomCartridge::SuperFamicomCartridge(const uint8_t *data, unsigned size)
|
|||
if(type == TypeSufamiTurbo) return;
|
||||
|
||||
const char* range = (rom_size > 0x200000) || (ram_size > 32 * 1024) ? "0000-7fff" : "0000-ffff";
|
||||
markup.append("cartridge region=", region == NTSC ? "NTSC" : "PAL", "\n");
|
||||
markup.append("board cic=", region == NTSC ? "411" : "413", "\n");
|
||||
|
||||
//detect appended firmware
|
||||
|
||||
|
@ -197,327 +197,310 @@ SuperFamicomCartridge::SuperFamicomCartridge(const uint8_t *data, unsigned size)
|
|||
if(type == TypeSuperGameBoy1Bios || type == TypeSuperGameBoy2Bios) {
|
||||
markup.append(
|
||||
" rom name=program.rom size=0x", hex(rom_size), "\n"
|
||||
" map id=rom address=00-7f,80-ff:8000-ffff mask=0x8000\n"
|
||||
" map address=00-7d,80-ff:8000-ffff mask=0x8000\n"
|
||||
" map address=40-7d,c0-ff:0000-7fff mask=0x8000\n"
|
||||
" icd2 revision=1\n"
|
||||
" rom name=sgb.boot.rom size=0x100\n"
|
||||
" map id=io address=00-3f,80-bf:6000-7fff\n"
|
||||
" map address=00-3f,80-bf:6000-67ff,7000-7fff\n"
|
||||
" brom name=sgb.boot.rom size=0x100\n"
|
||||
);
|
||||
}
|
||||
|
||||
else if(has_cx4) {
|
||||
markup.append(
|
||||
" hitachidsp model=HG51B169 frequency=20000000\n"
|
||||
" rom id=program name=program.rom size=0x", hex(rom_size), "\n"
|
||||
" rom id=data name=cx4.data.rom size=0xc00\n"
|
||||
" ram id=data size=0xc00\n"
|
||||
" map id=io address=00-3f,80-bf:6000-7fff\n"
|
||||
" map id=rom address=00-7f,80-ff:8000-ffff mask=0x8000\n"
|
||||
" map id=ram address=70-77:0000-7fff\n"
|
||||
" map address=00-3f,80-bf:6c00-6fff,7c00-7fff\n"
|
||||
" rom name=program.rom size=0x", hex(rom_size), "\n"
|
||||
" map address=00-3f,80-bf:8000-ffff mask=0x8000\n"
|
||||
" ram name=save.ram size=0\n"
|
||||
" map address=70-77:0000-7fff mask=0x8000\n"
|
||||
" drom name=cx4.data.rom size=0xc00\n"
|
||||
" dram name=cx4.data.ram size=0xc00 volatile\n"
|
||||
" map address=00-3f,80-bf:6000-6bff,7000-7bff mask=0xf000\n"
|
||||
);
|
||||
}
|
||||
|
||||
else if(has_spc7110) {
|
||||
markup.append(
|
||||
" spc7110\n"
|
||||
" rom id=program name=program.rom size=0x100000\n"
|
||||
" rom id=data name=data.rom size=0x", hex(rom_size - 0x100000), "\n"
|
||||
" map address=00-3f,80-bf:4800-483f\n"
|
||||
" map address=50,58:0000-ffff\n"
|
||||
" map=mcu address=00-3f,80-bf:8000-ffff mask=0x800000\n"
|
||||
" map=mcu address=c0-ff:0000-ffff mask=0xc00000\n"
|
||||
" prom name=program.rom size=0x100000\n"
|
||||
" drom name=data.rom size=0x", hex(rom_size - 0x100000), "\n"
|
||||
" ram name=save.ram size=0x", hex(ram_size), "\n"
|
||||
" map id=io address=00-3f,80-bf:4800-483f\n"
|
||||
" map id=io address=50:0000-ffff\n"
|
||||
" map id=rom address=00-3f,80-bf:8000-ffff\n"
|
||||
" map id=rom address=c0-ff:0000-ffff\n"
|
||||
" map id=ram address=00-3f,80-bf:6000-7fff mask=0xe000\n"
|
||||
" map address=00-3f,80-bf:6000-7fff mask=0xe000\n"
|
||||
);
|
||||
}
|
||||
|
||||
else if(has_sdd1) {
|
||||
markup.append(
|
||||
" sdd1\n"
|
||||
" map address=00-3f,80-bf:4800-4807\n"
|
||||
" rom name=program.rom size=0x", hex(rom_size), "\n"
|
||||
" map address=00-3f,80-bf:8000-ffff mask=0x808000\n"
|
||||
" map address=c0-ff:0000-ffff\n"
|
||||
);
|
||||
if(ram_size > 0) markup.append(
|
||||
" ram name=save.ram size=0x", hex(ram_size), "\n"
|
||||
);
|
||||
markup.append(
|
||||
" map id=io address=00-3f,80-bf:4800-4807\n"
|
||||
" map id=rom address=00-3f,80-bf:8000-ffff mask=0x8000\n"
|
||||
" map id=rom address=c0-ff:0000-ffff\n"
|
||||
);
|
||||
if(ram_size > 0) markup.append(
|
||||
" map id=ram address=20-3f,a0-bf:6000-7fff mask=0xe000\n"
|
||||
" map id=ram address=70-7f:0000-7fff\n"
|
||||
" map address=20-3f,a0-bf:6000-7fff mask=0xe000\n"
|
||||
" map address=70-7d:0000-7fff mask=0x8000\n"
|
||||
);
|
||||
}
|
||||
|
||||
else if(mapper == LoROM) {
|
||||
markup.append(
|
||||
" rom name=program.rom size=0x", hex(rom_size), "\n"
|
||||
" map address=00-7d,80-ff:8000-ffff mask=0x8000\n"
|
||||
" map address=40-6d,c0-ef:0000-7fff mask=0x8000\n"
|
||||
);
|
||||
if(ram_size > 0) markup.append(
|
||||
" ram name=save.ram size=0x", hex(ram_size), "\n"
|
||||
);
|
||||
markup.append(
|
||||
" map id=rom address=00-7f,80-ff:8000-ffff mask=0x8000\n"
|
||||
);
|
||||
if(ram_size > 0) markup.append(
|
||||
" map id=ram address=70-7f,f0-ff:", range, "\n"
|
||||
" map address=70-7d,f0-ff:", range, "\n"
|
||||
);
|
||||
}
|
||||
|
||||
else if(mapper == HiROM) {
|
||||
markup.append(
|
||||
" rom name=program.rom size=0x", hex(rom_size), "\n"
|
||||
" map address=00-3f,80-bf:8000-ffff\n"
|
||||
" map address=40-7f,c0-ff:0000-ffff\n"
|
||||
);
|
||||
if(ram_size > 0) markup.append(
|
||||
" ram name=save.ram size=0x", hex(ram_size), "\n"
|
||||
);
|
||||
markup.append(
|
||||
" map id=rom address=00-3f,80-bf:8000-ffff\n"
|
||||
" map id=rom address=40-7f,c0-ff:0000-ffff\n"
|
||||
);
|
||||
if(ram_size > 0) markup.append(
|
||||
" map id=ram address=10-3f,90-bf:6000-7fff mask=0xe000\n"
|
||||
" map address=10-3f,90-bf:6000-7fff mask=0xe000\n"
|
||||
);
|
||||
}
|
||||
|
||||
else if(mapper == ExLoROM) {
|
||||
markup.append(
|
||||
" rom name=program.rom size=0x", hex(rom_size), "\n"
|
||||
" map address=00-3f,80-bf:8000-ffff mask=0x8000\n"
|
||||
" map address=40-7d:0000-ffff\n"
|
||||
);
|
||||
if(ram_size > 0) markup.append(
|
||||
" ram name=save.ram size=0x", hex(ram_size), "\n"
|
||||
);
|
||||
markup.append(
|
||||
" map id=rom address=00-3f,80-bf:8000-ffff mask=0x8000\n"
|
||||
" map id=rom address=40-7f:0000-ffff\n"
|
||||
);
|
||||
if(ram_size > 0) markup.append(
|
||||
" map id=ram address=20-3f,a0-bf:6000-7fff\n"
|
||||
" map id=ram address=70-7f:0000-7fff\n"
|
||||
" map address=20-3f,a0-bf:6000-7fff mask=0xe000\n"
|
||||
" map address=70-7d:0000-7fff mask=0x8000\n"
|
||||
);
|
||||
}
|
||||
|
||||
else if(mapper == ExHiROM) {
|
||||
markup.append(
|
||||
" rom name=program.rom size=0x", hex(rom_size), "\n"
|
||||
" map address=00-3f:8000-ffff base=0x400000\n"
|
||||
" map address=40-7d:0000-ffff base=0x400000\n"
|
||||
" map address=80-bf:8000-ffff mask=0xc00000\n"
|
||||
" map address=c0-ff:0000-ffff mask=0xc00000\n"
|
||||
);
|
||||
if(ram_size > 0) markup.append(
|
||||
" ram name=save.ram size=0x", hex(ram_size), "\n"
|
||||
);
|
||||
markup.append(
|
||||
" map id=rom address=00-3f:8000-ffff base=0x400000\n"
|
||||
" map id=rom address=40-7f:0000-ffff base=0x400000\n"
|
||||
" map id=rom address=80-bf:8000-ffff mask=0xc00000\n"
|
||||
" map id=rom address=c0-ff:0000-ffff mask=0xc00000\n"
|
||||
);
|
||||
if(ram_size > 0) markup.append(
|
||||
" map id=ram address=20-3f,a0-bf:6000-7fff mask=0xe000\n"
|
||||
" map id=ram address=70-7f:", range, "\n"
|
||||
" map address=20-3f,a0-bf:6000-7fff mask=0xe000\n"
|
||||
" map address=70-7d:", range, "\n"
|
||||
);
|
||||
}
|
||||
|
||||
else if(mapper == SuperFXROM) {
|
||||
markup.append(
|
||||
" superfx revision=3\n"
|
||||
" superfx\n"
|
||||
" map address=00-3f,80-bf:3000-34ff\n"
|
||||
" rom name=program.rom size=0x", hex(rom_size), "\n"
|
||||
" map address=00-3f,80-bf:8000-ffff mask=0x8000\n"
|
||||
" map address=40-5f,c0-df:0000-ffff\n"
|
||||
);
|
||||
if(ram_size > 0) markup.append(
|
||||
" ram name=save.ram size=0x", hex(ram_size), "\n"
|
||||
);
|
||||
markup.append(
|
||||
" map id=io address=00-3f,80-bf:3000-32ff\n"
|
||||
" map id=rom address=00-3f,80-bf:8000-ffff mask=0x8000\n"
|
||||
" map id=rom address=40-5f,c0-df:0000-ffff\n"
|
||||
);
|
||||
if(ram_size > 0) markup.append(
|
||||
" map id=ram address=00-3f,80-bf:6000-7fff size=0x2000\n"
|
||||
" map id=ram address=70-71,f0-f1:0000-ffff\n"
|
||||
" map address=00-3f,80-bf:6000-7fff size=0x2000\n"
|
||||
" map address=70-71,f0-f1:0000-ffff\n"
|
||||
);
|
||||
}
|
||||
|
||||
else if(mapper == SA1ROM) {
|
||||
markup.append(
|
||||
" sa1\n"
|
||||
" map address=00-3f,80-bf:2200-23ff\n"
|
||||
" rom name=program.rom size=0x", hex(rom_size), "\n"
|
||||
" map address=00-3f,80-bf:8000-ffff mask=0x408000\n"
|
||||
" map address=c0-ff:0000-ffff\n"
|
||||
);
|
||||
if(ram_size > 0) markup.append(
|
||||
" ram id=bitmap name=save.ram size=0x", hex(ram_size), "\n"
|
||||
" bwram name=save.ram size=0x", hex(ram_size), "\n"
|
||||
" map address=00-3f,80-bf:6000-7fff size=0x2000\n"
|
||||
" map address=40-4f:0000-ffff\n"
|
||||
);
|
||||
markup.append(
|
||||
" ram id=internal size=0x800\n"
|
||||
" map id=io address=00-3f,80-bf:2200-23ff\n"
|
||||
" map id=rom address=00-3f,80-bf:8000-ffff\n"
|
||||
" map id=rom address=c0-ff:0000-ffff\n"
|
||||
);
|
||||
if(ram_size > 0) markup.append(
|
||||
" map id=bwram address=00-3f,80-bf:6000-7fff\n"
|
||||
" map id=bwram address=40-4f:0000-ffff\n"
|
||||
);
|
||||
markup.append(
|
||||
" map id=iram address=00-3f,80-bf:3000-37ff\n"
|
||||
" iram id=internal size=0x800 volatile\n"
|
||||
" map address=00-3f,80-bf:3000-37ff size=0x800\n"
|
||||
);
|
||||
}
|
||||
|
||||
else if(mapper == BSCLoROM) {
|
||||
markup.append(
|
||||
" rom name=program.rom size=0x", hex(rom_size), "\n"
|
||||
" map address=00-1f:8000-ffff base=0x000000 mask=0x8000\n"
|
||||
" map address=20-3f:8000-ffff base=0x100000 mask=0x8000\n"
|
||||
" map address=80-9f:8000-ffff base=0x200000 mask=0x8000\n"
|
||||
" map address=a0-bf:8000-ffff base=0x100000 mask=0x8000\n"
|
||||
" ram name=save.ram size=0x", hex(ram_size), "\n"
|
||||
" map id=rom address=00-1f:8000-ffff base=0x000000 mask=0x8000\n"
|
||||
" map id=rom address=20-3f:8000-ffff base=0x100000 mask=0x8000\n"
|
||||
" map id=rom address=80-9f:8000-ffff base=0x200000 mask=0x8000\n"
|
||||
" map id=rom address=a0-bf:8000-ffff base=0x100000 mask=0x8000\n"
|
||||
" map id=ram address=70-7f,f0-ff:0000-7fff\n"
|
||||
" map address=70-7d,f0-ff:0000-7fff mask=0x8000\n"
|
||||
" satellaview\n"
|
||||
" map id=rom address=c0-ef:0000-ffff\n"
|
||||
" map address=c0-ef:0000-ffff\n"
|
||||
);
|
||||
}
|
||||
|
||||
else if(mapper == BSCHiROM) {
|
||||
markup.append(
|
||||
" rom name=program.rom size=0x", hex(rom_size), "\n"
|
||||
" map address=00-1f,80-9f:8000-ffff\n"
|
||||
" map address=40-5f,c0-df:0000-ffff\n"
|
||||
" ram name=save.ram size=0x", hex(ram_size), "\n"
|
||||
" map id=rom address=00-1f,80-9f:8000-ffff\n"
|
||||
" map id=rom address=40-5f,c0-df:0000-ffff\n"
|
||||
" map id=ram address=20-3f,a0-bf:6000-7fff\n"
|
||||
" map address=20-3f,a0-bf:6000-7fff\n"
|
||||
" satellaview\n"
|
||||
" map id=rom address=20-3f,a0-bf:8000-ffff\n"
|
||||
" map id=rom address=60-7f,e0-ff:0000-ffff\n"
|
||||
" map address=20-3f,a0-bf:8000-ffff\n"
|
||||
" map address=60-7f,e0-ff:0000-ffff\n"
|
||||
);
|
||||
}
|
||||
|
||||
else if(mapper == BSXROM) {
|
||||
markup.append(
|
||||
" ram name=save.ram size=0x", hex(ram_size), "\n"
|
||||
" map address=10-1f:5000-5fff mask=0xf000\n"
|
||||
" mcc\n"
|
||||
" map address=00-0f:5000\n"
|
||||
" map=mcu address=00-3f,80-bf:8000-ffff\n"
|
||||
" map=mcu address=40-7d,c0-ff:0000-ffff\n"
|
||||
" rom name=program.rom size=0x", hex(rom_size), "\n"
|
||||
" ram id=save name=save.ram size=0x", hex(ram_size), "\n"
|
||||
" ram id=download name=download.ram size=0x80000\n"
|
||||
" map id=io address=00-3f,80-bf:5000-5fff\n"
|
||||
" map id=rom address=00-3f,80-bf:8000-ffff\n"
|
||||
" map id=rom address=40-7f,c0-ff:0000-ffff\n"
|
||||
" map id=ram address=20-3f:6000-7fff\n"
|
||||
" ram name=download.ram size=0x80000\n"
|
||||
" map address=00-3f,80-bf:6000-7fff mask=0xe000\n"
|
||||
);
|
||||
}
|
||||
|
||||
else if(mapper == STROM) {
|
||||
markup.append(
|
||||
" rom name=program.rom size=0x", hex(rom_size), "\n"
|
||||
" map id=rom address=00-1f,80-9f:8000-ffff mask=0x8000\n"
|
||||
" map address=00-1f,80-9f:8000-ffff mask=0x8000\n"
|
||||
" sufamiturbo\n"
|
||||
" map id=rom address=20-3f,a0-bf:8000-ffff mask=0x8000\n"
|
||||
" map id=ram address=60-6f,e0-ef:0000-ffff\n"
|
||||
" rom\n"
|
||||
" map address=20-3f,a0-bf:8000-ffff mask=0x8000\n"
|
||||
" ram\n"
|
||||
" map address=60-6f,e0-ef:0000-ffff\n"
|
||||
" sufamiturbo\n"
|
||||
" map id=rom address=40-5f,c0-df:0000-7fff mask=0x8000\n"
|
||||
" map id=rom address=40-5f,c0-df:8000-ffff mask=0x8000\n"
|
||||
" map id=ram address=70-7f,f0-ff:0000-ffff\n"
|
||||
" rom\n"
|
||||
" map address=40-5f,c0-df:0000-7fff mask=0x8000\n"
|
||||
" map address=40-5f,c0-df:8000-ffff mask=0x8000\n"
|
||||
" ram\n"
|
||||
" map address=70-7d,f0-ff:0000-ffff\n"
|
||||
);
|
||||
}
|
||||
|
||||
if(has_sharprtc) {
|
||||
markup.append(
|
||||
" sharprtc\n"
|
||||
" map address=00-3f,80-bf:2800-2801\n"
|
||||
" ram name=rtc.ram size=0x10\n"
|
||||
" map id=io address=00-3f,80-bf:2800-2801\n"
|
||||
);
|
||||
}
|
||||
|
||||
if(has_epsonrtc) {
|
||||
markup.append(
|
||||
" epsonrtc\n"
|
||||
" map address=00-3f,80-bf:4840-4842\n"
|
||||
" ram name=rtc.ram size=0x10\n"
|
||||
" map id=io address=00-3f,80-bf:4840-4842\n"
|
||||
);
|
||||
}
|
||||
|
||||
if(has_obc1) {
|
||||
markup.append(
|
||||
" obc1\n"
|
||||
" map address=00-3f,80-bf:6000-7fff mask=0xe000\n"
|
||||
" ram name=save.ram size=0x2000\n"
|
||||
" map id=io address=00-3f,80-bf:6000-7fff\n"
|
||||
);
|
||||
}
|
||||
|
||||
if(has_dsp1) {
|
||||
markup.append(
|
||||
" necdsp model=uPD7725 frequency=8000000\n"
|
||||
" rom id=program name=dsp1b.program.rom size=0x1800\n"
|
||||
" rom id=data name=dsp1b.data.rom size=0x800\n"
|
||||
" ram id=data size=0x200\n"
|
||||
);
|
||||
if(dsp1_mapper == DSP1LoROM1MB) markup.append(
|
||||
" map id=io address=20-3f,a0-bf:8000-ffff select=0x4000\n"
|
||||
" map address=20-3f,a0-bf:8000-ffff mask=0x3fff\n"
|
||||
);
|
||||
if(dsp1_mapper == DSP1LoROM2MB) markup.append(
|
||||
" map id=io address=60-6f,e0-ef:0000-7fff select=0x4000\n"
|
||||
" map address=60-6f,e0-ef:0000-7fff mask=0x3fff\n"
|
||||
);
|
||||
if(dsp1_mapper == DSP1HiROM) markup.append(
|
||||
" map id=io address=00-1f,80-9f:6000-7fff select=0x1000\n"
|
||||
" map address=00-1f,80-9f:6000-7fff mask=0xfff\n"
|
||||
);
|
||||
markup.append(
|
||||
" prom name=dsp1b.program.rom size=0x1800\n"
|
||||
" drom name=dsp1b.data.rom size=0x800\n"
|
||||
" dram name=dsp1b.data.ram size=0x200 volatile\n"
|
||||
);
|
||||
}
|
||||
|
||||
if(has_dsp2) {
|
||||
markup.append(
|
||||
" necdsp model=uPD7725 frequency=8000000\n"
|
||||
" rom id=program name=dsp2.program.rom size=0x1800\n"
|
||||
" rom id=data name=dsp2.data.rom size=0x800\n"
|
||||
" ram id=data size=0x200\n"
|
||||
" map id=io address=20-3f,a0-bf:8000-ffff select=0x4000\n"
|
||||
" map address=20-3f,a0-bf:8000-ffff mask=0x3fff\n"
|
||||
" prom name=dsp2.program.rom size=0x1800\n"
|
||||
" drom name=dsp2.data.rom size=0x800\n"
|
||||
" dram name=dsp2.data.ram size=0x200 volatile\n"
|
||||
);
|
||||
}
|
||||
|
||||
if(has_dsp3) {
|
||||
markup.append(
|
||||
" necdsp model=uPD7725 frequency=8000000\n"
|
||||
" rom id=program name=dsp3.program.rom size=0x1800\n"
|
||||
" rom id=data name=dsp3.data.rom size=0x800\n"
|
||||
" ram id=data size=0x200\n"
|
||||
" map id=io address=20-3f,a0-bf:8000-ffff select=0x4000\n"
|
||||
" map address=20-3f,a0-bf:8000-ffff mask=0x3fff\n"
|
||||
" prom name=dsp3.program.rom size=0x1800\n"
|
||||
" drom name=dsp3.data.rom size=0x800\n"
|
||||
" dram name=dsp3.data.ram size=0x200 volatile\n"
|
||||
);
|
||||
}
|
||||
|
||||
if(has_dsp4) {
|
||||
markup.append(
|
||||
" necdsp model=uPD7725 frequency=8000000\n"
|
||||
" rom id=program name=dsp4.program.rom size=0x1800\n"
|
||||
" rom id=data name=dsp4.data.rom size=0x800\n"
|
||||
" ram id=data size=0x200\n"
|
||||
" map id=io address=30-3f,b0-bf:8000-ffff select=0x4000\n"
|
||||
" map address=30-3f,b0-bf:8000-ffff mask=0x3fff\n"
|
||||
" prom name=dsp4.program.rom size=0x1800\n"
|
||||
" drom name=dsp4.data.rom size=0x800\n"
|
||||
" dram name=dsp4.data.ram size=0x200 volatile\n"
|
||||
);
|
||||
}
|
||||
|
||||
if(has_st010) {
|
||||
markup.append(
|
||||
" necdsp model=uPD96050 frequency=11000000\n"
|
||||
" rom id=program name=st010.program.rom size=0xc000\n"
|
||||
" rom id=data name=st010.data.rom size=0x1000\n"
|
||||
" ram id=data name=save.ram size=0x1000\n"
|
||||
" map id=io address=60-67,e0-e7:0000-3fff select=0x0001\n"
|
||||
" map id=ram address=68-6f,e8-ef:0000-7fff\n"
|
||||
" map address=60-67,e0-e7:0000-3fff\n"
|
||||
" prom name=st010.program.rom size=0xc000\n"
|
||||
" drom name=st010.data.rom size=0x1000\n"
|
||||
" dram name=save.ram size=0x1000\n"
|
||||
" map address=68-6f,e8-ef:0000-7fff mask=0x8000\n"
|
||||
);
|
||||
}
|
||||
|
||||
if(has_st011) {
|
||||
markup.append(
|
||||
" necdsp model=uPD96050 frequency=15000000\n"
|
||||
" rom id=program name=st011.program.rom size=0xc000\n"
|
||||
" rom id=data name=st011.data.rom size=0x1000\n"
|
||||
" ram id=data name=save.ram size=0x1000\n"
|
||||
" map id=io address=60-67,e0-e7:0000-3fff select=0x0001\n"
|
||||
" map id=ram address=68-6f,e8-ef:0000-7fff\n"
|
||||
" map address=60-67,e0-e7:0000-3fff\n"
|
||||
" prom name=st011.program.rom size=0xc000\n"
|
||||
" drom name=st011.data.rom size=0x1000\n"
|
||||
" dram name=save.ram size=0x1000\n"
|
||||
" map address=68-6f,e8-ef:0000-7fff mask=0x8000\n"
|
||||
);
|
||||
}
|
||||
|
||||
if(has_st018) {
|
||||
markup.append(
|
||||
" armdsp frequency=21477272\n"
|
||||
" rom id=program name=st018.program.rom size=0x20000\n"
|
||||
" rom id=data name=st018.data.rom size=0x8000\n"
|
||||
" ram name=save.ram size=0x4000\n"
|
||||
" map id=io address=00-3f,80-bf:3800-38ff\n"
|
||||
" map address=00-3f,80-bf:3800-38ff\n"
|
||||
" prom name=st018.program.rom size=0x20000\n"
|
||||
" drom name=st018.data.rom size=0x8000\n"
|
||||
" dram name=save.ram size=0x4000\n"
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
auto SuperFamicomCartridge::readHeader(const uint8_t *data, unsigned size) -> void {
|
||||
auto SuperFamicomCartridge::readHeader(const uint8* data, uint size) -> void {
|
||||
type = TypeUnknown;
|
||||
mapper = LoROM;
|
||||
dsp1_mapper = DSP1Unmapped;
|
||||
|
@ -559,12 +542,12 @@ auto SuperFamicomCartridge::readHeader(const uint8_t *data, unsigned size) -> vo
|
|||
return;
|
||||
}
|
||||
|
||||
const unsigned index = findHeader(data, size);
|
||||
const uint8_t mapperid = data[index + Mapper];
|
||||
const uint8_t rom_type = data[index + RomType];
|
||||
const uint8_t rom_size = data[index + RomSize];
|
||||
const uint8_t company = data[index + Company];
|
||||
const uint8_t regionid = data[index + CartRegion] & 0x7f;
|
||||
const uint index = findHeader(data, size);
|
||||
const uint8 mapperid = data[index + Mapper];
|
||||
const uint8 rom_type = data[index + RomType];
|
||||
const uint8 rom_size = data[index + RomSize];
|
||||
const uint8 company = data[index + Company];
|
||||
const uint8 regionid = data[index + CartRegion] & 0x7f;
|
||||
|
||||
ram_size = 1024 << (data[index + RamSize] & 7);
|
||||
if(ram_size == 1024) ram_size = 0; //no RAM present
|
||||
|
@ -579,7 +562,7 @@ auto SuperFamicomCartridge::readHeader(const uint8_t *data, unsigned size) -> vo
|
|||
|
||||
if(data[index + 0x13] == 0x00 || data[index + 0x13] == 0xff) {
|
||||
if(data[index + 0x14] == 0x00) {
|
||||
const uint8_t n15 = data[index + 0x15];
|
||||
const uint8 n15 = data[index + 0x15];
|
||||
if(n15 == 0x00 || n15 == 0x80 || n15 == 0x84 || n15 == 0x9c || n15 == 0xbc || n15 == 0xfc) {
|
||||
if(data[index + 0x1a] == 0x33 || data[index + 0x1a] == 0xff) {
|
||||
type = TypeBsx;
|
||||
|
@ -627,7 +610,7 @@ auto SuperFamicomCartridge::readHeader(const uint8_t *data, unsigned size) -> vo
|
|||
//detect presence of BS-X flash cartridge connector (reads extended header information)
|
||||
if(data[index - 14] == 'Z') {
|
||||
if(data[index - 11] == 'J') {
|
||||
uint8_t n13 = data[index - 13];
|
||||
uint8 n13 = data[index - 13];
|
||||
if((n13 >= 'A' && n13 <= 'Z') || (n13 >= '0' && n13 <= '9')) {
|
||||
if(company == 0x33 || (data[index - 10] == 0x00 && data[index - 4] == 0x00)) {
|
||||
has_bsx_slot = true;
|
||||
|
@ -746,10 +729,10 @@ auto SuperFamicomCartridge::readHeader(const uint8_t *data, unsigned size) -> vo
|
|||
}
|
||||
}
|
||||
|
||||
auto SuperFamicomCartridge::findHeader(const uint8_t *data, unsigned size) -> unsigned {
|
||||
unsigned score_lo = scoreHeader(data, size, 0x007fc0);
|
||||
unsigned score_hi = scoreHeader(data, size, 0x00ffc0);
|
||||
unsigned score_ex = scoreHeader(data, size, 0x40ffc0);
|
||||
auto SuperFamicomCartridge::findHeader(const uint8* data, uint size) -> uint {
|
||||
uint score_lo = scoreHeader(data, size, 0x007fc0);
|
||||
uint score_hi = scoreHeader(data, size, 0x00ffc0);
|
||||
uint score_ex = scoreHeader(data, size, 0x40ffc0);
|
||||
if(score_ex) score_ex += 4; //favor ExHiROM on images > 32mbits
|
||||
|
||||
if(score_lo >= score_hi && score_lo >= score_ex) {
|
||||
|
@ -761,16 +744,16 @@ auto SuperFamicomCartridge::findHeader(const uint8_t *data, unsigned size) -> un
|
|||
}
|
||||
}
|
||||
|
||||
auto SuperFamicomCartridge::scoreHeader(const uint8_t *data, unsigned size, unsigned addr) -> unsigned {
|
||||
auto SuperFamicomCartridge::scoreHeader(const uint8* data, uint size, uint addr) -> uint {
|
||||
if(size < addr + 64) return 0; //image too small to contain header at this location?
|
||||
int score = 0;
|
||||
|
||||
uint16_t resetvector = data[addr + ResetVector] | (data[addr + ResetVector + 1] << 8);
|
||||
uint16_t checksum = data[addr + Checksum ] | (data[addr + Checksum + 1] << 8);
|
||||
uint16_t complement = data[addr + Complement ] | (data[addr + Complement + 1] << 8);
|
||||
uint16 resetvector = data[addr + ResetVector] | (data[addr + ResetVector + 1] << 8);
|
||||
uint16 checksum = data[addr + Checksum ] | (data[addr + Checksum + 1] << 8);
|
||||
uint16 complement = data[addr + Complement ] | (data[addr + Complement + 1] << 8);
|
||||
|
||||
uint8_t resetop = data[(addr & ~0x7fff) | (resetvector & 0x7fff)]; //first opcode executed upon reset
|
||||
uint8_t mapper = data[addr + Mapper] & ~0x10; //mask off irrelevent FastROM-capable bit
|
||||
uint8 resetop = data[(addr & ~0x7fff) | (resetvector & 0x7fff)]; //first opcode executed upon reset
|
||||
uint8 mapper = data[addr + Mapper] & ~0x10; //mask off irrelevent FastROM-capable bit
|
||||
|
||||
//$00:[000-7fff] contains uninitialized RAM and MMIO.
|
||||
//reset vector must point to ROM at $00:[8000-ffff] to be considered valid.
|
||||
|
|
|
@ -152,7 +152,7 @@ struct InputJoypadDirectInput {
|
|||
property.dwData = false;
|
||||
device->SetProperty(DIPROP_AUTOCENTER, &property.diph);
|
||||
|
||||
DWORD dwAxes[2] = {DIJOFS_X, DIJOFS_Y};
|
||||
DWORD dwAxes[2] = {(DWORD)DIJOFS_X, (DWORD)DIJOFS_Y};
|
||||
LONG lDirection[2] = {0, 0};
|
||||
DICONSTANTFORCE force;
|
||||
force.lMagnitude = DI_FFNOMINALMAX; //full force
|
||||
|
|
|
@ -6,24 +6,52 @@ namespace SuperFamicom {
|
|||
#include "serialization.cpp"
|
||||
Cartridge cartridge;
|
||||
|
||||
auto Cartridge::manifest() -> string {
|
||||
string manifest = information.markup.cartridge;
|
||||
|
||||
if(information.markup.gameBoy) {
|
||||
manifest.append("\n[Super Game Boy]\n");
|
||||
manifest.append(information.markup.gameBoy);
|
||||
}
|
||||
|
||||
if(information.markup.satellaview) {
|
||||
manifest.append("\n[BS-X Satellaview]\n");
|
||||
manifest.append(information.markup.satellaview);
|
||||
}
|
||||
|
||||
if(information.markup.sufamiTurboA) {
|
||||
manifest.append("\n[Sufami Turbo - Slot A]\n");
|
||||
manifest.append(information.markup.sufamiTurboA);
|
||||
}
|
||||
|
||||
if(information.markup.sufamiTurboB) {
|
||||
manifest.append("\n[Sufami Turbo - Slot B]\n");
|
||||
manifest.append(information.markup.sufamiTurboB);
|
||||
}
|
||||
|
||||
return manifest;
|
||||
}
|
||||
|
||||
auto Cartridge::title() -> string {
|
||||
if(information.title.gameBoy.empty() == false) {
|
||||
return {information.title.cartridge, " + ", information.title.gameBoy};
|
||||
string title = information.title.cartridge;
|
||||
|
||||
if(information.title.gameBoy) {
|
||||
title.append(" + ", information.title.gameBoy);
|
||||
}
|
||||
|
||||
if(information.title.satellaview.empty() == false) {
|
||||
return {information.title.cartridge, " + ", information.title.satellaview};
|
||||
if(information.title.satellaview) {
|
||||
title.append(" + ", information.title.satellaview);
|
||||
}
|
||||
|
||||
if(information.title.sufamiTurboA.empty() == false) {
|
||||
if(information.title.sufamiTurboB.empty() == true) {
|
||||
return {information.title.cartridge, " + ", information.title.sufamiTurboA};
|
||||
} else {
|
||||
return {information.title.cartridge, " + ", information.title.sufamiTurboA, " + ", information.title.sufamiTurboB};
|
||||
}
|
||||
if(information.title.sufamiTurboA) {
|
||||
title.append(" + ", information.title.sufamiTurboA);
|
||||
}
|
||||
|
||||
return information.title.cartridge;
|
||||
if(information.title.sufamiTurboB) {
|
||||
title.append(" + ", information.title.sufamiTurboB);
|
||||
}
|
||||
|
||||
return title;
|
||||
}
|
||||
|
||||
auto Cartridge::load() -> void {
|
||||
|
@ -118,8 +146,8 @@ auto Cartridge::loadSuperGameBoy() -> void {
|
|||
auto document = BML::unserialize(information.markup.gameBoy);
|
||||
information.title.gameBoy = document["information/title"].text();
|
||||
|
||||
auto rom = document["cartridge/rom"];
|
||||
auto ram = document["cartridge/ram"];
|
||||
auto rom = document["board/rom"];
|
||||
auto ram = document["board/ram"];
|
||||
|
||||
GameBoy::cartridge.information.markup = information.markup.gameBoy;
|
||||
GameBoy::cartridge.load(GameBoy::System::Revision::SuperGameBoy);
|
||||
|
@ -134,7 +162,7 @@ auto Cartridge::loadSatellaview() -> void {
|
|||
auto document = BML::unserialize(information.markup.satellaview);
|
||||
information.title.satellaview = document["information/title"].text();
|
||||
|
||||
auto rom = document["cartridge/rom"];
|
||||
auto rom = document["board/rom"];
|
||||
|
||||
if(rom["name"]) {
|
||||
unsigned size = rom["size"].natural();
|
||||
|
@ -150,8 +178,8 @@ auto Cartridge::loadSufamiTurboA() -> void {
|
|||
auto document = BML::unserialize(information.markup.sufamiTurboA);
|
||||
information.title.sufamiTurboA = document["information/title"].text();
|
||||
|
||||
auto rom = document["cartridge/rom"];
|
||||
auto ram = document["cartridge/ram"];
|
||||
auto rom = document["board/rom"];
|
||||
auto ram = document["board/ram"];
|
||||
|
||||
if(rom["name"]) {
|
||||
unsigned size = rom["size"].natural();
|
||||
|
@ -166,7 +194,7 @@ auto Cartridge::loadSufamiTurboA() -> void {
|
|||
memory.append({ID::SufamiTurboSlotARAM, ram["name"].text()});
|
||||
}
|
||||
|
||||
if(document["cartridge/linkable"]) {
|
||||
if(document["board/linkable"]) {
|
||||
interface->loadRequest(ID::SufamiTurboSlotB, "Sufami Turbo - Slot B", "st", false);
|
||||
}
|
||||
}
|
||||
|
@ -176,8 +204,8 @@ auto Cartridge::loadSufamiTurboB() -> void {
|
|||
auto document = BML::unserialize(information.markup.sufamiTurboB);
|
||||
information.title.sufamiTurboB = document["information/title"].text();
|
||||
|
||||
auto rom = document["cartridge/rom"];
|
||||
auto ram = document["cartridge/ram"];
|
||||
auto rom = document["board/rom"];
|
||||
auto ram = document["board/ram"];
|
||||
|
||||
if(rom["name"]) {
|
||||
unsigned size = rom["size"].natural();
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
struct Cartridge : property<Cartridge> {
|
||||
enum class Region : unsigned { NTSC, PAL };
|
||||
|
||||
MappedRAM rom;
|
||||
MappedRAM ram;
|
||||
Cartridge() = default;
|
||||
~Cartridge() { unload(); }
|
||||
|
||||
auto loaded() const -> bool { return _loaded; }
|
||||
auto sha256() const -> string { return _sha256; }
|
||||
|
@ -28,6 +28,17 @@ struct Cartridge : property<Cartridge> {
|
|||
readonly<bool> hasSatellaviewSlot;
|
||||
readonly<bool> hasSufamiTurboSlots;
|
||||
|
||||
auto manifest() -> string;
|
||||
auto title() -> string;
|
||||
|
||||
auto load() -> void;
|
||||
auto unload() -> void;
|
||||
|
||||
auto serialize(serializer&) -> void;
|
||||
|
||||
MappedRAM rom;
|
||||
MappedRAM ram;
|
||||
|
||||
struct Mapping {
|
||||
function<auto (uint, uint8) -> uint8> reader;
|
||||
function<auto (uint, uint8) -> void> writer;
|
||||
|
@ -66,16 +77,6 @@ struct Cartridge : property<Cartridge> {
|
|||
} title;
|
||||
} information;
|
||||
|
||||
Cartridge() = default;
|
||||
~Cartridge() { unload(); }
|
||||
|
||||
auto title() -> string;
|
||||
|
||||
auto load() -> void;
|
||||
auto unload() -> void;
|
||||
|
||||
auto serialize(serializer&) -> void;
|
||||
|
||||
private:
|
||||
auto loadSuperGameBoy() -> void;
|
||||
auto loadSatellaview() -> void;
|
||||
|
@ -85,10 +86,12 @@ private:
|
|||
|
||||
//markup.cpp
|
||||
auto parseMarkup(const string&) -> void;
|
||||
auto parseMarkupMap(Mapping&, Markup::Node) -> void;
|
||||
auto parseMarkupMap(Markup::Node, SuperFamicom::Memory&) -> void;
|
||||
auto parseMarkupMap(Markup::Node, const function<uint8 (uint, uint8)>&, const function<void (uint, uint8)>&) -> void;
|
||||
auto parseMarkupMemory(MappedRAM&, Markup::Node, unsigned id, bool writable) -> void;
|
||||
|
||||
auto parseMarkupCartridge(Markup::Node) -> void;
|
||||
auto parseMarkupROM(Markup::Node) -> void;
|
||||
auto parseMarkupRAM(Markup::Node) -> void;
|
||||
auto parseMarkupICD2(Markup::Node) -> void;
|
||||
auto parseMarkupMCC(Markup::Node) -> void;
|
||||
auto parseMarkupSatellaview(Markup::Node) -> void;
|
||||
|
|
|
@ -10,68 +10,80 @@ Cartridge::Mapping::Mapping(const function<uint8 (uint, uint8)>& reader, const f
|
|||
|
||||
auto Cartridge::parseMarkup(const string& markup) -> void {
|
||||
auto document = BML::unserialize(markup);
|
||||
information.title.cartridge = document["information/title"].text();
|
||||
auto information = document["information"];
|
||||
auto board = document["board"];
|
||||
|
||||
auto cartridge = document["cartridge"];
|
||||
_region = cartridge["region"].text() != "PAL" ? Region::NTSC : Region::PAL;
|
||||
this->information.title.cartridge = information["title"].text();
|
||||
_region = board["cic"].text() == "413" ? Region::PAL : Region::NTSC;
|
||||
|
||||
mapping.reset();
|
||||
if(auto node = cartridge) parseMarkupCartridge(node);
|
||||
if(auto node = cartridge["icd2"]) parseMarkupICD2(node);
|
||||
if(auto node = cartridge["mcc"]) parseMarkupMCC(node);
|
||||
if(auto node = cartridge["satellaview"]) parseMarkupSatellaview(node);
|
||||
if(auto node = cartridge.find("sufamiturbo")) if(node(0)) parseMarkupSufamiTurbo(node(0), 0);
|
||||
if(auto node = cartridge.find("sufamiturbo")) if(node(1)) parseMarkupSufamiTurbo(node(1), 1);
|
||||
if(auto node = cartridge["nss"]) parseMarkupNSS(node);
|
||||
if(auto node = cartridge["event"]) parseMarkupEvent(node);
|
||||
if(auto node = cartridge["sa1"]) parseMarkupSA1(node);
|
||||
if(auto node = cartridge["superfx"]) parseMarkupSuperFX(node);
|
||||
if(auto node = cartridge["armdsp"]) parseMarkupARMDSP(node);
|
||||
if(auto node = cartridge["hitachidsp"]) parseMarkupHitachiDSP(node, cartridge["board/type"].text().match("2DC*") ? 2 : 1);
|
||||
if(auto node = cartridge["necdsp"]) parseMarkupNECDSP(node);
|
||||
if(auto node = cartridge["epsonrtc"]) parseMarkupEpsonRTC(node);
|
||||
if(auto node = cartridge["sharprtc"]) parseMarkupSharpRTC(node);
|
||||
if(auto node = cartridge["spc7110"]) parseMarkupSPC7110(node);
|
||||
if(auto node = cartridge["sdd1"]) parseMarkupSDD1(node);
|
||||
if(auto node = cartridge["obc1"]) parseMarkupOBC1(node);
|
||||
if(auto node = cartridge["msu1"]) parseMarkupMSU1(node);
|
||||
if(auto node = board["rom"]) parseMarkupROM(node);
|
||||
if(auto node = board["ram"]) parseMarkupRAM(node);
|
||||
if(auto node = board["icd2"]) parseMarkupICD2(node);
|
||||
if(auto node = board["mcc"]) parseMarkupMCC(node);
|
||||
if(auto node = board["satellaview"]) parseMarkupSatellaview(node);
|
||||
if(auto node = board.find("sufamiturbo")) if(node(0)) parseMarkupSufamiTurbo(node(0), 0);
|
||||
if(auto node = board.find("sufamiturbo")) if(node(1)) parseMarkupSufamiTurbo(node(1), 1);
|
||||
if(auto node = board["nss"]) parseMarkupNSS(node);
|
||||
if(auto node = board["event"]) parseMarkupEvent(node);
|
||||
if(auto node = board["sa1"]) parseMarkupSA1(node);
|
||||
if(auto node = board["superfx"]) parseMarkupSuperFX(node);
|
||||
if(auto node = board["armdsp"]) parseMarkupARMDSP(node);
|
||||
if(auto node = board["hitachidsp"]) parseMarkupHitachiDSP(node, document["information/board"].text().match("2DC*") ? 2 : 1);
|
||||
if(auto node = board["necdsp"]) parseMarkupNECDSP(node);
|
||||
if(auto node = board["epsonrtc"]) parseMarkupEpsonRTC(node);
|
||||
if(auto node = board["sharprtc"]) parseMarkupSharpRTC(node);
|
||||
if(auto node = board["spc7110"]) parseMarkupSPC7110(node);
|
||||
if(auto node = board["sdd1"]) parseMarkupSDD1(node);
|
||||
if(auto node = board["obc1"]) parseMarkupOBC1(node);
|
||||
if(auto node = board["msu1"]) parseMarkupMSU1(node);
|
||||
}
|
||||
|
||||
auto Cartridge::parseMarkupMap(Mapping& m, Markup::Node map) -> void {
|
||||
auto Cartridge::parseMarkupMap(Markup::Node map, SuperFamicom::Memory& memory) -> void {
|
||||
Mapping m{memory};
|
||||
m.addr = map["address"].text();
|
||||
m.size = map["size"].natural();
|
||||
m.base = map["base"].natural();
|
||||
m.mask = map["mask"].natural();
|
||||
if(m.size == 0) m.size = memory.size();
|
||||
if(m.size != 0) mapping.append(m);
|
||||
}
|
||||
|
||||
auto Cartridge::parseMarkupMemory(MappedRAM& ram, Markup::Node node, unsigned id, bool writable) -> void {
|
||||
auto Cartridge::parseMarkupMap(
|
||||
Markup::Node map,
|
||||
const function<uint8 (uint, uint8)>& reader,
|
||||
const function<void (uint, uint8)>& writer
|
||||
) -> void {
|
||||
Mapping m{reader, writer};
|
||||
m.addr = map["address"].text();
|
||||
m.size = map["size"].natural();
|
||||
m.base = map["base"].natural();
|
||||
m.mask = map["mask"].natural();
|
||||
mapping.append(m);
|
||||
}
|
||||
|
||||
auto Cartridge::parseMarkupMemory(MappedRAM& ram, Markup::Node node, uint id, bool writable) -> void {
|
||||
string name = node["name"].text();
|
||||
unsigned size = node["size"].natural();
|
||||
uint size = node["size"].natural();
|
||||
bool save = !(bool)node["volatile"];
|
||||
ram.map(allocate<uint8>(size, 0xff), size);
|
||||
if(name) {
|
||||
interface->loadRequest(id, name, !writable); //treat ROM as required; RAM as optional
|
||||
if(writable) memory.append({id, name});
|
||||
if(writable && save) memory.append({id, name});
|
||||
}
|
||||
}
|
||||
|
||||
auto Cartridge::parseMarkupCartridge(Markup::Node root) -> void {
|
||||
parseMarkupMemory(rom, root["rom"], ID::ROM, false);
|
||||
parseMarkupMemory(ram, root["ram"], ID::RAM, true);
|
||||
|
||||
auto Cartridge::parseMarkupROM(Markup::Node root) -> void {
|
||||
parseMarkupMemory(rom, root, ID::ROM, false);
|
||||
for(auto node : root.find("map")) {
|
||||
if(node["id"].text() == "rom") {
|
||||
Mapping m(rom);
|
||||
parseMarkupMap(m, node);
|
||||
if(m.size == 0) m.size = rom.size();
|
||||
mapping.append(m);
|
||||
}
|
||||
parseMarkupMap(node, rom);
|
||||
}
|
||||
}
|
||||
|
||||
if(node["id"].text() == "ram") {
|
||||
Mapping m(ram);
|
||||
parseMarkupMap(m, node);
|
||||
if(m.size == 0) m.size = ram.size();
|
||||
mapping.append(m);
|
||||
}
|
||||
auto Cartridge::parseMarkupRAM(Markup::Node root) -> void {
|
||||
parseMarkupMemory(ram, root, ID::RAM, true);
|
||||
for(auto node : root.find("map")) {
|
||||
parseMarkupMap(node, ram);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -83,15 +95,10 @@ auto Cartridge::parseMarkupICD2(Markup::Node root) -> void {
|
|||
GameBoy::cartridge.load_empty(GameBoy::System::Revision::SuperGameBoy);
|
||||
interface->loadRequest(ID::SuperGameBoy, "Game Boy", "gb", false);
|
||||
|
||||
string bootROMName = root["rom/name"].text();
|
||||
interface->loadRequest(ID::SuperGameBoyBootROM, bootROMName, true);
|
||||
interface->loadRequest(ID::SuperGameBoyBootROM, root["brom"]["name"].text(), true);
|
||||
|
||||
for(auto node : root.find("map")) {
|
||||
if(node["id"].text() == "io") {
|
||||
Mapping m({&ICD2::read, &icd2}, {&ICD2::write, &icd2});
|
||||
parseMarkupMap(m, node);
|
||||
mapping.append(m);
|
||||
}
|
||||
parseMarkupMap(node, {&ICD2::read, &icd2}, {&ICD2::write, &icd2});
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -101,26 +108,19 @@ auto Cartridge::parseMarkupMCC(Markup::Node root) -> void {
|
|||
|
||||
interface->loadRequest(ID::Satellaview, "BS-X Satellaview", "bs", false);
|
||||
|
||||
auto rom = root.find("rom");
|
||||
auto ram = root.find("ram");
|
||||
|
||||
parseMarkupMemory(mcc.rom, rom(0), ID::MCCROM, false);
|
||||
parseMarkupMemory(mcc.ram, ram(0), ID::MCCRAM, true);
|
||||
parseMarkupMemory(mcc.psram, ram(1), ID::MCCPSRAM, true);
|
||||
parseMarkupMemory(mcc.rom, root["rom"], ID::MCCROM, false);
|
||||
parseMarkupMemory(mcc.ram, root["ram"], ID::MCCRAM, true);
|
||||
|
||||
for(auto node : root.find("map")) {
|
||||
if(node["id"].text() == "rom"
|
||||
|| node["id"].text() == "ram") {
|
||||
Mapping m({&MCC::mcu_read, &mcc}, {&MCC::mcu_write, &mcc});
|
||||
parseMarkupMap(m, node);
|
||||
mapping.append(m);
|
||||
if(node.text() == "mcu") {
|
||||
parseMarkupMap(node, {&MCC::mcu_read, &mcc}, {&MCC::mcu_write, &mcc});
|
||||
} else {
|
||||
parseMarkupMap(node, {&MCC::read, &mcc}, {&MCC::write, &mcc});
|
||||
}
|
||||
}
|
||||
|
||||
if(node["id"].text() == "io") {
|
||||
Mapping m({&MCC::mmio_read, &mcc}, {&MCC::mmio_write, &mcc});
|
||||
parseMarkupMap(m, node);
|
||||
mapping.append(m);
|
||||
}
|
||||
for(auto node : root["ram"].find("map")) {
|
||||
parseMarkupMap(node, mcc.ram);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -129,14 +129,9 @@ auto Cartridge::parseMarkupSatellaview(Markup::Node root) -> void {
|
|||
|
||||
interface->loadRequest(ID::Satellaview, "BS-X Satellaview", "bs", false);
|
||||
|
||||
for(auto node : root.find("map")) {
|
||||
if(node["id"].text() == "rom") {
|
||||
if(satellaviewcartridge.memory.size() == 0) continue;
|
||||
|
||||
Mapping m(satellaviewcartridge);
|
||||
parseMarkupMap(m, node);
|
||||
mapping.append(m);
|
||||
}
|
||||
for(auto node : root["rom"].find("map")) {
|
||||
if(satellaviewcartridge.memory.size() == 0) continue;
|
||||
parseMarkupMap(node, satellaviewcartridge);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -148,26 +143,16 @@ auto Cartridge::parseMarkupSufamiTurbo(Markup::Node root, bool slot) -> void {
|
|||
interface->loadRequest(ID::SufamiTurboSlotA, "Sufami Turbo - Slot A", "st", false);
|
||||
}
|
||||
|
||||
for(auto node : root.find("map")) {
|
||||
for(auto node : root["rom"].find("map")) {
|
||||
SufamiTurboCartridge& cart = (slot == 0 ? sufamiturboA : sufamiturboB);
|
||||
if(cart.rom.size() == 0) continue;
|
||||
parseMarkupMap(node, cart.rom);
|
||||
}
|
||||
|
||||
if(node["id"].text() == "rom") {
|
||||
if(cart.rom.size() == 0) continue;
|
||||
|
||||
Mapping m(cart.rom);
|
||||
parseMarkupMap(m, node);
|
||||
if(m.size == 0) m.size = cart.rom.size();
|
||||
if(m.size) mapping.append(m);
|
||||
}
|
||||
|
||||
if(node["id"].text() == "ram") {
|
||||
if(cart.ram.size() == 0) continue;
|
||||
|
||||
Mapping m(cart.ram);
|
||||
parseMarkupMap(m, node);
|
||||
if(m.size == 0) m.size = cart.ram.size();
|
||||
if(m.size) mapping.append(m);
|
||||
}
|
||||
for(auto node : root["ram"].find("map")) {
|
||||
SufamiTurboCartridge& cart = (slot == 0 ? sufamiturboA : sufamiturboB);
|
||||
if(cart.ram.size() == 0) continue;
|
||||
parseMarkupMap(node, cart.ram);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -176,21 +161,18 @@ auto Cartridge::parseMarkupNSS(Markup::Node root) -> void {
|
|||
nss.dip = interface->dipSettings(root);
|
||||
|
||||
for(auto node : root.find("map")) {
|
||||
if(node["id"].text() == "io") {
|
||||
Mapping m({&NSS::read, &nss}, {&NSS::write, &nss});
|
||||
parseMarkupMap(m, node);
|
||||
mapping.append(m);
|
||||
}
|
||||
parseMarkupMap(node, {&NSS::read, &nss}, {&NSS::write, &nss});
|
||||
}
|
||||
}
|
||||
|
||||
auto Cartridge::parseMarkupEvent(Markup::Node root) -> void {
|
||||
auto roms = root.find("rom");
|
||||
if(roms.size() != 4) return;
|
||||
|
||||
hasEvent = true;
|
||||
|
||||
for(auto node : root.find("rom")) {
|
||||
unsigned id = node["id"].natural();
|
||||
if(id > 3) continue;
|
||||
parseMarkupMemory(event.rom[id], node, ID::EventROM0 + id, false);
|
||||
for(uint n : range(4)) {
|
||||
parseMarkupMemory(event.rom[n], roms[n], ID::EventROM0 + n, false);
|
||||
}
|
||||
parseMarkupMemory(event.ram, root["ram"], ID::EventRAM, true);
|
||||
|
||||
|
@ -200,10 +182,15 @@ auto Cartridge::parseMarkupEvent(Markup::Node root) -> void {
|
|||
|
||||
event.revision = root["revision"].text() == "B" ? 2 : 1;
|
||||
lstring part = root["timer"].text().split(":", 1L);
|
||||
if(part.size() == 1) event.timer = part(0).natural();
|
||||
if(part.size() == 2) event.timer = part(0).natural() * 60 + part(1).natural();
|
||||
if(part.size() == 1) event.timer = part[0].natural();
|
||||
if(part.size() == 2) event.timer = part[0].natural() * 60 + part[1].natural();
|
||||
|
||||
for(auto node : root.find("map")) {
|
||||
parseMarkupMap(node, {&Event::read, &event}, {&Event::write, &event});
|
||||
}
|
||||
|
||||
/*
|
||||
//todo: define and support markup for coprocessor/event
|
||||
if(node["id"].text() == "rom") {
|
||||
Mapping m({&Event::rom_read, &event}, [](unsigned, uint8) {});
|
||||
parseMarkupMap(m, node);
|
||||
|
@ -227,159 +214,101 @@ auto Cartridge::parseMarkupEvent(Markup::Node root) -> void {
|
|||
parseMarkupMap(m, node);
|
||||
mapping.append(m);
|
||||
}
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
auto Cartridge::parseMarkupSA1(Markup::Node root) -> void {
|
||||
hasSA1 = true;
|
||||
|
||||
auto rom = root.find("rom");
|
||||
auto ram = root.find("ram");
|
||||
|
||||
parseMarkupMemory(sa1.rom, rom(0), ID::SA1ROM, false);
|
||||
parseMarkupMemory(sa1.bwram, ram(0), ID::SA1BWRAM, true);
|
||||
parseMarkupMemory(sa1.iram, ram(1), ID::SA1IRAM, true);
|
||||
parseMarkupMemory(sa1.rom, root["rom"], ID::SA1ROM, false);
|
||||
parseMarkupMemory(sa1.bwram, root["bwram"], ID::SA1BWRAM, true);
|
||||
parseMarkupMemory(sa1.iram, root["iram"], ID::SA1IRAM, true);
|
||||
|
||||
for(auto node : root.find("map")) {
|
||||
if(node["id"].text() == "io") {
|
||||
Mapping m({&SA1::mmio_read, &sa1}, {&SA1::mmio_write, &sa1});
|
||||
parseMarkupMap(m, node);
|
||||
mapping.append(m);
|
||||
}
|
||||
parseMarkupMap(node, {&SA1::mmio_read, &sa1}, {&SA1::mmio_write, &sa1});
|
||||
}
|
||||
|
||||
if(node["id"].text() == "rom") {
|
||||
Mapping m({&SA1::mmcrom_read, &sa1}, {&SA1::mmcrom_write, &sa1});
|
||||
parseMarkupMap(m, node);
|
||||
mapping.append(m);
|
||||
}
|
||||
for(auto node : root["rom"].find("map")) {
|
||||
parseMarkupMap(node, {&SA1::mmcrom_read, &sa1}, {&SA1::mmcrom_write, &sa1});
|
||||
}
|
||||
|
||||
if(node["id"].text() == "bwram") {
|
||||
Mapping m({&SA1::mmcbwram_read, &sa1}, {&SA1::mmcbwram_write, &sa1});
|
||||
parseMarkupMap(m, node);
|
||||
mapping.append(m);
|
||||
}
|
||||
for(auto node : root["bwram"].find("map")) {
|
||||
parseMarkupMap(node, {&SA1::mmcbwram_read, &sa1}, {&SA1::mmcbwram_write, &sa1});
|
||||
}
|
||||
|
||||
if(node["id"].text() == "iram") {
|
||||
Mapping m(sa1.cpuiram);
|
||||
parseMarkupMap(m, node);
|
||||
if(m.size == 0) m.size = sa1.cpuiram.size();
|
||||
mapping.append(m);
|
||||
}
|
||||
for(auto node : root["iram"].find("map")) {
|
||||
parseMarkupMap(node, sa1.cpuiram);
|
||||
}
|
||||
}
|
||||
|
||||
auto Cartridge::parseMarkupSuperFX(Markup::Node root) -> void {
|
||||
hasSuperFX = true;
|
||||
|
||||
auto rom = root.find("rom");
|
||||
auto ram = root.find("ram");
|
||||
|
||||
parseMarkupMemory(superfx.rom, rom(0), ID::SuperFXROM, false);
|
||||
parseMarkupMemory(superfx.ram, ram(0), ID::SuperFXRAM, true);
|
||||
parseMarkupMemory(superfx.rom, root["rom"], ID::SuperFXROM, false);
|
||||
parseMarkupMemory(superfx.ram, root["ram"], ID::SuperFXRAM, true);
|
||||
|
||||
for(auto node : root.find("map")) {
|
||||
if(node["id"].text() == "io") {
|
||||
Mapping m({&SuperFX::mmio_read, &superfx}, {&SuperFX::mmio_write, &superfx});
|
||||
parseMarkupMap(m, node);
|
||||
mapping.append(m);
|
||||
}
|
||||
parseMarkupMap(node, {&SuperFX::mmio_read, &superfx}, {&SuperFX::mmio_write, &superfx});
|
||||
}
|
||||
|
||||
if(node["id"].text() == "rom") {
|
||||
Mapping m(superfx.cpurom);
|
||||
parseMarkupMap(m, node);
|
||||
if(m.size == 0) m.size = superfx.rom.size();
|
||||
mapping.append(m);
|
||||
}
|
||||
for(auto node : root["rom"].find("map")) {
|
||||
parseMarkupMap(node, superfx.cpurom);
|
||||
}
|
||||
|
||||
if(node["id"].text() == "ram") {
|
||||
Mapping m(superfx.cpuram);
|
||||
parseMarkupMap(m, node);
|
||||
if(m.size == 0) m.size = superfx.ram.size();
|
||||
mapping.append(m);
|
||||
}
|
||||
for(auto node : root["ram"].find("map")) {
|
||||
parseMarkupMap(node, superfx.cpuram);
|
||||
}
|
||||
}
|
||||
|
||||
auto Cartridge::parseMarkupARMDSP(Markup::Node root) -> void {
|
||||
hasARMDSP = true;
|
||||
|
||||
auto rom = root.find("rom");
|
||||
auto ram = root.find("ram");
|
||||
|
||||
string programROMName = rom(0)["name"].text();
|
||||
string dataROMName = rom(1)["name"].text();
|
||||
string dataRAMName = ram(0)["name"].text();
|
||||
|
||||
interface->loadRequest(ID::ArmDSPPROM, programROMName, true);
|
||||
interface->loadRequest(ID::ArmDSPDROM, dataROMName, true);
|
||||
if(dataRAMName.empty() == false) {
|
||||
interface->loadRequest(ID::ArmDSPRAM, dataRAMName, false);
|
||||
memory.append({ID::ArmDSPRAM, dataRAMName});
|
||||
}
|
||||
interface->loadRequest(ID::ArmDSPPROM, root["prom"]["name"].text(), true);
|
||||
interface->loadRequest(ID::ArmDSPDROM, root["drom"]["name"].text(), true);
|
||||
interface->loadRequest(ID::ArmDSPRAM, root["dram"]["name"].text(), false);
|
||||
memory.append({ID::ArmDSPRAM, root["dram"]["name"].text()});
|
||||
|
||||
for(auto node : root.find("map")) {
|
||||
if(node["id"].text() == "io") {
|
||||
Mapping m({&ArmDSP::mmio_read, &armdsp}, {&ArmDSP::mmio_write, &armdsp});
|
||||
parseMarkupMap(m, node);
|
||||
mapping.append(m);
|
||||
}
|
||||
parseMarkupMap(node, {&ArmDSP::mmio_read, &armdsp}, {&ArmDSP::mmio_write, &armdsp});
|
||||
}
|
||||
}
|
||||
|
||||
auto Cartridge::parseMarkupHitachiDSP(Markup::Node root, uint roms) -> void {
|
||||
hasHitachiDSP = true;
|
||||
|
||||
auto rom = root.find("rom");
|
||||
auto ram = root.find("ram");
|
||||
|
||||
parseMarkupMemory(hitachidsp.rom, rom(0), ID::HitachiDSPROM, false);
|
||||
parseMarkupMemory(hitachidsp.ram, ram(0), ID::HitachiDSPRAM, true);
|
||||
hitachidsp.Frequency = root["frequency"].natural();
|
||||
if(hitachidsp.Frequency == 0) hitachidsp.frequency = 20000000;
|
||||
hitachidsp.Roms = roms; //1 or 2
|
||||
|
||||
for(auto& word : hitachidsp.dataROM) word = 0x000000;
|
||||
for(auto& word : hitachidsp.dataRAM) word = 0x00;
|
||||
|
||||
hitachidsp.Frequency = root["frequency"].natural();
|
||||
if(hitachidsp.Frequency == 0) hitachidsp.frequency = 20000000;
|
||||
hitachidsp.Roms = roms;
|
||||
interface->loadRequest(ID::HitachiDSPDROM, root["drom"]["name"].text(), true);
|
||||
interface->loadRequest(ID::HitachiDSPDRAM, root["dram"]["name"].text(), false);
|
||||
|
||||
string dataROMName = rom(1)["name"].text();
|
||||
string dataRAMName = ram(1)["name"].text();
|
||||
|
||||
interface->loadRequest(ID::HitachiDSPDROM, dataROMName, true);
|
||||
if(dataRAMName.empty() == false) {
|
||||
interface->loadRequest(ID::HitachiDSPDRAM, dataRAMName, false);
|
||||
}
|
||||
parseMarkupMemory(hitachidsp.rom, root["rom"], ID::HitachiDSPROM, false);
|
||||
parseMarkupMemory(hitachidsp.ram, root["ram"], ID::HitachiDSPRAM, true);
|
||||
|
||||
for(auto node : root.find("map")) {
|
||||
if(node["id"].text() == "io") {
|
||||
Mapping m({&HitachiDSP::dsp_read, &hitachidsp}, {&HitachiDSP::dsp_write, &hitachidsp});
|
||||
parseMarkupMap(m, node);
|
||||
mapping.append(m);
|
||||
}
|
||||
parseMarkupMap(node, {&HitachiDSP::dsp_read, &hitachidsp}, {&HitachiDSP::dsp_write, &hitachidsp});
|
||||
}
|
||||
|
||||
if(node["id"].text() == "rom") {
|
||||
Mapping m({&HitachiDSP::rom_read, &hitachidsp}, {&HitachiDSP::rom_write, &hitachidsp});
|
||||
parseMarkupMap(m, node);
|
||||
if(m.size == 0) m.size = hitachidsp.rom.size();
|
||||
mapping.append(m);
|
||||
}
|
||||
for(auto node : root["rom"].find("map")) {
|
||||
parseMarkupMap(node, {&HitachiDSP::rom_read, &hitachidsp}, {&HitachiDSP::rom_write, &hitachidsp});
|
||||
}
|
||||
|
||||
if(node["id"].text() == "ram") {
|
||||
Mapping m({&HitachiDSP::ram_read, &hitachidsp}, {&HitachiDSP::ram_write, &hitachidsp});
|
||||
parseMarkupMap(m, node);
|
||||
if(m.size == 0) m.size = hitachidsp.ram.size();
|
||||
mapping.append(m);
|
||||
}
|
||||
for(auto node : root["ram"].find("map")) {
|
||||
parseMarkupMap(node, {&HitachiDSP::ram_read, &hitachidsp}, {&HitachiDSP::ram_write, &hitachidsp});
|
||||
}
|
||||
|
||||
for(auto node : root["dram"].find("map")) {
|
||||
parseMarkupMap(node, {&HitachiDSP::dram_read, &hitachidsp}, {&HitachiDSP::dram_write, &hitachidsp});
|
||||
}
|
||||
}
|
||||
|
||||
auto Cartridge::parseMarkupNECDSP(Markup::Node root) -> void {
|
||||
hasNECDSP = true;
|
||||
|
||||
for(auto& word : necdsp.programROM) word = 0x000000;
|
||||
for(auto& word : necdsp.dataROM) word = 0x0000;
|
||||
for(auto& word : necdsp.dataRAM) word = 0x0000;
|
||||
|
||||
necdsp.frequency = root["frequency"].natural();
|
||||
if(necdsp.frequency == 0) necdsp.frequency = 8000000;
|
||||
necdsp.revision
|
||||
|
@ -387,137 +316,91 @@ auto Cartridge::parseMarkupNECDSP(Markup::Node root) -> void {
|
|||
: root["model"].text() == "uPD96050" ? NECDSP::Revision::uPD96050
|
||||
: NECDSP::Revision::uPD7725;
|
||||
|
||||
auto rom = root.find("rom");
|
||||
auto ram = root.find("ram");
|
||||
|
||||
string programROMName = rom(0)["name"].text();
|
||||
string dataROMName = rom(1)["name"].text();
|
||||
string dataRAMName = ram(0)["name"].text();
|
||||
for(auto& word : necdsp.programROM) word = 0x000000;
|
||||
for(auto& word : necdsp.dataROM) word = 0x0000;
|
||||
for(auto& word : necdsp.dataRAM) word = 0x0000;
|
||||
|
||||
if(necdsp.revision == NECDSP::Revision::uPD7725) {
|
||||
interface->loadRequest(ID::Nec7725DSPPROM, programROMName, true);
|
||||
interface->loadRequest(ID::Nec7725DSPDROM, dataROMName, true);
|
||||
if(dataRAMName.empty() == false) {
|
||||
interface->loadRequest(ID::Nec7725DSPRAM, dataRAMName, false);
|
||||
memory.append({ID::Nec7725DSPRAM, dataRAMName});
|
||||
}
|
||||
interface->loadRequest(ID::Nec7725DSPPROM, root["prom"]["name"].text(), true);
|
||||
interface->loadRequest(ID::Nec7725DSPDROM, root["drom"]["name"].text(), true);
|
||||
interface->loadRequest(ID::Nec7725DSPRAM, root["dram"]["name"].text(), false);
|
||||
memory.append({ID::Nec7725DSPRAM, root["dram"]["name"].text()});
|
||||
}
|
||||
|
||||
if(necdsp.revision == NECDSP::Revision::uPD96050) {
|
||||
interface->loadRequest(ID::Nec96050DSPPROM, programROMName, true);
|
||||
interface->loadRequest(ID::Nec96050DSPDROM, dataROMName, true);
|
||||
if(dataRAMName.empty() == false) {
|
||||
interface->loadRequest(ID::Nec96050DSPRAM, dataRAMName, false);
|
||||
memory.append({ID::Nec96050DSPRAM, dataRAMName});
|
||||
}
|
||||
interface->loadRequest(ID::Nec96050DSPPROM, root["prom"]["name"].text(), true);
|
||||
interface->loadRequest(ID::Nec96050DSPDROM, root["drom"]["name"].text(), true);
|
||||
interface->loadRequest(ID::Nec96050DSPRAM, root["dram"]["name"].text(), false);
|
||||
memory.append({ID::Nec96050DSPRAM, root["dram"]["name"].text()});
|
||||
}
|
||||
|
||||
for(auto node : root.find("map")) {
|
||||
if(node["id"].text() == "io") {
|
||||
Mapping m({&NECDSP::read, &necdsp}, {&NECDSP::write, &necdsp});
|
||||
parseMarkupMap(m, node);
|
||||
mapping.append(m);
|
||||
necdsp.Select = node["select"].natural();
|
||||
}
|
||||
parseMarkupMap(node, {&NECDSP::read, &necdsp}, {&NECDSP::write, &necdsp});
|
||||
}
|
||||
|
||||
if(node["id"].text() == "ram") {
|
||||
Mapping m({&NECDSP::readRAM, &necdsp}, {&NECDSP::writeRAM, &necdsp});
|
||||
parseMarkupMap(m, node);
|
||||
mapping.append(m);
|
||||
}
|
||||
for(auto node : root["dram"].find("map")) {
|
||||
parseMarkupMap(node, {&NECDSP::readRAM, &necdsp}, {&NECDSP::writeRAM, &necdsp});
|
||||
}
|
||||
}
|
||||
|
||||
auto Cartridge::parseMarkupEpsonRTC(Markup::Node root) -> void {
|
||||
hasEpsonRTC = true;
|
||||
|
||||
string name = root["ram/name"].text();
|
||||
interface->loadRequest(ID::EpsonRTC, name, false);
|
||||
memory.append({ID::EpsonRTC, name});
|
||||
interface->loadRequest(ID::EpsonRTC, root["ram"]["name"].text(), false);
|
||||
memory.append({ID::EpsonRTC, root["ram"]["name"].text()});
|
||||
|
||||
for(auto node : root.find("map")) {
|
||||
if(node["id"].text() == "io") {
|
||||
Mapping m({&EpsonRTC::read, &epsonrtc}, {&EpsonRTC::write, &epsonrtc});
|
||||
parseMarkupMap(m, node);
|
||||
mapping.append(m);
|
||||
}
|
||||
parseMarkupMap(node, {&EpsonRTC::read, &epsonrtc}, {&EpsonRTC::write, &epsonrtc});
|
||||
}
|
||||
}
|
||||
|
||||
auto Cartridge::parseMarkupSharpRTC(Markup::Node root) -> void {
|
||||
hasSharpRTC = true;
|
||||
|
||||
string name = root["ram/name"].text();
|
||||
interface->loadRequest(ID::SharpRTC, name, false);
|
||||
memory.append({ID::SharpRTC, name});
|
||||
interface->loadRequest(ID::SharpRTC, root["ram"]["name"].text(), false);
|
||||
memory.append({ID::SharpRTC, root["ram"]["name"].text()});
|
||||
|
||||
for(auto node : root.find("map")) {
|
||||
if(node["id"].text() == "io") {
|
||||
Mapping m({&SharpRTC::read, &sharprtc}, {&SharpRTC::write, &sharprtc});
|
||||
parseMarkupMap(m, node);
|
||||
mapping.append(m);
|
||||
}
|
||||
parseMarkupMap(node, {&SharpRTC::read, &sharprtc}, {&SharpRTC::write, &sharprtc});
|
||||
}
|
||||
}
|
||||
|
||||
auto Cartridge::parseMarkupSPC7110(Markup::Node root) -> void {
|
||||
hasSPC7110 = true;
|
||||
|
||||
auto rom = root.find("rom");
|
||||
auto ram = root.find("ram");
|
||||
|
||||
parseMarkupMemory(spc7110.prom, rom(0), ID::SPC7110PROM, false);
|
||||
parseMarkupMemory(spc7110.drom, rom(1), ID::SPC7110DROM, false);
|
||||
parseMarkupMemory(spc7110.ram, ram(0), ID::SPC7110RAM, true);
|
||||
parseMarkupMemory(spc7110.prom, root["prom"], ID::SPC7110PROM, false);
|
||||
parseMarkupMemory(spc7110.drom, root["drom"], ID::SPC7110DROM, false);
|
||||
parseMarkupMemory(spc7110.ram, root["ram"], ID::SPC7110RAM, true);
|
||||
|
||||
for(auto node : root.find("map")) {
|
||||
if(node["id"].text() == "io") {
|
||||
Mapping m({&SPC7110::read, &spc7110}, {&SPC7110::write, &spc7110});
|
||||
parseMarkupMap(m, node);
|
||||
mapping.append(m);
|
||||
if(node.text() == "mcu") {
|
||||
parseMarkupMap(node, {&SPC7110::mcurom_read, &spc7110}, {&SPC7110::mcurom_write, &spc7110});
|
||||
} else {
|
||||
parseMarkupMap(node, {&SPC7110::read, &spc7110}, {&SPC7110::write, &spc7110});
|
||||
}
|
||||
}
|
||||
|
||||
if(node["id"].text() == "rom") {
|
||||
Mapping m({&SPC7110::mcurom_read, &spc7110}, {&SPC7110::mcurom_write, &spc7110});
|
||||
parseMarkupMap(m, node);
|
||||
mapping.append(m);
|
||||
}
|
||||
|
||||
if(node["id"].text() == "ram") {
|
||||
Mapping m({&SPC7110::mcuram_read, &spc7110}, {&SPC7110::mcuram_write, &spc7110});
|
||||
parseMarkupMap(m, node);
|
||||
mapping.append(m);
|
||||
}
|
||||
for(auto node : root["ram"].find("map")) {
|
||||
parseMarkupMap(node, {&SPC7110::mcuram_read, &spc7110}, {&SPC7110::mcuram_write, &spc7110});
|
||||
}
|
||||
}
|
||||
|
||||
auto Cartridge::parseMarkupSDD1(Markup::Node root) -> void {
|
||||
hasSDD1 = true;
|
||||
|
||||
auto rom = root.find("rom");
|
||||
auto ram = root.find("ram");
|
||||
|
||||
parseMarkupMemory(sdd1.rom, rom(0), ID::SDD1ROM, false);
|
||||
parseMarkupMemory(sdd1.ram, ram(0), ID::SDD1RAM, true);
|
||||
parseMarkupMemory(sdd1.rom, root["rom"], ID::SDD1ROM, false);
|
||||
parseMarkupMemory(sdd1.ram, root["ram"], ID::SDD1RAM, true);
|
||||
|
||||
for(auto node : root.find("map")) {
|
||||
if(node["id"].text() == "io") {
|
||||
Mapping m({&SDD1::read, &sdd1}, {&SDD1::write, &sdd1});
|
||||
parseMarkupMap(m, node);
|
||||
mapping.append(m);
|
||||
}
|
||||
parseMarkupMap(node, {&SDD1::read, &sdd1}, {&SDD1::write, &sdd1});
|
||||
}
|
||||
|
||||
if(node["id"].text() == "rom") {
|
||||
Mapping m({&SDD1::mcurom_read, &sdd1}, {&SDD1::mcurom_write, &sdd1});
|
||||
parseMarkupMap(m, node);
|
||||
mapping.append(m);
|
||||
}
|
||||
for(auto node : root["rom"].find("map")) {
|
||||
parseMarkupMap(node, {&SDD1::mcurom_read, &sdd1}, {&SDD1::mcurom_write, &sdd1});
|
||||
}
|
||||
|
||||
if(node["id"].text() == "ram") {
|
||||
Mapping m({&SDD1::mcuram_read, &sdd1}, {&SDD1::mcuram_write, &sdd1});
|
||||
parseMarkupMap(m, node);
|
||||
mapping.append(m);
|
||||
}
|
||||
for(auto node : root["ram"].find("map")) {
|
||||
parseMarkupMap(node, {&SDD1::mcuram_read, &sdd1}, {&SDD1::mcuram_write, &sdd1});
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -527,11 +410,7 @@ auto Cartridge::parseMarkupOBC1(Markup::Node root) -> void {
|
|||
parseMarkupMemory(obc1.ram, root["ram"], ID::OBC1RAM, true);
|
||||
|
||||
for(auto node : root.find("map")) {
|
||||
if(node["id"].text() == "io") {
|
||||
Mapping m({&OBC1::read, &obc1}, {&OBC1::write, &obc1});
|
||||
parseMarkupMap(m, node);
|
||||
mapping.append(m);
|
||||
}
|
||||
parseMarkupMap(node, {&OBC1::read, &obc1}, {&OBC1::write, &obc1});
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -539,10 +418,6 @@ auto Cartridge::parseMarkupMSU1(Markup::Node root) -> void {
|
|||
hasMSU1 = true;
|
||||
|
||||
for(auto node : root.find("map")) {
|
||||
if(node["id"].text() == "io") {
|
||||
Mapping m({&MSU1::mmioRead, &msu1}, {&MSU1::mmioWrite, &msu1});
|
||||
parseMarkupMap(m, node);
|
||||
mapping.append(m);
|
||||
}
|
||||
parseMarkupMap(node, {&MSU1::mmioRead, &msu1}, {&MSU1::mmioWrite, &msu1});
|
||||
}
|
||||
}
|
||||
|
|
|
@ -116,6 +116,13 @@ auto Event::ram_write(uint addr, uint8 data) -> void {
|
|||
return ram.write(bus.mirror(addr, ram.size()), data);
|
||||
}
|
||||
|
||||
auto Event::read(uint addr, uint8 data) -> uint8 {
|
||||
return data;
|
||||
}
|
||||
|
||||
auto Event::write(uint addr, uint8 data) -> void {
|
||||
}
|
||||
|
||||
auto Event::serialize(serializer& s) -> void {
|
||||
Thread::serialize(s);
|
||||
s.array(ram.data(), ram.size());
|
||||
|
|
|
@ -19,6 +19,9 @@ struct Event : Coprocessor {
|
|||
auto ram_read(uint addr, uint8) -> uint8;
|
||||
auto ram_write(uint addr, uint8 data) -> void;
|
||||
|
||||
auto read(uint addr, uint8 data) -> uint8;
|
||||
auto write(uint addr, uint8 data) -> void;
|
||||
|
||||
auto serialize(serializer&) -> void;
|
||||
|
||||
MappedRAM rom[4];
|
||||
|
|
|
@ -25,6 +25,10 @@ struct HitachiDSP : Processor::HG51B, Coprocessor {
|
|||
auto ram_read(uint addr, uint8 data) -> uint8;
|
||||
auto ram_write(uint addr, uint8 data) -> void;
|
||||
|
||||
//HG51B data RAM read/write
|
||||
auto dram_read(uint addr, uint8 data) -> uint8;
|
||||
auto dram_write(uint addr, uint8 data) -> void;
|
||||
|
||||
//CPU MMIO read/write
|
||||
auto dsp_read(uint addr, uint8 data) -> uint8;
|
||||
auto dsp_write(uint addr, uint8 data) -> void;
|
||||
|
|
|
@ -52,48 +52,55 @@ auto HitachiDSP::ram_write(uint addr, uint8 data) -> void {
|
|||
return ram.write(bus.mirror(addr, ram.size()), data);
|
||||
}
|
||||
|
||||
auto HitachiDSP::dsp_read(uint addr, uint8) -> uint8 {
|
||||
addr &= 0x1fff;
|
||||
auto HitachiDSP::dram_read(uint addr, uint8 data) -> uint8 {
|
||||
addr &= 0xfff;
|
||||
if(addr >= 0xc00) return data;
|
||||
return dataRAM[addr];
|
||||
}
|
||||
|
||||
//Data RAM
|
||||
if((addr >= 0x0000 && addr <= 0x0bff) || (addr >= 0x1000 && addr <= 0x1bff)) {
|
||||
return dataRAM[addr & 0x0fff];
|
||||
}
|
||||
auto HitachiDSP::dram_write(uint addr, uint8 data) -> void {
|
||||
addr &= 0xfff;
|
||||
if(addr >= 0xc00) return;
|
||||
dataRAM[addr] = data;
|
||||
}
|
||||
|
||||
auto HitachiDSP::dsp_read(uint addr, uint8) -> uint8 {
|
||||
addr = 0x7c00 | (addr & 0x03ff);
|
||||
|
||||
//MMIO
|
||||
switch(addr) {
|
||||
case 0x1f40: return mmio.dma_source >> 0;
|
||||
case 0x1f41: return mmio.dma_source >> 8;
|
||||
case 0x1f42: return mmio.dma_source >> 16;
|
||||
case 0x1f43: return mmio.dma_length >> 0;
|
||||
case 0x1f44: return mmio.dma_length >> 8;
|
||||
case 0x1f45: return mmio.dma_target >> 0;
|
||||
case 0x1f46: return mmio.dma_target >> 8;
|
||||
case 0x1f47: return mmio.dma_target >> 16;
|
||||
case 0x1f48: return mmio.r1f48;
|
||||
case 0x1f49: return mmio.program_offset >> 0;
|
||||
case 0x1f4a: return mmio.program_offset >> 8;
|
||||
case 0x1f4b: return mmio.program_offset >> 16;
|
||||
case 0x1f4c: return mmio.r1f4c;
|
||||
case 0x1f4d: return mmio.page_number >> 0;
|
||||
case 0x1f4e: return mmio.page_number >> 8;
|
||||
case 0x1f4f: return mmio.program_counter;
|
||||
case 0x1f50: return mmio.r1f50;
|
||||
case 0x1f51: return mmio.r1f51;
|
||||
case 0x1f52: return mmio.r1f52;
|
||||
case 0x1f53: case 0x1f54: case 0x1f55: case 0x1f56:
|
||||
case 0x1f57: case 0x1f58: case 0x1f59: case 0x1f5a:
|
||||
case 0x1f5b: case 0x1f5c: case 0x1f5d: case 0x1f5e:
|
||||
case 0x1f5f: return ((regs.halt == false) << 6) | ((regs.halt == true) << 1);
|
||||
case 0x7f40: return mmio.dma_source >> 0;
|
||||
case 0x7f41: return mmio.dma_source >> 8;
|
||||
case 0x7f42: return mmio.dma_source >> 16;
|
||||
case 0x7f43: return mmio.dma_length >> 0;
|
||||
case 0x7f44: return mmio.dma_length >> 8;
|
||||
case 0x7f45: return mmio.dma_target >> 0;
|
||||
case 0x7f46: return mmio.dma_target >> 8;
|
||||
case 0x7f47: return mmio.dma_target >> 16;
|
||||
case 0x7f48: return mmio.r1f48;
|
||||
case 0x7f49: return mmio.program_offset >> 0;
|
||||
case 0x7f4a: return mmio.program_offset >> 8;
|
||||
case 0x7f4b: return mmio.program_offset >> 16;
|
||||
case 0x7f4c: return mmio.r1f4c;
|
||||
case 0x7f4d: return mmio.page_number >> 0;
|
||||
case 0x7f4e: return mmio.page_number >> 8;
|
||||
case 0x7f4f: return mmio.program_counter;
|
||||
case 0x7f50: return mmio.r1f50;
|
||||
case 0x7f51: return mmio.r1f51;
|
||||
case 0x7f52: return mmio.r1f52;
|
||||
case 0x7f53: case 0x7f54: case 0x7f55: case 0x7f56:
|
||||
case 0x7f57: case 0x7f58: case 0x7f59: case 0x7f5a:
|
||||
case 0x7f5b: case 0x7f5c: case 0x7f5d: case 0x7f5e:
|
||||
case 0x7f5f: return ((regs.halt == false) << 6) | ((regs.halt == true) << 1);
|
||||
}
|
||||
|
||||
//Vector
|
||||
if(addr >= 0x1f60 && addr <= 0x1f7f) {
|
||||
if(addr >= 0x7f60 && addr <= 0x7f7f) {
|
||||
return mmio.vector[addr & 0x1f];
|
||||
}
|
||||
|
||||
//GPRs
|
||||
if((addr >= 0x1f80 && addr <= 0x1faf) || (addr >= 0x1fc0 && addr <= 0x1fef)) {
|
||||
if((addr >= 0x7f80 && addr <= 0x7faf) || (addr >= 0x7fc0 && addr <= 0x7fef)) {
|
||||
uint index = (addr & 0x3f) / 3; //0..15
|
||||
uint shift = ((addr & 0x3f) % 3) * 8; //0, 8, 16
|
||||
return regs.gpr[index] >> shift;
|
||||
|
@ -103,52 +110,46 @@ auto HitachiDSP::dsp_read(uint addr, uint8) -> uint8 {
|
|||
}
|
||||
|
||||
auto HitachiDSP::dsp_write(uint addr, uint8 data) -> void {
|
||||
addr &= 0x1fff;
|
||||
|
||||
//Data RAM
|
||||
if((addr >= 0x0000 && addr <= 0x0bff) || (addr >= 0x1000 && addr <= 0x1bff)) {
|
||||
dataRAM[addr & 0x0fff] = data;
|
||||
return;
|
||||
}
|
||||
addr = 0x7c00 | (addr & 0x03ff);
|
||||
|
||||
//MMIO
|
||||
switch(addr) {
|
||||
case 0x1f40: mmio.dma_source = (mmio.dma_source & 0xffff00) | (data << 0); return;
|
||||
case 0x1f41: mmio.dma_source = (mmio.dma_source & 0xff00ff) | (data << 8); return;
|
||||
case 0x1f42: mmio.dma_source = (mmio.dma_source & 0x00ffff) | (data << 16); return;
|
||||
case 0x1f43: mmio.dma_length = (mmio.dma_length & 0xff00) | (data << 0); return;
|
||||
case 0x1f44: mmio.dma_length = (mmio.dma_length & 0x00ff) | (data << 8); return;
|
||||
case 0x1f45: mmio.dma_target = (mmio.dma_target & 0xffff00) | (data << 0); return;
|
||||
case 0x1f46: mmio.dma_target = (mmio.dma_target & 0xff00ff) | (data << 8); return;
|
||||
case 0x1f47: mmio.dma_target = (mmio.dma_target & 0x00ffff) | (data << 16);
|
||||
case 0x7f40: mmio.dma_source = (mmio.dma_source & 0xffff00) | (data << 0); return;
|
||||
case 0x7f41: mmio.dma_source = (mmio.dma_source & 0xff00ff) | (data << 8); return;
|
||||
case 0x7f42: mmio.dma_source = (mmio.dma_source & 0x00ffff) | (data << 16); return;
|
||||
case 0x7f43: mmio.dma_length = (mmio.dma_length & 0xff00) | (data << 0); return;
|
||||
case 0x7f44: mmio.dma_length = (mmio.dma_length & 0x00ff) | (data << 8); return;
|
||||
case 0x7f45: mmio.dma_target = (mmio.dma_target & 0xffff00) | (data << 0); return;
|
||||
case 0x7f46: mmio.dma_target = (mmio.dma_target & 0xff00ff) | (data << 8); return;
|
||||
case 0x7f47: mmio.dma_target = (mmio.dma_target & 0x00ffff) | (data << 16);
|
||||
if(regs.halt) mmio.dma = true;
|
||||
return;
|
||||
case 0x1f48: mmio.r1f48 = data & 0x01; return;
|
||||
case 0x1f49: mmio.program_offset = (mmio.program_offset & 0xffff00) | (data << 0); return;
|
||||
case 0x1f4a: mmio.program_offset = (mmio.program_offset & 0xff00ff) | (data << 8); return;
|
||||
case 0x1f4b: mmio.program_offset = (mmio.program_offset & 0x00ffff) | (data << 16); return;
|
||||
case 0x1f4c: mmio.r1f4c = data & 0x03; return;
|
||||
case 0x1f4d: mmio.page_number = (mmio.page_number & 0x7f00) | ((data & 0xff) << 0); return;
|
||||
case 0x1f4e: mmio.page_number = (mmio.page_number & 0x00ff) | ((data & 0x7f) << 8); return;
|
||||
case 0x1f4f: mmio.program_counter = data;
|
||||
case 0x7f48: mmio.r1f48 = data & 0x01; return;
|
||||
case 0x7f49: mmio.program_offset = (mmio.program_offset & 0xffff00) | (data << 0); return;
|
||||
case 0x7f4a: mmio.program_offset = (mmio.program_offset & 0xff00ff) | (data << 8); return;
|
||||
case 0x7f4b: mmio.program_offset = (mmio.program_offset & 0x00ffff) | (data << 16); return;
|
||||
case 0x7f4c: mmio.r1f4c = data & 0x03; return;
|
||||
case 0x7f4d: mmio.page_number = (mmio.page_number & 0x7f00) | ((data & 0xff) << 0); return;
|
||||
case 0x7f4e: mmio.page_number = (mmio.page_number & 0x00ff) | ((data & 0x7f) << 8); return;
|
||||
case 0x7f4f: mmio.program_counter = data;
|
||||
if(regs.halt) {
|
||||
regs.pc = mmio.page_number * 256 + mmio.program_counter;
|
||||
regs.halt = false;
|
||||
}
|
||||
return;
|
||||
case 0x1f50: mmio.r1f50 = data & 0x77; return;
|
||||
case 0x1f51: mmio.r1f51 = data & 0x01; return;
|
||||
case 0x1f52: mmio.r1f52 = data & 0x01; return;
|
||||
case 0x7f50: mmio.r1f50 = data & 0x77; return;
|
||||
case 0x7f51: mmio.r1f51 = data & 0x01; return;
|
||||
case 0x7f52: mmio.r1f52 = data & 0x01; return;
|
||||
}
|
||||
|
||||
//Vector
|
||||
if(addr >= 0x1f60 && addr <= 0x1f7f) {
|
||||
if(addr >= 0x7f60 && addr <= 0x7f7f) {
|
||||
mmio.vector[addr & 0x1f] = data;
|
||||
return;
|
||||
}
|
||||
|
||||
//GPRs
|
||||
if((addr >= 0x1f80 && addr <= 0x1faf) || (addr >= 0x1fc0 && addr <= 0x1fef)) {
|
||||
if((addr >= 0x7f80 && addr <= 0x7faf) || (addr >= 0x7fc0 && addr <= 0x7fef)) {
|
||||
uint index = (addr & 0x3f) / 3;
|
||||
switch((addr & 0x3f) % 3) {
|
||||
case 0: regs.gpr[index] = (regs.gpr[index] & 0xffff00) | (data << 0); return;
|
||||
|
|
|
@ -14,7 +14,6 @@ auto MCC::load() -> void {
|
|||
auto MCC::unload() -> void {
|
||||
rom.reset();
|
||||
ram.reset();
|
||||
psram.reset();
|
||||
}
|
||||
|
||||
auto MCC::power() -> void {
|
||||
|
@ -24,25 +23,18 @@ auto MCC::reset() -> void {
|
|||
for(auto n : range(16)) r[n] = 0x00;
|
||||
r[0x07] = 0x80;
|
||||
r[0x08] = 0x80;
|
||||
mmio_commit();
|
||||
commit();
|
||||
}
|
||||
|
||||
auto MCC::memory_access(bool write, Memory& memory, uint addr, uint8 data) -> uint8 {
|
||||
if(write == 0) return memory_read(memory, addr, data);
|
||||
memory_write(memory, addr, data);
|
||||
}
|
||||
|
||||
auto MCC::memory_read(Memory& memory, uint addr, uint8 data) -> uint8 {
|
||||
addr = bus.mirror(addr, memory.size());
|
||||
return memory.read(addr, data);
|
||||
if(!write) {
|
||||
return memory.read(addr, data);
|
||||
} else {
|
||||
memory.write(addr, data);
|
||||
}
|
||||
}
|
||||
|
||||
auto MCC::memory_write(Memory& memory, uint addr, uint8 data) -> void {
|
||||
addr = bus.mirror(addr, memory.size());
|
||||
return memory.write(addr, data);
|
||||
}
|
||||
|
||||
//mcu_access() allows mcu_read() and mcu_write() to share decoding logic
|
||||
auto MCC::mcu_access(bool write, uint addr, uint8 data) -> uint8 {
|
||||
if((addr & 0xe08000) == 0x008000) { //$00-1f:8000-ffff
|
||||
if(r07 == 1) {
|
||||
|
@ -58,72 +50,60 @@ auto MCC::mcu_access(bool write, uint addr, uint8 data) -> uint8 {
|
|||
}
|
||||
}
|
||||
|
||||
if((addr & 0xe0e000) == 0x206000) { //$20-3f:6000-7fff
|
||||
return memory_access(write, psram, addr, data);
|
||||
}
|
||||
|
||||
if((addr & 0xf00000) == 0x400000) { //$40-4f:0000-ffff
|
||||
if(r05 == 0) return memory_access(write, psram, addr & 0x0fffff, data);
|
||||
if(r05 == 0) return memory_access(write, ram, addr & 0x0fffff, data);
|
||||
}
|
||||
|
||||
if((addr & 0xf00000) == 0x500000) { //$50-5f:0000-ffff
|
||||
if(r06 == 0) return memory_access(write, psram, addr & 0x0fffff, data);
|
||||
if(r06 == 0) return memory_access(write, ram, addr & 0x0fffff, data);
|
||||
}
|
||||
|
||||
if((addr & 0xf00000) == 0x600000) { //$60-6f:0000-ffff
|
||||
if(r03 == 1) return memory_access(write, psram, addr & 0x0fffff, data);
|
||||
if(r03 == 1) return memory_access(write, ram, addr & 0x0fffff, data);
|
||||
}
|
||||
|
||||
if((addr & 0xf80000) == 0x700000) { //$70-77:0000-ffff
|
||||
return memory_access(write, psram, addr & 0x07ffff, data);
|
||||
return memory_access(write, ram, addr & 0x07ffff, data);
|
||||
}
|
||||
|
||||
if(((addr & 0x408000) == 0x008000) //$00-3f|80-bf:8000-ffff
|
||||
|| ((addr & 0x400000) == 0x400000) //$40-7f|c0-ff:0000-ffff
|
||||
if(((addr & 0x408000) == 0x008000) //$00-3f,80-bf:8000-ffff
|
||||
|| ((addr & 0x400000) == 0x400000) //$40-7f,c0-ff:0000-ffff
|
||||
) {
|
||||
if(r02 == 0) addr = ((addr & 0x7f0000) >> 1) | (addr & 0x7fff);
|
||||
Memory& memory = (r01 == 0 ? (Memory&)satellaviewcartridge : (Memory&)psram);
|
||||
Memory& memory = (r01 == 0 ? (Memory&)satellaviewcartridge : (Memory&)ram);
|
||||
return memory_access(write, memory, addr & 0x7fffff, data);
|
||||
}
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
auto MCC::mcu_read(uint addr, uint8 data) -> uint8 {
|
||||
return mcu_access(0, addr, data);
|
||||
}
|
||||
|
||||
auto MCC::mcu_write(uint addr, uint8 data) -> void {
|
||||
mcu_access(1, addr, data);
|
||||
}
|
||||
|
||||
auto MCC::mmio_read(uint addr, uint8 data) -> uint8 {
|
||||
if((addr & 0xf0ffff) == 0x005000) { //$00-0f:5000
|
||||
uint8 n = (addr >> 16) & 15;
|
||||
return r[n];
|
||||
}
|
||||
|
||||
if((addr & 0xf8f000) == 0x105000) { //$10-17:5000-5fff
|
||||
return memory_read(ram, ((addr >> 16) & 7) * 0x1000 + (addr & 0xfff), data);
|
||||
}
|
||||
|
||||
return 0x00;
|
||||
}
|
||||
|
||||
auto MCC::mmio_write(uint addr, uint8 data) -> void {
|
||||
auto MCC::mcu_read(uint addr, uint8 data) -> uint8 {
|
||||
return mcu_access(false, addr, data);
|
||||
}
|
||||
|
||||
auto MCC::mcu_write(uint addr, uint8 data) -> void {
|
||||
mcu_access(true, addr, data);
|
||||
}
|
||||
|
||||
auto MCC::read(uint addr, uint8 data) -> uint8 {
|
||||
if((addr & 0xf0ffff) == 0x005000) { //$00-0f:5000
|
||||
uint8 n = (addr >> 16) & 15;
|
||||
return r[n];
|
||||
}
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
auto MCC::write(uint addr, uint8 data) -> void {
|
||||
if((addr & 0xf0ffff) == 0x005000) { //$00-0f:5000
|
||||
uint8 n = (addr >> 16) & 15;
|
||||
r[n] = data;
|
||||
if(n == 0x0e && data & 0x80) mmio_commit();
|
||||
if(n == 0x0e && data & 0x80) commit();
|
||||
return;
|
||||
}
|
||||
|
||||
if((addr & 0xf8f000) == 0x105000) { //$10-17:5000-5fff
|
||||
return memory_write(ram, ((addr >> 16) & 7) * 0x1000 + (addr & 0xfff), data);
|
||||
}
|
||||
}
|
||||
|
||||
auto MCC::mmio_commit() -> void {
|
||||
auto MCC::commit() -> void {
|
||||
r00 = r[0x00] & 0x80;
|
||||
r01 = r[0x01] & 0x80;
|
||||
r02 = r[0x02] & 0x80;
|
||||
|
|
|
@ -3,7 +3,6 @@
|
|||
struct MCC {
|
||||
MappedRAM rom;
|
||||
MappedRAM ram;
|
||||
MappedRAM psram;
|
||||
|
||||
auto init() -> void;
|
||||
auto load() -> void;
|
||||
|
@ -12,16 +11,15 @@ struct MCC {
|
|||
auto reset() -> void;
|
||||
|
||||
auto memory_access(bool write, Memory& memory, uint addr, uint8 data) -> uint8;
|
||||
auto memory_read(Memory& memory, uint addr, uint8 data) -> uint8;
|
||||
auto memory_write(Memory& memory, uint addr, uint8 data) -> void;
|
||||
|
||||
auto mcu_access(bool write, uint addr, uint8 data) -> uint8;
|
||||
|
||||
auto mcu_read(uint addr, uint8 data) -> uint8;
|
||||
auto mcu_write(uint addr, uint8 data) -> void;
|
||||
|
||||
auto mmio_read(uint addr, uint8 data) -> uint8;
|
||||
auto mmio_write(uint addr, uint8 data) -> void;
|
||||
auto mmio_commit() -> void;
|
||||
auto read(uint addr, uint8 data) -> uint8;
|
||||
auto write(uint addr, uint8 data) -> void;
|
||||
|
||||
auto commit() -> void;
|
||||
|
||||
auto serialize(serializer&) -> void;
|
||||
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
auto MCC::serialize(serializer& s) -> void {
|
||||
s.array(ram.data(), ram.size());
|
||||
s.array(psram.data(), psram.size());
|
||||
}
|
||||
|
|
|
@ -91,7 +91,7 @@ auto MSU1::reset() -> void {
|
|||
auto MSU1::dataOpen() -> void {
|
||||
if(dataFile.open()) dataFile.close();
|
||||
auto document = BML::unserialize(cartridge.information.markup.cartridge);
|
||||
string name = document["cartridge/msu1/rom/name"].text();
|
||||
string name = document["board/msu1/rom/name"].text();
|
||||
if(!name) name = "msu1.rom";
|
||||
if(dataFile.open({interface->path(ID::SuperFamicom), name}, file::mode::read)) {
|
||||
dataFile.seek(mmio.dataReadOffset);
|
||||
|
@ -102,7 +102,7 @@ auto MSU1::audioOpen() -> void {
|
|||
if(audioFile.open()) audioFile.close();
|
||||
auto document = BML::unserialize(cartridge.information.markup.cartridge);
|
||||
string name = {"track-", mmio.audioTrack, ".pcm"};
|
||||
for(auto track : document.find("cartridge/msu1/track")) {
|
||||
for(auto track : document.find("board/msu1/track")) {
|
||||
if(track["number"].natural() != mmio.audioTrack) continue;
|
||||
name = track["name"].text();
|
||||
break;
|
||||
|
|
|
@ -21,7 +21,7 @@ auto NECDSP::enter() -> void {
|
|||
|
||||
auto NECDSP::read(uint addr, uint8) -> uint8 {
|
||||
cpu.synchronizeCoprocessors();
|
||||
if(addr & Select) {
|
||||
if(addr & 1) {
|
||||
return uPD96050::readSR();
|
||||
} else {
|
||||
return uPD96050::readDR();
|
||||
|
@ -30,7 +30,7 @@ auto NECDSP::read(uint addr, uint8) -> uint8 {
|
|||
|
||||
auto NECDSP::write(uint addr, uint8 data) -> void {
|
||||
cpu.synchronizeCoprocessors();
|
||||
if(addr & Select) {
|
||||
if(addr & 1) {
|
||||
return uPD96050::writeSR(data);
|
||||
} else {
|
||||
return uPD96050::writeDR(data);
|
||||
|
|
|
@ -16,8 +16,6 @@ struct NECDSP : Processor::uPD96050, Coprocessor {
|
|||
|
||||
auto firmware() const -> vector<uint8>;
|
||||
auto serialize(serializer&) -> void;
|
||||
|
||||
unsigned Select;
|
||||
};
|
||||
|
||||
extern NECDSP necdsp;
|
||||
|
|
|
@ -1,9 +1,10 @@
|
|||
auto SA1::bus_read(uint addr, uint8 data) -> uint8 {
|
||||
if((addr & 0x40fe00) == 0x002200) { //$00-3f|80-bf:2200-23ff
|
||||
if((addr & 0x40fe00) == 0x002200) { //$00-3f,80-bf:2200-23ff
|
||||
return mmio_read(addr, data);
|
||||
}
|
||||
|
||||
if((addr & 0x408000) == 0x008000) { //$00-3f|80-bf:8000-ffff
|
||||
if((addr & 0x408000) == 0x008000) { //$00-3f,80-bf:8000-ffff
|
||||
addr = ((addr & 0x800000) >> 2) | ((addr & 0x3f0000) >> 1) | (addr & 0x7fff);
|
||||
return mmcrom_read(addr, data);
|
||||
}
|
||||
|
||||
|
@ -11,16 +12,16 @@ auto SA1::bus_read(uint addr, uint8 data) -> uint8 {
|
|||
return mmcrom_read(addr, data);
|
||||
}
|
||||
|
||||
if((addr & 0x40e000) == 0x006000) { //$00-3f|80-bf:6000-7fff
|
||||
if((addr & 0x40e000) == 0x006000) { //$00-3f,80-bf:6000-7fff
|
||||
return mmc_sa1_read(addr, data);
|
||||
}
|
||||
|
||||
if((addr & 0x40f800) == 0x000000) { //$00-3f|80-bf:0000-07ff
|
||||
if((addr & 0x40f800) == 0x000000) { //$00-3f,80-bf:0000-07ff
|
||||
synchronizeCPU();
|
||||
return iram.read(addr & 2047, data);
|
||||
}
|
||||
|
||||
if((addr & 0x40f800) == 0x003000) { //$00-3f|80-bf:3000-37ff
|
||||
if((addr & 0x40f800) == 0x003000) { //$00-3f,80-bf:3000-37ff
|
||||
synchronizeCPU();
|
||||
return iram.read(addr & 2047, data);
|
||||
}
|
||||
|
@ -40,20 +41,20 @@ auto SA1::bus_read(uint addr, uint8 data) -> uint8 {
|
|||
}
|
||||
|
||||
auto SA1::bus_write(uint addr, uint8 data) -> void {
|
||||
if((addr & 0x40fe00) == 0x002200) { //$00-3f|80-bf:2200-23ff
|
||||
if((addr & 0x40fe00) == 0x002200) { //$00-3f,80-bf:2200-23ff
|
||||
return mmio_write(addr, data);
|
||||
}
|
||||
|
||||
if((addr & 0x40e000) == 0x006000) { //$00-3f|80-bf:6000-7fff
|
||||
if((addr & 0x40e000) == 0x006000) { //$00-3f,80-bf:6000-7fff
|
||||
return mmc_sa1_write(addr, data);
|
||||
}
|
||||
|
||||
if((addr & 0x40f800) == 0x000000) { //$00-3f|80-bf:0000-07ff
|
||||
if((addr & 0x40f800) == 0x000000) { //$00-3f,80-bf:0000-07ff
|
||||
synchronizeCPU();
|
||||
return iram.write(addr & 2047, data);
|
||||
}
|
||||
|
||||
if((addr & 0x40f800) == 0x003000) { //$00-3f|80-bf:3000-37ff
|
||||
if((addr & 0x40f800) == 0x003000) { //$00-3f,80-bf:3000-37ff
|
||||
synchronizeCPU();
|
||||
return iram.write(addr & 2047, data);
|
||||
}
|
||||
|
@ -74,7 +75,8 @@ auto SA1::bus_write(uint addr, uint8 data) -> void {
|
|||
//to avoid syncing the S-CPU and SA-1*; as both chips are able to access
|
||||
//these ports.
|
||||
auto SA1::vbr_read(uint addr, uint8 data) -> uint8 {
|
||||
if((addr & 0x408000) == 0x008000) { //$00-3f|80-bf:8000-ffff
|
||||
if((addr & 0x408000) == 0x008000) { //$00-3f,80-bf:8000-ffff
|
||||
addr = ((addr & 0x800000) >> 2) | ((addr & 0x3f0000) >> 1) | (addr & 0x7fff);
|
||||
return mmcrom_read(addr, data);
|
||||
}
|
||||
|
||||
|
@ -82,7 +84,7 @@ auto SA1::vbr_read(uint addr, uint8 data) -> uint8 {
|
|||
return mmcrom_read(addr, data);
|
||||
}
|
||||
|
||||
if((addr & 0x40e000) == 0x006000) { //$00-3f|80-bf:6000-7fff
|
||||
if((addr & 0x40e000) == 0x006000) { //$00-3f,80-bf:6000-7fff
|
||||
return bwram.read(addr & (bwram.size() - 1), data);
|
||||
}
|
||||
|
||||
|
@ -90,11 +92,11 @@ auto SA1::vbr_read(uint addr, uint8 data) -> uint8 {
|
|||
return bwram.read(addr & (bwram.size() - 1), data);
|
||||
}
|
||||
|
||||
if((addr & 0x40f800) == 0x000000) { //$00-3f|80-bf:0000-07ff
|
||||
if((addr & 0x40f800) == 0x000000) { //$00-3f,80-bf:0000-07ff
|
||||
return iram.read(addr & 2047, data);
|
||||
}
|
||||
|
||||
if((addr & 0x40f800) == 0x003000) { //$00-3f|80-bf:3000-37ff
|
||||
if((addr & 0x40f800) == 0x003000) { //$00-3f,80-bf:3000-37ff
|
||||
return iram.read(addr & 2047, data);
|
||||
}
|
||||
|
||||
|
@ -122,55 +124,42 @@ auto SA1::op_write(uint addr, uint8 data) -> void {
|
|||
bus_write(addr, regs.mdr = data);
|
||||
}
|
||||
|
||||
//note: addresses are translated prior to invoking this function:
|
||||
//$00-3f,80-bf:8000-ffff mask=0x408000 => $00-3f:0000-ffff
|
||||
//$c0-ff:0000-ffff mask=0
|
||||
auto SA1::mmcrom_read(uint addr, uint8) -> uint8 {
|
||||
if((addr & 0xffffe0) == 0x00ffe0) {
|
||||
if(addr == 0xffea && sa1.mmio.cpu_nvsw) return sa1.mmio.snv >> 0;
|
||||
if(addr == 0xffeb && sa1.mmio.cpu_nvsw) return sa1.mmio.snv >> 8;
|
||||
if(addr == 0xffee && sa1.mmio.cpu_ivsw) return sa1.mmio.siv >> 0;
|
||||
if(addr == 0xffef && sa1.mmio.cpu_ivsw) return sa1.mmio.siv >> 8;
|
||||
//reset vector overrides
|
||||
if((addr & 0xffffe0) == 0x007fe0) { //$00:ffe0-ffef
|
||||
if(addr == 0x7fea && sa1.mmio.cpu_nvsw) return sa1.mmio.snv >> 0;
|
||||
if(addr == 0x7feb && sa1.mmio.cpu_nvsw) return sa1.mmio.snv >> 8;
|
||||
if(addr == 0x7fee && sa1.mmio.cpu_ivsw) return sa1.mmio.siv >> 0;
|
||||
if(addr == 0x7fef && sa1.mmio.cpu_ivsw) return sa1.mmio.siv >> 8;
|
||||
}
|
||||
|
||||
static auto read = [](uint addr) {
|
||||
return sa1.rom.read(bus.mirror(addr, sa1.rom.size()));
|
||||
};
|
||||
|
||||
if((addr & 0xe08000) == 0x008000) { //$00-1f:8000-ffff
|
||||
addr = ((addr & 0x1f0000) >> 1) | (addr & 0x007fff);
|
||||
if(mmio.cbmode == 0) return read(0x000000 | addr);
|
||||
return read((mmio.cb << 20) | addr);
|
||||
}
|
||||
bool lo = addr < 0x400000; //*bmode==0 only applies to $00-3f,80-bf:8000-ffff
|
||||
addr &= 0x3fffff;
|
||||
|
||||
if((addr & 0xe08000) == 0x208000) { //$20-3f:8000-ffff
|
||||
addr = ((addr & 0x1f0000) >> 1) | (addr & 0x007fff);
|
||||
if(mmio.dbmode == 0) return read(0x100000 | addr);
|
||||
return read((mmio.db << 20) | addr);
|
||||
}
|
||||
|
||||
if((addr & 0xe08000) == 0x808000) { //$80-9f:8000-ffff
|
||||
addr = ((addr & 0x1f0000) >> 1) | (addr & 0x007fff);
|
||||
if(mmio.ebmode == 0) return read(0x200000 | addr);
|
||||
return read((mmio.eb << 20) | addr);
|
||||
}
|
||||
|
||||
if((addr & 0xe08000) == 0xa08000) { //$a0-bf:8000-ffff
|
||||
addr = ((addr & 0x1f0000) >> 1) | (addr & 0x007fff);
|
||||
if(mmio.fbmode == 0) return read(0x300000 | addr);
|
||||
return read((mmio.fb << 20) | addr);
|
||||
}
|
||||
|
||||
if((addr & 0xf00000) == 0xc00000) { //$c0-cf:0000-ffff
|
||||
if(addr < 0x100000) { //$00-1f,8000-ffff; $c0-cf:0000-ffff
|
||||
if(lo && mmio.cbmode == 0) return read(addr);
|
||||
return read((mmio.cb << 20) | (addr & 0x0fffff));
|
||||
}
|
||||
|
||||
if((addr & 0xf00000) == 0xd00000) { //$d0-df:0000-ffff
|
||||
if(addr < 0x200000) { //$20-3f,8000-ffff; $d0-df:0000-ffff
|
||||
if(lo && mmio.dbmode == 0) return read(addr);
|
||||
return read((mmio.db << 20) | (addr & 0x0fffff));
|
||||
}
|
||||
|
||||
if((addr & 0xf00000) == 0xe00000) { //$e0-ef:0000-ffff
|
||||
if(addr < 0x300000) { //$80-9f,8000-ffff; $e0-ef:0000-ffff
|
||||
if(lo && mmio.ebmode == 0) return read(addr);
|
||||
return read((mmio.eb << 20) | (addr & 0x0fffff));
|
||||
}
|
||||
|
||||
if((addr & 0xf00000) == 0xf00000) { //$f0-ff:0000-ffff
|
||||
if(addr < 0x400000) { //$a0-bf,8000-ffff; $f0-ff:0000-ffff
|
||||
if(lo && mmio.fbmode == 0) return read(addr);
|
||||
return read((mmio.fb << 20) | (addr & 0x0fffff));
|
||||
}
|
||||
|
||||
|
@ -181,7 +170,7 @@ auto SA1::mmcrom_write(uint addr, uint8 data) -> void {
|
|||
}
|
||||
|
||||
auto SA1::mmcbwram_read(uint addr, uint8 data) -> uint8 {
|
||||
if((addr & 0x40e000) == 0x006000) { //$00-3f|80-bf:6000-7fff
|
||||
if(addr < 0x2000) { //$00-3f,80-bf:6000-7fff
|
||||
cpu.synchronizeCoprocessors();
|
||||
addr = bus.mirror(mmio.sbm * 0x2000 + (addr & 0x1fff), cpubwram.size());
|
||||
return cpubwram.read(addr);
|
||||
|
@ -195,7 +184,7 @@ auto SA1::mmcbwram_read(uint addr, uint8 data) -> uint8 {
|
|||
}
|
||||
|
||||
auto SA1::mmcbwram_write(uint addr, uint8 data) -> void {
|
||||
if((addr & 0x40e000) == 0x006000) { //$00-3f|80-bf:6000-7fff
|
||||
if(addr < 0x2000) { //$00-3f,80-bf:6000-7fff
|
||||
cpu.synchronizeCoprocessors();
|
||||
addr = bus.mirror(mmio.sbm * 0x2000 + (addr & 0x1fff), cpubwram.size());
|
||||
return cpubwram.write(addr, data);
|
||||
|
|
|
@ -13,8 +13,8 @@ auto SDD1::init() -> void {
|
|||
void SDD1::load() {
|
||||
//hook S-CPU DMA MMIO registers to gather information for struct dma[];
|
||||
//buffer address and transfer size information for use in SDD1::mcu_read()
|
||||
bus.map({&SDD1::read, &sdd1}, {&SDD1::write, &sdd1}, 0x00, 0x3f, 0x4300, 0x437f);
|
||||
bus.map({&SDD1::read, &sdd1}, {&SDD1::write, &sdd1}, 0x80, 0xbf, 0x4300, 0x437f);
|
||||
bus.map({&SDD1::dma_read, &sdd1}, {&SDD1::dma_write, &sdd1}, 0x00, 0x3f, 0x4300, 0x437f);
|
||||
bus.map({&SDD1::dma_read, &sdd1}, {&SDD1::dma_write, &sdd1}, 0x80, 0xbf, 0x4300, 0x437f);
|
||||
}
|
||||
|
||||
auto SDD1::unload() -> void {
|
||||
|
@ -42,11 +42,7 @@ auto SDD1::reset() -> void {
|
|||
}
|
||||
|
||||
auto SDD1::read(uint addr, uint8 data) -> uint8 {
|
||||
addr &= 0x40ffff;
|
||||
|
||||
if((addr & 0x404380) == 0x4300) {
|
||||
return cpu.mmio_read(addr, data);
|
||||
}
|
||||
addr = 0x4800 | (addr & 7);
|
||||
|
||||
switch(addr) {
|
||||
case 0x4804: return mmc[0] >> 20;
|
||||
|
@ -59,20 +55,7 @@ auto SDD1::read(uint addr, uint8 data) -> uint8 {
|
|||
}
|
||||
|
||||
auto SDD1::write(uint addr, uint8 data) -> void {
|
||||
addr &= 0xffff;
|
||||
|
||||
if((addr & 0x4380) == 0x4300) {
|
||||
uint channel = (addr >> 4) & 7;
|
||||
switch(addr & 15) {
|
||||
case 2: dma[channel].addr = (dma[channel].addr & 0xffff00) + (data << 0); break;
|
||||
case 3: dma[channel].addr = (dma[channel].addr & 0xff00ff) + (data << 8); break;
|
||||
case 4: dma[channel].addr = (dma[channel].addr & 0x00ffff) + (data << 16); break;
|
||||
|
||||
case 5: dma[channel].size = (dma[channel].size & 0xff00) + (data << 0); break;
|
||||
case 6: dma[channel].size = (dma[channel].size & 0x00ff) + (data << 8); break;
|
||||
}
|
||||
return cpu.mmio_write(addr, data);
|
||||
}
|
||||
addr = 0x4800 | (addr & 7);
|
||||
|
||||
switch(addr) {
|
||||
case 0x4800: sdd1_enable = data; break;
|
||||
|
@ -85,6 +68,23 @@ auto SDD1::write(uint addr, uint8 data) -> void {
|
|||
}
|
||||
}
|
||||
|
||||
auto SDD1::dma_read(uint addr, uint8 data) -> uint8 {
|
||||
return cpu.mmio_read(addr, data);
|
||||
}
|
||||
|
||||
auto SDD1::dma_write(uint addr, uint8 data) -> void {
|
||||
uint channel = (addr >> 4) & 7;
|
||||
switch(addr & 15) {
|
||||
case 2: dma[channel].addr = (dma[channel].addr & 0xffff00) + (data << 0); break;
|
||||
case 3: dma[channel].addr = (dma[channel].addr & 0xff00ff) + (data << 8); break;
|
||||
case 4: dma[channel].addr = (dma[channel].addr & 0x00ffff) + (data << 16); break;
|
||||
|
||||
case 5: dma[channel].size = (dma[channel].size & 0xff00) + (data << 0); break;
|
||||
case 6: dma[channel].size = (dma[channel].size & 0x00ff) + (data << 8); break;
|
||||
}
|
||||
return cpu.mmio_write(addr, data);
|
||||
}
|
||||
|
||||
auto SDD1::mmc_read(uint addr) -> uint8 {
|
||||
return rom.read(mmc[(addr >> 20) & 3] + (addr & 0x0fffff));
|
||||
}
|
||||
|
@ -108,13 +108,12 @@ auto SDD1::mmc_read(uint addr) -> uint8 {
|
|||
//the actual S-DD1 transfer can occur on any channel, but it is most likely limited to
|
||||
//one transfer per $420b write (for spooling purposes). however, this is not known for certain.
|
||||
auto SDD1::mcurom_read(uint addr, uint8) -> uint8 {
|
||||
if(addr < 0x400000) { //(addr & 0x408000) == 0x008000) { //$00-3f|80-bf:8000-ffff
|
||||
//map address=00-3f,80-bf:8000-ffff mask=0x808000 => 00-1f:0000-ffff
|
||||
if(addr < 0x200000) {
|
||||
return rom.read(addr);
|
||||
//addr = ((addr & 0x7f0000) >> 1) | (addr & 0x7fff);
|
||||
//return rom.read(addr);
|
||||
}
|
||||
|
||||
//$40-7f|c0-ff:0000-ffff (MMC)
|
||||
//map address=c0-ff:0000-ffff
|
||||
if(sdd1_enable & xfer_enable) {
|
||||
//at least one channel has S-DD1 decompression enabled ...
|
||||
for(auto n : range(8)) {
|
||||
|
@ -148,7 +147,7 @@ auto SDD1::mcurom_write(uint addr, uint8 data) -> void {
|
|||
}
|
||||
|
||||
auto SDD1::mcuram_read(uint addr, uint8 data) -> uint8 {
|
||||
if((addr & 0x60e000) == 0x006000) { //$00-3f|80-bf:6000-7fff
|
||||
if((addr & 0x60e000) == 0x006000) { //$00-3f,80-bf:6000-7fff
|
||||
return ram.read(addr & 0x1fff, data);
|
||||
}
|
||||
|
||||
|
@ -160,7 +159,7 @@ auto SDD1::mcuram_read(uint addr, uint8 data) -> uint8 {
|
|||
}
|
||||
|
||||
auto SDD1::mcuram_write(uint addr, uint8 data) -> void {
|
||||
if((addr & 0x60e000) == 0x006000) { //$00-3f|80-bf:6000-7fff
|
||||
if((addr & 0x60e000) == 0x006000) { //$00-3f,80-bf:6000-7fff
|
||||
return ram.write(addr & 0x1fff, data);
|
||||
}
|
||||
|
||||
|
|
|
@ -8,6 +8,9 @@ struct SDD1 {
|
|||
auto read(uint addr, uint8 data) -> uint8;
|
||||
auto write(uint addr, uint8 data) -> void;
|
||||
|
||||
auto dma_read(uint addr, uint8 data) -> uint8;
|
||||
auto dma_write(uint addr, uint8 data) -> void;
|
||||
|
||||
auto mmc_read(uint addr) -> uint8;
|
||||
|
||||
auto mcurom_read(uint addr, uint8 data) -> uint8;
|
||||
|
|
|
@ -111,15 +111,14 @@ auto SPC7110::reset() -> void {
|
|||
|
||||
auto SPC7110::read(uint addr, uint8 data) -> uint8 {
|
||||
cpu.synchronizeCoprocessors();
|
||||
if((addr & 0xff0000) == 0x500000) addr = 0x4800;
|
||||
addr = 0x4800 | (addr & 0x3f);
|
||||
if((addr & 0xff0000) == 0x500000) addr = 0x4800; //$50:0000-ffff == $4800
|
||||
if((addr & 0xff0000) == 0x580000) addr = 0x4808; //$58:0000-ffff == $4808
|
||||
addr = 0x4800 | (addr & 0x3f); //$00-3f,80-bf:4800-483f
|
||||
|
||||
switch(addr) {
|
||||
|
||||
//==================
|
||||
//decompression unit
|
||||
//==================
|
||||
|
||||
case 0x4800: {
|
||||
uint16 counter = r4809 | r480a << 8;
|
||||
counter--;
|
||||
|
@ -143,7 +142,6 @@ auto SPC7110::read(uint addr, uint8 data) -> uint8 {
|
|||
//==============
|
||||
//data port unit
|
||||
//==============
|
||||
|
||||
case 0x4810: {
|
||||
data = r4810;
|
||||
data_port_increment_4810();
|
||||
|
@ -165,7 +163,6 @@ auto SPC7110::read(uint addr, uint8 data) -> uint8 {
|
|||
//=====================
|
||||
//arithmetic logic unit
|
||||
//=====================
|
||||
|
||||
case 0x4820: return r4820;
|
||||
case 0x4821: return r4821;
|
||||
case 0x4822: return r4822;
|
||||
|
@ -186,13 +183,11 @@ auto SPC7110::read(uint addr, uint8 data) -> uint8 {
|
|||
//===================
|
||||
//memory control unit
|
||||
//===================
|
||||
|
||||
case 0x4830: return r4830;
|
||||
case 0x4831: return r4831;
|
||||
case 0x4832: return r4832;
|
||||
case 0x4833: return r4833;
|
||||
case 0x4834: return r4834;
|
||||
|
||||
}
|
||||
|
||||
return data;
|
||||
|
@ -200,14 +195,14 @@ auto SPC7110::read(uint addr, uint8 data) -> uint8 {
|
|||
|
||||
auto SPC7110::write(uint addr, uint8 data) -> void {
|
||||
cpu.synchronizeCoprocessors();
|
||||
addr = 0x4800 | (addr & 0x3f);
|
||||
if((addr & 0xff0000) == 0x500000) addr = 0x4800; //$50:0000-ffff == $4800
|
||||
if((addr & 0xff0000) == 0x580000) addr = 0x4808; //$58:0000-ffff == $4808
|
||||
addr = 0x4800 | (addr & 0x3f); //$00-3f,80-bf:4800-483f
|
||||
|
||||
switch(addr) {
|
||||
|
||||
//==================
|
||||
//decompression unit
|
||||
//==================
|
||||
|
||||
case 0x4801: r4801 = data; break;
|
||||
case 0x4802: r4802 = data; break;
|
||||
case 0x4803: r4803 = data; break;
|
||||
|
@ -223,7 +218,6 @@ auto SPC7110::write(uint addr, uint8 data) -> void {
|
|||
//==============
|
||||
//data port unit
|
||||
//==============
|
||||
|
||||
case 0x4811: r4811 = data; break;
|
||||
case 0x4812: r4812 = data; break;
|
||||
case 0x4813: r4813 = data; data_port_read(); break;
|
||||
|
@ -236,7 +230,6 @@ auto SPC7110::write(uint addr, uint8 data) -> void {
|
|||
//=====================
|
||||
//arithmetic logic unit
|
||||
//=====================
|
||||
|
||||
case 0x4820: r4820 = data; break;
|
||||
case 0x4821: r4821 = data; break;
|
||||
case 0x4822: r4822 = data; break;
|
||||
|
@ -250,13 +243,11 @@ auto SPC7110::write(uint addr, uint8 data) -> void {
|
|||
//===================
|
||||
//memory control unit
|
||||
//===================
|
||||
|
||||
case 0x4830: r4830 = data & 0x87; break;
|
||||
case 0x4831: r4831 = data & 0x07; break;
|
||||
case 0x4832: r4832 = data & 0x07; break;
|
||||
case 0x4833: r4833 = data & 0x07; break;
|
||||
case 0x4834: r4834 = data & 0x07; break;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -264,12 +255,12 @@ auto SPC7110::write(uint addr, uint8 data) -> void {
|
|||
//SPC7110::MCUROM
|
||||
//===============
|
||||
|
||||
//map address=00-3f,80-bf:8000-ffff mask=0x800000 => 00-3f:8000-ffff
|
||||
//map address=c0-ff:0000-ffff mask=0xc00000 => c0-ff:0000-ffff
|
||||
auto SPC7110::mcurom_read(uint addr, uint8 data) -> uint8 {
|
||||
uint mask = (1 << (r4834 & 3)) - 1; //8mbit, 16mbit, 32mbit, 64mbit DROM
|
||||
|
||||
if((addr & 0x708000) == 0x008000 //$00-0f|80-8f:8000-ffff
|
||||
|| (addr & 0xf00000) == 0xc00000 // $c0-cf:0000-ffff
|
||||
) {
|
||||
if(addr < 0x100000) { //$00-0f,80-8f:8000-ffff; $c0-cf:0000-ffff
|
||||
addr &= 0x0fffff;
|
||||
if(prom.size()) { //8mbit PROM
|
||||
return prom.read(bus.mirror(0x000000 + addr, prom.size()));
|
||||
|
@ -278,9 +269,7 @@ auto SPC7110::mcurom_read(uint addr, uint8 data) -> uint8 {
|
|||
return datarom_read(addr);
|
||||
}
|
||||
|
||||
if((addr & 0x708000) == 0x108000 //$10-1f|90-9f:8000-ffff
|
||||
|| (addr & 0xf00000) == 0xd00000 // $d0-df:0000-ffff
|
||||
) {
|
||||
if(addr < 0x200000) { //$10-1f,90-9f:8000-ffff; $d0-df:0000-ffff
|
||||
addr &= 0x0fffff;
|
||||
if(r4834 & 4) { //16mbit PROM
|
||||
return prom.read(bus.mirror(0x100000 + addr, prom.size()));
|
||||
|
@ -289,17 +278,13 @@ auto SPC7110::mcurom_read(uint addr, uint8 data) -> uint8 {
|
|||
return datarom_read(addr);
|
||||
}
|
||||
|
||||
if((addr & 0x708000) == 0x208000 //$20-2f|a0-af:8000-ffff
|
||||
|| (addr & 0xf00000) == 0xe00000 // $e0-ef:0000-ffff
|
||||
) {
|
||||
if(addr < 0x300000) { //$20-2f,a0-af:8000-ffff; $e0-ef:0000-ffff
|
||||
addr &= 0x0fffff;
|
||||
addr |= 0x100000 * (r4832 & 7);
|
||||
return datarom_read(addr);
|
||||
}
|
||||
|
||||
if((addr & 0x708000) == 0x308000 //$30-3f|b0-bf:8000-ffff
|
||||
|| (addr & 0xf00000) == 0xf00000 // $f0-ff:0000-ffff
|
||||
) {
|
||||
if(addr < 0x400000) { //$30-3f,b0-bf:8000-ffff; $f0-ff:0000-ffff
|
||||
addr &= 0x0fffff;
|
||||
addr |= 0x100000 * (r4833 & 7);
|
||||
return datarom_read(addr);
|
||||
|
@ -315,21 +300,18 @@ auto SPC7110::mcurom_write(uint addr, uint8 data) -> void {
|
|||
//SPC7110::MCURAM
|
||||
//===============
|
||||
|
||||
//map address=00-3f,80-bf:6000-7fff mask=0x80e000 => 00-07:0000-ffff
|
||||
auto SPC7110::mcuram_read(uint addr, uint8) -> uint8 {
|
||||
//$00-3f|80-bf:6000-7fff
|
||||
if(r4830 & 0x80) {
|
||||
uint bank = (addr >> 16) & 0x3f;
|
||||
addr = bus.mirror(bank * 0x2000 + (addr & 0x1fff), ram.size());
|
||||
addr = bus.mirror(addr, ram.size());
|
||||
return ram.read(addr);
|
||||
}
|
||||
return 0x00;
|
||||
}
|
||||
|
||||
auto SPC7110::mcuram_write(uint addr, uint8 data) -> void {
|
||||
//$00-3f|80-bf:6000-7fff
|
||||
if(r4830 & 0x80) {
|
||||
uint bank = (addr >> 16) & 0x3f;
|
||||
addr = bus.mirror(bank * 0x2000 + (addr & 0x1fff), ram.size());
|
||||
addr = bus.mirror(addr, ram.size());
|
||||
ram.write(addr, data);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -131,6 +131,10 @@ Interface::Interface() {
|
|||
}
|
||||
}
|
||||
|
||||
auto Interface::manifest() -> string {
|
||||
return cartridge.manifest();
|
||||
}
|
||||
|
||||
auto Interface::title() -> string {
|
||||
return cartridge.title();
|
||||
}
|
||||
|
@ -196,7 +200,6 @@ auto Interface::group(uint id) -> uint {
|
|||
case ID::SuperGameBoyBootROM:
|
||||
case ID::MCCROM:
|
||||
case ID::MCCRAM:
|
||||
case ID::MCCPSRAM:
|
||||
return 1;
|
||||
case ID::SuperGameBoy:
|
||||
case ID::SuperGameBoyManifest:
|
||||
|
@ -327,7 +330,6 @@ auto Interface::load(uint id, const stream& stream) -> void {
|
|||
|
||||
if(id == ID::MCCROM) mcc.rom.read(stream);
|
||||
if(id == ID::MCCRAM) mcc.ram.read(stream);
|
||||
if(id == ID::MCCPSRAM) mcc.psram.read(stream);
|
||||
|
||||
if(id == ID::SuperGameBoyManifest) cartridge.information.markup.gameBoy = stream.text();
|
||||
|
||||
|
@ -393,7 +395,6 @@ auto Interface::save(uint id, const stream& stream) -> void {
|
|||
if(id == ID::SuperGameBoyRAM) stream.write(GameBoy::cartridge.ramdata, GameBoy::cartridge.ramsize);
|
||||
|
||||
if(id == ID::MCCRAM) stream.write(mcc.ram.data(), mcc.ram.size());
|
||||
if(id == ID::MCCPSRAM) stream.write(mcc.psram.data(), mcc.psram.size());
|
||||
|
||||
if(id == ID::SufamiTurboSlotARAM) stream.write(sufamiturboA.ram.data(), sufamiturboA.ram.size());
|
||||
if(id == ID::SufamiTurboSlotBRAM) stream.write(sufamiturboB.ram.data(), sufamiturboB.ram.size());
|
||||
|
|
|
@ -66,7 +66,6 @@ struct ID {
|
|||
|
||||
MCCROM,
|
||||
MCCRAM,
|
||||
MCCPSRAM,
|
||||
|
||||
SuperGameBoyManifest,
|
||||
SuperGameBoyROM,
|
||||
|
@ -93,6 +92,7 @@ struct ID {
|
|||
struct Interface : Emulator::Interface {
|
||||
Interface();
|
||||
|
||||
auto manifest() -> string;
|
||||
auto title() -> string;
|
||||
auto videoFrequency() -> double;
|
||||
auto audioFrequency() -> double;
|
||||
|
|
|
@ -103,6 +103,7 @@ Presentation::Presentation() {
|
|||
loadSlot5.setText("Slot 5").onActivate([&] { program->loadState(5); });
|
||||
cheatEditor.setText("Cheat Editor").onActivate([&] { toolsManager->show(0); });
|
||||
stateManager.setText("State Manager").onActivate([&] { toolsManager->show(1); });
|
||||
manifestViewer.setText("Manifest Viewer").onActivate([&] { toolsManager->show(2); });
|
||||
|
||||
statusBar.setFont(Font().setBold());
|
||||
statusBar.setVisible(settings["UserInterface/ShowStatusBar"].boolean());
|
||||
|
|
|
@ -59,6 +59,7 @@ struct Presentation : Window {
|
|||
MenuSeparator toolsMenuSeparator{&toolsMenu};
|
||||
MenuItem cheatEditor{&toolsMenu};
|
||||
MenuItem stateManager{&toolsMenu};
|
||||
MenuItem manifestViewer{&toolsMenu};
|
||||
|
||||
FixedLayout layout{this};
|
||||
Viewport viewport{&layout, Geometry{0, 0, 1, 1}};
|
||||
|
|
|
@ -33,6 +33,7 @@ auto Program::loadMedia(Emulator::Interface& emulator_, Emulator::Interface::Med
|
|||
presentation->updateEmulator();
|
||||
toolsManager->cheatEditor.loadCheats();
|
||||
toolsManager->stateManager.doRefresh();
|
||||
toolsManager->manifestViewer.doRefresh();
|
||||
}
|
||||
|
||||
auto Program::unloadMedia() -> void {
|
||||
|
|
|
@ -0,0 +1,12 @@
|
|||
ManifestViewer::ManifestViewer(TabFrame* parent) : TabFrameItem(parent) {
|
||||
setImage(Icon::Emblem::Text);
|
||||
setText("Manifest Viewer");
|
||||
|
||||
layout.setMargin(5);
|
||||
manifestView.setEditable(false).setFont(Font().setFamily(Font::Mono));
|
||||
}
|
||||
|
||||
auto ManifestViewer::doRefresh() -> void {
|
||||
manifestView.setText("");
|
||||
if(emulator) manifestView.setText(emulator->manifest());
|
||||
}
|
|
@ -2,8 +2,10 @@
|
|||
#include "cheat-database.cpp"
|
||||
#include "cheat-editor.cpp"
|
||||
#include "state-manager.cpp"
|
||||
#include "manifest-viewer.cpp"
|
||||
CheatDatabase* cheatDatabase = nullptr;
|
||||
ToolsManager* toolsManager = nullptr;
|
||||
ManifestViewer* manifestViewer = nullptr;
|
||||
|
||||
ToolsManager::ToolsManager() {
|
||||
toolsManager = this;
|
||||
|
|
|
@ -76,6 +76,14 @@ struct StateManager : TabFrameItem {
|
|||
Button eraseButton{&controlLayout, Size{80, 0}};
|
||||
};
|
||||
|
||||
struct ManifestViewer : TabFrameItem {
|
||||
ManifestViewer(TabFrame*);
|
||||
auto doRefresh() -> void;
|
||||
|
||||
VerticalLayout layout{this};
|
||||
TextEdit manifestView{&layout, Size{~0, ~0}};
|
||||
};
|
||||
|
||||
struct ToolsManager : Window {
|
||||
ToolsManager();
|
||||
auto show(unsigned tool) -> void;
|
||||
|
@ -84,6 +92,7 @@ struct ToolsManager : Window {
|
|||
TabFrame panel{&layout, Size{~0, ~0}};
|
||||
CheatEditor cheatEditor{&panel};
|
||||
StateManager stateManager{&panel};
|
||||
ManifestViewer manifestViewer{&panel};
|
||||
};
|
||||
|
||||
extern CheatDatabase* cheatDatabase;
|
||||
|
|
Loading…
Reference in New Issue