diff --git a/bsnes/Makefile b/bsnes/Makefile index 4af87086..0ae818e5 100755 --- a/bsnes/Makefile +++ b/bsnes/Makefile @@ -1,7 +1,7 @@ include nall/Makefile snes := snes gameboy := gameboy -profile := accuracy +profile := compatibility ui := ui # debugger diff --git a/bsnes/phoenix/core/layout/vertical-layout.cpp b/bsnes/phoenix/core/layout/vertical-layout.cpp index 373c8249..e3185001 100755 --- a/bsnes/phoenix/core/layout/vertical-layout.cpp +++ b/bsnes/phoenix/core/layout/vertical-layout.cpp @@ -69,6 +69,10 @@ Geometry VerticalLayout::minimumLayoutGeometry() { return { 0, 0, maximumWidth ? MaximumSize : margin * 2 + width, maximumHeight ? MaximumSize : margin * 2 + height }; } +void VerticalLayout::reset() { + children.reset(); +} + void VerticalLayout::setGeometry(const Geometry &containerGeometry) { auto children = this->children; foreach(child, children) { diff --git a/bsnes/phoenix/core/layout/vertical-layout.hpp b/bsnes/phoenix/core/layout/vertical-layout.hpp index a280c269..fb78247e 100755 --- a/bsnes/phoenix/core/layout/vertical-layout.hpp +++ b/bsnes/phoenix/core/layout/vertical-layout.hpp @@ -5,6 +5,7 @@ struct VerticalLayout : public Layout { void append(Widget &widget, unsigned width, unsigned height, unsigned spacing = 0); Geometry minimumGeometry(); Geometry minimumLayoutGeometry(); + void reset(); void setGeometry(const Geometry &geometry); void setMargin(unsigned margin); void setParent(Window &parent); diff --git a/bsnes/snes/Makefile b/bsnes/snes/Makefile index d9c24d55..c0ee05bb 100755 --- a/bsnes/snes/Makefile +++ b/bsnes/snes/Makefile @@ -2,7 +2,7 @@ snes_objects := snes-system snes_objects += snes-cartridge snes-cheat snes_objects += snes-memory snes-cpucore snes-smpcore snes_objects += snes-cpu snes-smp snes-dsp snes-ppu -snes_objects += snes-icd2 snes-superfx snes-sa1 snes-necdsp +snes_objects += snes-nss snes-icd2 snes-superfx snes-sa1 snes-necdsp snes_objects += snes-bsx snes-srtc snes-sdd1 snes-spc7110 snes-cx4 snes_objects += snes-obc1 snes-st0018 snes-sufamiturbo snes_objects += snes-msu1 snes-serial @@ -39,6 +39,7 @@ obj/snes-ppu.o : $(snesppu)/ppu.cpp $(call rwildcard,$(snesppu)/) obj/snes-cartridge.o: $(snes)/cartridge/cartridge.cpp $(snes)/cartridge/* obj/snes-cheat.o : $(snes)/cheat/cheat.cpp $(snes)/cheat/* +obj/snes-nss.o : $(snes)/chip/nss/nss.cpp $(call rwildcard,$(snes)/chip/nss/) obj/snes-icd2.o : $(snes)/chip/icd2/icd2.cpp $(call rwildcard,$(snes)/chip/icd2/) obj/snes-superfx.o : $(snes)/chip/superfx/superfx.cpp $(call rwildcard,$(snes)/chip/superfx/) obj/snes-sa1.o : $(snes)/chip/sa1/sa1.cpp $(call rwildcard,$(snes)/chip/sa1/) diff --git a/bsnes/snes/alt/smp/smp.cpp b/bsnes/snes/alt/smp/smp.cpp index a309db05..08a67ef0 100755 --- a/bsnes/snes/alt/smp/smp.cpp +++ b/bsnes/snes/alt/smp/smp.cpp @@ -1,4 +1,4 @@ -//#define CYCLE_ACCURATE +#define CYCLE_ACCURATE #include diff --git a/bsnes/snes/cartridge/cartridge.cpp b/bsnes/snes/cartridge/cartridge.cpp index db47d958..4d2db951 100755 --- a/bsnes/snes/cartridge/cartridge.cpp +++ b/bsnes/snes/cartridge/cartridge.cpp @@ -17,6 +17,7 @@ void Cartridge::load(Mode cartridge_mode, const lstring &xml_list) { ram_size = 0; has_bsx_slot = false; + has_nss_dip = false; has_superfx = false; has_sa1 = false; has_necdsp = false; diff --git a/bsnes/snes/cartridge/cartridge.hpp b/bsnes/snes/cartridge/cartridge.hpp index 5678e028..9817ac41 100755 --- a/bsnes/snes/cartridge/cartridge.hpp +++ b/bsnes/snes/cartridge/cartridge.hpp @@ -34,6 +34,7 @@ public: readonly ram_size; readonly has_bsx_slot; + readonly has_nss_dip; readonly has_superfx; readonly has_sa1; readonly has_necdsp; @@ -75,6 +76,13 @@ public: }; linear_vector mapping; + struct Information { + struct NSS { + lstring setting; + lstring option[16]; + } nss; + } information; + void load(Mode, const lstring&); void unload(); @@ -91,6 +99,7 @@ private: 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&); diff --git a/bsnes/snes/cartridge/xml.cpp b/bsnes/snes/cartridge/xml.cpp index 24731888..59801eff 100755 --- a/bsnes/snes/cartridge/xml.cpp +++ b/bsnes/snes/cartridge/xml.cpp @@ -17,6 +17,9 @@ void Cartridge::parse_xml(const lstring &list) { } 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; @@ -32,6 +35,7 @@ void Cartridge::parse_xml_cartridge(const char *data) { foreach(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); @@ -97,6 +101,33 @@ void Cartridge::xml_parse_ram(xml_element &root) { } } +void Cartridge::xml_parse_nss(xml_element &root) { + has_nss_dip = true; + + foreach(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(); + foreach(attr, node.attribute) { + if(attr.name == "name") { + information.nss.setting[number] = attr.parse(); + } + } + foreach(leaf, node.element) { + string name; + unsigned value = 0x0000; + foreach(attr, leaf.attribute) { + if(attr.name == "name") name = attr.parse(); + if(attr.name == "value") value = (uint16)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; diff --git a/bsnes/snes/chip/chip.hpp b/bsnes/snes/chip/chip.hpp index c6a61700..fda6775f 100755 --- a/bsnes/snes/chip/chip.hpp +++ b/bsnes/snes/chip/chip.hpp @@ -3,6 +3,7 @@ struct Coprocessor : Processor { alwaysinline void synchronize_cpu(); }; +#include #include #include #include diff --git a/bsnes/snes/chip/nss/nss.cpp b/bsnes/snes/chip/nss/nss.cpp new file mode 100755 index 00000000..964973d0 --- /dev/null +++ b/bsnes/snes/chip/nss/nss.cpp @@ -0,0 +1,39 @@ +#include + +#define NSS_CPP +namespace SNES { + +NSS nss; + +void NSS::init() { +} + +void NSS::load() { + dip = 0x0000; + bus.map(Bus::MapMode::Direct, 0x00, 0x3f, 0x4100, 0x4101, { &NSS::read, this }, { &NSS::write, this }); + bus.map(Bus::MapMode::Direct, 0x80, 0xbf, 0x4100, 0x4101, { &NSS::read, this }, { &NSS::write, this }); +} + +void NSS::unload() { +} + +void NSS::power() { +} + +void NSS::reset() { +} + +void NSS::set_dip(uint16 dip) { + this->dip = dip; +} + +uint8 NSS::read(unsigned addr) { + if((addr & 0x40ffff) == 0x004100) return dip >> 0; + if((addr & 0x40ffff) == 0x004101) return dip >> 8; + return cpu.regs.mdr; +} + +void NSS::write(unsigned addr, uint8 data) { +} + +} diff --git a/bsnes/snes/chip/nss/nss.hpp b/bsnes/snes/chip/nss/nss.hpp new file mode 100755 index 00000000..3cab46da --- /dev/null +++ b/bsnes/snes/chip/nss/nss.hpp @@ -0,0 +1,17 @@ +class NSS { +public: + void init(); + void load(); + void unload(); + void power(); + void reset(); + + void set_dip(uint16 dip); + uint8 read(unsigned addr); + void write(unsigned addr, uint8 data); + +private: + uint16 dip; +}; + +extern NSS nss; diff --git a/bsnes/snes/snes.hpp b/bsnes/snes/snes.hpp index 0cafa6c0..d4991082 100755 --- a/bsnes/snes/snes.hpp +++ b/bsnes/snes/snes.hpp @@ -1,7 +1,7 @@ namespace SNES { namespace Info { static const char Name[] = "bsnes"; - static const char Version[] = "078.04"; + static const char Version[] = "078.05"; static const unsigned SerializerVersion = 20; } } diff --git a/bsnes/snes/system/system.cpp b/bsnes/snes/system/system.cpp index 56316e55..2060160f 100755 --- a/bsnes/snes/system/system.cpp +++ b/bsnes/snes/system/system.cpp @@ -70,6 +70,7 @@ void System::init(Interface *interface_) { assert(interface != 0); icd2.init(); + nss.init(); superfx.init(); sa1.init(); necdsp.init(); @@ -111,6 +112,7 @@ void System::load() { if(cartridge.mode() == Cartridge::Mode::SuperGameBoy) icd2.load(); if(cartridge.has_bsx_slot()) bsxflash.load(); + if(cartridge.has_nss_dip()) nss.load(); if(cartridge.has_superfx()) superfx.load(); if(cartridge.has_sa1()) sa1.load(); if(cartridge.has_necdsp()) necdsp.load(); @@ -134,6 +136,7 @@ void System::unload() { if(cartridge.mode() == Cartridge::Mode::SuperGameBoy) icd2.unload(); if(cartridge.has_bsx_slot()) bsxflash.unload(); + if(cartridge.has_nss_dip()) nss.unload(); if(cartridge.has_superfx()) superfx.unload(); if(cartridge.has_sa1()) sa1.unload(); if(cartridge.has_necdsp()) necdsp.unload(); @@ -169,6 +172,7 @@ void System::power() { if(cartridge.mode() == Cartridge::Mode::SuperGameBoy) icd2.power(); if(cartridge.has_bsx_slot()) bsxflash.power(); + if(cartridge.has_nss_dip()) nss.power(); if(cartridge.has_superfx()) superfx.power(); if(cartridge.has_sa1()) sa1.power(); if(cartridge.has_necdsp()) necdsp.power(); @@ -204,6 +208,7 @@ void System::reset() { if(cartridge.mode() == Cartridge::Mode::SuperGameBoy) icd2.reset(); if(cartridge.has_bsx_slot()) bsxflash.reset(); + if(cartridge.has_nss_dip()) nss.reset(); if(cartridge.has_superfx()) superfx.reset(); if(cartridge.has_sa1()) sa1.reset(); if(cartridge.has_necdsp()) necdsp.reset(); diff --git a/bsnes/ui/general/general.cpp b/bsnes/ui/general/general.cpp index 50e7f351..bf5f4061 100755 --- a/bsnes/ui/general/general.cpp +++ b/bsnes/ui/general/general.cpp @@ -2,3 +2,4 @@ #include "main-window.cpp" #include "file-browser.cpp" #include "slot-loader.cpp" +#include "nss-dip-window.cpp" diff --git a/bsnes/ui/general/general.hpp b/bsnes/ui/general/general.hpp index a0f43444..350af6e3 100755 --- a/bsnes/ui/general/general.hpp +++ b/bsnes/ui/general/general.hpp @@ -1,3 +1,4 @@ #include "main-window.hpp" #include "file-browser.hpp" #include "slot-loader.hpp" +#include "nss-dip-window.hpp" diff --git a/bsnes/ui/general/nss-dip-window.cpp b/bsnes/ui/general/nss-dip-window.cpp new file mode 100755 index 00000000..70aa8454 --- /dev/null +++ b/bsnes/ui/general/nss-dip-window.cpp @@ -0,0 +1,91 @@ +NSSDipWindow nssDipWindow; + +void NSSDipWindow::create() { + application.addWindow(this, "NSSDipWindow", "160,160"); + setTitle("NSS DIP Settings"); + + for(unsigned n = 0; n < 16; n++) { + dipName[n].setText("Unused"); + dipName[n].setVisible(false); + layout.append(dipName[n], { 0, 0, 16, 16 }); + + dipValue[n].setVisible(false); + layout.append(dipValue[n], { 0, 0, 16, 16 }); + } + + loadButton.setText("Load Cartridge"); + layout.append(loadButton, { 0, 0, 16, 16 }); + + append(layout); + setResizable(false); + setGeometry({ 0, 0, 400, 240 }); + + onClose = loadButton.onTick = { &NSSDipWindow::assign, this }; +} + +void NSSDipWindow::select() { + setVisible(false); + + for(unsigned n = 0; n < 16; n++) { + dipName[n].setText({ "DIP #", 1 + n, ":" }); + dipName[n].setVisible(false); + dipValue[n].reset(); + dipValue[n].setVisible(false); + } + + unsigned dipCount = SNES::cartridge.information.nss.setting.size(); + + for(unsigned n = 0; n < dipCount; n++) { + dipName[n].setText({ "DIP #", 1 + n, ": ", SNES::cartridge.information.nss.setting[n] }); + for(unsigned z = 0; z < SNES::cartridge.information.nss.option[n].size(); z++) { + lstring part; + part.split<1>(":", SNES::cartridge.information.nss.option[n][z]); + dipValue[n].append(part[1]); + } + } + + unsigned maximumLabelWidth = 50; + unsigned maximumComboWidth = 100; + unsigned controlHeight = dipValue[0].minimumGeometry().height; + + for(unsigned n = 0; n < dipCount; n++) { + maximumLabelWidth = max(maximumLabelWidth, dipName[n].minimumGeometry().width); + maximumComboWidth = max(maximumComboWidth, dipValue[n].minimumGeometry().width); + } + + for(unsigned n = 0; n < dipCount; n++) { + dipName[n].setGeometry({ 5, 5 + (controlHeight + 5) * n, maximumLabelWidth, controlHeight }); + dipName[n].setVisible(true); + + dipValue[n].setGeometry({ 5 + maximumLabelWidth + 5, 5 + (controlHeight + 5) * n, maximumComboWidth, controlHeight }); + dipValue[n].setVisible(true); + } + + unsigned buttonWidth = loadButton.minimumGeometry().width; + unsigned buttonHeight = loadButton.minimumGeometry().height; + + unsigned windowWidth = 5 + maximumLabelWidth + 5 + maximumComboWidth + 5; + unsigned windowHeight = 5 + (controlHeight + 5) * dipCount + buttonHeight + 5; + + loadButton.setGeometry({ windowWidth - 5 - buttonWidth, windowHeight - 5 - buttonHeight, buttonWidth, buttonHeight }); + + setGeometry({ geometry().x, geometry().y, windowWidth, windowHeight }); + setVisible(true); + loadButton.setFocused(); +} + +void NSSDipWindow::assign() { + unsigned dip = 0; + + for(unsigned n = 0; n < SNES::cartridge.information.nss.setting.size(); n++) { + unsigned position = dipValue[n].selection(); + lstring part; + part.split<1>(":", SNES::cartridge.information.nss.option[n][position]); + dip |= hex(part[0]); + } + + SNES::nss.set_dip(dip); + + setVisible(false); + application.pause = false; +} diff --git a/bsnes/ui/general/nss-dip-window.hpp b/bsnes/ui/general/nss-dip-window.hpp new file mode 100755 index 00000000..885eabf5 --- /dev/null +++ b/bsnes/ui/general/nss-dip-window.hpp @@ -0,0 +1,12 @@ +struct NSSDipWindow : TopLevelWindow { + FixedLayout layout; + Label dipName[16]; + ComboBox dipValue[16]; + Button loadButton; + + void create(); + void select(); + void assign(); +}; + +extern NSSDipWindow nssDipWindow; diff --git a/bsnes/ui/main.cpp b/bsnes/ui/main.cpp index 06c588c5..444b7ffc 100755 --- a/bsnes/ui/main.cpp +++ b/bsnes/ui/main.cpp @@ -54,6 +54,7 @@ void Application::main(int argc, char **argv) { fileBrowser.create(); singleSlotLoader.create(); doubleSlotLoader.create(); + nssDipWindow.create(); videoSettings.create(); audioSettings.create(); inputSettings.create(); diff --git a/bsnes/ui/utility/utility.cpp b/bsnes/ui/utility/utility.cpp index bd799a60..ed08475f 100755 --- a/bsnes/ui/utility/utility.cpp +++ b/bsnes/ui/utility/utility.cpp @@ -158,6 +158,12 @@ void Utility::cartridgeLoaded() { "Loaded ", notdir(cartridge.baseName), cartridge.patchApplied ? ", and applied UPS patch" : "" }); + + //NSS + if(SNES::cartridge.has_nss_dip()) { + nssDipWindow.select(); + application.pause = true; + } } void Utility::cartridgeUnloaded() {