Skip to content
Permalink
Browse files
smp: move the SMP I/O ports into the SMP itself, instead of half in t…
…he CPU and half in the APU RAM. I don't care what byuu thinks blargg's hardware tests showed, it is literally impossible for hardware to work that way
  • Loading branch information
awjackson committed Mar 14, 2015
1 parent fd32f52 commit df8312c3b4fc14d613e14d377309498423111d4e
@@ -3,15 +3,13 @@ class CPU : public Processor, public CPUcore, public PPUcounter, public MMIO {
enum : bool { Threaded = true };
array<Processor*> coprocessors;
alwaysinline void step(unsigned clocks);
alwaysinline void synchronize_smp();
void synchronize_smp();
void synchronize_ppu();
void synchronize_coprocessor();

uint8 pio();
bool joylatch();
bool interrupt_pending();
uint8 port_read(uint8 port);
void port_write(uint8 port, uint8 data);
uint8 mmio_read(unsigned addr);
void mmio_write(unsigned addr, uint8 data);

@@ -68,9 +66,6 @@ class CPU : public Processor, public CPUcore, public PPUcounter, public MMIO {
void hdma_init();
void dma_reset();

//registers
uint8 port_data[4];

struct Channel {
bool dma_enabled;
bool hdma_enabled;
@@ -12,14 +12,6 @@ bool CPU::interrupt_pending() {
return false;
}

uint8 CPU::port_read(uint8 port) {
return port_data[port & 3];
}

void CPU::port_write(uint8 port, uint8 data) {
port_data[port & 3] = data;
}

void CPU::op_io() {
add_clocks(6);
}
@@ -1,11 +1,6 @@
#ifdef CPU_CPP

uint8 CPU::mmio_read(unsigned addr) {
if((addr & 0xffc0) == 0x2140) {
synchronize_smp();
return smp.port_read(addr & 3);
}

switch(addr & 0xffff) {
case 0x2180: {
uint8 result = bus.read(0x7e0000 | status.wram_addr);
@@ -98,12 +93,6 @@ uint8 CPU::mmio_read(unsigned addr) {
}

void CPU::mmio_write(unsigned addr, uint8 data) {
if((addr & 0xffc0) == 0x2140) {
synchronize_smp();
port_write(addr & 3, data);
return;
}

switch(addr & 0xffff) {
case 0x2180: {
bus.write(0x7e0000 | status.wram_addr, data);
@@ -6,7 +6,6 @@ void CPU::serialize(serializer &s) {
PPUcounter::serialize(s);

queue.serialize(s);
s.array(port_data);

for(unsigned i = 0; i < 8; i++) {
s.integer(channel[i].dma_enabled);
@@ -3,13 +3,10 @@ class CPU : public Processor, public CPUcore, public PPUcounter, public MMIO {
enum : bool { Threaded = true };
array<Processor*> coprocessors;
alwaysinline void step(unsigned clocks);
alwaysinline void synchronize_smp();
void synchronize_smp();
void synchronize_ppu();
void synchronize_coprocessor();

uint8 port_read(uint2 port) const;
void port_write(uint2 port, uint8 data);

uint8 pio();
bool joylatch();
alwaysinline bool interrupt_pending() { return status.interrupt_pending; }
@@ -72,9 +69,6 @@ class CPU : public Processor, public CPUcore, public PPUcounter, public MMIO {
bool hdma_mode; //0 = init, 1 = run

//MMIO
//$2140-217f
uint8 port[4];

//$2181-$2183
uint17 wram_addr;

@@ -1,8 +1,5 @@
#ifdef CPU_CPP

uint8 CPU::port_read(uint2 port) const { return status.port[port]; }
void CPU::port_write(uint2 port, uint8 data) { status.port[port] = data; }

void CPU::op_io() {
status.clock_count = 6;
dma_edge();
@@ -355,9 +355,6 @@ void CPU::mmio_power() {
}

void CPU::mmio_reset() {
//$2140-217f
foreach(port, status.port) port = 0x00;

//$2181-$2183
status.wram_addr = 0x000000;

@@ -413,12 +410,6 @@ void CPU::mmio_reset() {
uint8 CPU::mmio_read(unsigned addr) {
addr &= 0xffff;

//APU
if((addr & 0xffc0) == 0x2140) { //$2140-$217f
synchronize_smp();
return smp.port_read(addr);
}

//DMA
if((addr & 0xff80) == 0x4300) { //$4300-$437f
unsigned i = (addr >> 4) & 7;
@@ -470,13 +461,6 @@ uint8 CPU::mmio_read(unsigned addr) {
void CPU::mmio_write(unsigned addr, uint8 data) {
addr &= 0xffff;

//APU
if((addr & 0xffc0) == 0x2140) { //$2140-$217f
synchronize_smp();
port_write(addr, data);
return;
}

//DMA
if((addr & 0xff80) == 0x4300) { //$4300-$437f
unsigned i = (addr >> 4) & 7;
@@ -44,8 +44,6 @@ void CPU::serialize(serializer &s) {
s.integer(status.hdma_pending);
s.integer(status.hdma_mode);

s.array(status.port);

s.integer(status.wram_addr);

s.integer(status.joypad_strobe_latch);
@@ -11,14 +11,6 @@ alwaysinline void SMP::ram_write(uint16 addr, uint8 data) {
if(status.ram_writable && !status.ram_disabled) memory::apuram[addr] = data;
}

uint8 SMP::port_read(uint2 port) const {
return memory::apuram[0xf4 + port];
}

void SMP::port_write(uint2 port, uint8 data) {
memory::apuram[0xf4 + port] = data;
}

alwaysinline uint8 SMP::op_busread(uint16 addr) {
uint8 r;
if((addr & 0xfff0) == 0x00f0) { //00f0-00ff
@@ -45,15 +37,12 @@ alwaysinline uint8 SMP::op_busread(uint16 addr) {
case 0xf6: //CPUIO2
case 0xf7: { //CPUIO3
synchronize_cpu();
r = cpu.port_read(addr);
r = port.cpu_to_smp[addr & 3];
} break;

case 0xf8: { //RAM0
r = status.ram0;
} break;

case 0xf9: { //RAM1
r = status.ram1;
case 0xf8: //PORT4
case 0xf9: { //PORT5
r = port.aux[addr & 1];
} break;

case 0xfa: //T0TARGET
@@ -108,16 +97,15 @@ alwaysinline void SMP::op_buswrite(uint16 addr, uint8 data) {
status.iplrom_enabled = data & 0x80;

if(data & 0x30) {
//one-time clearing of APU port read registers,
//emulated by simulating CPU writes of 0x00
//one-time clearing of APU port read registers
synchronize_cpu();
if(data & 0x20) {
cpu.port_write(2, 0x00);
cpu.port_write(3, 0x00);
port.cpu_to_smp[2] = 0;
port.cpu_to_smp[3] = 0;
}
if(data & 0x10) {
cpu.port_write(0, 0x00);
cpu.port_write(1, 0x00);
port.cpu_to_smp[0] = 0;
port.cpu_to_smp[1] = 0;
}
}

@@ -157,15 +145,12 @@ alwaysinline void SMP::op_buswrite(uint16 addr, uint8 data) {
case 0xf6: //CPUIO2
case 0xf7: { //CPUIO3
synchronize_cpu();
port_write(addr, data);
} break;

case 0xf8: { //RAM0
status.ram0 = data;
port.smp_to_cpu[addr & 3] = data;
} break;

case 0xf9: { //RAM1
status.ram1 = data;
case 0xf8: //PORT4
case 0xf9: { //PORT5
port.aux[addr & 1] = data;
} break;

case 0xfa: { //T0TARGET
@@ -0,0 +1,13 @@
#ifdef SMP_CPP

uint8 SMP::mmio_read(unsigned addr) {
cpu.synchronize_smp();
return port.smp_to_cpu[addr & 3];
}

void SMP::mmio_write(unsigned addr, uint8 data) {
cpu.synchronize_smp();
port.cpu_to_smp[addr & 3] = data;
}

#endif
@@ -0,0 +1,2 @@
uint8 mmio_read(unsigned addr);
void mmio_write(unsigned addr, uint8 data);
@@ -19,8 +19,9 @@ void SMP::serialize(serializer &s) {

s.integer(status.dsp_addr);

s.integer(status.ram0);
s.integer(status.ram1);
s.array(port.cpu_to_smp);
s.array(port.smp_to_cpu);
s.array(port.aux);

s.integer(t0.stage0_ticks);
s.integer(t0.stage1_ticks);
@@ -13,6 +13,7 @@ namespace SNES {
#include "serialization.cpp"
#include "iplrom.cpp"
#include "memory/memory.cpp"
#include "mmio/mmio.cpp"
#include "timing/timing.cpp"

void SMP::step(unsigned clocks) {
@@ -93,9 +94,16 @@ void SMP::reset() {
//$00f2
status.dsp_addr = 0x00;

//$00f8,$00f9
status.ram0 = 0x00;
status.ram1 = 0x00;
//$00f4-$00f7
for(unsigned i = 0; i < 4; i++) {
port.cpu_to_smp[i] = 0;
port.smp_to_cpu[i] = 0;
}

//$00f8-$00f9
for(unsigned i = 0; i < 2; i++) {
port.aux[i] = 0;
}

t0.stage0_ticks = 0;
t1.stage0_ticks = 0;
@@ -1,13 +1,10 @@
class SMP : public Processor, public SMPcore {
class SMP : public Processor, public SMPcore, public MMIO {
public:
enum : bool { Threaded = true };
alwaysinline void step(unsigned clocks);
alwaysinline void synchronize_cpu();
alwaysinline void synchronize_dsp();

uint8 port_read(uint2 port) const;
void port_write(uint2 port, uint8 data);

void enter();
void power();
void reset();
@@ -20,6 +17,7 @@ class SMP : public Processor, public SMPcore {

private:
#include "memory/memory.hpp"
#include "mmio/mmio.hpp"
#include "timing/timing.hpp"

struct {
@@ -41,12 +39,17 @@ class SMP : public Processor, public SMPcore {

//$00f2
uint8 dsp_addr;

//$00f8,$00f9
uint8 ram0;
uint8 ram1;
} status;

struct {
//$00f4-$00f7
uint8 cpu_to_smp[4];
uint8 smp_to_cpu[4];

//$00f8-$00f9
uint8 aux[2];
} port;

static void Enter();
debugvirtual void op_step();

@@ -3,7 +3,7 @@ namespace SNES {
static const char Name[] = "bsnes-classic";
static const char Version[] = "073u1";
static const unsigned SerializerSignature = 0x43545342; //'BSTC'
static const unsigned SerializerVersion = 2;
static const unsigned SerializerVersion = 3;
}
}

@@ -107,7 +107,7 @@ void System::power() {

bus.power();
for(unsigned i = 0x2100; i <= 0x213f; i++) memory::mmio.map(i, ppu);
for(unsigned i = 0x2140; i <= 0x217f; i++) memory::mmio.map(i, cpu);
for(unsigned i = 0x2140; i <= 0x217f; i++) memory::mmio.map(i, smp);
for(unsigned i = 0x2180; i <= 0x2183; i++) memory::mmio.map(i, cpu);
for(unsigned i = 0x4016; i <= 0x4017; i++) memory::mmio.map(i, cpu);
for(unsigned i = 0x4200; i <= 0x421f; i++) memory::mmio.map(i, cpu);

0 comments on commit df8312c

Please sign in to comment.