diff --git a/bsnes/nall/lzss.hpp b/bsnes/nall/lzss.hpp index 521b36c66..fb3e0ba63 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 3dcd53fa4..4a21e202e 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 000000000..b3bc1a337 --- /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 d4b919e0d..8198c55c6 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 8e815ae08..6bf1c78f4 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 000000000..d44f8c1cd --- /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 435725cf4..a58a04f7d 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 9530c51d7..1ce83be74 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 000000000..fccf5db6f --- /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 4af8eff93..3a4b66177 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 000000000..3b3bf6fd4 --- /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 000000000..c7aea46e5 --- /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 44434355f..c5a0bfe7a 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 f22df0994..44198cc6c 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 000000000..e69de29bb diff --git a/bsnes/nes/cartridge/chip/chip.hpp b/bsnes/nes/cartridge/chip/chip.hpp new file mode 100755 index 000000000..b30e88b48 --- /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 000000000..42a9d10ea --- /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 783fd0d72..b1d6ca1df 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 675edb6de..c31548967 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 171d0edce..aa94b01b1 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 608a02bd1..6e80b5851 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 e496a0f79..b227de8d4 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 b86059909..9a517659e 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; }