Update to v092r02 release.

byuu says:

Changelog:
- merged AWJ's hires color blending improvements (most notably: fixes
  Marvelous' text)
- created sfc/base/ to store base unit (expansion port device) emulation
- synchronized the markup of Satellaview and Sufami Turbo cartridge
  slots in the board markup
- fixed "Initializing ..." typo in timing settings

If at all possible, I'd really like to have heavy testing of games that
use hires graphics to check for any regressions.
I trust AWJ's code, and all of the test ROMs I have thrown at it all
appear to work great. But better safe than sorry. Same deal for any core
changes, it's a lot better to catch it now than after v093 is released.
This commit is contained in:
Tim Allen
2013-01-23 19:28:35 +11:00
parent bbc33fe05f
commit d9400084c2
20 changed files with 407 additions and 404 deletions

View File

@@ -3,7 +3,7 @@
namespace Emulator { namespace Emulator {
static const char Name[] = "higan"; 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 Author[] = "byuu";
static const char License[] = "GPLv3"; static const char License[] = "GPLv3";
} }

View File

@@ -1,13 +1,14 @@
sfc_objects := sfc-interface sfc-system sfc-controller sfc_objects := sfc-interface sfc-system sfc-controller
sfc_objects += sfc-cartridge sfc-cheat sfc_objects += sfc-cartridge sfc-cheat
sfc_objects += sfc-memory sfc-cpu sfc-smp sfc-dsp sfc-ppu 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-icd2 sfc-bsx sfc-nss sfc-event
sfc_objects += sfc-sa1 sfc-superfx sfc_objects += sfc-sa1 sfc-superfx
sfc_objects += sfc-armdsp sfc-hitachidsp sfc-necdsp sfc_objects += sfc-armdsp sfc-hitachidsp sfc-necdsp
sfc_objects += sfc-epsonrtc sfc-sharprtc sfc_objects += sfc-epsonrtc sfc-sharprtc
sfc_objects += sfc-spc7110 sfc-sdd1 sfc-obc1 sfc_objects += sfc-spc7110 sfc-sdd1 sfc-obc1
sfc_objects += sfc-hsu1 sfc-msu1 sfc_objects += sfc-hsu1 sfc-msu1
sfc_objects += sfc-satellaview sfc-sufamiturbo sfc_objects += sfc-satellaviewcart sfc-sufamiturbo
objects += $(sfc_objects) objects += $(sfc_objects)
ifeq ($(profile),accuracy) ifeq ($(profile),accuracy)
@@ -32,38 +33,40 @@ else
$(error unknown profile.) $(error unknown profile.)
endif endif
obj/sfc-interface.o: $(sfc)/interface/interface.cpp $(call rwildcard,$(sfc)/interface) 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-system.o: $(sfc)/system/system.cpp $(call rwildcard,$(sfc)/system/)
obj/sfc-controller.o: $(sfc)/controller/controller.cpp $(call rwildcard,$(sfc)/controller/) obj/sfc-controller.o: $(sfc)/controller/controller.cpp $(call rwildcard,$(sfc)/controller/)
obj/sfc-cartridge.o: $(sfc)/cartridge/cartridge.cpp $(sfc)/cartridge/* obj/sfc-cartridge.o: $(sfc)/cartridge/cartridge.cpp $(sfc)/cartridge/*
obj/sfc-cheat.o: $(sfc)/cheat/cheat.cpp $(sfc)/cheat/* obj/sfc-cheat.o: $(sfc)/cheat/cheat.cpp $(sfc)/cheat/*
obj/sfc-memory.o: $(sfc)/memory/memory.cpp $(call rwildcard,$(sfc)/memory/) obj/sfc-memory.o: $(sfc)/memory/memory.cpp $(call rwildcard,$(sfc)/memory/)
obj/sfc-cpu.o: $(sfccpu)/cpu.cpp $(call rwildcard,$(sfccpu)/) obj/sfc-cpu.o: $(sfccpu)/cpu.cpp $(call rwildcard,$(sfccpu)/)
obj/sfc-smp.o: $(sfcsmp)/smp.cpp $(call rwildcard,$(sfcsmp)/) obj/sfc-smp.o: $(sfcsmp)/smp.cpp $(call rwildcard,$(sfcsmp)/)
obj/sfc-dsp.o: $(sfcdsp)/dsp.cpp $(call rwildcard,$(sfcdsp)/) obj/sfc-dsp.o: $(sfcdsp)/dsp.cpp $(call rwildcard,$(sfcdsp)/)
obj/sfc-ppu.o: $(sfcppu)/ppu.cpp $(call rwildcard,$(sfcppu)/) 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-satellaviewbase.o: $(sfc)/base/satellaview/satellaview.cpp $(call rwildcard,$(sfc)/base/satellaview/)
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-sa1.o: $(sfc)/chip/sa1/sa1.cpp $(call rwildcard,$(sfc)/chip/sa1/) obj/sfc-icd2.o: $(sfc)/chip/icd2/icd2.cpp $(call rwildcard,$(sfc)/chip/icd2/)
obj/sfc-superfx.o: $(sfc)/chip/superfx/superfx.cpp $(call rwildcard,$(sfc)/chip/superfx/) 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-sa1.o: $(sfc)/chip/sa1/sa1.cpp $(call rwildcard,$(sfc)/chip/sa1/)
obj/sfc-hitachidsp.o: $(sfc)/chip/hitachidsp/hitachidsp.cpp $(call rwildcard,$(sfc)/chip/hitachidsp/) obj/sfc-superfx.o: $(sfc)/chip/superfx/superfx.cpp $(call rwildcard,$(sfc)/chip/superfx/)
obj/sfc-necdsp.o: $(sfc)/chip/necdsp/necdsp.cpp $(call rwildcard,$(sfc)/chip/necdsp/)
obj/sfc-epsonrtc.o: $(sfc)/chip/epsonrtc/epsonrtc.cpp $(call rwildcard,$(sfc)/chip/epsonrtc/) obj/sfc-armdsp.o: $(sfc)/chip/armdsp/armdsp.cpp $(call rwildcard,$(sfc)/chip/armdsp/)
obj/sfc-sharprtc.o: $(sfc)/chip/sharprtc/sharprtc.cpp $(call rwildcard,$(sfc)/chip/sharprtc/) 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-epsonrtc.o: $(sfc)/chip/epsonrtc/epsonrtc.cpp $(call rwildcard,$(sfc)/chip/epsonrtc/)
obj/sfc-sdd1.o: $(sfc)/chip/sdd1/sdd1.cpp $(sfc)/chip/sdd1/* obj/sfc-sharprtc.o: $(sfc)/chip/sharprtc/sharprtc.cpp $(call rwildcard,$(sfc)/chip/sharprtc/)
obj/sfc-obc1.o: $(sfc)/chip/obc1/obc1.cpp $(sfc)/chip/obc1/*
obj/sfc-hsu1.o: $(sfc)/chip/hsu1/hsu1.cpp $(sfc)/chip/hsu1/* obj/sfc-spc7110.o: $(sfc)/chip/spc7110/spc7110.cpp $(sfc)/chip/spc7110/*
obj/sfc-msu1.o: $(sfc)/chip/msu1/msu1.cpp $(sfc)/chip/msu1/* 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-hsu1.o: $(sfc)/chip/hsu1/hsu1.cpp $(sfc)/chip/hsu1/*
obj/sfc-sufamiturbo.o: $(sfc)/slot/sufamiturbo/sufamiturbo.cpp $(call rwildcard,$(sfc)/slot/sufamiturbo/) 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/)

1
higan/sfc/base/base.hpp Normal file
View File

@@ -0,0 +1 @@
#include <sfc/base/satellaview/satellaview.hpp>

View File

@@ -1,26 +1,37 @@
#ifdef BSX_CPP #include <sfc/sfc.hpp>
BSXSatellaview bsxsatellaview; #define SATELLAVIEW_BASE_UNIT_CPP
namespace SuperFamicom {
void BSXSatellaview::init() { SatellaviewBaseUnit satellaviewbaseunit;
void SatellaviewBaseUnit::init() {
} }
void BSXSatellaview::load() { void SatellaviewBaseUnit::load() {
bus.map({&BSXSatellaview::mmio_read, &bsxsatellaview}, {&BSXSatellaview::mmio_write, &bsxsatellaview}, 0x00, 0x3f, 0x2188, 0x219f); bus.map(
bus.map({&BSXSatellaview::mmio_read, &bsxsatellaview}, {&BSXSatellaview::mmio_write, &bsxsatellaview}, 0x80, 0xbf, 0x2188, 0x219f); {&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(&regs, 0x00, sizeof regs); memset(&regs, 0x00, sizeof regs);
} }
uint8 BSXSatellaview::mmio_read(unsigned addr) { uint8 SatellaviewBaseUnit::read(unsigned addr) {
addr &= 0xffff; addr &= 0xffff;
switch(addr) { switch(addr) {
@@ -78,7 +89,7 @@ uint8 BSXSatellaview::mmio_read(unsigned addr) {
return cpu.regs.mdr; return cpu.regs.mdr;
} }
void BSXSatellaview::mmio_write(unsigned addr, uint8 data) { void SatellaviewBaseUnit::write(unsigned addr, uint8 data) {
addr &= 0xffff; addr &= 0xffff;
switch(addr) { switch(addr) {
@@ -139,4 +150,4 @@ void BSXSatellaview::mmio_write(unsigned addr, uint8 data) {
} }
} }
#endif }

View File

@@ -1,12 +1,12 @@
struct BSXSatellaview { struct SatellaviewBaseUnit : Memory {
void init(); void init();
void load(); void load();
void unload(); void unload();
void power(); void power();
void reset(); void reset();
uint8 mmio_read(unsigned addr); uint8 read(unsigned addr);
void mmio_write(unsigned addr, uint8 data); void write(unsigned addr, uint8 data);
private: private:
struct { struct {
@@ -22,4 +22,4 @@ private:
} regs; } regs;
}; };
extern BSXSatellaview bsxsatellaview; extern SatellaviewBaseUnit satellaviewbaseunit;

View File

@@ -100,8 +100,8 @@ private:
void parse_markup_cartridge(Markup::Node); void parse_markup_cartridge(Markup::Node);
void parse_markup_icd2(Markup::Node); void parse_markup_icd2(Markup::Node);
void parse_markup_bsx(Markup::Node); void parse_markup_bsx(Markup::Node);
void parse_markup_bsxslot(Markup::Node); void parse_markup_satellaview(Markup::Node);
void parse_markup_sufamiturbo(Markup::Node); void parse_markup_sufamiturbo(Markup::Node, bool slot);
void parse_markup_nss(Markup::Node); void parse_markup_nss(Markup::Node);
void parse_markup_event(Markup::Node); void parse_markup_event(Markup::Node);
void parse_markup_sa1(Markup::Node); void parse_markup_sa1(Markup::Node);

View File

@@ -11,8 +11,9 @@ void Cartridge::parse_markup(const char *markup) {
parse_markup_cartridge(cartridge); parse_markup_cartridge(cartridge);
parse_markup_icd2(cartridge["icd2"]); parse_markup_icd2(cartridge["icd2"]);
parse_markup_bsx(cartridge["bsx"]); parse_markup_bsx(cartridge["bsx"]);
parse_markup_bsxslot(cartridge["bsxslot"]); parse_markup_satellaview(cartridge["satellaview"]);
parse_markup_sufamiturbo(cartridge["sufamiturbo"]); parse_markup_sufamiturbo(cartridge["sufamiturbo[0]"], 0);
parse_markup_sufamiturbo(cartridge["sufamiturbo[1]"], 1);
parse_markup_nss(cartridge["nss"]); parse_markup_nss(cartridge["nss"]);
parse_markup_event(cartridge["event"]); parse_markup_event(cartridge["event"]);
parse_markup_sa1(cartridge["sa1"]); 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; if(root.exists() == false) return;
has_bs_slot = true; has_bs_slot = true;
interface->loadRequest(ID::Satellaview, "BS-X Satellaview", "bs"); interface->loadRequest(ID::Satellaview, "BS-X Satellaview", "bs");
for(auto &node : root) { for(auto &node : root.find("map")) {
if(node.name != "map") continue;
if(node["id"].data == "rom") { if(node["id"].data == "rom") {
if(satellaviewcartridge.memory.size() == 0) continue; 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; if(root.exists() == false) return;
has_st_slots = true; has_st_slots = true;
//load required slot A (will request slot B if slot A cartridge is linkable) if(slot == 0) {
interface->loadRequest(ID::SufamiTurboSlotA, "Sufami Turbo - Slot A", "st"); //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) { for(auto &node : root.find("map")) {
if(slot.name != "slot") continue; SufamiTurboCartridge &cart = (slot == 0 ? sufamiturboA : sufamiturboB);
bool slotid = slot["id"].data == "A" ? 0 : slot["id"].data == "B" ? 1 : 0;
for(auto &node : slot) { if(node["id"].data == "rom") {
if(node.name != "map") continue; if(cart.rom.size() == 0) continue;
if(node["id"].data == "rom") { Mapping m(cart.rom);
SuperFamicom::Memory &memory = slotid == 0 ? sufamiturboA.rom : sufamiturboB.rom; parse_markup_map(m, node);
if(memory.size() == 0) continue; if(m.size == 0) m.size = cart.rom.size();
if(m.size) mapping.append(m);
}
Mapping m(memory); if(node["id"].data == "ram") {
parse_markup_map(m, node); if(cart.ram.size() == 0) continue;
if(m.size == 0) m.size = memory.size();
if(m.size) mapping.append(m);
}
if(node["id"].data == "ram") { Mapping m(cart.ram);
SuperFamicom::Memory &memory = slotid == 0 ? sufamiturboA.ram : sufamiturboB.ram; parse_markup_map(m, node);
if(memory.size() == 0) continue; if(m.size == 0) m.size = cart.ram.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);
}
} }
} }
} }

View File

@@ -2,6 +2,145 @@
#define BSX_CPP #define BSX_CPP
namespace SuperFamicom { 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;
}
} }

View File

@@ -1,2 +1,34 @@
#include "satellaview/satellaview.hpp" struct BSXCartridge {
#include "cartridge/cartridge.hpp" 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;

View File

@@ -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

View File

@@ -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;

View File

@@ -1,4 +1,8 @@
#ifdef BSX_CPP
void BSXCartridge::serialize(serializer &s) { void BSXCartridge::serialize(serializer &s) {
s.array(ram.data(), ram.size()); s.array(ram.data(), ram.size());
s.array(psram.data(), psram.size()); s.array(psram.data(), psram.size());
} }
#endif

View File

@@ -5,7 +5,7 @@ Configuration config;
Configuration::Configuration() { Configuration::Configuration() {
controller_port1 = Input::Device::Joypad; controller_port1 = Input::Device::Joypad;
controller_port2 = Input::Device::Joypad; controller_port2 = Input::Device::Joypad;
expansion_port = System::ExpansionPortDevice::BSX; expansion_port = System::ExpansionPortDevice::Satellaview;
region = System::Region::Autodetect; region = System::Region::Autodetect;
random = true; random = true;

View File

@@ -3,159 +3,130 @@
void PPU::Screen::scanline() { void PPU::Screen::scanline() {
output = self.output + self.vcounter() * 1024; output = self.output + self.vcounter() * 1024;
if(self.display.interlace && self.field()) output += 512; 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() { void PPU::Screen::run() {
if(ppu.vcounter() == 0) return; if(ppu.vcounter() == 0) return;
uint32 color; auto palette = &video.palette[self.regs.display_brightness << 15];
if(self.regs.pseudo_hires == false && self.regs.bgmode != 5 && self.regs.bgmode != 6) { bool hires = self.regs.pseudo_hires || self.regs.bgmode == 5 || self.regs.bgmode == 6;
color = get_pixel(0); auto sscolor = get_pixel_sub(hires);
*output++ = color; auto mscolor = get_pixel_main();
*output++ = color;
} else { *output++ = palette[hires ? sscolor : mscolor];
color = get_pixel(1); *output++ = palette[mscolor];
*output++ = color;
color = get_pixel(0);
*output++ = color;
}
} }
uint32 PPU::Screen::get_pixel(bool swap) { uint16 PPU::Screen::get_pixel_sub(bool hires) {
if(ppu.regs.overscan == false && ppu.vcounter() >= 225) return 0x0000; if(self.regs.display_disable || (!self.regs.overscan && self.vcounter() >= 225)) return 0;
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;
unsigned priority = 0;
if(self.bg1.output.sub.priority) { 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)) { 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 { } 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) { if(self.bg2.output.sub.priority > priority) {
priority_sub = self.bg2.output.sub.priority; priority = self.bg2.output.sub.priority;
color_sub = get_color(self.bg2.output.sub.palette); math.sub.color = get_color(self.bg2.output.sub.palette);
source_sub = BG2;
} }
if(self.bg3.output.sub.priority > priority_sub) { if(self.bg3.output.sub.priority > priority) {
priority_sub = self.bg3.output.sub.priority; priority = self.bg3.output.sub.priority;
color_sub = get_color(self.bg3.output.sub.palette); math.sub.color = get_color(self.bg3.output.sub.palette);
source_sub = BG3;
} }
if(self.bg4.output.sub.priority > priority_sub) { if(self.bg4.output.sub.priority > priority) {
priority_sub = self.bg4.output.sub.priority; priority = self.bg4.output.sub.priority;
color_sub = get_color(self.bg4.output.sub.palette); math.sub.color = get_color(self.bg4.output.sub.palette);
source_sub = BG4;
} }
if(self.sprite.output.sub.priority > priority_sub) { if(self.sprite.output.sub.priority > priority) {
priority_sub = self.sprite.output.sub.priority; priority = self.sprite.output.sub.priority;
color_sub = get_color(self.sprite.output.sub.palette); math.sub.color = 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(math.transparent = (priority == 0)) math.sub.color = get_color(0);
if(swap == true) { if(!hires) return 0;
std::swap(priority_main, priority_sub); if(!math.sub.color_enable) return math.main.color_enable ? math.sub.color : 0;
std::swap(color_main, color_sub);
std::swap(source_main, source_sub);
}
uint16 output; return addsub(
if(!regs.addsub_mode) { math.main.color_enable ? math.sub.color : 0,
source_sub = BACK; math.addsub_mode ? math.main.color : fixed_color()
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];
} }
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(!regs.color_mode) {
if(!halve) { if(!math.color_halve) {
unsigned sum = x + y; unsigned sum = x + y;
unsigned carry = (sum - ((x ^ y) & 0x0421)) & 0x8420; unsigned carry = (sum - ((x ^ y) & 0x0421)) & 0x8420;
return (sum - carry) | (carry - (carry >> 5)); return (sum - carry) | (carry - (carry >> 5));
@@ -165,7 +136,7 @@ uint16 PPU::Screen::addsub(unsigned x, unsigned y, bool halve) {
} else { } else {
unsigned diff = x - y + 0x8420; unsigned diff = x - y + 0x8420;
unsigned borrow = (diff - ((x ^ y) & 0x8420)) & 0x8420; unsigned borrow = (diff - ((x ^ y) & 0x8420)) & 0x8420;
if(!halve) { if(!math.color_halve) {
return (diff - borrow) & (borrow - (borrow >> 5)); return (diff - borrow) & (borrow - (borrow >> 5));
} else { } else {
return (((diff - borrow) & (borrow - (borrow >> 5))) & 0x7bde) >> 1; 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); + ((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() { void PPU::Screen::reset() {
regs.addsub_mode = random(false); regs.addsub_mode = random(false);
regs.direct_color = random(false); regs.direct_color = random(false);

View File

@@ -19,14 +19,26 @@ struct Screen {
uint5 color_r; uint5 color_r;
} regs; } regs;
struct Math {
struct Layer {
uint16 color;
bool color_enable;
} main, sub;
bool transparent;
bool addsub_mode;
bool color_halve;
} math;
void scanline(); void scanline();
void run(); void run();
void reset(); void reset();
uint32 get_pixel(bool swap); uint16 get_pixel_sub(bool hires);
uint16 addsub(unsigned x, unsigned y, bool halve); uint16 get_pixel_main();
uint16 addsub(unsigned x, unsigned y);
uint16 get_color(unsigned palette); uint16 get_color(unsigned palette);
uint16 get_direct_color(unsigned palette, unsigned tile); uint16 get_direct_color(unsigned palette, unsigned tile);
uint16 fixed_color() const;
void serialize(serializer&); void serialize(serializer&);
Screen(PPU &self); Screen(PPU &self);

View File

@@ -279,6 +279,14 @@ void PPU::Screen::serialize(serializer &s) {
s.integer(regs.color_b); s.integer(regs.color_b);
s.integer(regs.color_g); s.integer(regs.color_g);
s.integer(regs.color_r); 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 #endif

View File

@@ -12,7 +12,7 @@
namespace SuperFamicom { namespace SuperFamicom {
namespace Info { namespace Info {
static const char Name[] = "bsnes"; static const char Name[] = "bsnes";
static const unsigned SerializerVersion = 25; static const unsigned SerializerVersion = 26;
} }
} }
@@ -65,6 +65,7 @@ namespace SuperFamicom {
#include <sfc/controller/controller.hpp> #include <sfc/controller/controller.hpp>
#include <sfc/system/system.hpp> #include <sfc/system/system.hpp>
#include <sfc/base/base.hpp>
#include <sfc/chip/chip.hpp> #include <sfc/chip/chip.hpp>
#include <sfc/slot/slot.hpp> #include <sfc/slot/slot.hpp>
#include <sfc/cartridge/cartridge.hpp> #include <sfc/cartridge/cartridge.hpp>

View File

@@ -64,7 +64,7 @@ void System::runthreadtosave() {
void System::init() { void System::init() {
assert(interface != nullptr); assert(interface != nullptr);
bsxsatellaview.init(); satellaviewbaseunit.init();
icd2.init(); icd2.init();
bsxcartridge.init(); bsxcartridge.init();
nss.init(); nss.init();
@@ -119,7 +119,7 @@ void System::load() {
cpu.enable(); cpu.enable();
ppu.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_gb_slot()) icd2.load();
if(cartridge.has_bs_cart()) bsxcartridge.load(); if(cartridge.has_bs_cart()) bsxcartridge.load();
if(cartridge.has_nss_dip()) nss.load(); if(cartridge.has_nss_dip()) nss.load();
@@ -144,7 +144,7 @@ void System::load() {
} }
void System::unload() { 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_gb_slot()) icd2.unload();
if(cartridge.has_bs_cart()) bsxcartridge.unload(); if(cartridge.has_bs_cart()) bsxcartridge.unload();
if(cartridge.has_nss_dip()) nss.unload(); if(cartridge.has_nss_dip()) nss.unload();
@@ -173,7 +173,7 @@ void System::power() {
dsp.power(); dsp.power();
ppu.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_gb_slot()) icd2.power();
if(cartridge.has_bs_cart()) bsxcartridge.power(); if(cartridge.has_bs_cart()) bsxcartridge.power();
if(cartridge.has_nss_dip()) nss.power(); if(cartridge.has_nss_dip()) nss.power();
@@ -201,7 +201,7 @@ void System::reset() {
dsp.reset(); dsp.reset();
ppu.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_gb_slot()) icd2.reset();
if(cartridge.has_bs_cart()) bsxcartridge.reset(); if(cartridge.has_bs_cart()) bsxcartridge.reset();
if(cartridge.has_nss_dip()) nss.reset(); if(cartridge.has_nss_dip()) nss.reset();
@@ -247,7 +247,7 @@ void System::frame() {
System::System() { System::System() {
region = Region::Autodetect; region = Region::Autodetect;
expansion = ExpansionPortDevice::BSX; expansion = ExpansionPortDevice::Satellaview;
} }
} }

View File

@@ -2,7 +2,7 @@ struct Interface;
struct System : property<System> { struct System : property<System> {
enum class Region : unsigned { NTSC = 0, PAL = 1, Autodetect = 2 }; 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 run();
void runtosave(); void runtosave();

View File

@@ -81,7 +81,7 @@ void TimingSettings::analyzeStart() {
settings->panelList.setEnabled(false); settings->panelList.setEnabled(false);
videoAdjust.analyze.setEnabled(false); videoAdjust.analyze.setEnabled(false);
audioAdjust.analyze.setEnabled(false); audioAdjust.analyze.setEnabled(false);
settings->setStatusText("Initiailizing ..."); settings->setStatusText("Initializing ...");
OS::processEvents(); OS::processEvents();
analysis.stop = false; analysis.stop = false;