From 21f9fe4cd50fef725315f4944475adf44925aee3 Mon Sep 17 00:00:00 2001 From: Tim Allen Date: Tue, 4 Oct 2011 22:55:39 +1100 Subject: [PATCH] Update to v082r29 release. byuu says: I doubt anyone is going to like these changes, but oh well. The base height output for NES+SNES is now always 256x240. The Enable Overscan option blanks out borders around the screen. This eliminates the need for an overscan software filter. For NES, it's 16px from the top and bottom, and 8px from the left and right. Anything less and you get scrolling artifacts in countless games. For the SNES, it's only 16px from the top and bottom. Main point is that most NTSC SNES games are 224-height games, so you'll have black borders. Oh well, hack the source if you want. Game Boy overscan option does nothing. Everything except for the cheats.xml file now uses BML markup. I need to write a converter for cheats.xml still. Cut the SNES board parsing code in half, 30KB->16KB. Much cleaner now. Took the opportunity to fix a mistake I made back with the XML spec: all numbers are integers, but can be prefixed with 0x to become hexadecimal. Before, offset/size values defaulted to hex-mode even without a prefix, unlike frequency/etc values. The XML shaders have gone in their own direction anyway, with most being multi-pass and incompatible with bsnes. So that said, please don't extend the BML functionality from your end. But f eel free to add to the XML spec, since other emulators now use that as well. And don't misunderstand, I love the work that's being done there. It's pretty awesome to see multi-pass shader capabilities, and the RAM watching stuff is just amazing. If there are any really awesome single-pass shaders that people would like, I can convert it from XML and include it with future releases. On that topic, I removed the watercolor/hdr-tv ones from the binary packages (still in the source archive) ... they are neat, but not very useful for actual gaming. If we had more than one, I'd remove the Direct3D sepia one. Not going to use shaders from a certain bipolar manic, because I'd never hear the end of it if I did :/ Oh, one change I think people will like: MSU1 no longer requires a memory map specification, so MSU1 authors won't have to keep updating to my newer revisions of board markups. Basically, if there's not a board with an msu1 section, it'll check if "gamename.msu" exists. If it does, MSU1 gets mapped to 00-3f,80-bf:2000-2007. If all you want is music, make a blank, zero-byte gamename.msu file. --- bsnes/gameboy/cartridge/cartridge.cpp | 50 +- bsnes/gameboy/cartridge/cartridge.hpp | 2 +- bsnes/gameboy/interface/interface.cpp | 4 +- bsnes/gameboy/interface/interface.hpp | 2 +- bsnes/nall/gameboy/cartridge.hpp | 19 +- bsnes/nall/snes/cartridge.hpp | 598 +++++++++----------- bsnes/nall/string/bml.hpp | 171 +++--- bsnes/nes/cartridge/board/board.cpp | 2 +- bsnes/nes/cartridge/ines.cpp | 46 +- bsnes/ruby/video/direct3d.cpp | 26 +- bsnes/ruby/video/opengl.hpp | 28 +- bsnes/snes/cartridge/cartridge.cpp | 8 +- bsnes/snes/cartridge/cartridge.hpp | 50 +- bsnes/snes/cartridge/markup.cpp | 557 +++++++++++++++++++ bsnes/snes/cartridge/xml.cpp | 765 -------------------------- bsnes/snes/interface/interface.cpp | 12 +- bsnes/snes/interface/interface.hpp | 2 +- bsnes/ui/interface/gameboy.cpp | 2 +- bsnes/ui/interface/nes.cpp | 22 +- bsnes/ui/interface/snes.cpp | 70 +-- bsnes/ui/main.cpp | 2 +- bsnes/ui/tools/cheat-editor.cpp | 8 +- bsnes/ui/utility/utility.cpp | 6 +- 23 files changed, 1038 insertions(+), 1414 deletions(-) create mode 100755 bsnes/snes/cartridge/markup.cpp delete mode 100755 bsnes/snes/cartridge/xml.cpp diff --git a/bsnes/gameboy/cartridge/cartridge.cpp b/bsnes/gameboy/cartridge/cartridge.cpp index 21ee755f..7edc50da 100755 --- a/bsnes/gameboy/cartridge/cartridge.cpp +++ b/bsnes/gameboy/cartridge/cartridge.cpp @@ -16,7 +16,7 @@ namespace GameBoy { #include "serialization.cpp" Cartridge cartridge; -void Cartridge::load(const string &xml, const uint8_t *data, unsigned size) { +void Cartridge::load(const string &markup, const uint8_t *data, unsigned size) { if(size == 0) size = 32768; romdata = allocate(romsize = size, 0xff); if(data) memcpy(romdata, data, size); @@ -33,42 +33,24 @@ void Cartridge::load(const string &xml, const uint8_t *data, unsigned size) { info.romsize = 0; info.ramsize = 0; - xml_element document = xml_parse(xml); - for(auto &head : document.element) { - if(head.name == "cartridge") { - for(auto &attr : head.attribute) { - if(attr.name == "mapper") { - if(attr.content == "none") info.mapper = Mapper::MBC0; - if(attr.content == "MBC1") info.mapper = Mapper::MBC1; - if(attr.content == "MBC2") info.mapper = Mapper::MBC2; - if(attr.content == "MBC3") info.mapper = Mapper::MBC3; - if(attr.content == "MBC5") info.mapper = Mapper::MBC5; - if(attr.content == "MMM01") info.mapper = Mapper::MMM01; - if(attr.content == "HuC1") info.mapper = Mapper::HuC1; - if(attr.content == "HuC3") info.mapper = Mapper::HuC3; - } + BML::Document document(markup); - if(attr.name == "rtc") info.rtc = (attr.content == "true" ? true : false); - if(attr.name == "rumble") info.rumble = (attr.content == "true" ? true : false); - } + auto &mapperid = document["cartridge"]["mapper"].value; + if(mapperid == "none" ) info.mapper = Mapper::MBC0; + if(mapperid == "MBC1" ) info.mapper = Mapper::MBC1; + if(mapperid == "MBC2" ) info.mapper = Mapper::MBC2; + if(mapperid == "MBC3" ) info.mapper = Mapper::MBC3; + if(mapperid == "MBC5" ) info.mapper = Mapper::MBC5; + if(mapperid == "MMM01") info.mapper = Mapper::MMM01; + if(mapperid == "HuC1" ) info.mapper = Mapper::HuC1; + if(mapperid == "HuC3" ) info.mapper = Mapper::HuC3; - for(auto &elem : head.element) { - if(elem.name == "rom") { - for(auto &attr : elem.attribute) { - if(attr.name == "size") info.romsize = hex(attr.content); - } - } + info.rtc = document["cartridge"]["rtc"].exists(); + info.rumble = document["cartridge"]["rumble"].exists(); - if(elem.name == "ram") { - info.ram = true; - for(auto &attr : elem.attribute) { - if(attr.name == "size") info.ramsize = hex(attr.content); - if(attr.name == "battery") info.battery = (attr.content == "true" ? true : false); - } - } - } - } - } + info.romsize = hex(document["cartridge"]["rom"]["size"].value); + info.ramsize = hex(document["cartridge"]["ram"]["size"].value); + info.battery = document["cartridge"]["ram"]["non-volatile"].exists(); switch(info.mapper) { default: case Mapper::MBC0: mapper = &mbc0; break; diff --git a/bsnes/gameboy/cartridge/cartridge.hpp b/bsnes/gameboy/cartridge/cartridge.hpp index 8508814b..00b5b613 100755 --- a/bsnes/gameboy/cartridge/cartridge.hpp +++ b/bsnes/gameboy/cartridge/cartridge.hpp @@ -45,7 +45,7 @@ struct Cartridge : MMIO, property { MMIO *mapper; bool bootrom_enable; - void load(const string &xml, const uint8_t *data, unsigned size); + void load(const string &markup, const uint8_t *data, unsigned size); void unload(); uint8 rom_read(unsigned addr); diff --git a/bsnes/gameboy/interface/interface.cpp b/bsnes/gameboy/interface/interface.cpp index 4d2d0243..4222da49 100755 --- a/bsnes/gameboy/interface/interface.cpp +++ b/bsnes/gameboy/interface/interface.cpp @@ -29,8 +29,8 @@ bool Interface::cartridgeLoaded() { return cartridge.loaded(); } -void Interface::loadCartridge(const string &xml, const uint8_t *data, unsigned size) { - cartridge.load(xml, data, size); +void Interface::loadCartridge(const string &markup, const uint8_t *data, unsigned size) { + cartridge.load(markup, data, size); system.power(); } diff --git a/bsnes/gameboy/interface/interface.hpp b/bsnes/gameboy/interface/interface.hpp index 0d79aa5a..7e2400b1 100755 --- a/bsnes/gameboy/interface/interface.hpp +++ b/bsnes/gameboy/interface/interface.hpp @@ -10,7 +10,7 @@ public: virtual void initialize(Interface*); virtual bool cartridgeLoaded(); - virtual void loadCartridge(const string &xml, const uint8_t *data, unsigned size); + virtual void loadCartridge(const string &markup, const uint8_t *data, unsigned size); virtual void unloadCartridge(); enum class Memory : unsigned { diff --git a/bsnes/nall/gameboy/cartridge.hpp b/bsnes/nall/gameboy/cartridge.hpp index af04e0bb..19ff065d 100755 --- a/bsnes/nall/gameboy/cartridge.hpp +++ b/bsnes/nall/gameboy/cartridge.hpp @@ -5,7 +5,7 @@ namespace nall { class GameBoyCartridge { public: - string xml; + string markup; inline GameBoyCartridge(uint8_t *data, unsigned size); //private: @@ -22,7 +22,7 @@ public: }; GameBoyCartridge::GameBoyCartridge(uint8_t *romdata, unsigned romsize) { - xml = "\n"; + markup = ""; if(romsize < 0x4000) return; info.mapper = "unknown"; @@ -100,18 +100,15 @@ GameBoyCartridge::GameBoyCartridge(uint8_t *romdata, unsigned romsize) { if(info.mapper == "MBC2") info.ramsize = 512; //512 x 4-bit - xml.append("\n"); + markup.append("cartridge mapper=", info.mapper); + if(info.rtc) markup.append(" rtc"); + if(info.rumble) markup.append(" rumble"); + markup.append("\n"); - xml.append(" \n"); //TODO: trust/check info.romsize? + markup.append("\t" "rom size=", hex(romsize), "\n"); //TODO: trust/check info.romsize? if(info.ramsize > 0) - xml.append(" \n"); - - xml.append("\n"); - xml.transform("'", "\""); + markup.append("\t" "ram size=", hex(info.ramsize), info.battery ? " non-volatile\n" : "\n"); } } diff --git a/bsnes/nall/snes/cartridge.hpp b/bsnes/nall/snes/cartridge.hpp index 6847ba3a..cac3fb1a 100755 --- a/bsnes/nall/snes/cartridge.hpp +++ b/bsnes/nall/snes/cartridge.hpp @@ -3,10 +3,10 @@ namespace nall { -class SNESCartridge { +class SnesCartridge { public: - string xmlMemoryMap; - inline SNESCartridge(const uint8_t *data, unsigned size); + string markup; + inline SnesCartridge(const uint8_t *data, unsigned size); //private: inline void read_header(const uint8_t *data, unsigned size); @@ -105,436 +105,346 @@ public: bool has_st018; }; -SNESCartridge::SNESCartridge(const uint8_t *data, unsigned size) { +#define T "\t" + +SnesCartridge::SnesCartridge(const uint8_t *data, unsigned size) { read_header(data, size); - string xml = "\n"; + string xml; + markup = ""; if(type == TypeBsx) { - xml.append(""); - xmlMemoryMap = xml.transform("'", "\""); + markup.append("cartridge"); return; } if(type == TypeSufamiTurbo) { - xml.append(""); - xmlMemoryMap = xml.transform("'", "\""); + markup.append("cartridge"); return; } if(type == TypeGameBoy) { - xml.append("\n"); + markup.append("cartridge rtc=", gameboy_has_rtc(data, size), "\n"); if(gameboy_ram_size(data, size) > 0) { - xml.append(" \n"); + markup.append(T "ram size=0x", hex(gameboy_ram_size(data, size)), "\n"); } - xml.append("\n"); - xmlMemoryMap = xml.transform("'", "\""); return; } - xml.append("\n"); + markup.append("cartridge region=", region == NTSC ? "NTSC\n" : "PAL\n"); if(type == TypeSuperGameBoy1Bios) { - xml.append(" \n"); - xml.append(" \n"); - xml.append(" \n"); - xml.append(" \n"); - xml.append(" \n"); - xml.append(" \n"); - xml.append(" \n"); - xml.append(" \n"); + markup.append(T "rom\n"); + markup.append(T T "map mode=linear address=00-7f:8000-ffff\n"); + markup.append(T T "map mode=linear address=80-ff:8000-ffff\n"); + markup.append(T "icd2 revision=1\n"); + markup.append(T T "map address=00-3f:6000-7fff\n"); + markup.append(T T "map address=80-bf:6000-7fff\n"); } else if(type == TypeSuperGameBoy2Bios) { - xml.append(" \n"); - xml.append(" \n"); - xml.append(" \n"); - xml.append(" \n"); - xml.append(" \n"); - xml.append(" \n"); - xml.append(" \n"); - xml.append(" \n"); + markup.append(T "rom\n"); + markup.append(T T "map mode=linear address=00-7f:8000-ffff\n"); + markup.append(T T "map mode=linear address=80-ff:8000-ffff\n"); + markup.append(T "icd2 revision=1\n"); + markup.append(T T "map address=00-3f:6000-7fff\n"); + markup.append(T T "map address=80-bf:6000-7fff\n"); } else if(has_cx4) { - xml.append(" \n"); - xml.append(" \n"); - xml.append(" \n"); - xml.append(" \n"); - xml.append(" \n"); - xml.append(" \n"); - xml.append(" \n"); - xml.append(" \n"); - xml.append(" \n"); - xml.append(" \n"); + markup.append(T "hitachidsp model=HG51B169 frequency=20000000 firmware=cx4.bin sha256=ae8d4d1961b93421ff00b3caa1d0f0ce7783e749772a3369c36b3dbf0d37ef18\n"); + markup.append(T T "rom\n"); + markup.append(T T T "map mode=linear address=00-7f:8000-ffff\n"); + markup.append(T T T "map mode=linear address=80-ff:8000-ffff\n"); + markup.append(T T "mmio\n"); + markup.append(T T T "map address=00-3f:6000-7fff\n"); + markup.append(T T T "map address=80-bf:6000-7fff\n"); } else if(has_spc7110) { - xml.append(" \n"); - xml.append(" \n"); - xml.append(" \n"); - xml.append(" \n"); - xml.append(" \n"); + markup.append(T "rom\n"); + markup.append(T T "map mode=shadow address=00-0f:8000-ffff\n"); + markup.append(T T "map mode=shadow address=80-bf:8000-ffff\n"); + markup.append(T T "map mode=linear address=c0-cf:0000-ffff\n"); - xml.append(" \n"); - xml.append(" \n"); - xml.append(" \n"); - xml.append(" \n"); - xml.append(" \n"); - xml.append(" \n"); - xml.append(" \n"); - xml.append(" \n"); - xml.append(" \n"); - xml.append(" \n"); - xml.append(" \n"); - xml.append(" \n"); + markup.append(T "spc7110\n"); + markup.append(T T "mcu\n"); + markup.append(T T T "map address=d0-ff:0000-ffff offset=0x100000 size=0x", hex(size - 0x100000), "\n"); + markup.append(T T "ram size=0x", hex(ram_size), "\n"); + markup.append(T T T "map mode=linear address=00:6000-7fff\n"); + markup.append(T T T "map mode=linear address=30:6000-7fff\n"); + markup.append(T T "mmio\n"); + markup.append(T T T "map address=00-3f:4800-483f\n"); + markup.append(T T T "map address=80-bf:4800-483f\n"); if(has_spc7110rtc) { - xml.append(" \n"); - xml.append(" \n"); - xml.append(" \n"); - xml.append(" \n"); + markup.append(T T "rtc\n"); + markup.append(T T T "map address=00-3f:4840-4842\n"); + markup.append(T T T "map address=80-bf:4840-4842\n"); } - xml.append(" \n"); - xml.append(" \n"); - xml.append(" \n"); - xml.append(" \n"); + markup.append(T T "dcu\n"); + markup.append(T T T "map address=50:0000-ffff\n"); } else if(mapper == LoROM) { - xml.append(" \n"); - xml.append(" \n"); - xml.append(" \n"); - xml.append(" \n"); + markup.append(T "rom\n"); + markup.append(T T "map mode=linear address=00-7f:8000-ffff\n"); + markup.append(T T "map mode=linear address=80-ff:8000-ffff\n"); if(ram_size > 0) { - xml.append(" \n"); - xml.append(" \n"); - xml.append(" \n"); + markup.append(T "ram size=0x", hex(ram_size), "\n"); + markup.append(T T "map mode=linear address=20-3f:6000-7fff\n"); + markup.append(T T "map mode=linear address=a0-bf:6000-7fff\n"); if((rom_size > 0x200000) || (ram_size > 32 * 1024)) { - xml.append(" \n"); - xml.append(" \n"); + markup.append(T T "map mode=linear address=70-7f:0000-7fff\n"); + markup.append(T T "map mode=linear address=f0-ff:0000-7fff\n"); } else { - xml.append(" \n"); - xml.append(" \n"); + markup.append(T T "map mode=linear address=70-7f:0000-ffff\n"); + markup.append(T T "map mode=linear address=f0-ff:0000-ffff\n"); } - xml.append(" \n"); } } else if(mapper == HiROM) { - xml.append(" \n"); - xml.append(" \n"); - xml.append(" \n"); - xml.append(" \n"); - xml.append(" \n"); - xml.append(" \n"); + markup.append(T "rom\n"); + markup.append(T T "map mode=shadow address=00-3f:8000-ffff\n"); + markup.append(T T "map mode=linear address=40-7f:0000-ffff\n"); + markup.append(T T "map mode=shadow address=80-bf:8000-ffff\n"); + markup.append(T T "map mode=linear address=c0-ff:0000-ffff\n"); if(ram_size > 0) { - xml.append(" \n"); - xml.append(" \n"); - xml.append(" \n"); + markup.append(T "ram size=0x", hex(ram_size), "\n"); + markup.append(T T "map mode=linear address=20-3f:6000-7fff\n"); + markup.append(T T "map mode=linear address=a0-bf:6000-7fff\n"); if((rom_size > 0x200000) || (ram_size > 32 * 1024)) { - xml.append(" \n"); + markup.append(T T "map mode=linear address=70-7f:0000-7fff\n"); } else { - xml.append(" \n"); + markup.append(T T "map mode=linear address=70-7f:0000-ffff\n"); } - xml.append(" \n"); } } else if(mapper == ExLoROM) { - xml.append(" \n"); - xml.append(" \n"); - xml.append(" \n"); - xml.append(" \n"); - xml.append(" \n"); + markup.append(T "rom\n"); + markup.append(T T "map mode=linear address=00-3f:8000-ffff\n"); + markup.append(T T "map mode=linear address=40-7f:0000-ffff\n"); + markup.append(T T "map mode=linear address=80-bf:8000-ffff\n"); if(ram_size > 0) { - xml.append(" \n"); - xml.append(" \n"); - xml.append(" \n"); - xml.append(" \n"); - xml.append(" \n"); + markup.append(T "ram size=0x", hex(ram_size), "\n"); + markup.append(T T "map mode=linear address=20-3f:6000-7fff\n"); + markup.append(T T "map mode=linear address=a0-bf:6000-7fff\n"); + markup.append(T T "map mode=linear address=70-7f:0000-7fff\n"); } } else if(mapper == ExHiROM) { - xml.append(" \n"); - xml.append(" \n"); - xml.append(" \n"); - xml.append(" \n"); - xml.append(" \n"); - xml.append(" \n"); + markup.append(T "rom\n"); + markup.append(T T "map mode=shadow address=00-3f:8000-ffff offset=0x400000\n"); + markup.append(T T "map mode=linear address=40-7f:0000-ffff offset=0x400000\n"); + markup.append(T T "map mode=shadow address=80-bf:8000-ffff offset=0x000000\n"); + markup.append(T T "map mode=linear address=c0-ff:0000-ffff offset=0x000000\n"); if(ram_size > 0) { - xml.append(" \n"); - xml.append(" \n"); - xml.append(" \n"); + markup.append(T "ram size=0x", hex(ram_size), "\n"); + markup.append(T T "map mode=linear address=20-3f:6000-7fff\n"); + markup.append(T T "map mode=linear address=a0-bf:6000-7fff\n"); if((rom_size > 0x200000) || (ram_size > 32 * 1024)) { - xml.append(" \n"); + markup.append(T T "map mode=linear address=70-7f:0000-7fff\n"); } else { - xml.append(" \n"); + markup.append(T T "map mode=linear address=70-7f:0000-ffff\n"); } - xml.append(" \n"); } } else if(mapper == SuperFXROM) { - xml.append(" \n"); - xml.append(" \n"); - xml.append(" \n"); - xml.append(" \n"); - xml.append(" \n"); - xml.append(" \n"); - xml.append(" \n"); - xml.append(" \n"); - xml.append(" \n"); - xml.append(" \n"); - xml.append(" \n"); - xml.append(" \n"); - xml.append(" \n"); - xml.append(" \n"); - xml.append(" \n"); - xml.append(" \n"); - xml.append(" \n"); - xml.append(" \n"); + markup.append(T "superfx revision=2\n"); + markup.append(T T "rom\n"); + markup.append(T T T "map mode=linear address=00-3f:8000-ffff\n"); + markup.append(T T T "map mode=linear address=40-5f:0000-ffff\n"); + markup.append(T T T "map mode=linear address=80-bf:8000-ffff\n"); + markup.append(T T T "map mode=linear address=c0-df:0000-ffff\n"); + markup.append(T T "ram size=0x", hex(ram_size), "\n"); + markup.append(T T T "map mode=linear address=00-3f:6000-7fff size=0x2000\n"); + markup.append(T T T "map mode=linear address=60-7f:0000-ffff\n"); + markup.append(T T T "map mode=linear address=80-bf:6000-7fff size=0x2000\n"); + markup.append(T T T "map mode=linear address=e0-ff:0000-ffff\n"); + markup.append(T T "mmio\n"); + markup.append(T T T "map address=00-3f:3000-32ff\n"); + markup.append(T T T "map address=80-bf:3000-32ff\n"); } else if(mapper == SA1ROM) { - xml.append(" \n"); - xml.append(" \n"); - xml.append(" \n"); - xml.append(" \n"); - xml.append(" \n"); - xml.append(" \n"); - xml.append(" \n"); - xml.append(" \n"); - xml.append(" \n"); - xml.append(" \n"); - xml.append(" \n"); - xml.append(" \n"); - xml.append(" \n"); - xml.append(" \n"); - xml.append(" \n"); - xml.append(" \n"); - xml.append(" \n"); - xml.append(" \n"); - xml.append(" \n"); - xml.append(" \n"); - xml.append(" \n"); - xml.append(" \n"); - xml.append(" \n"); - xml.append(" \n"); + markup.append(T "sa1\n"); + markup.append(T T "mcu\n"); + markup.append(T T T "rom\n"); + markup.append(T T T T "map mode=direct address=00-3f:8000-ffff\n"); + markup.append(T T T T "map mode=direct address=80-bf:8000-ffff\n"); + markup.append(T T T T "map mode=direct address=c0-ff:0000-ffff\n"); + markup.append(T T T "ram\n"); + markup.append(T T T T "map mode=direct address=00-3f:6000-7fff\n"); + markup.append(T T T T "map mode=direct address=80-bf:6000-7fff\n"); + markup.append(T T "iram size=0x800\n"); + markup.append(T T T "map mode=linear address=00-3f:3000-37ff\n"); + markup.append(T T T "map mode=linear address=80-bf:3000-37ff\n"); + markup.append(T T "bwram size=0x", hex(ram_size), "\n"); + markup.append(T T T "map mode=linear address=40-4f:0000-ffff\n"); + markup.append(T T "mmio\n"); + markup.append(T T T "map address=00-3f:2200-23ff\n"); + markup.append(T T T "map address=80-bf:2200-23ff\n"); } else if(mapper == BSCLoROM) { - xml.append(" \n"); - xml.append(" \n"); - xml.append(" \n"); - xml.append(" \n"); - xml.append(" \n"); - xml.append(" \n"); - xml.append(" \n"); - xml.append(" \n"); - xml.append(" \n"); - xml.append(" \n"); - xml.append(" \n"); - xml.append(" \n"); - xml.append(" \n"); - xml.append(" \n"); - xml.append(" \n"); + markup.append(T "rom\n"); + markup.append(T T "map mode=linear address=00-1f:8000-ffff offset=0x000000\n"); + markup.append(T T "map mode=linear address=20-3f:8000-ffff offset=0x100000\n"); + markup.append(T T "map mode=linear address=80-9f:8000-ffff offset=0x200000\n"); + markup.append(T T "map mode=linear address=a0-bf:8000-ffff offset=0x100000\n"); + markup.append(T "ram size=0x", hex(ram_size), "\n"); + markup.append(T T "map mode=linear address=70-7f:0000-7fff\n"); + markup.append(T T "map mode=linear address=f0-ff:0000-7fff\n"); + markup.append(T "bsx\n"); + markup.append(T T "slot\n"); + markup.append(T T T "map mode=linear address=c0-ef:0000-ffff\n"); } else if(mapper == BSCHiROM) { - xml.append(" \n"); - xml.append(" \n"); - xml.append(" \n"); - xml.append(" \n"); - xml.append(" \n"); - xml.append(" \n"); - xml.append(" \n"); - xml.append(" \n"); - xml.append(" \n"); - xml.append(" \n"); - xml.append(" \n"); - xml.append(" \n"); - xml.append(" \n"); - xml.append(" \n"); - xml.append(" \n"); - xml.append(" \n"); - xml.append(" \n"); - xml.append(" \n"); + markup.append(T "rom\n"); + markup.append(T T "map mode=shadow address=00-1f:8000-ffff\n"); + markup.append(T T "map mode=linear address=40-5f:0000-ffff\n"); + markup.append(T T "map mode=shadow address=80-9f:8000-ffff\n"); + markup.append(T T "map mode=linear address=c0-df:0000-ffff\n"); + markup.append(T "ram size=0x", hex(ram_size), "\n"); + markup.append(T T "map mode=linear address=20-3f:6000-7fff\n"); + markup.append(T T "map mode=linear address=a0-bf:6000-7fff\n"); + markup.append(T "bsx\n"); + markup.append(T T "slot\n"); + markup.append(T T T "map mode=shadow address=20-3f:8000-ffff\n"); + markup.append(T T T "map mode=linear address=60-7f:0000-ffff\n"); + markup.append(T T T "map mode=shadow address=a0-bf:8000-ffff\n"); + markup.append(T T T "map mode=linear address=e0-ff:0000-ffff\n"); } else if(mapper == BSXROM) { - xml.append(" \n"); - xml.append(" \n"); - xml.append(" \n"); - xml.append(" \n"); - xml.append(" \n"); - xml.append(" \n"); - xml.append(" \n"); - xml.append(" \n"); - xml.append(" \n"); - xml.append(" \n"); - xml.append(" \n"); - xml.append(" \n"); - xml.append(" \n"); + markup.append(T "bsx\n"); + markup.append(T T "mcu\n"); + markup.append(T T T "map address=00-3f:8000-ffff\n"); + markup.append(T T T "map address=80-bf:8000-ffff\n"); + markup.append(T T T "map address=40-7f:0000-ffff\n"); + markup.append(T T T "map address=c0-ff:0000-ffff\n"); + markup.append(T T T "map address=20-3f:6000-7fff\n"); + markup.append(T T "mmio\n"); + markup.append(T T T "map address=00-3f:5000-5fff\n"); + markup.append(T T T "map address=80-bf:5000-5fff\n"); } else if(mapper == STROM) { - xml.append(" \n"); - xml.append(" \n"); - xml.append(" \n"); - xml.append(" \n"); - xml.append(" \n"); - xml.append(" \n"); - xml.append(" \n"); - xml.append(" \n"); - xml.append(" \n"); - xml.append(" \n"); - xml.append(" \n"); - xml.append(" \n"); - xml.append(" \n"); - xml.append(" \n"); - xml.append(" \n"); - xml.append(" \n"); - xml.append(" \n"); - xml.append(" \n"); - xml.append(" \n"); - xml.append(" \n"); - xml.append(" \n"); - xml.append(" \n"); - xml.append(" \n"); - xml.append(" \n"); - xml.append(" \n"); - xml.append(" \n"); + markup.append(T "rom\n"); + markup.append(T T "map mode=linear address=00-1f:8000-ffff\n"); + markup.append(T T "map mode=linear address=80-9f:8000-ffff\n"); + markup.append(T "sufamiturbo\n"); + markup.append(T T "slot id=A\n"); + markup.append(T T T "rom\n"); + markup.append(T T T T "map mode=linear address=20-3f:8000-ffff\n"); + markup.append(T T T T "map mode=linear address=a0-bf:8000-ffff\n"); + markup.append(T T T "ram size=0x20000\n"); + markup.append(T T T T "map mode=linear address=60-63:8000-ffff\n"); + markup.append(T T T T "map mode=linear address=e0-e3:8000-ffff\n"); + markup.append(T T "slot id=B\n"); + markup.append(T T T "rom\n"); + markup.append(T T T T "map mode=linear address=40-5f:8000-ffff\n"); + markup.append(T T T T "map mode=linear address=c0-df:8000-ffff\n"); + markup.append(T T T "ram size=0x20000\n"); + markup.append(T T T T "map mode=linear address=70-73:8000-ffff\n"); + markup.append(T T T T "map mode=linear address=f0-f3:8000-ffff\n"); } if(has_srtc) { - xml.append(" \n"); - xml.append(" \n"); - xml.append(" \n"); - xml.append(" \n"); + markup.append(T "srtc\n"); + markup.append(T T "map address=00-3f:2800-2801\n"); + markup.append(T T "map address=80-bf:2800-2801\n"); } if(has_sdd1) { - xml.append(" \n"); - xml.append(" \n"); - xml.append(" \n"); - xml.append(" \n"); - xml.append(" \n"); - xml.append(" \n"); - xml.append(" \n"); - xml.append(" \n"); - xml.append(" \n"); + markup.append(T "sdd1\n"); + markup.append(T T "mcu\n"); + markup.append(T T T "map address=c0-ff:0000-ffff\n"); + markup.append(T T "mmio\n"); + markup.append(T T T "map address=00-3f:4800-4807\n"); + markup.append(T T T "map address=80-bf:4800-4807\n"); } if(has_dsp1) { - xml.append(" \n"); + markup.append(T "necdsp model=uPD7725 frequency=8000000 firmware=dsp1b.bin sha256=4d42db0f36faef263d6b93f508e8c1c4ae8fc2605fd35e3390ecc02905cd420c\n"); if(dsp1_mapper == DSP1LoROM1MB) { - xml.append(" \n"); - xml.append(" \n"); - xml.append(" \n"); - xml.append(" \n"); - xml.append(" \n"); - xml.append(" \n"); - xml.append(" \n"); - xml.append(" \n"); + markup.append(T T "dr\n"); + markup.append(T T T "map address=20-3f:8000-bfff\n"); + markup.append(T T T "map address=a0-bf:8000-bfff\n"); + markup.append(T T "sr\n"); + markup.append(T T T "map address=20-3f:c000-ffff\n"); + markup.append(T T T "map address=a0-bf:c000-ffff\n"); } else if(dsp1_mapper == DSP1LoROM2MB) { - xml.append(" \n"); - xml.append(" \n"); - xml.append(" \n"); - xml.append(" \n"); - xml.append(" \n"); - xml.append(" \n"); - xml.append(" \n"); - xml.append(" \n"); + markup.append(T T "dr\n"); + markup.append(T T T "map address=60-6f:0000-3fff\n"); + markup.append(T T T "map address=e0-ef:0000-3fff\n"); + markup.append(T T "sr\n"); + markup.append(T T T "map address=60-6f:4000-7fff\n"); + markup.append(T T T "map address=e0-ef:4000-7fff\n"); } else if(dsp1_mapper == DSP1HiROM) { - xml.append(" \n"); - xml.append(" \n"); - xml.append(" \n"); - xml.append(" \n"); - xml.append(" \n"); - xml.append(" \n"); - xml.append(" \n"); - xml.append(" \n"); + markup.append(T T "dr\n"); + markup.append(T T T "map address=00-1f:6000-6fff\n"); + markup.append(T T T "map address=80-9f:6000-6fff\n"); + markup.append(T T "sr\n"); + markup.append(T T T "map address=00-1f:7000-7fff\n"); + markup.append(T T T "map address=80-9f:7000-7fff\n"); } - xml.append(" \n"); } if(has_dsp2) { - xml.append(" \n"); - xml.append(" \n"); - xml.append(" \n"); - xml.append(" \n"); - xml.append(" \n"); - xml.append(" \n"); - xml.append(" \n"); - xml.append(" \n"); - xml.append(" \n"); - xml.append(" \n"); + markup.append(T "necdsp model=uPD7725 frequency=8000000 firmware=dsp2.bin sha256=5efbdf96ed0652790855225964f3e90e6a4d466cfa64df25b110933c6cf94ea1\n"); + markup.append(T T "dr\n"); + markup.append(T T T "map address=20-3f:8000-bfff\n"); + markup.append(T T T "map address=a0-bf:8000-bfff\n"); + markup.append(T T "sr\n"); + markup.append(T T T "map address=20-3f:c000-ffff\n"); + markup.append(T T T "map address=a0-bf:c000-ffff\n"); } if(has_dsp3) { - xml.append(" \n"); - xml.append(" \n"); - xml.append(" \n"); - xml.append(" \n"); - xml.append(" \n"); - xml.append(" \n"); - xml.append(" \n"); - xml.append(" \n"); - xml.append(" \n"); - xml.append(" \n"); + markup.append(T "necdsp model=uPD7725 frequency=8000000 firmware=dsp3.bin sha256=2e635f72e4d4681148bc35429421c9b946e4f407590e74e31b93b8987b63ba90\n"); + markup.append(T T "dr\n"); + markup.append(T T T "map address=20-3f:8000-bfff\n"); + markup.append(T T T "map address=a0-bf:8000-bfff\n"); + markup.append(T T "sr\n"); + markup.append(T T T "map address=20-3f:c000-ffff\n"); + markup.append(T T T "map address=a0-bf:c000-ffff\n"); } if(has_dsp4) { - xml.append(" \n"); - xml.append(" \n"); - xml.append(" \n"); - xml.append(" \n"); - xml.append(" \n"); - xml.append(" \n"); - xml.append(" \n"); - xml.append(" \n"); - xml.append(" \n"); - xml.append(" \n"); + markup.append(T "necdsp model=uPD7725 frequency=8000000 firmware=dsp4.bin sha256=63ede17322541c191ed1fdf683872554a0a57306496afc43c59de7c01a6e764a\n"); + markup.append(T T "dr\n"); + markup.append(T T T "map address=30-3f:8000-bfff\n"); + markup.append(T T T "map address=b0-bf:8000-bfff\n"); + markup.append(T T "sr\n"); + markup.append(T T T "map address=30-3f:c000-ffff\n"); + markup.append(T T T "map address=b0-bf:c000-ffff\n"); } if(has_obc1) { - xml.append(" \n"); - xml.append(" \n"); - xml.append(" \n"); - xml.append(" \n"); + markup.append(T "obc1\n"); + markup.append(T T "map address=00-3f:6000-7fff\n"); + markup.append(T T "map address=80-bf:6000-7fff\n"); } if(has_st010) { - xml.append(" \n"); - xml.append(" \n"); - xml.append(" \n"); - xml.append(" \n"); - xml.append(" \n"); - xml.append(" \n"); - xml.append(" \n"); - xml.append(" \n"); - xml.append(" \n"); - xml.append(" \n"); - xml.append(" \n"); - xml.append(" \n"); - xml.append(" \n"); - xml.append(" \n"); + markup.append(T "necdsp model=uPD96050 frequency=10000000 firmware=st0010.bin sha256=55c697e864562445621cdf8a7bf6e84ae91361e393d382a3704e9aa55559041e\n"); + markup.append(T T "dr\n"); + markup.append(T T T "map address=60:0000\n"); + markup.append(T T T "map address=e0:0000\n"); + markup.append(T T "sr\n"); + markup.append(T T T "map address=60:0001\n"); + markup.append(T T T "map address=e0:0001\n"); + markup.append(T T "dp\n"); + markup.append(T T T "map address=68-6f:0000-0fff\n"); + markup.append(T T T "map address=e8-ef:0000-0fff\n"); } if(has_st011) { - xml.append(" \n"); - xml.append(" \n"); - xml.append(" \n"); - xml.append(" \n"); - xml.append(" \n"); - xml.append(" \n"); - xml.append(" \n"); - xml.append(" \n"); - xml.append(" \n"); - xml.append(" \n"); - xml.append(" \n"); - xml.append(" \n"); - xml.append(" \n"); - xml.append(" \n"); + markup.append(T "necdsp model=uPD96050 frequency=15000000 firmware=st0011.bin sha256=651b82a1e26c4fa8dd549e91e7f923012ed2ca54c1d9fd858655ab30679c2f0e\n"); + markup.append(T T "dr\n"); + markup.append(T T T "map address=60:0000\n"); + markup.append(T T T "map address=e0:0000\n"); + markup.append(T T "sr\n"); + markup.append(T T T "map address=60:0001\n"); + markup.append(T T T "map address=e0:0001\n"); + markup.append(T T "dp\n"); + markup.append(T T T "map address=68-6f:0000-0fff\n"); + markup.append(T T T "map address=e8-ef:0000-0fff\n"); } if(has_st018) { - xml.append(" \n"); - xml.append(" \n"); - xml.append(" \n"); - xml.append(" \n"); + markup.append(T "setarisc firmware=ST-0018\n"); + markup.append(T T "map address=00-3f:3800-38ff\n"); + markup.append(T T "map address=80-bf:3800-38ff\n"); } - - xml.append("\n"); - xmlMemoryMap = xml.transform("'", "\""); } -void SNESCartridge::read_header(const uint8_t *data, unsigned size) { +#undef T + +void SnesCartridge::read_header(const uint8_t *data, unsigned size) { type = TypeUnknown; mapper = LoROM; dsp1_mapper = DSP1Unmapped; @@ -762,7 +672,7 @@ void SNESCartridge::read_header(const uint8_t *data, unsigned size) { } } -unsigned SNESCartridge::find_header(const uint8_t *data, unsigned size) { +unsigned SnesCartridge::find_header(const uint8_t *data, unsigned size) { unsigned score_lo = score_header(data, size, 0x007fc0); unsigned score_hi = score_header(data, size, 0x00ffc0); unsigned score_ex = score_header(data, size, 0x40ffc0); @@ -777,7 +687,7 @@ unsigned SNESCartridge::find_header(const uint8_t *data, unsigned size) { } } -unsigned SNESCartridge::score_header(const uint8_t *data, unsigned size, unsigned addr) { +unsigned SnesCartridge::score_header(const uint8_t *data, unsigned size, unsigned addr) { if(size < addr + 64) return 0; //image too small to contain header at this location? int score = 0; @@ -858,7 +768,7 @@ unsigned SNESCartridge::score_header(const uint8_t *data, unsigned size, unsigne return score; } -unsigned SNESCartridge::gameboy_ram_size(const uint8_t *data, unsigned size) { +unsigned SnesCartridge::gameboy_ram_size(const uint8_t *data, unsigned size) { if(size < 512) return 0; switch(data[0x0149]) { case 0x00: return 0 * 1024; @@ -871,7 +781,7 @@ unsigned SNESCartridge::gameboy_ram_size(const uint8_t *data, unsigned size) { } } -bool SNESCartridge::gameboy_has_rtc(const uint8_t *data, unsigned size) { +bool SnesCartridge::gameboy_has_rtc(const uint8_t *data, unsigned size) { if(size < 512) return false; if(data[0x0147] == 0x0f ||data[0x0147] == 0x10) return true; return false; diff --git a/bsnes/nall/string/bml.hpp b/bsnes/nall/string/bml.hpp index 10d62a6c..4f8139cc 100755 --- a/bsnes/nall/string/bml.hpp +++ b/bsnes/nall/string/bml.hpp @@ -1,124 +1,97 @@ #ifdef NALL_STRING_INTERNAL_HPP //BML v1.0 parser -//revision 0.03 +//revision 0.05 namespace nall { namespace BML { -inline static string encode(const char *s) { +inline static string indent(const char *s, unsigned depth) { array output; - while(*s) { - char c = *s++; - (c == '\n') ? output.append("{lf}", 4) : - (c == '{') ? output.append("{lb}", 4) : - (c == '}') ? output.append("{rb}", 4) : - output.append(c); - } - output.append(0); + do { + for(unsigned n = 0; n < depth; n++) output.append('\t'); + do output.append(*s); while(*s && *s++ != '\n'); + } while(*s); return output.get(); } struct Node { cstring name; cstring value; - signed depth; private: linear_vector children; - inline bool valid(char p) const { - if(p >= 'A' && p <= 'Z') return true; - if(p >= 'a' && p <= 'z') return true; - if(p >= '0' && p <= '9') return true; - if(p == '-' || p == '.') return true; - return false; + inline bool valid(char p) const { //A-Za-z0-9-. + return p - 'A' < 26u | p - 'a' < 26u | p - '0' < 10u | p - '-' < 2u; } - inline unsigned parseDepth(char *p) { + inline unsigned parseDepth(char *&p) { + while(*p == '\n' || *p == '#') { + while(*p != '\n') *p++ = 0; + *p++ = 0; //'\n' + } unsigned depth = 0; - while(*p == '\t') depth++, p++; + while(p[depth] == '\t') depth++; return depth; } inline void parseName(char *&p) { - if(valid(*p)) { - name = p; - while(valid(*p)) p++; - } + if(valid(*p) == false) throw "Missing node name"; + name = p; + while(valid(*p)) p++; } inline void parseValue(char *&p) { - *p++ = 0; //'{' + char terminal = *p == ':' ? '\n' : ' '; //':' or '=' + *p++ = 0; + value = p; + while(*p && *p != terminal && *p != '\n') p++; + } + + inline void parseBlock(char *&p, unsigned depth) { value = p; char *w = p; - while(*p) { - if(*p == '\n') throw "Unclosed node value"; - if(*p == '}') break; - if(*p == '{') { - if(*(p + 1) == 'l' && *(p + 2) == 'b' && *(p + 3) == '}') *w++ = '{', p += 4; - else if(*(p + 1) == 'r' && *(p + 2) == 'b' && *(p + 3) == '}') *w++ = '}', p += 4; - else if(*(p + 1) == 'l' && *(p + 2) == 'f' && *(p + 3) == '}') *w++ = '\n', p += 4; - else throw "Unrecognized escape sequence"; - continue; - } - *w++ = *p++; + while(parseDepth(p) > depth) { + p += depth + 1; + while(*p && *p != '\n') *w++ = *p++; + if(*p && *p != '\n') throw "Multi-line value missing line feed"; + *w++ = *p; } - - if(*p != '}') throw "Unclosed node value"; - *w = *p++ = 0; //'}' + *(w - 1) = 0; //'\n' } inline void parseLine(char *&p) { - depth = parseDepth(p); + unsigned depth = parseDepth(p); while(*p == '\t') p++; parseName(p); - bool multiLine = false; - if(*p == ':') { - multiLine = true; - *p++ = 0; - } else if(*p == '{') { - parseValue(p); - if(*p != ' ' && *p != '\n') throw "Invalid character after first node value"; - } + bool multiLine = *p == '~'; + if(multiLine) *p++ = 0; + else if(*p == ':' || *p == '=') parseValue(p); + if(*p && *p != ' ' && *p != '\n') throw "Invalid character encountered"; while(*p == ' ') { *p++ = 0; Node node; node.parseName(p); - if(*p == '{') node.parseValue(p); - if(*p != ' ' && *p != '\n') throw "Invalid character after node"; + if(*p == ':' || *p == '=') node.parseValue(p); + if(*p && *p != ' ' && *p != '\n') throw "Invalid character after node"; + if(*p == '\n') *p++ = 0; children.append(node); } - if(*p == 0) throw "Missing line feed"; - while(*p == '\n') *p++ = 0; + if(multiLine) return parseBlock(p, depth); - if(multiLine == false) { - while(parseDepth(p) > depth) { - Node node; - node.parseLine(p); - children.append(node); - } - } else { - value = p; - char *w = p; - while(parseDepth(p) > depth) { - p += depth + 1; - while(*p && *p != '\n') *w++ = *p++; - if(*p != '\n') throw "Multi-line value missing line feed"; - *w++ = *p++; - } - *(w - 1) = 0; - if(value == p) value = p - 1; //no text data copied, point it back at null data - *(p - 1) = 0; + while(parseDepth(p) > depth) { + Node node; + node.parseLine(p); + children.append(node); } } inline void parse(char *&p) { while(*p) { - while(*p == '\n') *p++ = 0; Node node; node.parseLine(p); children.append(node); @@ -135,41 +108,41 @@ public: return node; } - inline bool exists() const { - return name; - } - - inline bool load(const char *document) { - if(document == nullptr) return false; - char *p = strdup(document); - name = nullptr; - value = p; - try { - parse(p); - } catch(const char *error) { - free((void*)(const char*)value); - children.reset(); - return false; - } - depth = -1; - return true; - } - - inline void constructor() { - depth = 0; - name = ""; - value = ""; - } - + inline bool exists() const { return name; } unsigned size() const { return children.size(); } Node* begin() { return children.begin(); } Node* end() { return children.end(); } const Node* begin() const { return children.begin(); } const Node* end() const { return children.end(); } + inline Node() : name(""), value("") {} + friend class Document; +}; - inline Node() { constructor(); } - inline Node(const char *document) { constructor(); load(document); } - inline ~Node() { if(depth == -1) free((void*)(const char*)value); } +struct Document : Node { + cstring error; + + inline bool load(const char *document) { + if(document == nullptr) return false; + this->document = strdup(document); + char *p = this->document; + try { + this->error = nullptr; + parse(p); + } catch(const char *error) { + this->error = error; + free(this->document); + this->document = nullptr; + children.reset(); + return false; + } + return true; + } + + inline Document(const char *document = "") : document(nullptr), error(nullptr) { if(*document) load(document); } + inline ~Document() { if(document) free(document); } + +private: + char *document; }; } diff --git a/bsnes/nes/cartridge/board/board.cpp b/bsnes/nes/cartridge/board/board.cpp index 5c1e4fda..58f9a4a8 100755 --- a/bsnes/nes/cartridge/board/board.cpp +++ b/bsnes/nes/cartridge/board/board.cpp @@ -102,7 +102,7 @@ Board::~Board() { } Board* Board::load(const string &markup, const uint8_t *data, unsigned size) { - BML::Node document(markup); + BML::Document document(markup); auto &board = document["cartridge"]["board"]; string type = board["type"].value; diff --git a/bsnes/nes/cartridge/ines.cpp b/bsnes/nes/cartridge/ines.cpp index d117b95d..0eefe638 100755 --- a/bsnes/nes/cartridge/ines.cpp +++ b/bsnes/nes/cartridge/ines.cpp @@ -20,65 +20,65 @@ static string iNES(const uint8_t *data, unsigned size) { switch(mapper) { default: - output.append("\tboard type{NES-NROM-256}\n"); - output.append("\t\tmirror{", mirror == 0 ? "horizontal" : "vertical", "}\n"); + output.append("\tboard type:NES-NROM-256\n"); + output.append("\t\tmirror:", mirror == 0 ? "horizontal" : "vertical", "\n"); break; case 1: - output.append("\tboard type{NES-SXROM}\n"); - output.append("\t\tchip type{MMC1B2}\n"); + output.append("\tboard type:NES-SXROM\n"); + output.append("\t\tchip type:MMC1B2\n"); prgram = 8192; break; case 2: - output.append("\tboard type{NES-UOROM}\n"); - output.append("\t\tmirror{", mirror == 0 ? "horizontal" : "vertical", "}\n"); + output.append("\tboard type:NES-UOROM\n"); + output.append("\t\tmirror:", mirror == 0 ? "horizontal" : "vertical", "\n"); break; case 3: - output.append("\tboard type{NES-CNROM}\n"); - output.append("\t\tmirror{", mirror == 0 ? "horizontal" : "vertical", "}\n"); + output.append("\tboard type:NES-CNROM\n"); + output.append("\t\tmirror:", mirror == 0 ? "horizontal" : "vertical", "\n"); break; case 4: - output.append("\tboard type{NES-TLROM}\n"); - output.append("\t\tchip type{MMC3B}\n"); + output.append("\tboard type:NES-TLROM\n"); + output.append("\t\tchip type:MMC3B\n"); prgram = 8192; break; case 7: - output.append("\tboard type{NES-AOROM}\n"); + output.append("\tboard type:NES-AOROM\n"); break; case 16: - output.append("\tboard type{BANDAI-FCG}\n"); - output.append("\t\tchip type{LZ93D50}\n"); + output.append("\tboard type:BANDAI-FCG\n"); + output.append("\t\tchip type:LZ93D50\n"); break; case 24: - output.append("\tboard type{KONAMI-VRC-6}\n"); - output.append("\t\tchip type{VRC6}\n"); + output.append("\tboard type:KONAMI-VRC-6\n"); + output.append("\t\tchip type:VRC6\n"); break; case 26: - output.append("\tboard type{KONAMI-VRC-6}\n"); - output.append("\t\tchip type{VRC6}\n"); + output.append("\tboard type:KONAMI-VRC-6\n"); + output.append("\t\tchip type:VRC6\n"); prgram = 8192; break; case 34: - output.append("\tboard type{NES-BNROM}\n"); - output.append("\t\tmirror{", mirror == 0 ? "horizontal" : "vertical", "}\n"); + output.append("\tboard type:NES-BNROM\n"); + output.append("\t\tmirror:", mirror == 0 ? "horizontal" : "vertical", "\n"); break; case 66: - output.append("\tboard type{NES-GNROM}\n"); - output.append("\t\tmirror{", mirror == 0 ? "horizontal" : "vertical", "}\n"); + output.append("\tboard type:NES-GNROM\n"); + output.append("\t\tmirror:", mirror == 0 ? "horizontal" : "vertical", "\n"); break; } - output.append("\t\tprg rom{", prgrom, "} ram{", prgram, "}\n"); - output.append("\t\tchr rom{", chrrom, "} ram{", chrram, "}\n"); + output.append("\t\tprg rom=", prgrom, " ram=", prgram, "\n"); + output.append("\t\tchr rom=", chrrom, " ram=", chrram, "\n"); print(output, "\n"); diff --git a/bsnes/ruby/video/direct3d.cpp b/bsnes/ruby/video/direct3d.cpp index 9d642148..f4bdd599 100755 --- a/bsnes/ruby/video/direct3d.cpp +++ b/bsnes/ruby/video/direct3d.cpp @@ -24,7 +24,7 @@ public: LPDIRECT3DTEXTURE9 texture; LPDIRECT3DSURFACE9 surface; LPD3DXEFFECT effect; - string shader_source_xml; + string shader_source_markup; bool lost; unsigned iwidth, iheight; @@ -268,7 +268,7 @@ public: //failure to do so causes scaling issues on some video drivers. if(state.width != rd.right || state.height != rd.bottom) { init(); - set_shader(shader_source_xml); + set_shader(shader_source_markup); return; } @@ -336,26 +336,14 @@ public: } if(!source || !*source) { - shader_source_xml = ""; + shader_source_markup = ""; return; } - shader_source_xml = source; + shader_source_markup = source; - bool is_hlsl = false; - string shader_source; - xml_element document = xml_parse(shader_source_xml); - for(auto &head : document.element) { - if(head.name == "shader") { - for(auto &attribute : head.attribute) { - if(attribute.name == "language" && attribute.content == "HLSL") is_hlsl = true; - } - for(auto &element : head.element) { - if(element.name == "source") { - if(is_hlsl) shader_source = element.parse(); - } - } - } - } + BML::Document document(shader_source_markup); + bool is_hlsl = document["shader"]["language"].value == "HLSL"; + string shader_source = document["shader"].value; if(shader_source == "") return; HMODULE d3dx; diff --git a/bsnes/ruby/video/opengl.hpp b/bsnes/ruby/video/opengl.hpp index 836054d7..a606c752 100755 --- a/bsnes/ruby/video/opengl.hpp +++ b/bsnes/ruby/video/opengl.hpp @@ -136,29 +136,11 @@ public: } if(source) { - bool is_glsl = false; - fragmentfilter = 0; - string fragment_source; - string vertex_source; - - xml_element document = xml_parse(source); - for(auto &head : document.element) { - if(head.name == "shader") { - for(auto &attribute : head.attribute) { - if(attribute.name == "language" && attribute.content == "GLSL") is_glsl = true; - } - for(auto &element : head.element) { - if(element.name == "fragment") { - for(auto &attribute : element.attribute) { - if(attribute.name == "filter") fragmentfilter = attribute.content == "linear" ? 1 : 0; - } - fragment_source = element.parse(); - } else if(element.name == "vertex") { - vertex_source = element.parse(); - } - } - } - } + BML::Document document(source); + bool is_glsl = document["shader"]["language"].value == "GLSL"; + fragmentfilter = document["shader"]["fragment"]["filter"].value == "linear" ? 1 : 0; + string fragment_source = document["shader"]["fragment"].value; + string vertex_source = document["shader"]["vertex"].value; if(is_glsl) { if(fragment_source != "") set_fragment_shader(fragment_source); diff --git a/bsnes/snes/cartridge/cartridge.cpp b/bsnes/snes/cartridge/cartridge.cpp index 549e6f03..c76e2a34 100755 --- a/bsnes/snes/cartridge/cartridge.cpp +++ b/bsnes/snes/cartridge/cartridge.cpp @@ -6,12 +6,12 @@ #define CARTRIDGE_CPP namespace SNES { -#include "xml.cpp" +#include "markup.cpp" #include "serialization.cpp" Cartridge cartridge; -void Cartridge::load(Mode cartridge_mode, const lstring &xml_list) { +void Cartridge::load(Mode cartridge_mode, const char *markup) { mode = cartridge_mode; region = Region::NTSC; ram_size = 0; @@ -33,8 +33,8 @@ void Cartridge::load(Mode cartridge_mode, const lstring &xml_list) { nvram.reset(); - parse_xml(xml_list); -//print(xml_list[0], "\n\n"); + parse_markup(markup); + print(markup, "\n\n"); if(ram_size > 0) { ram.map(allocate(ram_size, 0xff), ram_size); diff --git a/bsnes/snes/cartridge/cartridge.hpp b/bsnes/snes/cartridge/cartridge.hpp index 1fbca2a0..f384fac9 100755 --- a/bsnes/snes/cartridge/cartridge.hpp +++ b/bsnes/snes/cartridge/cartridge.hpp @@ -82,7 +82,7 @@ struct Cartridge : property { } nss; } information; - void load(Mode, const lstring&); + void load(Mode, const char*); void unload(); void serialize(serializer&); @@ -90,35 +90,27 @@ struct Cartridge : property { ~Cartridge(); private: - void parse_xml(const lstring&); - void parse_xml_cartridge(const char*); - void parse_xml_bsx(const char*); - void parse_xml_sufami_turbo(const char*, bool); - void parse_xml_gameboy(const char*); + void parse_markup(const char*); + unsigned parse_markup_integer(cstring&); + void parse_markup_map(Mapping&, BML::Node&); - void xml_parse_rom(xml_element&); - void xml_parse_ram(xml_element&); - void xml_parse_nss(xml_element&); - void xml_parse_icd2(xml_element&); - void xml_parse_superfx(xml_element&); - void xml_parse_sa1(xml_element&); - void xml_parse_necdsp(xml_element&); - void xml_parse_hitachidsp(xml_element&); - void xml_parse_bsx(xml_element&); - void xml_parse_sufamiturbo(xml_element&); - void xml_parse_supergameboy(xml_element&); - void xml_parse_srtc(xml_element&); - void xml_parse_sdd1(xml_element&); - void xml_parse_spc7110(xml_element&); - void xml_parse_obc1(xml_element&); - void xml_parse_setarisc(xml_element&); - void xml_parse_msu1(xml_element&); - void xml_parse_link(xml_element&); - - unsigned xml_parse_hex(const string&); - unsigned xml_parse_unsigned(const string&); - void xml_parse_address(Mapping&, const string&); - void xml_parse_mode(Mapping&, const string&); + void parse_markup_rom(BML::Node&); + void parse_markup_ram(BML::Node&); + void parse_markup_nss(BML::Node&); + void parse_markup_icd2(BML::Node&); + void parse_markup_superfx(BML::Node&); + void parse_markup_sa1(BML::Node&); + void parse_markup_necdsp(BML::Node&); + void parse_markup_hitachidsp(BML::Node&); + void parse_markup_bsx(BML::Node&); + void parse_markup_sufamiturbo(BML::Node&); + void parse_markup_srtc(BML::Node&); + void parse_markup_sdd1(BML::Node&); + void parse_markup_spc7110(BML::Node&); + void parse_markup_obc1(BML::Node&); + void parse_markup_setarisc(BML::Node&); + void parse_markup_msu1(BML::Node&); + void parse_markup_link(BML::Node&); }; extern Cartridge cartridge; diff --git a/bsnes/snes/cartridge/markup.cpp b/bsnes/snes/cartridge/markup.cpp new file mode 100755 index 00000000..2696a17b --- /dev/null +++ b/bsnes/snes/cartridge/markup.cpp @@ -0,0 +1,557 @@ +#ifdef CARTRIDGE_CPP + +void Cartridge::parse_markup(const char *markup) { + mapping.reset(); + information.nss.setting.reset(); + + BML::Document document(markup); + auto &cartridge = document["cartridge"]; + region = cartridge["region"].value != "PAL" ? Region::NTSC : Region::PAL; + + parse_markup_rom(cartridge["rom"]); + parse_markup_ram(cartridge["ram"]); + parse_markup_nss(cartridge["nss"]); + parse_markup_icd2(cartridge["icd2"]); + parse_markup_sa1(cartridge["sa1"]); + parse_markup_superfx(cartridge["superfx"]); + parse_markup_necdsp(cartridge["necdsp"]); + parse_markup_hitachidsp(cartridge["hitachidsp"]); + parse_markup_bsx(cartridge["bsx"]); + parse_markup_sufamiturbo(cartridge["sufamiturbo"]); + parse_markup_srtc(cartridge["srtc"]); + parse_markup_sdd1(cartridge["sdd1"]); + parse_markup_spc7110(cartridge["spc7110"]); + parse_markup_obc1(cartridge["obc1"]); + parse_markup_setarisc(cartridge["setarisc"]); + parse_markup_msu1(cartridge["msu1"]); + parse_markup_link(cartridge["link"]); +} + +// + +unsigned Cartridge::parse_markup_integer(cstring &data) { + if(strbegin(data, "0x")) return hex(data); + return decimal(data); +} + +void Cartridge::parse_markup_map(Mapping &m, BML::Node &map) { + m.offset = parse_markup_integer(map["offset"].value); + m.size = parse_markup_integer(map["size"].value); + + string data = map["mode"].value; + if(data == "direct") m.mode = Bus::MapMode::Direct; + if(data == "linear") m.mode = Bus::MapMode::Linear; + if(data == "shadow") m.mode = Bus::MapMode::Shadow; + + lstring part; + part.split(":", map["address"].value); + if(part.size() != 2) return; + + lstring subpart; + subpart.split("-", part[0]); + if(subpart.size() == 1) { + m.banklo = hex(subpart[0]); + m.bankhi = m.banklo; + } else if(subpart.size() == 2) { + m.banklo = hex(subpart[0]); + m.bankhi = hex(subpart[1]); + } + + subpart.split("-", part[1]); + if(subpart.size() == 1) { + m.addrlo = hex(subpart[0]); + m.addrhi = m.addrlo; + } else if(subpart.size() == 2) { + m.addrlo = hex(subpart[0]); + m.addrhi = hex(subpart[1]); + } +} + +// + +void Cartridge::parse_markup_rom(BML::Node &root) { + if(root.exists() == false) return; + for(auto &node : root) { + if(node.name != "map") continue; + Mapping m(rom); + parse_markup_map(m, node); + if(m.size == 0) m.size = rom.size(); + mapping.append(m); + } +} + +void Cartridge::parse_markup_ram(BML::Node &root) { + if(root.exists() == false) return; + ram_size = parse_markup_integer(root["size"].value); + for(auto &node : root) { + Mapping m(ram); + parse_markup_map(m, node); + if(m.size == 0) m.size = ram_size; + mapping.append(m); + } +} + +void Cartridge::parse_markup_nss(BML::Node &root) { + if(root.exists() == false) return; + has_nss_dip = true; + for(auto &node : root) { + if(node.name != "setting") continue; + unsigned number = information.nss.setting.size(); + if(number >= 16) break; //more than 16 DIP switches is not physically possible + + information.nss.option[number].reset(); + information.nss.setting[number] = node["name"].value; + for(auto &leaf : node) { + if(leaf.name != "option") continue; + string name = leaf["name"].value; + unsigned value = parse_markup_integer(leaf["value"].value); + information.nss.option[number].append({ hex<4>(value), ":", name }); + } + } +} + +void Cartridge::parse_markup_icd2(BML::Node &root) { + if(root.exists() == false) return; + if(mode != Mode::SuperGameBoy) return; + + icd2.revision = max(1, parse_markup_integer(root["revision"].value)); + + for(auto &node : root) { + if(node.name != "map") continue; + Mapping m({ &ICD2::read, &icd2 }, { &ICD2::write, &icd2 }); + parse_markup_map(m, node); + mapping.append(m); + } +} + +void Cartridge::parse_markup_superfx(BML::Node &root) { + if(root.exists() == false) return; + has_superfx = true; + + for(auto &node : root) { + if(node.name == "rom") { + for(auto &leaf : node) { + if(leaf.name != "map") continue; + Mapping m(superfx.rom); + parse_markup_map(m, leaf); + mapping.append(m); + } + } + if(node.name == "ram") { + for(auto &leaf : node) { + if(leaf.name == "size") { + ram_size = parse_markup_integer(leaf.value); + continue; + } + if(leaf.name != "map") continue; + Mapping m(superfx.ram); + parse_markup_map(m, leaf); + if(m.size == 0) m.size = ram_size; + mapping.append(m); + } + } + if(node.name == "mmio") { + for(auto &leaf : node) { + if(leaf.name != "map") continue; + Mapping m({ &SuperFX::mmio_read, &superfx }, { &SuperFX::mmio_write, &superfx }); + parse_markup_map(m, leaf); + mapping.append(m); + } + } + } +} + +void Cartridge::parse_markup_sa1(BML::Node &root) { + if(root.exists() == false) return; + has_sa1 = true; + + auto &mcurom = root["mcu"]["rom"]; + auto &mcuram = root["mcu"]["ram"]; + auto &iram = root["iram"]; + auto &bwram = root["bwram"]; + auto &mmio = root["mmio"]; + + for(auto &node : mcurom) { + if(node.name != "map") continue; + Mapping m({ &SA1::mmc_read, &sa1 }, { &SA1::mmc_write, &sa1 }); + parse_markup_map(m, node); + mapping.append(m); + } + + for(auto &node : mcuram) { + if(node.name != "map") continue; + Mapping m({ &SA1::mmc_cpu_read, &sa1 }, { &SA1::mmc_cpu_write, &sa1 }); + parse_markup_map(m, node); + mapping.append(m); + } + + for(auto &node : iram) { + if(node.name != "map") continue; + Mapping m(sa1.cpuiram); + parse_markup_map(m, node); + if(m.size == 0) m.size = 2048; + mapping.append(m); + } + + ram_size = parse_markup_integer(bwram["size"].value); + for(auto &node : bwram) { + if(node.name != "map") continue; + Mapping m(sa1.cpubwram); + parse_markup_map(m, node); + if(m.size == 0) m.size = ram_size; + mapping.append(m); + } + + for(auto &node : mmio) { + if(node.name != "map") continue; + Mapping m({ &SA1::mmio_read, &sa1 }, { &SA1::mmio_write, &sa1 }); + parse_markup_map(m, node); + mapping.append(m); + } +} + +void Cartridge::parse_markup_necdsp(BML::Node &root) { + if(root.exists() == false) return; + has_necdsp = true; + + for(unsigned n = 0; n < 16384; n++) necdsp.programROM[n] = 0x000000; + for(unsigned n = 0; n < 2048; n++) necdsp.dataROM[n] = 0x0000; + + necdsp.frequency = parse_markup_integer(root["frequency"].value); + if(necdsp.frequency == 0) necdsp.frequency = 8000000; + necdsp.revision + = root["model"].value == "uPD7725" ? NECDSP::Revision::uPD7725 + : root["model"].value == "uPD96050" ? NECDSP::Revision::uPD96050 + : NECDSP::Revision::uPD7725; + string firmware = root["firmware"].value; + string sha256 = root["sha256"].value; + + string path = { dir(interface->path(Slot::Base, ".dsp")), firmware }; + unsigned promsize = (necdsp.revision == NECDSP::Revision::uPD7725 ? 2048 : 16384); + unsigned dromsize = (necdsp.revision == NECDSP::Revision::uPD7725 ? 1024 : 2048); + unsigned filesize = promsize * 3 + dromsize * 2; + + file fp; + if(fp.open(path, file::mode::read) == false) { + interface->message({ "Warning: NEC DSP firmware ", firmware, " is missing." }); + } else if(fp.size() != filesize) { + interface->message({ "Warning: NEC DSP firmware ", firmware, " is of the wrong file size." }); + fp.close(); + } else { + for(unsigned n = 0; n < promsize; n++) necdsp.programROM[n] = fp.readm(3); + for(unsigned n = 0; n < dromsize; n++) necdsp.dataROM[n] = fp.readm(2); + + if(sha256 != "") { + //XML file specified SHA256 sum for program. Verify file matches the hash. + fp.seek(0); + uint8_t data[filesize]; + fp.read(data, filesize); + + if(sha256 != nall::sha256(data, filesize)) { + interface->message({ "Warning: NEC DSP firmware ", firmware, " SHA256 sum is incorrect." }); + } + } + + fp.close(); + } + + for(auto &node : root) { + if(node.name == "dr") { + for(auto &leaf : node) { + Mapping m({ &NECDSP::dr_read, &necdsp }, { &NECDSP::dr_write, &necdsp }); + parse_markup_map(m, leaf); + mapping.append(m); + } + } + if(node.name == "sr") { + for(auto &leaf : node) { + Mapping m({ &NECDSP::sr_read, &necdsp }, { &NECDSP::sr_write, &necdsp }); + parse_markup_map(m, leaf); + mapping.append(m); + } + } + if(node.name == "dp") { + for(auto &leaf : node) { + Mapping m({ &NECDSP::dp_read, &necdsp }, { &NECDSP::dp_write, &necdsp }); + parse_markup_map(m, leaf); + mapping.append(m); + } + } + } +} + +void Cartridge::parse_markup_hitachidsp(BML::Node &root) { + if(root.exists() == false) return; + has_hitachidsp = true; + + for(unsigned n = 0; n < 1024; n++) hitachidsp.dataROM[n] = 0x000000; + + hitachidsp.frequency = parse_markup_integer(root["frequency"].value); + if(hitachidsp.frequency == 0) hitachidsp.frequency = 20000000; + string firmware = root["firmware"].value; + string sha256 = root["sha256"].value; + + string path = { dir(interface->path(Slot::Base, ".dsp")), firmware }; + file fp; + if(fp.open(path, file::mode::read) == false) { + interface->message({ "Warning: Hitachi DSP firmware ", firmware, " is missing." }); + } else if(fp.size() != 1024 * 3) { + interface->message({ "Warning: Hitachi DSP firmware ", firmware, " is of the wrong file size." }); + fp.close(); + } else { + for(unsigned n = 0; n < 1024; n++) hitachidsp.dataROM[n] = fp.readl(3); + + if(sha256 != "") { + //XML file specified SHA256 sum for program. Verify file matches the hash. + fp.seek(0); + uint8 data[3072]; + fp.read(data, 3072); + + if(sha256 != nall::sha256(data, 3072)) { + interface->message({ "Warning: Hitachi DSP firmware ", firmware, " SHA256 sum is incorrect." }); + } + } + + fp.close(); + } + + for(auto &node : root) { + if(node.name == "rom") { + for(auto &leaf : node) { + if(leaf.name != "map") continue; + Mapping m({ &HitachiDSP::rom_read, &hitachidsp }, { &HitachiDSP::rom_write, &hitachidsp }); + parse_markup_map(m, leaf); + mapping.append(m); + } + } + if(node.name == "mmio") { + for(auto &leaf : node) { + Mapping m({ &HitachiDSP::dsp_read, &hitachidsp }, { &HitachiDSP::dsp_write, &hitachidsp }); + parse_markup_map(m, leaf); + mapping.append(m); + } + } + } +} + +void Cartridge::parse_markup_bsx(BML::Node &root) { + if(root.exists() == false) return; + if(mode != Mode::BsxSlotted && mode != Mode::Bsx) return; + + for(auto &node : root["slot"]) { + if(node.name != "map") continue; + Mapping m(bsxflash.memory); + parse_markup_map(m, node); + mapping.append(m); + } + + for(auto &node : root["mmio"]) { + if(node.name != "map") continue; + Mapping m({ &BSXCartridge::mmio_read, &bsxcartridge }, { &BSXCartridge::mmio_write, &bsxcartridge }); + parse_markup_map(m, node); + mapping.append(m); + } + + for(auto &node : root["mcu"]) { + if(node.name != "map") continue; + Mapping m({ &BSXCartridge::mcu_read, &bsxcartridge }, { &BSXCartridge::mcu_write, &bsxcartridge }); + parse_markup_map(m, node); + mapping.append(m); + } +} + +void Cartridge::parse_markup_sufamiturbo(BML::Node &root) { + if(root.exists() == false) return; + if(mode != Mode::SufamiTurbo) return; + + for(auto &slot : root) { + if(slot.name != "slot") continue; + bool slotid = slot["id"].value == "A" ? 0 : slot["id"].value == "B" ? 1 : 0; + for(auto &node : slot) { + if(node.name == "rom") { + for(auto &leaf : node) { + if(leaf.name != "map") continue; + Memory &memory = slotid == 0 ? sufamiturbo.slotA.rom : sufamiturbo.slotB.rom; + Mapping m(memory); + parse_markup_map(m, leaf); + if(m.size == 0) m.size = memory.size(); + if(m.size) mapping.append(m); + } + } + if(node.name == "ram") { + unsigned ram_size = parse_markup_integer(node["size"].value); + for(auto &leaf : node) { + if(leaf.name != "map") continue; + Memory &memory = slotid == 0 ? sufamiturbo.slotA.ram : sufamiturbo.slotB.ram; + Mapping m(memory); + parse_markup_map(m, leaf); + if(m.size == 0) m.size = ram_size; + if(m.size) mapping.append(m); + } + } + } + } +} + +void Cartridge::parse_markup_srtc(BML::Node &root) { + if(root.exists() == false) return; + has_srtc = true; + + for(auto &node : root) { + if(node.name != "map") continue; + Mapping m({ &SRTC::read, &srtc }, { &SRTC::write, &srtc }); + parse_markup_map(m, node); + mapping.append(m); + } +} + +void Cartridge::parse_markup_sdd1(BML::Node &root) { + if(root.exists() == false) return; + has_sdd1 = true; + + for(auto &node : root["mmio"]) { + if(node.name != "map") continue; + Mapping m({ &SDD1::mmio_read, &sdd1 }, { &SDD1::mmio_write, &sdd1 }); + parse_markup_map(m, node); + mapping.append(m); + } + + for(auto &node : root["mcu"]) { + if(node.name != "map") continue; + Mapping m({ &SDD1::mcu_read, &sdd1 }, { &SDD1::mcu_write, &sdd1 }); + parse_markup_map(m, node); + mapping.append(m); + } +} + +void Cartridge::parse_markup_spc7110(BML::Node &root) { + if(root.exists() == false) return; + has_spc7110 = true; + + auto &ram = root["ram"]; + auto &mmio = root["mmio"]; + auto &mcu = root["mcu"]; + auto &dcu = root["dcu"]; + auto &rtc = root["rtc"]; + + ram_size = parse_markup_integer(ram["size"].value); + for(auto &node : ram) { + if(node.name != "map") continue; + Mapping m({ &SPC7110::ram_read, &spc7110 }, { &SPC7110::ram_write, &spc7110 }); + parse_markup_map(m, node); + mapping.append(m); + } + + for(auto &node : mmio) { + if(node.name != "map") continue; + Mapping m({ &SPC7110::mmio_read, &spc7110 }, { &SPC7110::mmio_write, &spc7110 }); + parse_markup_map(m, node); + mapping.append(m); + } + + spc7110.data_rom_offset = parse_markup_integer(mcu["offset"].value); + if(spc7110.data_rom_offset == 0) spc7110.data_rom_offset = 0x100000; + for(auto &node : mcu) { + if(node.name != "map") continue; + Mapping m({ &SPC7110::mcu_read, &spc7110 }, { &SPC7110::mcu_write, &spc7110 }); + parse_markup_map(m, node); + mapping.append(m); + } + + for(auto &node : dcu) { + if(node.name != "map") continue; + Mapping m({ &SPC7110::dcu_read, &spc7110 }, { &SPC7110::dcu_write, &spc7110 }); + parse_markup_map(m, node); + mapping.append(m); + } + + for(auto &node : rtc) { + if(node.name != "map") continue; + Mapping m({ &SPC7110::mmio_read, &spc7110 }, { &SPC7110::mmio_write, &spc7110 }); + parse_markup_map(m, node); + mapping.append(m); + } +} + +void Cartridge::parse_markup_obc1(BML::Node &root) { + if(root.exists() == false) return; + has_obc1 = true; + + for(auto &node : root) { + if(node.name != "map") continue; + Mapping m({ &OBC1::read, &obc1 }, { &OBC1::write, &obc1 }); + parse_markup_map(m, node); + mapping.append(m); + } +} + +void Cartridge::parse_markup_setarisc(BML::Node &root) { + if(root.exists() == false) return; + has_st0018 = true; + + for(auto &node : root) { + if(node.name != "map") continue; + Mapping m({ &ST0018::mmio_read, &st0018 }, { &ST0018::mmio_write, &st0018 }); + parse_markup_map(m, node); + mapping.append(m); + } +} + +void Cartridge::parse_markup_msu1(BML::Node &root) { + if(root.exists() == false) { + has_msu1 = file::exists(interface->path(Cartridge::Slot::Base, ".msu")); + if(has_msu1) { + Mapping m({ &MSU1::mmio_read, &msu1 }, { &MSU1::mmio_write, &msu1 }); + m.banklo = 0x00, m.bankhi = 0x3f, m.addrlo = 0x2000, m.addrhi = 0x2007; + mapping.append(m); + m.banklo = 0x80, m.bankhi = 0xbf, m.addrlo = 0x2000, m.addrhi = 0x2007; + mapping.append(m); + } + return; + } + + has_msu1 = true; + + for(auto &node : root) { + if(node.name != "map") continue; + Mapping m({ &MSU1::mmio_read, &msu1 }, { &MSU1::mmio_write, &msu1 }); + parse_markup_map(m, node); + mapping.append(m); + } +} + +void Cartridge::parse_markup_link(BML::Node &root) { + if(root.exists() == false) return; + has_link = true; + + link.frequency = max(1, parse_markup_integer(root["frequency"].value)); + link.program = root["program"].value; + + for(auto &node : root) { + if(node.name != "map") continue; + Mapping m({ &Link::read, &link }, { &Link::write, &link }); + parse_markup_map(m, node); + mapping.append(m); + } +} + +Cartridge::Mapping::Mapping() { + mode = Bus::MapMode::Direct; + banklo = bankhi = addrlo = addrhi = offset = size = 0; +} + +Cartridge::Mapping::Mapping(Memory &memory) { + read = { &Memory::read, &memory }; + write = { &Memory::write, &memory }; + mode = Bus::MapMode::Direct; + banklo = bankhi = addrlo = addrhi = offset = size = 0; +} + +Cartridge::Mapping::Mapping(const function &read_, const function &write_) { + read = read_; + write = write_; + mode = Bus::MapMode::Direct; + banklo = bankhi = addrlo = addrhi = offset = size = 0; +} + +#endif diff --git a/bsnes/snes/cartridge/xml.cpp b/bsnes/snes/cartridge/xml.cpp deleted file mode 100755 index d49b94a0..00000000 --- a/bsnes/snes/cartridge/xml.cpp +++ /dev/null @@ -1,765 +0,0 @@ -#ifdef CARTRIDGE_CPP - -void Cartridge::parse_xml(const lstring &list) { - mapping.reset(); - parse_xml_cartridge(list[0]); - - if(mode == Mode::BsxSlotted) { - parse_xml_bsx(list[1]); - } else if(mode == Mode::Bsx) { - parse_xml_bsx(list[1]); - } else if(mode == Mode::SufamiTurbo) { - parse_xml_sufami_turbo(list[1], 0); - parse_xml_sufami_turbo(list[2], 1); - } else if(mode == Mode::SuperGameBoy) { - parse_xml_gameboy(list[1]); - } -} - -void Cartridge::parse_xml_cartridge(const char *data) { - //reset cartridge information - information.nss.setting.reset(); - - xml_element document = xml_parse(data); - if(document.element.size() == 0) return; - - for(auto &head : document.element) { - if(head.name == "cartridge") { - for(auto &attr : head.attribute) { - if(attr.name == "region") { - if(attr.content == "NTSC") region = Region::NTSC; - if(attr.content == "PAL") region = Region::PAL; - } - } - - for(auto &node : head.element) { - if(node.name == "rom") xml_parse_rom(node); - if(node.name == "ram") xml_parse_ram(node); - if(node.name == "nss") xml_parse_nss(node); - if(node.name == "icd2") xml_parse_icd2(node); - if(node.name == "superfx") xml_parse_superfx(node); - if(node.name == "sa1") xml_parse_sa1(node); - if(node.name == "necdsp") xml_parse_necdsp(node); - if(node.name == "hitachidsp") xml_parse_hitachidsp(node); - if(node.name == "bsx") xml_parse_bsx(node); - if(node.name == "sufamiturbo") xml_parse_sufamiturbo(node); - if(node.name == "srtc") xml_parse_srtc(node); - if(node.name == "sdd1") xml_parse_sdd1(node); - if(node.name == "spc7110") xml_parse_spc7110(node); - if(node.name == "obc1") xml_parse_obc1(node); - if(node.name == "setarisc") xml_parse_setarisc(node); - if(node.name == "msu1") xml_parse_msu1(node); - if(node.name == "link") xml_parse_link(node); - } - } - } -} - -void Cartridge::parse_xml_bsx(const char *data) { - has_bsx_slot = true; -} - -void Cartridge::parse_xml_sufami_turbo(const char *data, bool slot) { -} - -void Cartridge::parse_xml_gameboy(const char *data) { -} - -void Cartridge::xml_parse_rom(xml_element &root) { - for(auto &leaf : root.element) { - if(leaf.name == "map") { - Mapping m(rom); - for(auto &attr : leaf.attribute) { - if(attr.name == "address") xml_parse_address(m, attr.content); - if(attr.name == "mode") xml_parse_mode(m, attr.content); - if(attr.name == "offset") m.offset = xml_parse_hex(attr.content); - if(attr.name == "size") m.size = xml_parse_hex(attr.content); - } - if(m.size == 0) m.size = rom.size(); - mapping.append(m); - } - } -} - -void Cartridge::xml_parse_ram(xml_element &root) { - for(auto &attr : root.attribute) { - if(attr.name == "size") ram_size = xml_parse_hex(attr.content); - } - - for(auto &leaf : root.element) { - if(leaf.name == "map") { - Mapping m(ram); - for(auto &attr : leaf.attribute) { - if(attr.name == "address") xml_parse_address(m, attr.content); - if(attr.name == "mode") xml_parse_mode(m, attr.content); - if(attr.name == "offset") m.offset = xml_parse_hex(attr.content); - if(attr.name == "size") m.size = xml_parse_hex(attr.content); - } - if(m.size == 0) m.size = ram_size; - mapping.append(m); - } - } -} - -void Cartridge::xml_parse_nss(xml_element &root) { - has_nss_dip = true; - - for(auto &node : root.element) { - if(node.name == "setting") { - unsigned number = information.nss.setting.size(); - if(number >= 16) break; //more than 16 DIP switches is not possible - - information.nss.option[number].reset(); - for(auto &attr : node.attribute) { - if(attr.name == "name") { - information.nss.setting[number] = attr.parse(); - } - } - for(auto &leaf : node.element) { - string name; - unsigned value = 0x0000; - for(auto &attr : leaf.attribute) { - if(attr.name == "name") name = attr.parse(); - if(attr.name == "value") value = (uint16)xml_parse_hex(attr.content); - } - information.nss.option[number].append({ hex<4>(value), ":", name }); - } - } - } -} - -void Cartridge::xml_parse_icd2(xml_element &root) { - if(mode != Mode::SuperGameBoy) return; - icd2.revision = 1; - - for(auto &attr : root.attribute) { - if(attr.name == "revision") { - if(attr.content == "1") icd2.revision = 1; - if(attr.content == "2") icd2.revision = 2; - } - } - - for(auto &node : root.element) { - if(node.name == "map") { - Mapping m({ &ICD2::read, &icd2 }, { &ICD2::write, &icd2 }); - for(auto &attr : node.attribute) { - if(attr.name == "address") xml_parse_address(m, attr.content); - } - mapping.append(m); - } - } -} - -void Cartridge::xml_parse_superfx(xml_element &root) { - has_superfx = true; - - for(auto &node : root.element) { - if(node.name == "rom") { - for(auto &leaf : node.element) { - if(leaf.name == "map") { - Mapping m(superfx.rom); - for(auto &attr : leaf.attribute) { - if(attr.name == "address") xml_parse_address(m, attr.content); - if(attr.name == "mode") xml_parse_mode(m, attr.content); - if(attr.name == "offset") m.offset = xml_parse_hex(attr.content); - if(attr.name == "size") m.size = xml_parse_hex(attr.content); - } - mapping.append(m); - } - } - } else if(node.name == "ram") { - for(auto &attr : node.attribute) { - if(attr.name == "size") ram_size = xml_parse_hex(attr.content); - } - - for(auto &leaf : node.element) { - if(leaf.name == "map") { - Mapping m(superfx.ram); - for(auto &attr : leaf.attribute) { - if(attr.name == "address") xml_parse_address(m, attr.content); - if(attr.name == "mode") xml_parse_mode(m, attr.content); - if(attr.name == "offset") m.offset = xml_parse_hex(attr.content); - if(attr.name == "size") m.size = xml_parse_hex(attr.content); - } - if(m.size == 0) m.size = ram_size; - mapping.append(m); - } - } - } else if(node.name == "mmio") { - for(auto &leaf : node.element) { - if(leaf.name == "map") { - Mapping m({ &SuperFX::mmio_read, &superfx }, { &SuperFX::mmio_write, &superfx }); - for(auto &attr : leaf.attribute) { - if(attr.name == "address") xml_parse_address(m, attr.content); - } - mapping.append(m); - } - } - } - } -} - -void Cartridge::xml_parse_sa1(xml_element &root) { - has_sa1 = true; - - for(auto &node : root.element) { - if(node.name == "mcu") { - for(auto &subnode : node.element) { - if(subnode.name == "rom") { - for(auto &leaf : subnode.element) { - if(leaf.name == "map") { - Mapping m({ &SA1::mmc_read, &sa1 }, { &SA1::mmc_write, &sa1 }); - for(auto &attr : leaf.attribute) { - if(attr.name == "address") xml_parse_address(m, attr.content); - if(attr.name == "mode") xml_parse_mode(m, attr.content); - if(attr.name == "offset") m.offset = xml_parse_hex(attr.content); - if(attr.name == "size") m.size = xml_parse_hex(attr.content); - } - mapping.append(m); - } - } - } else if(subnode.name == "ram") { - for(auto &leaf : subnode.element) { - if(leaf.name == "map") { - Mapping m({ &SA1::mmc_cpu_read, &sa1 }, { &SA1::mmc_cpu_write, &sa1 }); - for(auto &attr : leaf.attribute) { - if(attr.name == "address") xml_parse_address(m, attr.content); - } - mapping.append(m); - } - } - } - } - } else if(node.name == "iram") { - for(auto &leaf : node.element) { - if(leaf.name == "map") { - Mapping m(sa1.cpuiram); - for(auto &attr : leaf.attribute) { - if(attr.name == "address") xml_parse_address(m, attr.content); - if(attr.name == "mode") xml_parse_mode(m, attr.content); - if(attr.name == "offset") m.offset = xml_parse_hex(attr.content); - if(attr.name == "size") m.size = xml_parse_hex(attr.content); - } - if(m.size == 0) m.size = 2048; - mapping.append(m); - } - } - } else if(node.name == "bwram") { - for(auto &attr : node.attribute) { - if(attr.name == "size") ram_size = xml_parse_hex(attr.content); - } - - for(auto &leaf : node.element) { - if(leaf.name == "map") { - Mapping m(sa1.cpubwram); - for(auto &attr : leaf.attribute) { - if(attr.name == "address") xml_parse_address(m, attr.content); - if(attr.name == "mode") xml_parse_mode(m, attr.content); - if(attr.name == "offset") m.offset = xml_parse_hex(attr.content); - if(attr.name == "size") m.size = xml_parse_hex(attr.content); - } - if(m.size == 0) m.size = ram_size; - mapping.append(m); - } - } - } else if(node.name == "mmio") { - for(auto &leaf : node.element) { - if(leaf.name == "map") { - Mapping m({ &SA1::mmio_read, &sa1 }, { &SA1::mmio_write, &sa1 }); - for(auto &attr : leaf.attribute) { - if(attr.name == "address") xml_parse_address(m, attr.content); - } - mapping.append(m); - } - } - } - } -} - -void Cartridge::xml_parse_necdsp(xml_element &root) { - has_necdsp = true; - necdsp.revision = NECDSP::Revision::uPD7725; - necdsp.frequency = 8000000; - - for(unsigned n = 0; n < 16384; n++) necdsp.programROM[n] = 0x000000; - for(unsigned n = 0; n < 2048; n++) necdsp.dataROM[n] = 0x0000; - - string firmware, sha256; - - for(auto &attr : root.attribute) { - if(attr.name == "model") { - if(attr.content == "uPD7725" ) necdsp.revision = NECDSP::Revision::uPD7725; - if(attr.content == "uPD96050") necdsp.revision = NECDSP::Revision::uPD96050; - } else if(attr.name == "frequency") { - necdsp.frequency = xml_parse_unsigned(attr.content); - } else if(attr.name == "firmware") { - firmware = attr.content; - } else if(attr.name == "sha256") { - sha256 = attr.content; - } - } - - string path = { dir(interface->path(Slot::Base, ".dsp")), firmware }; - unsigned promsize = (necdsp.revision == NECDSP::Revision::uPD7725 ? 2048 : 16384); - unsigned dromsize = (necdsp.revision == NECDSP::Revision::uPD7725 ? 1024 : 2048); - unsigned filesize = promsize * 3 + dromsize * 2; - - file fp; - if(fp.open(path, file::mode::read) == false) { - interface->message({ "Warning: NEC DSP firmware ", firmware, " is missing." }); - } else if(fp.size() != filesize) { - interface->message({ "Warning: NEC DSP firmware ", firmware, " is of the wrong file size." }); - fp.close(); - } else { - for(unsigned n = 0; n < promsize; n++) necdsp.programROM[n] = fp.readm(3); - for(unsigned n = 0; n < dromsize; n++) necdsp.dataROM[n] = fp.readm(2); - - if(sha256 != "") { - //XML file specified SHA256 sum for program. Verify file matches the hash. - fp.seek(0); - uint8_t data[filesize]; - fp.read(data, filesize); - - if(sha256 != nall::sha256(data, filesize)) { - interface->message({ "Warning: Hitachi DSP firmware ", firmware, " SHA256 sum is incorrect." }); - } - } - - fp.close(); - } - - for(auto &node : root.element) { - if(node.name == "dr") { - for(auto &leaf : node.element) { - if(leaf.name == "map") { - Mapping m({ &NECDSP::dr_read, &necdsp }, { &NECDSP::dr_write, &necdsp }); - for(auto &attr : leaf.attribute) { - if(attr.name == "address") xml_parse_address(m, attr.content); - } - mapping.append(m); - } - } - } else if(node.name == "sr") { - for(auto &leaf : node.element) { - if(leaf.name == "map") { - Mapping m({ &NECDSP::sr_read, &necdsp }, { &NECDSP::sr_write, &necdsp }); - for(auto &attr : leaf.attribute) { - if(attr.name == "address") xml_parse_address(m, attr.content); - } - mapping.append(m); - } - } - } else if(node.name == "dp") { - for(auto &leaf : node.element) { - if(leaf.name == "map") { - Mapping m({ &NECDSP::dp_read, &necdsp }, { &NECDSP::dp_write, &necdsp }); - for(auto &attr : leaf.attribute) { - if(attr.name == "address") xml_parse_address(m, attr.content); - } - mapping.append(m); - } - } - } - } -} - -void Cartridge::xml_parse_hitachidsp(xml_element &root) { - has_hitachidsp = true; - hitachidsp.frequency = 20000000; - - for(unsigned n = 0; n < 1024; n++) hitachidsp.dataROM[n] = 0x000000; - - string firmware, sha256; - - for(auto &attr : root.attribute) { - if(attr.name == "frequency") { - hitachidsp.frequency = xml_parse_unsigned(attr.content); - } else if(attr.name == "firmware") { - firmware = attr.content; - } else if(attr.name == "sha256") { - sha256 = attr.content; - } - } - - string path = { dir(interface->path(Slot::Base, ".dsp")), firmware }; - file fp; - if(fp.open(path, file::mode::read) == false) { - interface->message({ "Warning: Hitachi DSP firmware ", firmware, " is missing." }); - } else if(fp.size() != 1024 * 3) { - interface->message({ "Warning: Hitachi DSP firmware ", firmware, " is of the wrong file size." }); - fp.close(); - } else { - for(unsigned n = 0; n < 1024; n++) hitachidsp.dataROM[n] = fp.readl(3); - - if(sha256 != "") { - //XML file specified SHA256 sum for program. Verify file matches the hash. - fp.seek(0); - uint8 data[3072]; - fp.read(data, 3072); - - if(sha256 != nall::sha256(data, 3072)) { - interface->message({ "Warning: Hitachi DSP firmware ", firmware, " SHA256 sum is incorrect." }); - } - } - - fp.close(); - } - - for(auto &node : root.element) { - if(node.name == "rom") { - for(auto &leaf : node.element) { - if(leaf.name == "map") { - Mapping m({ &HitachiDSP::rom_read, &hitachidsp }, { &HitachiDSP::rom_write, &hitachidsp }); - for(auto &attr : leaf.attribute) { - if(attr.name == "address") xml_parse_address(m, attr.content); - if(attr.name == "mode") xml_parse_mode(m, attr.content); - if(attr.name == "offset") m.offset = xml_parse_hex(attr.content); - if(attr.name == "size") m.size = xml_parse_hex(attr.content); - } - mapping.append(m); - } - } - } - if(node.name == "mmio") { - for(auto &leaf : node.element) { - Mapping m({ &HitachiDSP::dsp_read, &hitachidsp }, { &HitachiDSP::dsp_write, &hitachidsp }); - for(auto &attr : leaf.attribute) { - if(attr.name == "address") xml_parse_address(m, attr.content); - } - mapping.append(m); - } - } - } -} - -void Cartridge::xml_parse_bsx(xml_element &root) { - if(mode != Mode::BsxSlotted && mode != Mode::Bsx) return; - - for(auto &node : root.element) { - if(node.name == "slot") { - for(auto &leaf : node.element) { - if(leaf.name == "map") { - Mapping m(bsxflash.memory); - for(auto &attr : leaf.attribute) { - if(attr.name == "address") xml_parse_address(m, attr.content); - if(attr.name == "mode") xml_parse_mode(m, attr.content); - if(attr.name == "offset") m.offset = xml_parse_hex(attr.content); - if(attr.name == "size") m.size = xml_parse_hex(attr.content); - } - mapping.append(m); - } - } - } else if(node.name == "mcu") { - for(auto &leaf : node.element) { - if(leaf.name == "map") { - Mapping m({ &BSXCartridge::mcu_read, &bsxcartridge }, { &BSXCartridge::mcu_write, &bsxcartridge }); - for(auto &attr : leaf.attribute) { - if(attr.name == "address") xml_parse_address(m, attr.content); - } - mapping.append(m); - } - } - } else if(node.name == "mmio") { - for(auto &leaf : node.element) { - if(leaf.name == "map") { - Mapping m({ &BSXCartridge::mmio_read, &bsxcartridge }, { &BSXCartridge::mmio_write, &bsxcartridge }); - for(auto &attr : leaf.attribute) { - if(attr.name == "address") xml_parse_address(m, attr.content); - } - mapping.append(m); - } - } - } - } -} - -void Cartridge::xml_parse_sufamiturbo(xml_element &root) { - if(mode != Mode::SufamiTurbo) return; - - for(auto &node : root.element) { - if(node.name == "slot") { - bool slotid = 0; - for(auto &attr : node.attribute) { - if(attr.name == "id") { - if(attr.content == "A") slotid = 0; - if(attr.content == "B") slotid = 1; - } - } - - for(auto &slot : node.element) { - if(slot.name == "rom") { - for(auto &leaf : slot.element) { - if(leaf.name == "map") { - Memory &memory = slotid == 0 ? sufamiturbo.slotA.rom : sufamiturbo.slotB.rom; - Mapping m(memory); - for(auto &attr : leaf.attribute) { - if(attr.name == "address") xml_parse_address(m, attr.content); - if(attr.name == "mode") xml_parse_mode(m, attr.content); - if(attr.name == "offset") m.offset = xml_parse_hex(attr.content); - if(attr.name == "size") m.size = xml_parse_hex(attr.content); - } - if(m.size == 0) m.size = memory.size(); - if(m.size) mapping.append(m); - } - } - } else if(slot.name == "ram") { - unsigned ram_size = 0; - - for(auto &attr : slot.attribute) { - if(attr.name == "size") ram_size = xml_parse_hex(attr.content); - } - - for(auto &leaf : slot.element) { - if(leaf.name == "map") { - Memory &memory = slotid == 0 ? sufamiturbo.slotA.ram : sufamiturbo.slotB.ram; - Mapping m(memory); - for(auto &attr : leaf.attribute) { - if(attr.name == "address") xml_parse_address(m, attr.content); - if(attr.name == "mode") xml_parse_mode(m, attr.content); - if(attr.name == "offset") m.offset = xml_parse_hex(attr.content); - if(attr.name == "size") m.size = xml_parse_hex(attr.content); - } - if(m.size == 0) m.size = ram_size; - if(m.size) mapping.append(m); - } - } - } - } - } - } -} - -void Cartridge::xml_parse_srtc(xml_element &root) { - has_srtc = true; - - for(auto &node : root.element) { - if(node.name == "map") { - Mapping m({ &SRTC::read, &srtc }, { &SRTC::write, &srtc }); - for(auto &attr : node.attribute) { - if(attr.name == "address") xml_parse_address(m, attr.content); - } - mapping.append(m); - } - } -} - -void Cartridge::xml_parse_sdd1(xml_element &root) { - has_sdd1 = true; - - for(auto &node : root.element) { - if(node.name == "mcu") { - for(auto &leaf : node.element) { - if(leaf.name == "map") { - Mapping m({ &SDD1::mcu_read, &sdd1 }, { &SDD1::mcu_write, &sdd1 }); - for(auto &attr : leaf.attribute) { - if(attr.name == "address") xml_parse_address(m, attr.content); - } - mapping.append(m); - } - } - } else if(node.name == "mmio") { - for(auto &leaf : node.element) { - if(leaf.name == "map") { - Mapping m({ &SDD1::mmio_read, &sdd1 }, { &SDD1::mmio_write, &sdd1 }); - for(auto &attr : leaf.attribute) { - if(attr.name == "address") xml_parse_address(m, attr.content); - } - mapping.append(m); - } - } - } - } -} - -void Cartridge::xml_parse_spc7110(xml_element &root) { - has_spc7110 = true; - spc7110.data_rom_offset = 0x100000; - - for(auto &node : root.element) { - if(node.name == "dcu") { - for(auto &leaf : node.element) { - if(leaf.name == "map") { - Mapping m({ &SPC7110::dcu_read, &spc7110 }, { &SPC7110::dcu_write, &spc7110 }); - for(auto &attr : leaf.attribute) { - if(attr.name == "address") xml_parse_address(m, attr.content); - } - mapping.append(m); - } - } - } else if(node.name == "mcu") { - for(auto &leaf : node.element) { - if(leaf.name == "map") { - Mapping m({ &SPC7110::mcu_read, &spc7110 }, { &SPC7110::mcu_write, &spc7110 }); - for(auto &attr : leaf.attribute) { - if(attr.name == "address") xml_parse_address(m, attr.content); - if(attr.name == "offset") spc7110.data_rom_offset = xml_parse_hex(attr.content); - } - mapping.append(m); - } - } - } else if(node.name == "mmio") { - for(auto &leaf : node.element) { - if(leaf.name == "map") { - Mapping m({ &SPC7110::mmio_read, &spc7110 }, { &SPC7110::mmio_write, &spc7110 }); - for(auto &attr : leaf.attribute) { - if(attr.name == "address") xml_parse_address(m, attr.content); - } - mapping.append(m); - } - } - } else if(node.name == "ram") { - for(auto &attr : node.attribute) { - if(attr.name == "size") ram_size = xml_parse_hex(attr.content); - } - - for(auto &leaf : node.element) { - if(leaf.name == "map") { - Mapping m({ &SPC7110::ram_read, &spc7110 }, { &SPC7110::ram_write, &spc7110 }); - for(auto &attr : leaf.attribute) { - if(attr.name == "address") xml_parse_address(m, attr.content); - if(attr.name == "mode") xml_parse_mode(m, attr.content); - if(attr.name == "offset") m.offset = xml_parse_hex(attr.content); - if(attr.name == "size") m.size = xml_parse_hex(attr.content); - } - mapping.append(m); - } - } - } else if(node.name == "rtc") { - has_spc7110rtc = true; - - for(auto &leaf : node.element) { - if(leaf.name == "map") { - Mapping m({ &SPC7110::mmio_read, &spc7110 }, { &SPC7110::mmio_write, &spc7110 }); - for(auto &attr : leaf.attribute) { - if(attr.name == "address") xml_parse_address(m, attr.content); - } - mapping.append(m); - } - } - } - } -} - -void Cartridge::xml_parse_obc1(xml_element &root) { - has_obc1 = true; - - for(auto &node : root.element) { - if(node.name == "map") { - Mapping m({ &OBC1::read, &obc1 }, { &OBC1::write, &obc1 }); - for(auto &attr : node.attribute) { - if(attr.name == "address") xml_parse_address(m, attr.content); - } - mapping.append(m); - } - } -} - -void Cartridge::xml_parse_setarisc(xml_element &root) { - has_st0018 = true; - - for(auto &node : root.element) { - if(node.name == "map") { - Mapping m({ &ST0018::mmio_read, &st0018 }, { &ST0018::mmio_write, &st0018 }); - for(auto &attr : node.attribute) { - if(attr.name == "address") xml_parse_address(m, attr.content); - } - mapping.append(m); - } - } -} - -void Cartridge::xml_parse_msu1(xml_element &root) { - has_msu1 = true; - - for(auto &node : root.element) { - if(node.name == "map") { - Mapping m({ &MSU1::mmio_read, &msu1 }, { &MSU1::mmio_write, &msu1 }); - for(auto &attr : node.attribute) { - if(attr.name == "address") xml_parse_address(m, attr.content); - } - mapping.append(m); - } - } -} - -void Cartridge::xml_parse_link(xml_element &root) { - has_link = true; - link.frequency = 1; - link.program = ""; - - for(auto &attr : root.attribute) { - if(attr.name == "frequency") link.frequency = xml_parse_unsigned(attr.content); - if(attr.name == "program") link.program = attr.content; - } - - for(auto &node : root.element) { - if(node.name == "map") { - Mapping m({ &Link::read, &link }, { &Link::write, &link }); - for(auto &attr : node.attribute) { - if(attr.name == "address") xml_parse_address(m, attr.content); - } - mapping.append(m); - } - } -} - -unsigned Cartridge::xml_parse_hex(const string &s) { - return hex(s); -} - -unsigned Cartridge::xml_parse_unsigned(const string &s) { - if(s.beginswith("0x")) return hex(s); - return integer(s); -} - -void Cartridge::xml_parse_address(Mapping &m, const string &data) { - lstring part; - part.split(":", data); - if(part.size() != 2) return; - - lstring subpart; - subpart.split("-", part[0]); - if(subpart.size() == 1) { - m.banklo = hex(subpart[0]); - m.bankhi = m.banklo; - } else if(subpart.size() == 2) { - m.banklo = hex(subpart[0]); - m.bankhi = hex(subpart[1]); - } - - subpart.split("-", part[1]); - if(subpart.size() == 1) { - m.addrlo = hex(subpart[0]); - m.addrhi = m.addrlo; - } else if(subpart.size() == 2) { - m.addrlo = hex(subpart[0]); - m.addrhi = hex(subpart[1]); - } -} - -void Cartridge::xml_parse_mode(Mapping &m, const string& data) { - if(data == "direct") m.mode = Bus::MapMode::Direct; - else if(data == "linear") m.mode = Bus::MapMode::Linear; - else if(data == "shadow") m.mode = Bus::MapMode::Shadow; -} - -Cartridge::Mapping::Mapping() { - mode = Bus::MapMode::Direct; - banklo = bankhi = addrlo = addrhi = offset = size = 0; -} - -Cartridge::Mapping::Mapping(Memory &memory) { - read = { &Memory::read, &memory }; - write = { &Memory::write, &memory }; - mode = Bus::MapMode::Direct; - banklo = bankhi = addrlo = addrhi = offset = size = 0; -} - -Cartridge::Mapping::Mapping(const function &read_, const function &write_) { - read = read_; - write = write_; - mode = Bus::MapMode::Direct; - banklo = bankhi = addrlo = addrhi = offset = size = 0; -} - -#endif diff --git a/bsnes/snes/interface/interface.cpp b/bsnes/snes/interface/interface.cpp index 334dfdce..75ab28b7 100755 --- a/bsnes/snes/interface/interface.cpp +++ b/bsnes/snes/interface/interface.cpp @@ -29,21 +29,21 @@ bool Interface::cartridgeLoaded() { void Interface::loadCartridge(const CartridgeData &base) { cartridge.rom.copy(base.data, base.size); - cartridge.load(Cartridge::Mode::Normal, { base.xml }); + cartridge.load(Cartridge::Mode::Normal, base.markup); system.power(); } void Interface::loadSatellaviewSlottedCartridge(const CartridgeData &base, const CartridgeData &slot) { cartridge.rom.copy(base.data, base.size); if(slot.data) bsxflash.memory.copy(slot.data, slot.size); - cartridge.load(Cartridge::Mode::BsxSlotted, { base.xml, slot.xml }); + cartridge.load(Cartridge::Mode::BsxSlotted, base.markup); system.power(); } void Interface::loadSatellaviewCartridge(const CartridgeData &base, const CartridgeData &slot) { cartridge.rom.copy(base.data, base.size); if(slot.data) bsxflash.memory.copy(slot.data, slot.size); - cartridge.load(Cartridge::Mode::Bsx, { base.xml, slot.xml }); + cartridge.load(Cartridge::Mode::Bsx, base.markup); system.power(); } @@ -51,14 +51,14 @@ void Interface::loadSufamiTurboCartridge(const CartridgeData &base, const Cartri cartridge.rom.copy(base.data, base.size); if(slotA.data) sufamiturbo.slotA.rom.copy(slotA.data, slotA.size); if(slotB.data) sufamiturbo.slotB.rom.copy(slotB.data, slotB.size); - cartridge.load(Cartridge::Mode::SufamiTurbo, { base.xml, slotA.xml, slotB.xml }); + cartridge.load(Cartridge::Mode::SufamiTurbo, base.markup); system.power(); } void Interface::loadSuperGameBoyCartridge(const CartridgeData &base, const CartridgeData &slot) { cartridge.rom.copy(base.data, base.size); - GameBoy::cartridge.load(slot.xml, slot.data, slot.size); - cartridge.load(Cartridge::Mode::SuperGameBoy, { base.xml, "" }); + GameBoy::cartridge.load(slot.markup, slot.data, slot.size); + cartridge.load(Cartridge::Mode::SuperGameBoy, base.markup); system.power(); } diff --git a/bsnes/snes/interface/interface.hpp b/bsnes/snes/interface/interface.hpp index f2d75638..d4be719c 100755 --- a/bsnes/snes/interface/interface.hpp +++ b/bsnes/snes/interface/interface.hpp @@ -8,7 +8,7 @@ struct Interface { virtual void connect(bool port, Input::Device device); struct CartridgeData { - string xml; + string markup; const uint8_t *data; unsigned size; }; diff --git a/bsnes/ui/interface/gameboy.cpp b/bsnes/ui/interface/gameboy.cpp index a8bf1bbe..748abed6 100755 --- a/bsnes/ui/interface/gameboy.cpp +++ b/bsnes/ui/interface/gameboy.cpp @@ -7,7 +7,7 @@ bool InterfaceGameBoy::loadCartridge(const string &filename) { interface->baseName = nall::basename(filename); GameBoyCartridge info(data, size); - GameBoy::Interface::loadCartridge(info.xml, data, size); + GameBoy::Interface::loadCartridge(info.markup, data, size); delete[] data; if(GameBoy::Interface::memorySize(GameBoy::Interface::Memory::RAM) > 0) { diff --git a/bsnes/ui/interface/nes.cpp b/bsnes/ui/interface/nes.cpp index 6e80b585..8c3b6991 100755 --- a/bsnes/ui/interface/nes.cpp +++ b/bsnes/ui/interface/nes.cpp @@ -71,13 +71,7 @@ bool InterfaceNES::loadState(const string &filename) { void InterfaceNES::videoRefresh(const uint16_t *data) { static uint16_t output[256 * 240]; - unsigned height = 240; - if(config->video.enableOverscan == false) { - height = 224; - data += 8 * 256; - } - - for(unsigned y = 0; y < height; y++) { + for(unsigned y = 0; y < 240; y++) { const uint16_t *sp = data + y * 256; uint16_t *dp = output + y * 256; for(unsigned x = 0; x < 256; x++) { @@ -86,7 +80,19 @@ void InterfaceNES::videoRefresh(const uint16_t *data) { } } - interface->videoRefresh(output, 256 * 2, 256, height); + if(config->video.enableOverscan == false) { + for(unsigned y = 0; y < 240; y++) { + uint16_t *dp = output + y * 256; + if(y < 16 || y >= 224) { + memset(dp, 0, 256 * 2); + } else { + memset(dp + 0, 0, 8 * 2); + memset(dp + 248, 0, 8 * 2); + } + } + } + + interface->videoRefresh(output, 256 * 2, 256, 240); } void InterfaceNES::audioSample(int16_t sample) { diff --git a/bsnes/ui/interface/snes.cpp b/bsnes/ui/interface/snes.cpp index 54e8498f..87baa3b3 100755 --- a/bsnes/ui/interface/snes.cpp +++ b/bsnes/ui/interface/snes.cpp @@ -30,11 +30,11 @@ bool InterfaceSNES::loadCartridge(const string &basename) { interface->baseName = nall::basename(basename); interface->slotName = { nall::basename(basename) }; - string xml; - xml.readfile({ interface->baseName, ".xml" }); - if(xml == "") xml = SNESCartridge(data, size).xmlMemoryMap; + string markup; + markup.readfile({ interface->baseName, ".bml" }); + if(markup == "") markup = SnesCartridge(data, size).markup; - SNES::Interface::loadCartridge({ xml, data, size }); + SNES::Interface::loadCartridge({ markup, data, size }); delete[] data; loadMemory(); @@ -53,11 +53,11 @@ bool InterfaceSNES::loadSatellaviewSlottedCartridge(const string &basename, cons if(data[1]) interface->baseName.append("+", nall::basename(notdir(slotname))); interface->slotName = { nall::basename(basename), nall::basename(slotname) }; - string xml; - xml.readfile({ interface->baseName, ".xml" }); - if(xml == "") xml = SNESCartridge(data[0], size[0]).xmlMemoryMap; + string markup; + markup.readfile({ interface->baseName, ".bml" }); + if(markup == "") markup = SnesCartridge(data[0], size[0]).markup; - SNES::Interface::loadSatellaviewSlottedCartridge({ xml, data[0], size[0] }, { "", data[1], size[1] }); + SNES::Interface::loadSatellaviewSlottedCartridge({ markup, data[0], size[0] }, { "", data[1], size[1] }); delete[] data[0]; if(data[1]) delete[] data[1]; @@ -77,11 +77,11 @@ bool InterfaceSNES::loadSatellaviewCartridge(const string &basename, const strin if(data[1]) interface->baseName.append("+", nall::basename(notdir(slotname))); interface->slotName = { nall::basename(basename), nall::basename(slotname) }; - string xml; - xml.readfile({ interface->baseName, ".xml" }); - if(xml == "") xml = SNESCartridge(data[0], size[0]).xmlMemoryMap; + string markup; + markup.readfile({ interface->baseName, ".bml" }); + if(markup == "") markup = SnesCartridge(data[0], size[0]).markup; - SNES::Interface::loadSatellaviewCartridge({ xml, data[0], size[0] }, { "", data[1], size[1] }); + SNES::Interface::loadSatellaviewCartridge({ markup, data[0], size[0] }, { "", data[1], size[1] }); delete[] data[0]; if(data[1]) delete[] data[1]; @@ -104,11 +104,11 @@ bool InterfaceSNES::loadSufamiTurboCartridge(const string &basename, const strin else if(data[2]) interface->baseName = nall::basename(slotBname); interface->slotName = { nall::basename(basename), nall::basename(slotAname), nall::basename(slotBname) }; - string xml; - xml.readfile({ interface->baseName, ".xml" }); - if(xml == "") xml = SNESCartridge(data[0], size[0]).xmlMemoryMap; + string markup; + markup.readfile({ interface->baseName, ".bml" }); + if(markup == "") markup = SnesCartridge(data[0], size[0]).markup; - SNES::Interface::loadSufamiTurboCartridge({ xml, data[0], size[0] }, { "", data[1], size[1] }, { "", data[2], size[2] }); + SNES::Interface::loadSufamiTurboCartridge({ markup, data[0], size[0] }, { "", data[1], size[1] }, { "", data[2], size[2] }); delete[] data[0]; if(data[1]) delete[] data[1]; if(data[2]) delete[] data[2]; @@ -129,14 +129,14 @@ bool InterfaceSNES::loadSuperGameBoyCartridge(const string &basename, const stri if(data[1]) interface->baseName = nall::basename(slotname); interface->slotName = { nall::basename(basename), nall::basename(slotname) }; - string xml; - xml.readfile({ interface->baseName, ".xml" }); - if(xml == "") xml = SNESCartridge(data[0], size[0]).xmlMemoryMap; + string markup; + markup.readfile({ interface->baseName, ".bml" }); + if(markup == "") markup = SnesCartridge(data[0], size[0]).markup; - string gbXml; - gbXml.readfile({ nall::basename(slotname), ".xml" }); - if(gbXml == "") gbXml = GameBoyCartridge(data[1], size[1]).xml; - SNES::Interface::loadSuperGameBoyCartridge({ xml, data[0], size[0] }, { gbXml, data[1], size[1] }); + string gbMarkup; + gbMarkup.readfile({ nall::basename(slotname), ".bml" }); + if(gbMarkup == "") gbMarkup = GameBoyCartridge(data[1], size[1]).markup; + SNES::Interface::loadSuperGameBoyCartridge({ markup, data[0], size[0] }, { gbMarkup, data[1], size[1] }); delete[] data[0]; if(data[1]) delete[] data[1]; @@ -194,21 +194,14 @@ bool InterfaceSNES::loadState(const string &filename) { // void InterfaceSNES::videoRefresh(const uint32_t *data, bool hires, bool interlace, bool overscan) { - static uint16_t output[512 * 478]; + static uint16_t output[512 * 480]; unsigned width = 256 << hires; - unsigned height = (config->video.enableOverscan ? 240 : 224) << interlace; + unsigned height = 240 << interlace; unsigned pitch = 1024 >> interlace; - //data[] = scanline { 8 (blank) + 240 (video) + 8 (blank) } - //first line of video data is not rendered (effectively blank as well) - if(config->video.enableOverscan) { - if(overscan == false) data += 1 * 1024; // 8 + 224 + 8 - if(overscan == true ) data += 9 * 1024; // 0 + 240 + 0 - } else { - if(overscan == false) data += 9 * 1024; // 0 + 224 + 0 - if(overscan == true ) data += 16 * 1024; //-8 + 224 + -8 - } + if(overscan == false) data += 1 * 1024; // 8 + 224 + 8 + if(overscan == true ) data += 9 * 1024; // 0 + 240 + 0 for(unsigned y = 0; y < height; y++) { const uint32_t *sp = data + y * pitch; @@ -218,6 +211,15 @@ void InterfaceSNES::videoRefresh(const uint32_t *data, bool hires, bool interlac } } + if(config->video.enableOverscan == false) { + unsigned mask = 8 << interlace; + for(unsigned y = 0; y < height; y++) { + if(y < mask || y >= height - mask) { + memset(output + y * 512, 0, width * 2); + } + } + } + interface->videoRefresh(output, 512 * 2, width, height); } diff --git a/bsnes/ui/main.cpp b/bsnes/ui/main.cpp index e8ec4715..96c25d75 100755 --- a/bsnes/ui/main.cpp +++ b/bsnes/ui/main.cpp @@ -49,7 +49,7 @@ Application::Application(int argc, char **argv) { inputManager = new InputManager; utility = new Utility; - title = "bsnes v082.28"; + title = "bsnes v082.29"; string fontFamily = Intrinsics::platform() == Intrinsics::Platform::Windows ? "Tahoma, " : "Sans, "; normalFont = { fontFamily, "8" }; diff --git a/bsnes/ui/tools/cheat-editor.cpp b/bsnes/ui/tools/cheat-editor.cpp index 90238170..87d88cc2 100755 --- a/bsnes/ui/tools/cheat-editor.cpp +++ b/bsnes/ui/tools/cheat-editor.cpp @@ -129,7 +129,7 @@ bool CheatEditor::load(const string &filename) { if(data.readfile(filename) == false) return false; unsigned n = 0; - BML::Node document(data); + BML::Document document(data); for(auto &cheat : document["cartridge"]) { if(cheat.name != "cheat") continue; cheatList.setChecked(n, cheat["enable"].exists()); @@ -161,11 +161,11 @@ bool CheatEditor::save(const string &filename) { file fp; if(fp.open(filename, file::mode::write) == false) return false; - fp.print("cartridge sha256{", interface->sha256(), "}\n"); + fp.print("cartridge sha256:", interface->sha256(), "\n"); for(unsigned n = 0; n <= lastSave; n++) { fp.print("\tcheat", cheatList.checked(n) ? " enable" : "", "\n"); - fp.print("\t\tdescription{", BML::encode(cheatText[n][Desc]), "}\n"); - fp.print("\t\tcode{", BML::encode(cheatText[n][Code]), "}\n"); + fp.print("\t\tdescription:", cheatText[n][Desc], "\n"); + fp.print("\t\tcode:", cheatText[n][Code], "\n"); } fp.close(); diff --git a/bsnes/ui/utility/utility.cpp b/bsnes/ui/utility/utility.cpp index 4c0cc05c..f224acd8 100755 --- a/bsnes/ui/utility/utility.cpp +++ b/bsnes/ui/utility/utility.cpp @@ -43,14 +43,14 @@ void Utility::resizeMainWindow(bool shrink) { unsigned width = geometry.width, height = geometry.height; switch(interface->mode()) { - case Interface::Mode::NES: width = 256, height = config->video.enableOverscan ? 240 : 224; break; - case Interface::Mode::SNES: width = 256, height = config->video.enableOverscan ? 240 : 224; break; + case Interface::Mode::NES: width = 256, height = 240; break; + case Interface::Mode::SNES: width = 256, height = 240; break; case Interface::Mode::GameBoy: width = 160, height = 144; break; } if(config->video.correctAspectRatio) { if(interface->mode() != Interface::Mode::GameBoy) { - width = (double)width * (config->video.enableOverscan ? 1.225 : 1.149); + width = (double)width * 1.226; } }