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 {
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";
}

View File

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

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() {
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(&regs, 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
}

View File

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

View File

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

View File

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

View File

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

View File

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

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) {
s.array(ram.data(), ram.size());
s.array(psram.data(), psram.size());
}
#endif

View File

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

View File

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

View File

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

View File

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

View File

@ -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 <sfc/controller/controller.hpp>
#include <sfc/system/system.hpp>
#include <sfc/base/base.hpp>
#include <sfc/chip/chip.hpp>
#include <sfc/slot/slot.hpp>
#include <sfc/cartridge/cartridge.hpp>

View File

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

View File

@ -2,7 +2,7 @@ struct Interface;
struct System : property<System> {
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();

View File

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