diff --git a/higan/emulator/emulator.hpp b/higan/emulator/emulator.hpp index 00cbf2c3..f6be2504 100755 --- a/higan/emulator/emulator.hpp +++ b/higan/emulator/emulator.hpp @@ -3,7 +3,7 @@ namespace Emulator { static const char Name[] = "higan"; - static const char Version[] = "092.01"; + static const char Version[] = "092.02"; static const char Author[] = "byuu"; static const char License[] = "GPLv3"; } diff --git a/higan/sfc/Makefile b/higan/sfc/Makefile index 2bc987e6..f18b65ab 100755 --- a/higan/sfc/Makefile +++ b/higan/sfc/Makefile @@ -1,13 +1,14 @@ sfc_objects := sfc-interface sfc-system sfc-controller sfc_objects += sfc-cartridge sfc-cheat sfc_objects += sfc-memory sfc-cpu sfc-smp sfc-dsp sfc-ppu +sfc_objects += sfc-satellaviewbase sfc_objects += sfc-icd2 sfc-bsx sfc-nss sfc-event sfc_objects += sfc-sa1 sfc-superfx sfc_objects += sfc-armdsp sfc-hitachidsp sfc-necdsp sfc_objects += sfc-epsonrtc sfc-sharprtc sfc_objects += sfc-spc7110 sfc-sdd1 sfc-obc1 sfc_objects += sfc-hsu1 sfc-msu1 -sfc_objects += sfc-satellaview sfc-sufamiturbo +sfc_objects += sfc-satellaviewcart sfc-sufamiturbo objects += $(sfc_objects) ifeq ($(profile),accuracy) @@ -32,38 +33,40 @@ else $(error unknown profile.) endif -obj/sfc-interface.o: $(sfc)/interface/interface.cpp $(call rwildcard,$(sfc)/interface) -obj/sfc-system.o: $(sfc)/system/system.cpp $(call rwildcard,$(sfc)/system/) -obj/sfc-controller.o: $(sfc)/controller/controller.cpp $(call rwildcard,$(sfc)/controller/) -obj/sfc-cartridge.o: $(sfc)/cartridge/cartridge.cpp $(sfc)/cartridge/* -obj/sfc-cheat.o: $(sfc)/cheat/cheat.cpp $(sfc)/cheat/* -obj/sfc-memory.o: $(sfc)/memory/memory.cpp $(call rwildcard,$(sfc)/memory/) -obj/sfc-cpu.o: $(sfccpu)/cpu.cpp $(call rwildcard,$(sfccpu)/) -obj/sfc-smp.o: $(sfcsmp)/smp.cpp $(call rwildcard,$(sfcsmp)/) -obj/sfc-dsp.o: $(sfcdsp)/dsp.cpp $(call rwildcard,$(sfcdsp)/) -obj/sfc-ppu.o: $(sfcppu)/ppu.cpp $(call rwildcard,$(sfcppu)/) +obj/sfc-interface.o: $(sfc)/interface/interface.cpp $(call rwildcard,$(sfc)/interface) +obj/sfc-system.o: $(sfc)/system/system.cpp $(call rwildcard,$(sfc)/system/) +obj/sfc-controller.o: $(sfc)/controller/controller.cpp $(call rwildcard,$(sfc)/controller/) +obj/sfc-cartridge.o: $(sfc)/cartridge/cartridge.cpp $(sfc)/cartridge/* +obj/sfc-cheat.o: $(sfc)/cheat/cheat.cpp $(sfc)/cheat/* +obj/sfc-memory.o: $(sfc)/memory/memory.cpp $(call rwildcard,$(sfc)/memory/) +obj/sfc-cpu.o: $(sfccpu)/cpu.cpp $(call rwildcard,$(sfccpu)/) +obj/sfc-smp.o: $(sfcsmp)/smp.cpp $(call rwildcard,$(sfcsmp)/) +obj/sfc-dsp.o: $(sfcdsp)/dsp.cpp $(call rwildcard,$(sfcdsp)/) +obj/sfc-ppu.o: $(sfcppu)/ppu.cpp $(call rwildcard,$(sfcppu)/) -obj/sfc-icd2.o: $(sfc)/chip/icd2/icd2.cpp $(call rwildcard,$(sfc)/chip/icd2/) -obj/sfc-bsx.o: $(sfc)/chip/bsx/bsx.cpp $(call rwildcard,$(sfc)/chip/bsx/) -obj/sfc-nss.o: $(sfc)/chip/nss/nss.cpp $(call rwildcard,$(sfc)/chip/nss/) -obj/sfc-event.o: $(sfc)/chip/event/event.cpp $(call rwildcard,$(sfc)/chip/event/) +obj/sfc-satellaviewbase.o: $(sfc)/base/satellaview/satellaview.cpp $(call rwildcard,$(sfc)/base/satellaview/) -obj/sfc-sa1.o: $(sfc)/chip/sa1/sa1.cpp $(call rwildcard,$(sfc)/chip/sa1/) -obj/sfc-superfx.o: $(sfc)/chip/superfx/superfx.cpp $(call rwildcard,$(sfc)/chip/superfx/) +obj/sfc-icd2.o: $(sfc)/chip/icd2/icd2.cpp $(call rwildcard,$(sfc)/chip/icd2/) +obj/sfc-bsx.o: $(sfc)/chip/bsx/bsx.cpp $(call rwildcard,$(sfc)/chip/bsx/) +obj/sfc-nss.o: $(sfc)/chip/nss/nss.cpp $(call rwildcard,$(sfc)/chip/nss/) +obj/sfc-event.o: $(sfc)/chip/event/event.cpp $(call rwildcard,$(sfc)/chip/event/) -obj/sfc-armdsp.o: $(sfc)/chip/armdsp/armdsp.cpp $(call rwildcard,$(sfc)/chip/armdsp/) -obj/sfc-hitachidsp.o: $(sfc)/chip/hitachidsp/hitachidsp.cpp $(call rwildcard,$(sfc)/chip/hitachidsp/) -obj/sfc-necdsp.o: $(sfc)/chip/necdsp/necdsp.cpp $(call rwildcard,$(sfc)/chip/necdsp/) +obj/sfc-sa1.o: $(sfc)/chip/sa1/sa1.cpp $(call rwildcard,$(sfc)/chip/sa1/) +obj/sfc-superfx.o: $(sfc)/chip/superfx/superfx.cpp $(call rwildcard,$(sfc)/chip/superfx/) -obj/sfc-epsonrtc.o: $(sfc)/chip/epsonrtc/epsonrtc.cpp $(call rwildcard,$(sfc)/chip/epsonrtc/) -obj/sfc-sharprtc.o: $(sfc)/chip/sharprtc/sharprtc.cpp $(call rwildcard,$(sfc)/chip/sharprtc/) +obj/sfc-armdsp.o: $(sfc)/chip/armdsp/armdsp.cpp $(call rwildcard,$(sfc)/chip/armdsp/) +obj/sfc-hitachidsp.o: $(sfc)/chip/hitachidsp/hitachidsp.cpp $(call rwildcard,$(sfc)/chip/hitachidsp/) +obj/sfc-necdsp.o: $(sfc)/chip/necdsp/necdsp.cpp $(call rwildcard,$(sfc)/chip/necdsp/) -obj/sfc-spc7110.o: $(sfc)/chip/spc7110/spc7110.cpp $(sfc)/chip/spc7110/* -obj/sfc-sdd1.o: $(sfc)/chip/sdd1/sdd1.cpp $(sfc)/chip/sdd1/* -obj/sfc-obc1.o: $(sfc)/chip/obc1/obc1.cpp $(sfc)/chip/obc1/* +obj/sfc-epsonrtc.o: $(sfc)/chip/epsonrtc/epsonrtc.cpp $(call rwildcard,$(sfc)/chip/epsonrtc/) +obj/sfc-sharprtc.o: $(sfc)/chip/sharprtc/sharprtc.cpp $(call rwildcard,$(sfc)/chip/sharprtc/) -obj/sfc-hsu1.o: $(sfc)/chip/hsu1/hsu1.cpp $(sfc)/chip/hsu1/* -obj/sfc-msu1.o: $(sfc)/chip/msu1/msu1.cpp $(sfc)/chip/msu1/* +obj/sfc-spc7110.o: $(sfc)/chip/spc7110/spc7110.cpp $(sfc)/chip/spc7110/* +obj/sfc-sdd1.o: $(sfc)/chip/sdd1/sdd1.cpp $(sfc)/chip/sdd1/* +obj/sfc-obc1.o: $(sfc)/chip/obc1/obc1.cpp $(sfc)/chip/obc1/* -obj/sfc-satellaview.o: $(sfc)/slot/satellaview/satellaview.cpp $(call rwildcard,$(sfc)/slot/satellaview/) -obj/sfc-sufamiturbo.o: $(sfc)/slot/sufamiturbo/sufamiturbo.cpp $(call rwildcard,$(sfc)/slot/sufamiturbo/) +obj/sfc-hsu1.o: $(sfc)/chip/hsu1/hsu1.cpp $(sfc)/chip/hsu1/* +obj/sfc-msu1.o: $(sfc)/chip/msu1/msu1.cpp $(sfc)/chip/msu1/* + +obj/sfc-satellaviewcart.o: $(sfc)/slot/satellaview/satellaview.cpp $(call rwildcard,$(sfc)/slot/satellaview/) +obj/sfc-sufamiturbo.o: $(sfc)/slot/sufamiturbo/sufamiturbo.cpp $(call rwildcard,$(sfc)/slot/sufamiturbo/) diff --git a/higan/sfc/base/base.hpp b/higan/sfc/base/base.hpp new file mode 100644 index 00000000..e0cd5ee4 --- /dev/null +++ b/higan/sfc/base/base.hpp @@ -0,0 +1 @@ +#include diff --git a/higan/sfc/chip/bsx/satellaview/satellaview.cpp b/higan/sfc/base/satellaview/satellaview.cpp old mode 100755 new mode 100644 similarity index 77% rename from higan/sfc/chip/bsx/satellaview/satellaview.cpp rename to higan/sfc/base/satellaview/satellaview.cpp index d988657b..236b8ee4 --- a/higan/sfc/chip/bsx/satellaview/satellaview.cpp +++ b/higan/sfc/base/satellaview/satellaview.cpp @@ -1,26 +1,37 @@ -#ifdef BSX_CPP +#include -BSXSatellaview bsxsatellaview; +#define SATELLAVIEW_BASE_UNIT_CPP +namespace SuperFamicom { -void BSXSatellaview::init() { +SatellaviewBaseUnit satellaviewbaseunit; + +void SatellaviewBaseUnit::init() { } -void BSXSatellaview::load() { - bus.map({&BSXSatellaview::mmio_read, &bsxsatellaview}, {&BSXSatellaview::mmio_write, &bsxsatellaview}, 0x00, 0x3f, 0x2188, 0x219f); - bus.map({&BSXSatellaview::mmio_read, &bsxsatellaview}, {&BSXSatellaview::mmio_write, &bsxsatellaview}, 0x80, 0xbf, 0x2188, 0x219f); +void SatellaviewBaseUnit::load() { + bus.map( + {&SatellaviewBaseUnit::read, &satellaviewbaseunit}, + {&SatellaviewBaseUnit::write, &satellaviewbaseunit}, + 0x00, 0x3f, 0x2188, 0x219f + ); + bus.map( + {&SatellaviewBaseUnit::read, &satellaviewbaseunit}, + {&SatellaviewBaseUnit::write, &satellaviewbaseunit}, + 0x80, 0xbf, 0x2188, 0x219f + ); } -void BSXSatellaview::unload() { +void SatellaviewBaseUnit::unload() { } -void BSXSatellaview::power() { +void SatellaviewBaseUnit::power() { } -void BSXSatellaview::reset() { +void SatellaviewBaseUnit::reset() { memset(®s, 0x00, sizeof regs); } -uint8 BSXSatellaview::mmio_read(unsigned addr) { +uint8 SatellaviewBaseUnit::read(unsigned addr) { addr &= 0xffff; switch(addr) { @@ -78,7 +89,7 @@ uint8 BSXSatellaview::mmio_read(unsigned addr) { return cpu.regs.mdr; } -void BSXSatellaview::mmio_write(unsigned addr, uint8 data) { +void SatellaviewBaseUnit::write(unsigned addr, uint8 data) { addr &= 0xffff; switch(addr) { @@ -139,4 +150,4 @@ void BSXSatellaview::mmio_write(unsigned addr, uint8 data) { } } -#endif +} diff --git a/higan/sfc/chip/bsx/satellaview/satellaview.hpp b/higan/sfc/base/satellaview/satellaview.hpp old mode 100755 new mode 100644 similarity index 72% rename from higan/sfc/chip/bsx/satellaview/satellaview.hpp rename to higan/sfc/base/satellaview/satellaview.hpp index 56caf0b7..2fb7ddde --- a/higan/sfc/chip/bsx/satellaview/satellaview.hpp +++ b/higan/sfc/base/satellaview/satellaview.hpp @@ -1,12 +1,12 @@ -struct BSXSatellaview { +struct SatellaviewBaseUnit : Memory { void init(); void load(); void unload(); void power(); void reset(); - uint8 mmio_read(unsigned addr); - void mmio_write(unsigned addr, uint8 data); + uint8 read(unsigned addr); + void write(unsigned addr, uint8 data); private: struct { @@ -22,4 +22,4 @@ private: } regs; }; -extern BSXSatellaview bsxsatellaview; +extern SatellaviewBaseUnit satellaviewbaseunit; diff --git a/higan/sfc/cartridge/cartridge.hpp b/higan/sfc/cartridge/cartridge.hpp index 57ba483b..6a63482d 100755 --- a/higan/sfc/cartridge/cartridge.hpp +++ b/higan/sfc/cartridge/cartridge.hpp @@ -100,8 +100,8 @@ private: void parse_markup_cartridge(Markup::Node); void parse_markup_icd2(Markup::Node); void parse_markup_bsx(Markup::Node); - void parse_markup_bsxslot(Markup::Node); - void parse_markup_sufamiturbo(Markup::Node); + void parse_markup_satellaview(Markup::Node); + void parse_markup_sufamiturbo(Markup::Node, bool slot); void parse_markup_nss(Markup::Node); void parse_markup_event(Markup::Node); void parse_markup_sa1(Markup::Node); diff --git a/higan/sfc/cartridge/markup.cpp b/higan/sfc/cartridge/markup.cpp index b9518a15..9e904a61 100755 --- a/higan/sfc/cartridge/markup.cpp +++ b/higan/sfc/cartridge/markup.cpp @@ -11,8 +11,9 @@ void Cartridge::parse_markup(const char *markup) { parse_markup_cartridge(cartridge); parse_markup_icd2(cartridge["icd2"]); parse_markup_bsx(cartridge["bsx"]); - parse_markup_bsxslot(cartridge["bsxslot"]); - parse_markup_sufamiturbo(cartridge["sufamiturbo"]); + parse_markup_satellaview(cartridge["satellaview"]); + parse_markup_sufamiturbo(cartridge["sufamiturbo[0]"], 0); + parse_markup_sufamiturbo(cartridge["sufamiturbo[1]"], 1); parse_markup_nss(cartridge["nss"]); parse_markup_event(cartridge["event"]); parse_markup_sa1(cartridge["sa1"]); @@ -125,15 +126,13 @@ void Cartridge::parse_markup_bsx(Markup::Node root) { } } -void Cartridge::parse_markup_bsxslot(Markup::Node root) { +void Cartridge::parse_markup_satellaview(Markup::Node root) { if(root.exists() == false) return; has_bs_slot = true; interface->loadRequest(ID::Satellaview, "BS-X Satellaview", "bs"); - for(auto &node : root) { - if(node.name != "map") continue; - + for(auto &node : root.find("map")) { if(node["id"].data == "rom") { if(satellaviewcartridge.memory.size() == 0) continue; @@ -144,39 +143,34 @@ void Cartridge::parse_markup_bsxslot(Markup::Node root) { } } -void Cartridge::parse_markup_sufamiturbo(Markup::Node root) { +void Cartridge::parse_markup_sufamiturbo(Markup::Node root, bool slot) { if(root.exists() == false) return; has_st_slots = true; - //load required slot A (will request slot B if slot A cartridge is linkable) - interface->loadRequest(ID::SufamiTurboSlotA, "Sufami Turbo - Slot A", "st"); + if(slot == 0) { + //load required slot A (will request slot B if slot A cartridge is linkable) + interface->loadRequest(ID::SufamiTurboSlotA, "Sufami Turbo - Slot A", "st"); + } - for(auto &slot : root) { - if(slot.name != "slot") continue; - bool slotid = slot["id"].data == "A" ? 0 : slot["id"].data == "B" ? 1 : 0; + for(auto &node : root.find("map")) { + SufamiTurboCartridge &cart = (slot == 0 ? sufamiturboA : sufamiturboB); - for(auto &node : slot) { - if(node.name != "map") continue; + if(node["id"].data == "rom") { + if(cart.rom.size() == 0) continue; - if(node["id"].data == "rom") { - SuperFamicom::Memory &memory = slotid == 0 ? sufamiturboA.rom : sufamiturboB.rom; - if(memory.size() == 0) continue; + Mapping m(cart.rom); + parse_markup_map(m, node); + if(m.size == 0) m.size = cart.rom.size(); + if(m.size) mapping.append(m); + } - Mapping m(memory); - parse_markup_map(m, node); - if(m.size == 0) m.size = memory.size(); - if(m.size) mapping.append(m); - } + if(node["id"].data == "ram") { + if(cart.ram.size() == 0) continue; - if(node["id"].data == "ram") { - SuperFamicom::Memory &memory = slotid == 0 ? sufamiturboA.ram : sufamiturboB.ram; - if(memory.size() == 0) continue; - - Mapping m(memory); - parse_markup_map(m, node); - if(m.size == 0) m.size = memory.size(); - if(m.size) mapping.append(m); - } + Mapping m(cart.ram); + parse_markup_map(m, node); + if(m.size == 0) m.size = cart.ram.size(); + if(m.size) mapping.append(m); } } } diff --git a/higan/sfc/chip/bsx/bsx.cpp b/higan/sfc/chip/bsx/bsx.cpp index bf0d9c03..b2381fc6 100755 --- a/higan/sfc/chip/bsx/bsx.cpp +++ b/higan/sfc/chip/bsx/bsx.cpp @@ -2,6 +2,145 @@ #define BSX_CPP namespace SuperFamicom { - #include "satellaview/satellaview.cpp" - #include "cartridge/cartridge.cpp" + +#include "serialization.cpp" +BSXCartridge bsxcartridge; + +void BSXCartridge::init() { +} + +void BSXCartridge::load() { +} + +void BSXCartridge::unload() { + rom.reset(); + ram.reset(); + psram.reset(); +} + +void BSXCartridge::power() { +} + +void BSXCartridge::reset() { + for(unsigned i = 0; i < 16; i++) r[i] = 0x00; + r[0x07] = 0x80; + r[0x08] = 0x80; + mmio_commit(); +} + +uint8 BSXCartridge::memory_access(bool write, Memory &memory, unsigned addr, uint8 data) { + if(write == 0) return memory_read(memory, addr); + memory_write(memory, addr, data); +} + +uint8 BSXCartridge::memory_read(Memory &memory, unsigned addr) { + addr = bus.mirror(addr, memory.size()); + return memory.read(addr); +} + +void BSXCartridge::memory_write(Memory &memory, unsigned addr, uint8 data) { + addr = bus.mirror(addr, memory.size()); + return memory.write(addr, data); +} + +//mcu_access() allows mcu_read() and mcu_write() to share decoding logic +uint8 BSXCartridge::mcu_access(bool write, unsigned addr, uint8 data) { + if((addr & 0xe08000) == 0x008000) { //$00-1f:8000-ffff + if(r07 == 1) { + addr = ((addr & 0x1f0000) >> 1) | (addr & 0x7fff); + return memory_access(write, rom, addr, data); + } + } + + if((addr & 0xe08000) == 0x808000) { //$80-9f:8000-ffff + if(r08 == 1) { + addr = ((addr & 0x1f0000) >> 1) | (addr & 0x7fff); + return memory_access(write, rom, addr, data); + } + } + + if((addr & 0xe0e000) == 0x206000) { //$20-3f:6000-7fff + return memory_access(write, psram, addr, data); + } + + if((addr & 0xf00000) == 0x400000) { //$40-4f:0000-ffff + if(r05 == 0) return memory_access(write, psram, addr & 0x0fffff, data); + } + + if((addr & 0xf00000) == 0x500000) { //$50-5f:0000-ffff + if(r06 == 0) return memory_access(write, psram, addr & 0x0fffff, data); + } + + if((addr & 0xf00000) == 0x600000) { //$60-6f:0000-ffff + if(r03 == 1) return memory_access(write, psram, addr & 0x0fffff, data); + } + + if((addr & 0xf80000) == 0x700000) { //$70-77:0000-ffff + return memory_access(write, psram, addr & 0x07ffff, data); + } + + if(((addr & 0x408000) == 0x008000) //$00-3f|80-bf:8000-ffff + || ((addr & 0x400000) == 0x400000) //$40-7f|c0-ff:0000-ffff + ) { + if(r02 == 0) addr = ((addr & 0x7f0000) >> 1) | (addr & 0x7fff); + Memory &memory = (r01 == 0 ? (Memory&)satellaviewcartridge : (Memory&)psram); + return memory_access(write, memory, addr & 0x7fffff, data); + } + + return cpu.regs.mdr; +} + +uint8 BSXCartridge::mcu_read(unsigned addr) { + return mcu_access(0, addr); +} + +void BSXCartridge::mcu_write(unsigned addr, uint8 data) { + mcu_access(1, addr, data); +} + +uint8 BSXCartridge::mmio_read(unsigned addr) { + if((addr & 0xf0ffff) == 0x005000) { //$00-0f:5000 + uint8 n = (addr >> 16) & 15; + return r[n]; + } + + if((addr & 0xf8f000) == 0x105000) { //$10-17:5000-5fff + return memory_read(ram, ((addr >> 16) & 7) * 0x1000 + (addr & 0xfff)); + } + + return 0x00; +} + +void BSXCartridge::mmio_write(unsigned addr, uint8 data) { + if((addr & 0xf0ffff) == 0x005000) { //$00-0f:5000 + uint8 n = (addr >> 16) & 15; + r[n] = data; + if(n == 0x0e && data & 0x80) mmio_commit(); + return; + } + + if((addr & 0xf8f000) == 0x105000) { //$10-17:5000-5fff + return memory_write(ram, ((addr >> 16) & 7) * 0x1000 + (addr & 0xfff), data); + } +} + +void BSXCartridge::mmio_commit() { + r00 = r[0x00] & 0x80; + r01 = r[0x01] & 0x80; + r02 = r[0x02] & 0x80; + r03 = r[0x03] & 0x80; + r04 = r[0x04] & 0x80; + r05 = r[0x05] & 0x80; + r06 = r[0x06] & 0x80; + r07 = r[0x07] & 0x80; + r08 = r[0x08] & 0x80; + r09 = r[0x09] & 0x80; + r0a = r[0x0a] & 0x80; + r0b = r[0x0b] & 0x80; + r0c = r[0x0c] & 0x80; + r0d = r[0x0d] & 0x80; + r0e = r[0x0e] & 0x80; + r0f = r[0x0f] & 0x80; +} + } diff --git a/higan/sfc/chip/bsx/bsx.hpp b/higan/sfc/chip/bsx/bsx.hpp index dd761a05..19815ca9 100755 --- a/higan/sfc/chip/bsx/bsx.hpp +++ b/higan/sfc/chip/bsx/bsx.hpp @@ -1,2 +1,34 @@ -#include "satellaview/satellaview.hpp" -#include "cartridge/cartridge.hpp" +struct BSXCartridge { + MappedRAM rom; + MappedRAM ram; + MappedRAM psram; + + void init(); + void load(); + void unload(); + void power(); + void reset(); + + uint8 memory_access(bool write, Memory &memory, unsigned addr, uint8 data); + uint8 memory_read(Memory &memory, unsigned addr); + void memory_write(Memory &memory, unsigned addr, uint8 data); + + uint8 mcu_access(bool write, unsigned addr, uint8 data = 0x00); + uint8 mcu_read(unsigned addr); + void mcu_write(unsigned addr, uint8 data); + + uint8 mmio_read(unsigned addr); + void mmio_write(unsigned addr, uint8 data); + void mmio_commit(); + + void serialize(serializer&); + +private: + uint8 r[16]; + bool r00, r01, r02, r03; + bool r04, r05, r06, r07; + bool r08, r09, r0a, r0b; + bool r0c, r0d, r0e, r0f; +}; + +extern BSXCartridge bsxcartridge; diff --git a/higan/sfc/chip/bsx/cartridge/cartridge.cpp b/higan/sfc/chip/bsx/cartridge/cartridge.cpp deleted file mode 100755 index c025e36a..00000000 --- a/higan/sfc/chip/bsx/cartridge/cartridge.cpp +++ /dev/null @@ -1,143 +0,0 @@ -#ifdef BSX_CPP - -#include "serialization.cpp" -BSXCartridge bsxcartridge; - -void BSXCartridge::init() { -} - -void BSXCartridge::load() { -} - -void BSXCartridge::unload() { - rom.reset(); - ram.reset(); - psram.reset(); -} - -void BSXCartridge::power() { -} - -void BSXCartridge::reset() { - for(unsigned i = 0; i < 16; i++) r[i] = 0x00; - r[0x07] = 0x80; - r[0x08] = 0x80; - mmio_commit(); -} - -uint8 BSXCartridge::memory_access(bool write, Memory &memory, unsigned addr, uint8 data) { - if(write == 0) return memory_read(memory, addr); - memory_write(memory, addr, data); -} - -uint8 BSXCartridge::memory_read(Memory &memory, unsigned addr) { - addr = bus.mirror(addr, memory.size()); - return memory.read(addr); -} - -void BSXCartridge::memory_write(Memory &memory, unsigned addr, uint8 data) { - addr = bus.mirror(addr, memory.size()); - return memory.write(addr, data); -} - -//mcu_access() allows mcu_read() and mcu_write() to share decoding logic -uint8 BSXCartridge::mcu_access(bool write, unsigned addr, uint8 data) { - if((addr & 0xe08000) == 0x008000) { //$00-1f:8000-ffff - if(r07 == 1) { - addr = ((addr & 0x1f0000) >> 1) | (addr & 0x7fff); - return memory_access(write, rom, addr, data); - } - } - - if((addr & 0xe08000) == 0x808000) { //$80-9f:8000-ffff - if(r08 == 1) { - addr = ((addr & 0x1f0000) >> 1) | (addr & 0x7fff); - return memory_access(write, rom, addr, data); - } - } - - if((addr & 0xe0e000) == 0x206000) { //$20-3f:6000-7fff - return memory_access(write, psram, addr, data); - } - - if((addr & 0xf00000) == 0x400000) { //$40-4f:0000-ffff - if(r05 == 0) return memory_access(write, psram, addr & 0x0fffff, data); - } - - if((addr & 0xf00000) == 0x500000) { //$50-5f:0000-ffff - if(r06 == 0) return memory_access(write, psram, addr & 0x0fffff, data); - } - - if((addr & 0xf00000) == 0x600000) { //$60-6f:0000-ffff - if(r03 == 1) return memory_access(write, psram, addr & 0x0fffff, data); - } - - if((addr & 0xf80000) == 0x700000) { //$70-77:0000-ffff - return memory_access(write, psram, addr & 0x07ffff, data); - } - - if(((addr & 0x408000) == 0x008000) //$00-3f|80-bf:8000-ffff - || ((addr & 0x400000) == 0x400000) //$40-7f|c0-ff:0000-ffff - ) { - if(r02 == 0) addr = ((addr & 0x7f0000) >> 1) | (addr & 0x7fff); - Memory &memory = (r01 == 0 ? (Memory&)satellaviewcartridge : (Memory&)psram); - return memory_access(write, memory, addr & 0x7fffff, data); - } - - return cpu.regs.mdr; -} - -uint8 BSXCartridge::mcu_read(unsigned addr) { - return mcu_access(0, addr); -} - -void BSXCartridge::mcu_write(unsigned addr, uint8 data) { - mcu_access(1, addr, data); -} - -uint8 BSXCartridge::mmio_read(unsigned addr) { - if((addr & 0xf0ffff) == 0x005000) { //$00-0f:5000 - uint8 n = (addr >> 16) & 15; - return r[n]; - } - - if((addr & 0xf8f000) == 0x105000) { //$10-17:5000-5fff - return memory_read(ram, ((addr >> 16) & 7) * 0x1000 + (addr & 0xfff)); - } - - return 0x00; -} - -void BSXCartridge::mmio_write(unsigned addr, uint8 data) { - if((addr & 0xf0ffff) == 0x005000) { //$00-0f:5000 - uint8 n = (addr >> 16) & 15; - r[n] = data; - if(n == 0x0e && data & 0x80) mmio_commit(); - return; - } - - if((addr & 0xf8f000) == 0x105000) { //$10-17:5000-5fff - return memory_write(ram, ((addr >> 16) & 7) * 0x1000 + (addr & 0xfff), data); - } -} - -void BSXCartridge::mmio_commit() { - r00 = r[0x00] & 0x80; - r01 = r[0x01] & 0x80; - r02 = r[0x02] & 0x80; - r03 = r[0x03] & 0x80; - r04 = r[0x04] & 0x80; - r05 = r[0x05] & 0x80; - r06 = r[0x06] & 0x80; - r07 = r[0x07] & 0x80; - r08 = r[0x08] & 0x80; - r09 = r[0x09] & 0x80; - r0a = r[0x0a] & 0x80; - r0b = r[0x0b] & 0x80; - r0c = r[0x0c] & 0x80; - r0d = r[0x0d] & 0x80; - r0e = r[0x0e] & 0x80; - r0f = r[0x0f] & 0x80; -} - -#endif diff --git a/higan/sfc/chip/bsx/cartridge/cartridge.hpp b/higan/sfc/chip/bsx/cartridge/cartridge.hpp deleted file mode 100755 index 19815ca9..00000000 --- a/higan/sfc/chip/bsx/cartridge/cartridge.hpp +++ /dev/null @@ -1,34 +0,0 @@ -struct BSXCartridge { - MappedRAM rom; - MappedRAM ram; - MappedRAM psram; - - void init(); - void load(); - void unload(); - void power(); - void reset(); - - uint8 memory_access(bool write, Memory &memory, unsigned addr, uint8 data); - uint8 memory_read(Memory &memory, unsigned addr); - void memory_write(Memory &memory, unsigned addr, uint8 data); - - uint8 mcu_access(bool write, unsigned addr, uint8 data = 0x00); - uint8 mcu_read(unsigned addr); - void mcu_write(unsigned addr, uint8 data); - - uint8 mmio_read(unsigned addr); - void mmio_write(unsigned addr, uint8 data); - void mmio_commit(); - - void serialize(serializer&); - -private: - uint8 r[16]; - bool r00, r01, r02, r03; - bool r04, r05, r06, r07; - bool r08, r09, r0a, r0b; - bool r0c, r0d, r0e, r0f; -}; - -extern BSXCartridge bsxcartridge; diff --git a/higan/sfc/chip/bsx/cartridge/serialization.cpp b/higan/sfc/chip/bsx/serialization.cpp old mode 100755 new mode 100644 similarity index 83% rename from higan/sfc/chip/bsx/cartridge/serialization.cpp rename to higan/sfc/chip/bsx/serialization.cpp index a982d822..aed4206b --- a/higan/sfc/chip/bsx/cartridge/serialization.cpp +++ b/higan/sfc/chip/bsx/serialization.cpp @@ -1,4 +1,8 @@ +#ifdef BSX_CPP + void BSXCartridge::serialize(serializer &s) { s.array(ram.data(), ram.size()); s.array(psram.data(), psram.size()); } + +#endif diff --git a/higan/sfc/config/config.cpp b/higan/sfc/config/config.cpp index 701af94c..f53ee1ca 100755 --- a/higan/sfc/config/config.cpp +++ b/higan/sfc/config/config.cpp @@ -5,7 +5,7 @@ Configuration config; Configuration::Configuration() { controller_port1 = Input::Device::Joypad; controller_port2 = Input::Device::Joypad; - expansion_port = System::ExpansionPortDevice::BSX; + expansion_port = System::ExpansionPortDevice::Satellaview; region = System::Region::Autodetect; random = true; diff --git a/higan/sfc/ppu/screen/screen.cpp b/higan/sfc/ppu/screen/screen.cpp index f59eea1a..94fbdb3e 100755 --- a/higan/sfc/ppu/screen/screen.cpp +++ b/higan/sfc/ppu/screen/screen.cpp @@ -3,159 +3,130 @@ void PPU::Screen::scanline() { output = self.output + self.vcounter() * 1024; if(self.display.interlace && self.field()) output += 512; + + //the first hires pixel of each scanline is transparent + //note: exact value initializations are not confirmed on hardware + math.main.color = get_color(0); + math.sub.color = math.main.color; + + math.main.color_enable = !(self.window.regs.col_main_mask & 1); + math.sub.color_enable = !(self.window.regs.col_sub_mask & 1) && regs.back_color_enable; + + math.transparent = true; + math.addsub_mode = false; + math.color_halve = regs.color_halve && !regs.addsub_mode && math.main.color_enable; } void PPU::Screen::run() { if(ppu.vcounter() == 0) return; - uint32 color; - if(self.regs.pseudo_hires == false && self.regs.bgmode != 5 && self.regs.bgmode != 6) { - color = get_pixel(0); - *output++ = color; - *output++ = color; - } else { - color = get_pixel(1); - *output++ = color; - color = get_pixel(0); - *output++ = color; - } + auto palette = &video.palette[self.regs.display_brightness << 15]; + bool hires = self.regs.pseudo_hires || self.regs.bgmode == 5 || self.regs.bgmode == 6; + auto sscolor = get_pixel_sub(hires); + auto mscolor = get_pixel_main(); + + *output++ = palette[hires ? sscolor : mscolor]; + *output++ = palette[mscolor]; } -uint32 PPU::Screen::get_pixel(bool swap) { - if(ppu.regs.overscan == false && ppu.vcounter() >= 225) return 0x0000; - - enum source_t { BG1, BG2, BG3, BG4, OAM, BACK }; - bool color_enable[] = { regs.bg1_color_enable, regs.bg2_color_enable, regs.bg3_color_enable, regs.bg4_color_enable, regs.oam_color_enable, regs.back_color_enable }; - - //=========== - //main screen - //=========== - - unsigned priority_main = 0; - unsigned color_main; - unsigned source_main; - - if(self.bg1.output.main.priority) { - priority_main = self.bg1.output.main.priority; - if(regs.direct_color && (self.regs.bgmode == 3 || self.regs.bgmode == 4 || self.regs.bgmode == 7)) { - color_main = get_direct_color(self.bg1.output.main.palette, self.bg1.output.main.tile); - } else { - color_main = get_color(self.bg1.output.main.palette); - } - source_main = BG1; - } - if(self.bg2.output.main.priority > priority_main) { - priority_main = self.bg2.output.main.priority; - color_main = get_color(self.bg2.output.main.palette); - source_main = BG2; - } - if(self.bg3.output.main.priority > priority_main) { - priority_main = self.bg3.output.main.priority; - color_main = get_color(self.bg3.output.main.palette); - source_main = BG3; - } - if(self.bg4.output.main.priority > priority_main) { - priority_main = self.bg4.output.main.priority; - color_main = get_color(self.bg4.output.main.palette); - source_main = BG4; - } - if(self.sprite.output.main.priority > priority_main) { - priority_main = self.sprite.output.main.priority; - color_main = get_color(self.sprite.output.main.palette); - source_main = OAM; - } - if(priority_main == 0) { - color_main = get_color(0); - source_main = BACK; - } - - //========== - //sub screen - //========== - - unsigned priority_sub = 0; - unsigned color_sub; - unsigned source_sub; +uint16 PPU::Screen::get_pixel_sub(bool hires) { + if(self.regs.display_disable || (!self.regs.overscan && self.vcounter() >= 225)) return 0; + unsigned priority = 0; if(self.bg1.output.sub.priority) { - priority_sub = self.bg1.output.sub.priority; + priority = self.bg1.output.sub.priority; if(regs.direct_color && (self.regs.bgmode == 3 || self.regs.bgmode == 4 || self.regs.bgmode == 7)) { - color_sub = get_direct_color(self.bg1.output.sub.palette, self.bg1.output.sub.tile); + math.sub.color = get_direct_color(self.bg1.output.sub.palette, self.bg1.output.sub.tile); } else { - color_sub = get_color(self.bg1.output.sub.palette); + math.sub.color = get_color(self.bg1.output.sub.palette); } - source_sub = BG1; } - if(self.bg2.output.sub.priority > priority_sub) { - priority_sub = self.bg2.output.sub.priority; - color_sub = get_color(self.bg2.output.sub.palette); - source_sub = BG2; + if(self.bg2.output.sub.priority > priority) { + priority = self.bg2.output.sub.priority; + math.sub.color = get_color(self.bg2.output.sub.palette); } - if(self.bg3.output.sub.priority > priority_sub) { - priority_sub = self.bg3.output.sub.priority; - color_sub = get_color(self.bg3.output.sub.palette); - source_sub = BG3; + if(self.bg3.output.sub.priority > priority) { + priority = self.bg3.output.sub.priority; + math.sub.color = get_color(self.bg3.output.sub.palette); } - if(self.bg4.output.sub.priority > priority_sub) { - priority_sub = self.bg4.output.sub.priority; - color_sub = get_color(self.bg4.output.sub.palette); - source_sub = BG4; + if(self.bg4.output.sub.priority > priority) { + priority = self.bg4.output.sub.priority; + math.sub.color = get_color(self.bg4.output.sub.palette); } - if(self.sprite.output.sub.priority > priority_sub) { - priority_sub = self.sprite.output.sub.priority; - color_sub = get_color(self.sprite.output.sub.palette); - source_sub = OAM; - } - if(priority_sub == 0) { - if(self.regs.pseudo_hires == true || self.regs.bgmode == 5 || self.regs.bgmode == 6) { - color_sub = get_color(0); - } else { - color_sub = (regs.color_b << 10) + (regs.color_g << 5) + (regs.color_r << 0); - } - source_sub = BACK; + if(self.sprite.output.sub.priority > priority) { + priority = self.sprite.output.sub.priority; + math.sub.color = get_color(self.sprite.output.sub.palette); } + if(math.transparent = (priority == 0)) math.sub.color = get_color(0); - if(swap == true) { - std::swap(priority_main, priority_sub); - std::swap(color_main, color_sub); - std::swap(source_main, source_sub); - } + if(!hires) return 0; + if(!math.sub.color_enable) return math.main.color_enable ? math.sub.color : 0; - uint16 output; - if(!regs.addsub_mode) { - source_sub = BACK; - color_sub = (regs.color_b << 10) + (regs.color_g << 5) + (regs.color_r << 0); - } - - if(self.window.output.main.color_enable == false) { - if(self.window.output.sub.color_enable == false) { - return 0x0000; - } - color_main = 0x0000; - } - - bool color_exempt = (source_main == OAM && self.sprite.output.main.palette < 192); - if(!color_exempt && color_enable[source_main] && self.window.output.sub.color_enable) { - bool halve = false; - if(regs.color_halve && self.window.output.main.color_enable) { - if(!regs.addsub_mode || source_sub != BACK) halve = true; - } - output = addsub(color_main, color_sub, halve); - } else { - output = color_main; - } - - //======== - //lighting - //======== - - if(self.regs.display_disable) return 0; - return video.palette[self.regs.display_brightness << 15 | output]; + return addsub( + math.main.color_enable ? math.sub.color : 0, + math.addsub_mode ? math.main.color : fixed_color() + ); } -uint16 PPU::Screen::addsub(unsigned x, unsigned y, bool halve) { +uint16 PPU::Screen::get_pixel_main() { + if(self.regs.display_disable || (!self.regs.overscan && self.vcounter() >= 225)) return 0; + + unsigned priority = 0; + if(self.bg1.output.main.priority) { + priority = self.bg1.output.main.priority; + if(regs.direct_color && (self.regs.bgmode == 3 || self.regs.bgmode == 4 || self.regs.bgmode == 7)) { + math.main.color = get_direct_color(self.bg1.output.main.palette, self.bg1.output.main.tile); + } else { + math.main.color = get_color(self.bg1.output.main.palette); + } + math.sub.color_enable = regs.bg1_color_enable; + } + if(self.bg2.output.main.priority > priority) { + priority = self.bg2.output.main.priority; + math.main.color = get_color(self.bg2.output.main.palette); + math.sub.color_enable = regs.bg2_color_enable; + } + if(self.bg3.output.main.priority > priority) { + priority = self.bg3.output.main.priority; + math.main.color = get_color(self.bg3.output.main.palette); + math.sub.color_enable = regs.bg3_color_enable; + } + if(self.bg4.output.main.priority > priority) { + priority = self.bg4.output.main.priority; + math.main.color = get_color(self.bg4.output.main.palette); + math.sub.color_enable = regs.bg4_color_enable; + } + if(self.sprite.output.main.priority > priority) { + priority = self.sprite.output.main.priority; + math.main.color = get_color(self.sprite.output.main.palette); + math.sub.color_enable = regs.oam_color_enable && self.sprite.output.main.palette >= 192; + } + if(priority == 0) { + math.main.color = get_color(0); + math.sub.color_enable = regs.back_color_enable; + } + + if(!self.window.output.sub.color_enable) math.sub.color_enable = false; + math.main.color_enable = self.window.output.main.color_enable; + if(!math.sub.color_enable) return math.main.color_enable ? math.main.color : 0; + + if(regs.addsub_mode && math.transparent) { + math.addsub_mode = false; + math.color_halve = false; + } else { + math.addsub_mode = regs.addsub_mode; + math.color_halve = regs.color_halve && math.main.color_enable; + } + + return addsub( + math.main.color_enable ? math.main.color : 0, + math.addsub_mode ? math.sub.color : fixed_color() + ); +} + +uint16 PPU::Screen::addsub(unsigned x, unsigned y) { if(!regs.color_mode) { - if(!halve) { + if(!math.color_halve) { unsigned sum = x + y; unsigned carry = (sum - ((x ^ y) & 0x0421)) & 0x8420; return (sum - carry) | (carry - (carry >> 5)); @@ -165,7 +136,7 @@ uint16 PPU::Screen::addsub(unsigned x, unsigned y, bool halve) { } else { unsigned diff = x - y + 0x8420; unsigned borrow = (diff - ((x ^ y) & 0x8420)) & 0x8420; - if(!halve) { + if(!math.color_halve) { return (diff - borrow) & (borrow - (borrow >> 5)); } else { return (((diff - borrow) & (borrow - (borrow >> 5))) & 0x7bde) >> 1; @@ -188,6 +159,10 @@ uint16 PPU::Screen::get_direct_color(unsigned palette, unsigned tile) { + ((palette << 2) & 0x001c) + ((tile >> 9) & 0x0002); } +uint16 PPU::Screen::fixed_color() const { + return (regs.color_b << 10) | (regs.color_g << 5) | (regs.color_r << 0); +} + void PPU::Screen::reset() { regs.addsub_mode = random(false); regs.direct_color = random(false); diff --git a/higan/sfc/ppu/screen/screen.hpp b/higan/sfc/ppu/screen/screen.hpp index 6c674841..ca861818 100755 --- a/higan/sfc/ppu/screen/screen.hpp +++ b/higan/sfc/ppu/screen/screen.hpp @@ -19,14 +19,26 @@ struct Screen { uint5 color_r; } regs; + struct Math { + struct Layer { + uint16 color; + bool color_enable; + } main, sub; + bool transparent; + bool addsub_mode; + bool color_halve; + } math; + void scanline(); void run(); void reset(); - uint32 get_pixel(bool swap); - uint16 addsub(unsigned x, unsigned y, bool halve); + uint16 get_pixel_sub(bool hires); + uint16 get_pixel_main(); + uint16 addsub(unsigned x, unsigned y); uint16 get_color(unsigned palette); uint16 get_direct_color(unsigned palette, unsigned tile); + uint16 fixed_color() const; void serialize(serializer&); Screen(PPU &self); diff --git a/higan/sfc/ppu/serialization.cpp b/higan/sfc/ppu/serialization.cpp index d8d6ec91..07a56a63 100755 --- a/higan/sfc/ppu/serialization.cpp +++ b/higan/sfc/ppu/serialization.cpp @@ -279,6 +279,14 @@ void PPU::Screen::serialize(serializer &s) { s.integer(regs.color_b); s.integer(regs.color_g); s.integer(regs.color_r); + + s.integer(math.main.color); + s.integer(math.main.color_enable); + s.integer(math.sub.color); + s.integer(math.sub.color_enable); + s.integer(math.transparent); + s.integer(math.addsub_mode); + s.integer(math.color_halve); } #endif diff --git a/higan/sfc/sfc.hpp b/higan/sfc/sfc.hpp index 3219e28e..501a7202 100755 --- a/higan/sfc/sfc.hpp +++ b/higan/sfc/sfc.hpp @@ -12,7 +12,7 @@ namespace SuperFamicom { namespace Info { static const char Name[] = "bsnes"; - static const unsigned SerializerVersion = 25; + static const unsigned SerializerVersion = 26; } } @@ -65,6 +65,7 @@ namespace SuperFamicom { #include #include + #include #include #include #include diff --git a/higan/sfc/system/system.cpp b/higan/sfc/system/system.cpp index a69812b2..69f6eead 100755 --- a/higan/sfc/system/system.cpp +++ b/higan/sfc/system/system.cpp @@ -64,7 +64,7 @@ void System::runthreadtosave() { void System::init() { assert(interface != nullptr); - bsxsatellaview.init(); + satellaviewbaseunit.init(); icd2.init(); bsxcartridge.init(); nss.init(); @@ -119,7 +119,7 @@ void System::load() { cpu.enable(); ppu.enable(); - if(expansion() == ExpansionPortDevice::BSX) bsxsatellaview.load(); + if(expansion() == ExpansionPortDevice::Satellaview) satellaviewbaseunit.load(); if(cartridge.has_gb_slot()) icd2.load(); if(cartridge.has_bs_cart()) bsxcartridge.load(); if(cartridge.has_nss_dip()) nss.load(); @@ -144,7 +144,7 @@ void System::load() { } void System::unload() { - if(expansion() == ExpansionPortDevice::BSX) bsxsatellaview.unload(); + if(expansion() == ExpansionPortDevice::Satellaview) satellaviewbaseunit.unload(); if(cartridge.has_gb_slot()) icd2.unload(); if(cartridge.has_bs_cart()) bsxcartridge.unload(); if(cartridge.has_nss_dip()) nss.unload(); @@ -173,7 +173,7 @@ void System::power() { dsp.power(); ppu.power(); - if(expansion() == ExpansionPortDevice::BSX) bsxsatellaview.power(); + if(expansion() == ExpansionPortDevice::Satellaview) satellaviewbaseunit.power(); if(cartridge.has_gb_slot()) icd2.power(); if(cartridge.has_bs_cart()) bsxcartridge.power(); if(cartridge.has_nss_dip()) nss.power(); @@ -201,7 +201,7 @@ void System::reset() { dsp.reset(); ppu.reset(); - if(expansion() == ExpansionPortDevice::BSX) bsxsatellaview.reset(); + if(expansion() == ExpansionPortDevice::Satellaview) satellaviewbaseunit.reset(); if(cartridge.has_gb_slot()) icd2.reset(); if(cartridge.has_bs_cart()) bsxcartridge.reset(); if(cartridge.has_nss_dip()) nss.reset(); @@ -247,7 +247,7 @@ void System::frame() { System::System() { region = Region::Autodetect; - expansion = ExpansionPortDevice::BSX; + expansion = ExpansionPortDevice::Satellaview; } } diff --git a/higan/sfc/system/system.hpp b/higan/sfc/system/system.hpp index 3bb08aef..1374fa7a 100755 --- a/higan/sfc/system/system.hpp +++ b/higan/sfc/system/system.hpp @@ -2,7 +2,7 @@ struct Interface; struct System : property { enum class Region : unsigned { NTSC = 0, PAL = 1, Autodetect = 2 }; - enum class ExpansionPortDevice : unsigned { None = 0, BSX = 1 }; + enum class ExpansionPortDevice : unsigned { None = 0, Satellaview = 1 }; void run(); void runtosave(); diff --git a/higan/target-ethos/settings/timing.cpp b/higan/target-ethos/settings/timing.cpp index cd734454..a1b1fbc1 100755 --- a/higan/target-ethos/settings/timing.cpp +++ b/higan/target-ethos/settings/timing.cpp @@ -81,7 +81,7 @@ void TimingSettings::analyzeStart() { settings->panelList.setEnabled(false); videoAdjust.analyze.setEnabled(false); audioAdjust.analyze.setEnabled(false); - settings->setStatusText("Initiailizing ..."); + settings->setStatusText("Initializing ..."); OS::processEvents(); analysis.stop = false;