From 7115047d85cd25608eecdd447157649264bcc032 Mon Sep 17 00:00:00 2001 From: Tim Allen Date: Thu, 29 Sep 2011 22:44:49 +1000 Subject: [PATCH] Update to v082r26 release. byuu says: .cht files now use BML-formatted data. I'm still going to request the cheats.xml file as-is, and will write my own converter for embedding during releases. This is where parsing 2MB markup files in 10ms is really going to be nice. Had to use an evil hack before for actually searching for games. This has the start of the board/chip separation from mappers for NES, and it has a barebones iNES->board markup converter. You can specify your own board markup and bypass the need for an iNES header, so in other words it will load No-Intro style games with a proper board file. Long-term, we'll have an internal database for commercial boards, and probably folder.fc/prg.rom{,chr.rom} loading support. Since they can't co-exist, the mappers are currently disabled, and I've only ported the easy ones. So no MMC1/MMC3/VRC6 in this release. I need to make them into chips first. --- bsnes/nall/lzss.hpp | 2 +- bsnes/nall/string.hpp | 3 + bsnes/nall/string/bml.hpp | 127 +++++++++++++++++++++++++ bsnes/nall/string/bsv.hpp | 117 +++++++++++------------ bsnes/nes/Makefile | 6 +- bsnes/nes/cartridge/board/axrom.cpp | 50 ++++++++++ bsnes/nes/cartridge/board/board.cpp | 139 ++++++++++++++++------------ bsnes/nes/cartridge/board/board.hpp | 33 +++++-- bsnes/nes/cartridge/board/cnrom.cpp | 54 +++++++++++ bsnes/nes/cartridge/board/nrom.cpp | 27 ++---- bsnes/nes/cartridge/board/sxrom.cpp | 29 ++++++ bsnes/nes/cartridge/board/uxrom.cpp | 54 +++++++++++ bsnes/nes/cartridge/cartridge.cpp | 91 +++--------------- bsnes/nes/cartridge/cartridge.hpp | 16 +--- bsnes/nes/cartridge/chip/chip.cpp | 0 bsnes/nes/cartridge/chip/chip.hpp | 2 + bsnes/nes/cartridge/ines.cpp | 66 +++++++++++++ bsnes/nes/interface/interface.cpp | 4 +- bsnes/nes/interface/interface.hpp | 2 +- bsnes/nes/nes.hpp | 3 +- bsnes/ui/interface/nes.cpp | 6 +- bsnes/ui/main.cpp | 2 +- bsnes/ui/tools/cheat-editor.cpp | 49 +++------- 23 files changed, 597 insertions(+), 285 deletions(-) create mode 100755 bsnes/nall/string/bml.hpp create mode 100755 bsnes/nes/cartridge/board/axrom.cpp create mode 100755 bsnes/nes/cartridge/board/cnrom.cpp create mode 100755 bsnes/nes/cartridge/board/sxrom.cpp create mode 100755 bsnes/nes/cartridge/board/uxrom.cpp create mode 100755 bsnes/nes/cartridge/chip/chip.cpp create mode 100755 bsnes/nes/cartridge/chip/chip.hpp create mode 100755 bsnes/nes/cartridge/ines.cpp diff --git a/bsnes/nall/lzss.hpp b/bsnes/nall/lzss.hpp index 521b36c6..fb3e0ba6 100755 --- a/bsnes/nall/lzss.hpp +++ b/bsnes/nall/lzss.hpp @@ -34,7 +34,7 @@ protected: unsigned sourceSize; public: - inline lzss() : sourceData(nullptr), sourceSize(nullptr) {} + inline lzss() : sourceData(nullptr), sourceSize(0) {} }; void lzss::source(const uint8_t *data, unsigned size) { diff --git a/bsnes/nall/string.hpp b/bsnes/nall/string.hpp index 3dcd53fa..4a21e202 100755 --- a/bsnes/nall/string.hpp +++ b/bsnes/nall/string.hpp @@ -20,7 +20,9 @@ #include +#define NALL_STRING_INTERNAL_HPP #include +#include #include #include #include @@ -38,5 +40,6 @@ #include #include #include +#undef NALL_STRING_INTERNAL_HPP #endif diff --git a/bsnes/nall/string/bml.hpp b/bsnes/nall/string/bml.hpp new file mode 100755 index 00000000..b3bc1a33 --- /dev/null +++ b/bsnes/nall/string/bml.hpp @@ -0,0 +1,127 @@ +#ifdef NALL_STRING_INTERNAL_HPP + +//BML parser +//version 0.02 + +namespace nall { +namespace BML { + +struct Node : linear_vector { + Node *parent; + const char *cname; + const char *cvalue; + + inline string name() { return cname; } + inline string value() { return cvalue; } + +private: + 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; + if(p == '.' || p == '_') return true; + if(p == ':') return true; + return false; + } + + inline bool space(char p) const { + return p == ' ' || p == '\t'; + } + + inline unsigned parseDepth(char *p) { + unsigned depth = 0; + while(space(*p)) depth++, p++; + return depth; + } + + inline void parseNode(char *&p) { + if(valid(*p)) { + cname = p; + while(valid(*p)) p++; + if(*p != '=') return; + *p++ = 0; + } + if(*p == '\n') throw "Missing node value"; + + if(valid(*p)) { + cvalue = p; + while(valid(*p)) p++; + } else { + char terminal = *p++; + cvalue = p; + while(*p && *p != terminal) p++; + if(*p == 0) throw "Unclosed terminal"; + *p++ = 0; + } + } + + inline void parseLine(char *&p) { + unsigned depth = parseDepth(p); + while(space(*p)) p++; + parseNode(p); + + while(space(*p)) { + *p++ = 0; + Node node(this); + node.parseNode(p); + append(node); + } + + if(*p == '\n') *p++ = 0; + + while(parseDepth(p) > depth) { + Node node(this); + node.parseLine(p); + append(node); + } + } + + inline void parse(char *&p, unsigned parentDepth = 0) { + while(*p) { + while(*p == '\n') *p++ = 0; + Node node(this); + node.parseLine(p); + append(node); + } + } + +public: + inline Node& operator[](const string &name) { + for(auto &node : *this) { + if(!strcmp(node.cname, name)) return node; + } + static Node node; + return node; + } + + inline bool exists() { + return parent != nullptr; + } + + inline string content(const string &separator = "\n") const { + string result; + for(auto &node : *this) result.append(node.cvalue, separator); + result.rtrim<1>(separator); + return result; + } + + inline Node(const string &document) : parent(nullptr), cname(nullptr), cvalue(nullptr) { + char *p = strdup(document); + cvalue = p; + try { + parse(p); + } catch(const char *error) { + reset(); + } + } + + inline Node(Node *parent) : parent(parent), cname(""), cvalue("") {} + inline Node() : parent(nullptr), cname(""), cvalue("") {} + inline ~Node() { if(cname == nullptr && cvalue) free((void*)cvalue); } +}; + +} +} + +#endif diff --git a/bsnes/nall/string/bsv.hpp b/bsnes/nall/string/bsv.hpp index d4b919e0..8198c55c 100755 --- a/bsnes/nall/string/bsv.hpp +++ b/bsnes/nall/string/bsv.hpp @@ -1,74 +1,75 @@ -#ifndef NALL_STRING_BSV_HPP -#define NALL_STRING_BSV_HPP +#ifdef NALL_STRING_INTERNAL_HPP //BSV parser -//version 0.01 +//version 0.02 namespace nall { -inline string bsv_decode(const char *input) { - string output; - unsigned offset = 0; - while(*input) { - //illegal characters - if(*input == '}' ) return ""; - if(*input == '\r') return ""; - if(*input == '\n') return ""; +struct BSV { + static inline string decode(const char *input) { + string output; + unsigned offset = 0; + while(*input) { + //illegal characters + if(*input == '}' ) return ""; + if(*input == '\r') return ""; + if(*input == '\n') return ""; - //normal characters - if(*input != '{') { output[offset++] = *input++; continue; } + //normal characters + if(*input != '{') { output[offset++] = *input++; continue; } - //entities - if(strbegin(input, "{lf}")) { output[offset++] = '\n'; input += 4; continue; } - if(strbegin(input, "{lb}")) { output[offset++] = '{'; input += 4; continue; } - if(strbegin(input, "{rb}")) { output[offset++] = '}'; input += 4; continue; } + //entities + if(strbegin(input, "{lf}")) { output[offset++] = '\n'; input += 4; continue; } + if(strbegin(input, "{lb}")) { output[offset++] = '{'; input += 4; continue; } + if(strbegin(input, "{rb}")) { output[offset++] = '}'; input += 4; continue; } - //illegal entities - return ""; + //illegal entities + return ""; + } + output[offset] = 0; + return output; } - output[offset] = 0; - return output; -} -inline string bsv_encode(const char *input) { - string output; - unsigned offset = 0; - while(*input) { - //illegal characters - if(*input == '\r') return ""; + static inline string encode(const char *input) { + string output; + unsigned offset = 0; + while(*input) { + //illegal characters + if(*input == '\r') return ""; - if(*input == '\n') { - output[offset++] = '{'; - output[offset++] = 'l'; - output[offset++] = 'f'; - output[offset++] = '}'; - input++; - continue; + if(*input == '\n') { + output[offset++] = '{'; + output[offset++] = 'l'; + output[offset++] = 'f'; + output[offset++] = '}'; + input++; + continue; + } + + if(*input == '{') { + output[offset++] = '{'; + output[offset++] = 'l'; + output[offset++] = 'b'; + output[offset++] = '}'; + input++; + continue; + } + + if(*input == '}') { + output[offset++] = '{'; + output[offset++] = 'r'; + output[offset++] = 'b'; + output[offset++] = '}'; + input++; + continue; + } + + output[offset++] = *input++; } - - if(*input == '{') { - output[offset++] = '{'; - output[offset++] = 'l'; - output[offset++] = 'b'; - output[offset++] = '}'; - input++; - continue; - } - - if(*input == '}') { - output[offset++] = '{'; - output[offset++] = 'r'; - output[offset++] = 'b'; - output[offset++] = '}'; - input++; - continue; - } - - output[offset++] = *input++; + output[offset] = 0; + return output; } - output[offset] = 0; - return output; -} +}; } diff --git a/bsnes/nes/Makefile b/bsnes/nes/Makefile index 8e815ae0..6bf1c78f 100755 --- a/bsnes/nes/Makefile +++ b/bsnes/nes/Makefile @@ -1,6 +1,5 @@ nes_objects := nes-interface nes-system nes-scheduler nes-input -nes_objects += nes-mapper nes-cartridge nes-memory -nes_objects += nes-cpu nes-apu nes-ppu +nes_objects += nes-memory nes-cartridge nes-cpu nes-apu nes-ppu nes_objects += nes-cheat objects += $(nes_objects) @@ -8,9 +7,8 @@ obj/nes-interface.o: $(nes)/interface/interface.cpp $(call rwildcard,$(nes)/inte obj/nes-system.o: $(nes)/system/system.cpp $(call rwildcard,$(nes)/system/) obj/nes-scheduler.o: $(nes)/scheduler/scheduler.cpp $(call rwildcard,$(nes)/scheduler/) obj/nes-input.o: $(nes)/input/input.cpp $(call rwildcard,$(nes)/input/) -obj/nes-mapper.o: $(nes)/mapper/mapper.cpp $(call rwildcard,$(nes)/mapper/) -obj/nes-cartridge.o: $(nes)/cartridge/cartridge.cpp $(call rwildcard,$(nes)/cartridge/) obj/nes-memory.o: $(nes)/memory/memory.cpp $(call rwildcard,$(nes)/memory/) +obj/nes-cartridge.o: $(nes)/cartridge/cartridge.cpp $(call rwildcard,$(nes)/cartridge/) obj/nes-cpu.o: $(nes)/cpu/cpu.cpp $(call rwildcard,$(nes)/cpu/) obj/nes-apu.o: $(nes)/apu/apu.cpp $(call rwildcard,$(nes)/apu/) obj/nes-ppu.o: $(nes)/ppu/ppu.cpp $(call rwildcard,$(nes)/ppu/) diff --git a/bsnes/nes/cartridge/board/axrom.cpp b/bsnes/nes/cartridge/board/axrom.cpp new file mode 100755 index 00000000..d44f8c1c --- /dev/null +++ b/bsnes/nes/cartridge/board/axrom.cpp @@ -0,0 +1,50 @@ +//NES-AMROM +//NES-ANROM +//NES-AN1ROM +//NES-AOROM + +struct AxROM : Board { + +uint4 prg_bank; +bool mirror_select; + +uint8 prg_read(unsigned addr) { + if(addr & 0x8000) return Board::prg_read((prg_bank << 15) | (addr & 0x7fff)); + return cpu.mdr(); +} + +void prg_write(unsigned addr, uint8 data) { + if(addr & 0x8000) { + prg_bank = data & 0x0f; + mirror_select = data & 0x10; + } +} + +uint8 chr_read(unsigned addr) { + if(addr & 0x2000) return ppu.ciram_read((mirror_select << 10) | (addr & 0x03ff)); + return Board::chr_read(addr); +} + +void chr_write(unsigned addr, uint8 data) { + if(addr & 0x2000) return ppu.ciram_write((mirror_select << 10) | (addr & 0x03ff), data); + return Board::chr_write(addr, data); +} + +void power() { + reset(); +} + +void reset() { + prg_bank = 0x0f; + mirror_select = 0; +} + +void serialize(serializer &s) { + s.integer(prg_bank); + s.integer(mirror_select); +} + +AxROM(BML::Node &board, const uint8_t *data, unsigned size) : Board(board, data, size) { +} + +}; diff --git a/bsnes/nes/cartridge/board/board.cpp b/bsnes/nes/cartridge/board/board.cpp index 435725cf..a58a04f7 100755 --- a/bsnes/nes/cartridge/board/board.cpp +++ b/bsnes/nes/cartridge/board/board.cpp @@ -1,4 +1,8 @@ +#include "axrom.cpp" +#include "cnrom.cpp" #include "nrom.cpp" +#include "sxrom.cpp" +#include "uxrom.cpp" unsigned Board::mirror(unsigned addr, unsigned size) const { unsigned base = 0; @@ -18,73 +22,94 @@ unsigned Board::mirror(unsigned addr, unsigned size) const { return base; } +void Board::main() { + while(true) { + if(scheduler.sync == Scheduler::SynchronizeMode::All) { + scheduler.exit(Scheduler::ExitReason::SynchronizeEvent); + } + + cartridge.clock += 12 * 4095; + tick(); + } +} + +void Board::tick() { + cartridge.clock += 12; + if(cartridge.clock >= 0 && scheduler.sync != Scheduler::SynchronizeMode::All) co_switch(cpu.thread); +} + uint8 Board::prg_read(unsigned addr) { - return prg.data[mirror(addr, prg.size)]; + return prgrom.data[mirror(addr, prgrom.size)]; } void Board::prg_write(unsigned addr, uint8 data) { - prg.data[mirror(addr, prg.size)] = data; + prgrom.data[mirror(addr, prgrom.size)] = data; } uint8 Board::chr_read(unsigned addr) { - return chr.data[mirror(addr, chr.size)]; + if(chrrom.size) return chrrom.data[mirror(addr, chrrom.size)]; + if(chrram.size) return chrram.data[mirror(addr, chrram.size)]; + return 0u; } void Board::chr_write(unsigned addr, uint8 data) { - chr.data[mirror(addr, chr.size)] = data; + if(chrram.size) chrram.data[mirror(addr, chrram.size)] = data; } -Board* Board::create(const string &xml, const uint8_t *data, unsigned size) { - string type; - string configuration; - - xml_element document = xml_parse(xml); - for(auto &head : document.element) { - if(head.name == "cartridge") { - for(auto &node : head.element) { - if(node.name == "board") { - configuration = node.content; - for(auto &attr : node.attribute) { - if(attr.name == "type") type = attr.parse(); - } - } - } - } - } - - Board *board = nullptr; - if(type == "NES-NROM-256") board = new NROM; - assert(board != nullptr); - - for(auto &head : document.element) { - if(head.name == "cartridge") { - for(auto &node : head.element) { - if(node.name == "board") { - for(auto &leaf : node.element) { - if(leaf.name == "prg") { - for(auto &attr : leaf.attribute) { - if(attr.name == "size") board->prg.size = decimal(attr.content); - } - } - - if(leaf.name == "chr") { - for(auto &attr : leaf.attribute) { - if(attr.name == "size") board->chr.size = decimal(attr.content); - } - } - } - } - } - } - } - - board->prg.data = new uint8[board->prg.size]; - memcpy(board->prg.data, data, board->prg.size); - - board->chr.data = new uint8[board->chr.size]; - memcpy(board->chr.data, data + board->prg.size, board->chr.size); - - board->configure({ "\n", configuration, "\n" }); - - return board; +Board::Memory Board::memory() { + return prgram; +} + +void Board::power() { +} + +void Board::reset() { +} + +void Board::serialize(serializer &s) { + if(prgram.size) s.array(prgram.data, prgram.size); + if(chrram.size) s.array(chrram.data, chrram.size); +} + +Board::Board(BML::Node &board, const uint8_t *data, unsigned size) { + information.type = board["type"].value(); + information.battery = board["prg"]["battery"].value(); + + prgrom.size = decimal(board["prg"]["rom"].value()); + prgram.size = decimal(board["prg"]["ram"].value()); + chrrom.size = decimal(board["chr"]["rom"].value()); + chrram.size = decimal(board["chr"]["ram"].value()); + + if(prgrom.size) prgrom.data = new uint8[prgrom.size](); + if(prgram.size) prgram.data = new uint8[prgram.size](); + if(chrrom.size) chrrom.data = new uint8[chrrom.size](); + if(chrram.size) chrram.data = new uint8[chrram.size](); + + if(prgrom.size) memcpy(prgrom.data, data, prgrom.size); + if(chrrom.size) memcpy(chrrom.data, data + prgrom.size, chrrom.size); +} + +Board::~Board() { + if(prgrom.size) delete[] prgrom.data; + if(prgram.size) delete[] prgram.data; + if(chrrom.size) delete[] chrrom.data; + if(chrram.size) delete[] chrram.data; +} + +Board* Board::load(const string &markup, const uint8_t *data, unsigned size) { + BML::Node document(markup); + auto &board = document["cartridge"]["board"]; + string type = board["type"].value(); + + if(type == "NES-AMROM" ) return new AxROM(board, data, size); + if(type == "NES-ANROM" ) return new AxROM(board, data, size); + if(type == "NES-AN1ROM" ) return new AxROM(board, data, size); + if(type == "NES-AOROM" ) return new AxROM(board, data, size); + if(type == "NES-CNROM" ) return new CNROM(board, data, size); + if(type == "NES-NROM-256") return new NROM(board, data, size); + if(type == "NES-UNROM" ) return new UxROM(board, data, size); + if(type == "NES-SXROM" ) return new SxROM(board, data, size); + if(type == "NES-UOROM" ) return new UxROM(board, data, size); + + return nullptr; } diff --git a/bsnes/nes/cartridge/board/board.hpp b/bsnes/nes/cartridge/board/board.hpp index 9530c51d..1ce83be7 100755 --- a/bsnes/nes/cartridge/board/board.hpp +++ b/bsnes/nes/cartridge/board/board.hpp @@ -1,25 +1,40 @@ struct Board { + struct Memory { + uint8_t *data; + unsigned size; + inline Memory() : data(nullptr), size(0u) {} + }; + unsigned mirror(unsigned addr, unsigned size) const; + virtual void main(); + virtual void tick(); + virtual uint8 prg_read(unsigned addr); virtual void prg_write(unsigned addr, uint8 data); virtual uint8 chr_read(unsigned addr); virtual void chr_write(unsigned addr, uint8 data); - virtual void configure(const string &xml) = 0; + virtual Memory memory(); - static Board* create(const string &xml, const uint8_t *data, unsigned size); + virtual void power(); + virtual void reset(); + + virtual void serialize(serializer&); + Board(BML::Node &board, const uint8_t *data, unsigned size); + ~Board(); + + static Board* load(const string &markup, const uint8_t *data, unsigned size); struct Information { string type; + bool battery; } information; - struct Memory { - uint8_t *data; - unsigned size; - }; - - Memory prg; - Memory chr; +protected: + Memory prgrom; + Memory prgram; + Memory chrrom; + Memory chrram; }; diff --git a/bsnes/nes/cartridge/board/cnrom.cpp b/bsnes/nes/cartridge/board/cnrom.cpp new file mode 100755 index 00000000..fccf5db6 --- /dev/null +++ b/bsnes/nes/cartridge/board/cnrom.cpp @@ -0,0 +1,54 @@ +//NES-CNROM + +struct CNROM : Board { + +struct Settings { + bool mirror; //0 = horizontal, 1 = vertical +} settings; + +uint2 chr_bank; + +uint8 prg_read(unsigned addr) { + if(addr & 0x8000) return Board::prg_read(addr & 0x7fff); + return cpu.mdr(); +} + +void prg_write(unsigned addr, uint8 data) { + if(addr & 0x8000) chr_bank = data & 0x03; +} + +uint8 chr_read(unsigned addr) { + if(addr & 0x2000) { + if(settings.mirror == 0) addr = ((addr & 0x0800) >> 1) | (addr & 0x03ff); + return ppu.ciram_read(addr & 0x07ff); + } + addr = (chr_bank * 0x2000) + (addr & 0x1fff); + return Board::chr_read(addr); +} + +void chr_write(unsigned addr, uint8 data) { + if(addr & 0x2000) { + if(settings.mirror == 0) addr = ((addr & 0x0800) >> 1) | (addr & 0x03ff); + return ppu.ciram_write(addr & 0x07ff, data); + } + addr = (chr_bank * 0x2000) + (addr & 0x1fff); + Board::chr_write(addr, data); +} + +void power() { + reset(); +} + +void reset() { + chr_bank = 0; +} + +void serialize(serializer &s) { + s.integer(chr_bank); +} + +CNROM(BML::Node &board, const uint8_t *data, unsigned size) : Board(board, data, size) { + settings.mirror = board["mirror"].value() == "vertical" ? 1 : 0; +} + +}; diff --git a/bsnes/nes/cartridge/board/nrom.cpp b/bsnes/nes/cartridge/board/nrom.cpp index 4af8eff9..3a4b6617 100755 --- a/bsnes/nes/cartridge/board/nrom.cpp +++ b/bsnes/nes/cartridge/board/nrom.cpp @@ -1,7 +1,10 @@ +//NES-NROM-128 +//NES-NROM-256 + struct NROM : Board { struct Settings { - enum class Mirror : unsigned { Horizontal, Vertical } mirror; + bool mirror; //0 = horizontal, 1 = vertical } settings; uint8 prg_read(unsigned addr) { @@ -14,7 +17,7 @@ void prg_write(unsigned addr, uint8 data) { uint8 chr_read(unsigned addr) { if(addr & 0x2000) { - if(settings.mirror == Settings::Mirror::Horizontal) addr = ((addr & 0x0800) >> 1) | (addr & 0x03ff); + if(settings.mirror == 0) addr = ((addr & 0x0800) >> 1) | (addr & 0x03ff); return ppu.ciram_read(addr & 0x07ff); } return Board::chr_read(addr); @@ -22,26 +25,14 @@ uint8 chr_read(unsigned addr) { void chr_write(unsigned addr, uint8 data) { if(addr & 0x2000) { - if(settings.mirror == Settings::Mirror::Horizontal) addr = ((addr & 0x0800) >> 1) | (addr & 0x03ff); - return ppu.ciram_write(addr, data); + if(settings.mirror == 0) addr = ((addr & 0x0800) >> 1) | (addr & 0x03ff); + return ppu.ciram_write(addr & 0x07ff, data); } return Board::chr_write(addr, data); } -void configure(const string &xml) { - xml_element document = xml_parse(xml); - for(auto &node : document.element) { - if(node.name == "mirror") { - for(auto &attr : node.attribute) { - if(attr.name == "type") { - if(attr.content == "horizontal") settings.mirror = Settings::Mirror::Horizontal; - if(attr.content == "vertical" ) settings.mirror = Settings::Mirror::Vertical; - } - } - } - } +NROM(BML::Node &board, const uint8_t *data, unsigned size) : Board(board, data, size) { + settings.mirror = board["mirror"].value() == "vertical" ? 1 : 0; } }; - -NROM nrom; diff --git a/bsnes/nes/cartridge/board/sxrom.cpp b/bsnes/nes/cartridge/board/sxrom.cpp new file mode 100755 index 00000000..3b3bf6fd --- /dev/null +++ b/bsnes/nes/cartridge/board/sxrom.cpp @@ -0,0 +1,29 @@ +//NES-SAROM +//NES-SBROM +//NES-SCROM +//NES-SC1ROM +//NES-SEROM +//NES-SFROM +//NES-SGROM +//NES-SHROM +//NES-SH1ROM +//NES-SIROM +//NES-SJROM +//NES-SKROM +//NES-SLROM +//NES-SL1ROM +//NES-SL2ROM +//NES-SL3ROM +//NES-SLRROM +//NES-SMROM +//NES-SNROM +//NES-SOROM +//NES-SUROM +//NES-SXROM + +struct SxROM : Board { + +SxROM(BML::Node &board, const uint8_t *data, unsigned size) : Board(board, data, size) { +} + +}; diff --git a/bsnes/nes/cartridge/board/uxrom.cpp b/bsnes/nes/cartridge/board/uxrom.cpp new file mode 100755 index 00000000..c7aea46e --- /dev/null +++ b/bsnes/nes/cartridge/board/uxrom.cpp @@ -0,0 +1,54 @@ +//NES-UNROM +//NES-UOROM + +struct UxROM : Board { + +struct Settings { + bool mirror; //0 = horizontal, 1 = vertical +} settings; + +uint4 prg_bank; + +uint8 prg_read(unsigned addr) { + if((addr & 0xc000) == 0x8000) return Board::prg_read((prg_bank << 14) | (addr & 0x3fff)); + if((addr & 0xc000) == 0xc000) return Board::prg_read(( 0x0f << 14) | (addr & 0x3fff)); + return cpu.mdr(); +} + +void prg_write(unsigned addr, uint8 data) { + if(addr & 0x8000) prg_bank = data & 0x0f; +} + +uint8 chr_read(unsigned addr) { + if(addr & 0x2000) { + if(settings.mirror == 0) addr = ((addr & 0x0800) >> 1) | (addr & 0x03ff); + return ppu.ciram_read(addr); + } + return Board::chr_read(addr); +} + +void chr_write(unsigned addr, uint8 data) { + if(addr & 0x2000) { + if(settings.mirror == 0) addr = ((addr & 0x0800) >> 1) | (addr & 0x03ff); + return ppu.ciram_write(addr, data); + } + return Board::chr_write(addr, data); +} + +void power() { + reset(); +} + +void reset() { + prg_bank = 0; +} + +void serialize(serializer &s) { + s.integer(prg_bank); +} + +UxROM(BML::Node &board, const uint8_t *data, unsigned size) : Board(board, data, size) { + settings.mirror = board["mirror"].value() == "vertical" ? 1 : 0; +} + +}; diff --git a/bsnes/nes/cartridge/cartridge.cpp b/bsnes/nes/cartridge/cartridge.cpp index 44434355..c5a0bfe7 100755 --- a/bsnes/nes/cartridge/cartridge.cpp +++ b/bsnes/nes/cartridge/cartridge.cpp @@ -2,10 +2,9 @@ namespace NES { +#include "ines.cpp" +#include "chip/chip.cpp" #include "board/board.cpp" - -//#define BOARD - Cartridge cartridge; void Cartridge::Main() { @@ -13,92 +12,42 @@ void Cartridge::Main() { } void Cartridge::main() { - mapper->main(); + board->main(); } -void Cartridge::load(const string &xml, const uint8_t *data, unsigned size) { - #ifdef BOARD - rom_size = size; - rom_data = new uint8[rom_size]; - memcpy(rom_data, data, size); - #else - rom_size = size - 16; - rom_data = new uint8[rom_size]; - memcpy(rom_data, data + 16, size - 16); - #endif - - #ifdef BOARD - prg_size = 32768; - chr_size = 8192; - #else - prg_size = data[4] * 0x4000; - chr_size = data[5] * 0x2000; - #endif - - prg_data = new uint8[prg_size]; - memcpy(prg_data, rom_data, prg_size); - - if(chr_size) { - chr_ram = false; - chr_data = new uint8[chr_size]; - memcpy(chr_data, rom_data + prg_size, chr_size); +void Cartridge::load(const string &markup, const uint8_t *data, unsigned size) { + if((size & 0xff) == 0) { + sha256 = nall::sha256(data, size); + board = Board::load(markup, data, size); } else { - chr_ram = true; - chr_size = 0x2000; - chr_data = new uint8[chr_size](); + board = Board::load(markup != "" ? markup : iNES(data, size), data + 16, size - 16); } - mirroring = ((data[6] & 0x08) >> 2) | (data[6] & 0x01); - - uint8 mapperNumber = ((data[7] >> 4) << 4) | (data[6] >> 4); - switch(mapperNumber) { - default : mapper = &Mapper::none; break; - case 1: mapper = &Mapper::mmc1; break; - case 2: mapper = &Mapper::uorom; break; - case 3: mapper = &Mapper::cnrom; break; - case 4: mapper = &Mapper::mmc3; break; - case 7: mapper = &Mapper::aorom; break; - case 16: mapper = &Mapper::bandaiFCG; break; - case 24: mapper = &Mapper::vrc6; Mapper::vrc6.abus_swap = 0; break; - case 26: mapper = &Mapper::vrc6; Mapper::vrc6.abus_swap = 1; break; - } - - sha256 = nall::sha256(rom_data, rom_size); - - #ifdef BOARD - board = Board::create(xml, rom_data, rom_size); - #endif - system.load(); loaded = true; } void Cartridge::unload() { if(loaded == false) return; - - delete[] rom_data; - delete[] prg_data; - delete[] chr_data; - loaded = false; } unsigned Cartridge::ram_size() { - return mapper->ram_size(); + return board->memory().size; } uint8* Cartridge::ram_data() { - return mapper->ram_data(); + return board->memory().data; } void Cartridge::power() { create(Cartridge::Main, 21477272); - mapper->power(); + board->power(); } void Cartridge::reset() { create(Cartridge::Main, 21477272); - mapper->reset(); + board->reset(); } Cartridge::Cartridge() { @@ -106,37 +55,23 @@ Cartridge::Cartridge() { } uint8 Cartridge::prg_read(unsigned addr) { -#ifdef BOARD return board->prg_read(addr); -#endif - return mapper->prg_read(addr); } void Cartridge::prg_write(unsigned addr, uint8 data) { -#ifdef BOARD return board->prg_write(addr, data); -#endif - return mapper->prg_write(addr, data); } uint8 Cartridge::chr_read(unsigned addr) { -#ifdef BOARD return board->chr_read(addr); -#endif - return mapper->chr_read(addr); } void Cartridge::chr_write(unsigned addr, uint8 data) { -#ifdef BOARD return board->chr_write(addr, data); -#endif - return mapper->chr_write(addr, data); } void Cartridge::serialize(serializer &s) { - if(chr_ram) s.array(chr_data, chr_size); - - return mapper->serialize(s); + return board->serialize(s); } } diff --git a/bsnes/nes/cartridge/cartridge.hpp b/bsnes/nes/cartridge/cartridge.hpp index f22df099..44198cc6 100755 --- a/bsnes/nes/cartridge/cartridge.hpp +++ b/bsnes/nes/cartridge/cartridge.hpp @@ -1,10 +1,11 @@ +#include "chip/chip.hpp" #include "board/board.hpp" struct Cartridge : Processor, property { static void Main(); void main(); - void load(const string &xml, const uint8_t *data, unsigned size); + void load(const string &markup, const uint8_t *data, unsigned size); void unload(); unsigned ram_size(); @@ -21,25 +22,12 @@ struct Cartridge : Processor, property { //privileged: Board *board; - Mapper::Mapper *mapper; uint8 prg_read(unsigned addr); void prg_write(unsigned addr, uint8 data); uint8 chr_read(unsigned addr); void chr_write(unsigned addr, uint8 data); - - uint8 *rom_data; - unsigned rom_size; - - uint8 *prg_data; - unsigned prg_size; - - uint8 *chr_data; - unsigned chr_size; - - bool chr_ram; - unsigned mirroring; }; extern Cartridge cartridge; diff --git a/bsnes/nes/cartridge/chip/chip.cpp b/bsnes/nes/cartridge/chip/chip.cpp new file mode 100755 index 00000000..e69de29b diff --git a/bsnes/nes/cartridge/chip/chip.hpp b/bsnes/nes/cartridge/chip/chip.hpp new file mode 100755 index 00000000..b30e88b4 --- /dev/null +++ b/bsnes/nes/cartridge/chip/chip.hpp @@ -0,0 +1,2 @@ +struct Chip { +}; diff --git a/bsnes/nes/cartridge/ines.cpp b/bsnes/nes/cartridge/ines.cpp new file mode 100755 index 00000000..42a9d10e --- /dev/null +++ b/bsnes/nes/cartridge/ines.cpp @@ -0,0 +1,66 @@ +static string iNES(const uint8_t *data, unsigned size) { + if(size < 16) return ""; + if(data[0] != 'N') return ""; + if(data[1] != 'E') return ""; + if(data[2] != 'S') return ""; + if(data[3] != 0x1a) return ""; + + string output; + + unsigned mapper = ((data[7] >> 4) << 4) | (data[6] >> 4); + unsigned mirror = ((data[6] & 0x08) >> 2) | (data[6] & 0x01); + unsigned prgrom = data[4] * 0x4000; + unsigned chrrom = data[5] * 0x2000; + unsigned prgram = 0; + unsigned chrram = chrrom == 0 ? 8192 : 0; + + print("iNES mapper: ", mapper, "\n"); + + output.append("cartridge\n"); + + switch(mapper) { + default: + output.append(" board type=NES-NROM-256\n"); + output.append(" mirror=", mirror == 0 ? "horizontal" : "vertical", "\n"); + break; + + case 1: + output.append(" board type=NES-SXROM\n"); + break; + + case 2: + output.append(" board type=NES-UOROM\n"); + output.append(" mirror=", mirror == 0 ? "horizontal" : "vertical", "\n"); + break; + + case 3: + output.append(" board type=NES-CNROM\n"); + output.append(" mirror=", mirror == 0 ? "horizontal" : "vertical", "\n"); + break; + + case 7: + output.append(" board type=NES-AOROM\n"); + break; + } + + output.append(" prg rom=", prgrom, " ram=", prgram, "\n"); + output.append(" chr rom=", chrrom, " ram=", chrram, "\n"); + + print(output, "\n"); + + return output; +} + +/* + switch(mapperNumber) { +//default : mapper = &Mapper::none; break; +//case 1: mapper = &Mapper::mmc1; break; +//case 2: mapper = &Mapper::uorom; break; +//case 3: mapper = &Mapper::cnrom; break; + case 4: mapper = &Mapper::mmc3; break; +//case 7: mapper = &Mapper::aorom; break; + case 16: mapper = &Mapper::bandaiFCG; break; + case 24: mapper = &Mapper::vrc6; Mapper::vrc6.abus_swap = 0; break; + case 26: mapper = &Mapper::vrc6; Mapper::vrc6.abus_swap = 1; break; + } +*/ diff --git a/bsnes/nes/interface/interface.cpp b/bsnes/nes/interface/interface.cpp index 783fd0d7..b1d6ca1d 100755 --- a/bsnes/nes/interface/interface.cpp +++ b/bsnes/nes/interface/interface.cpp @@ -27,8 +27,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/nes/interface/interface.hpp b/bsnes/nes/interface/interface.hpp index 675edb6d..c3154896 100755 --- a/bsnes/nes/interface/interface.hpp +++ b/bsnes/nes/interface/interface.hpp @@ -8,7 +8,7 @@ struct Interface { 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/nes/nes.hpp b/bsnes/nes/nes.hpp index 171d0edc..aa94b01b 100755 --- a/bsnes/nes/nes.hpp +++ b/bsnes/nes/nes.hpp @@ -99,9 +99,8 @@ namespace NES { #include #include #include - #include - #include #include + #include #include #include #include diff --git a/bsnes/ui/interface/nes.cpp b/bsnes/ui/interface/nes.cpp index 608a02bd..6e80b585 100755 --- a/bsnes/ui/interface/nes.cpp +++ b/bsnes/ui/interface/nes.cpp @@ -20,10 +20,10 @@ bool InterfaceNES::loadCartridge(const string &filename) { interface->unloadCartridge(); interface->baseName = nall::basename(filename); - string xml; - xml.readfile({ interface->baseName, ".xml" }); + string markup; + markup.readfile({ interface->baseName, ".bml" }); - NES::Interface::loadCartridge(xml, fp.data(), fp.size()); + NES::Interface::loadCartridge(markup, fp.data(), fp.size()); fp.close(); if(NES::Interface::memorySize(NES::Interface::Memory::RAM) > 0) { diff --git a/bsnes/ui/main.cpp b/bsnes/ui/main.cpp index e496a0f7..b227de8d 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.25"; + title = "bsnes v082.26"; 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 b8605990..9a517659 100755 --- a/bsnes/ui/tools/cheat-editor.cpp +++ b/bsnes/ui/tools/cheat-editor.cpp @@ -129,31 +129,13 @@ bool CheatEditor::load(const string &filename) { if(data.readfile(filename) == false) return false; unsigned n = 0; - xml_element document = xml_parse(data); - for(auto &head : document.element) { - if(head.name == "cartridge") { - for(auto &node : head.element) { - if(node.name == "cheat") { - bool enable = false; - string description; - string code; - for(auto &attribute : node.attribute) { - if(attribute.name == "enabled") enable = (attribute.parse() == "true"); - } - for(auto &element : node.element) { - if(element.name == "description") description = element.parse(); - else if(element.name == "code") code.append(element.parse(), "+"); - } - code.rtrim<1>("+"); - - cheatList.setChecked(n, enable); - cheatText[n][Code] = code; - cheatText[n][Desc] = description; - - if(++n >= 128) break; - } - } - } + BML::Node document(data); + for(auto &cheat : document["cartridge"]) { + if(cheat.name() != "cheat") continue; + cheatList.setChecked(n, cheat["enable"].exists()); + cheatText[n][Code] = cheat["code"].value(); + cheatText[n][Desc] = cheat["description"].value(); + if(++n >= 128) break; } updateUI(), updateInterface(); @@ -179,21 +161,14 @@ bool CheatEditor::save(const string &filename) { file fp; if(fp.open(filename, file::mode::write) == false) return false; - fp.print("\n"); - fp.print("\n"); + fp.print("cartridge sha256=", interface->sha256(), "\n"); for(unsigned n = 0; n <= lastSave; n++) { - fp.print(" \n"); - fp.print(" ", cheatText[n][Desc], "\n"); - lstring list; - list.split("+", cheatText[n][Code]); - for(auto &code : list) { - fp.print(" ", code, "\n"); - } - fp.print(" \n"); + fp.print(" cheat", cheatList.checked(n) ? " enable" : "", "\n"); + fp.print(" description=|", cheatText[n][Desc], "|\n"); + fp.print(" code=|", cheatText[n][Code], "|\n"); } - fp.print("\n"); - fp.close(); + fp.close(); return true; }