o cleanup
This commit is contained in:
269
tools/bsnes/smp/ssmp/memory/memory.cpp
Executable file
269
tools/bsnes/smp/ssmp/memory/memory.cpp
Executable file
@@ -0,0 +1,269 @@
|
||||
#ifdef SSMP_CPP
|
||||
|
||||
alwaysinline
|
||||
uint8 sSMP::ram_read(uint16 addr) {
|
||||
if(addr < 0xffc0) return memory::apuram[addr];
|
||||
if(status.iplrom_enabled == false) return memory::apuram[addr];
|
||||
return iplrom[addr & 0x3f];
|
||||
}
|
||||
|
||||
alwaysinline
|
||||
void sSMP::ram_write(uint16 addr, uint8 data) {
|
||||
//writes to $ffc0-$ffff always go to spcram, even if the iplrom is enabled
|
||||
memory::apuram[addr] = data;
|
||||
}
|
||||
|
||||
//
|
||||
|
||||
alwaysinline
|
||||
uint8 sSMP::port_read(uint8 port) {
|
||||
return memory::apuram[0xf4 + (port & 3)];
|
||||
}
|
||||
|
||||
alwaysinline
|
||||
void sSMP::port_write(uint8 port, uint8 data) {
|
||||
memory::apuram[0xf4 + (port & 3)] = data;
|
||||
}
|
||||
|
||||
//
|
||||
|
||||
alwaysinline
|
||||
uint8 sSMP::op_busread(uint16 addr) {
|
||||
uint8 r;
|
||||
if((addr & 0xfff0) == 0x00f0) {
|
||||
//addr >= 0x00f0 && addr <= 0x00ff
|
||||
switch(addr) {
|
||||
case 0xf0: { //TEST -- write-only register
|
||||
r = 0x00;
|
||||
} break;
|
||||
|
||||
case 0xf1: { //CONTROL -- write-only register
|
||||
r = 0x00;
|
||||
} break;
|
||||
|
||||
case 0xf2: { //DSPADDR
|
||||
r = status.dsp_addr;
|
||||
} break;
|
||||
|
||||
case 0xf3: { //DSPDATA
|
||||
//0x80-0xff are read-only mirrors of 0x00-0x7f
|
||||
r = dsp.read(status.dsp_addr & 0x7f);
|
||||
} break;
|
||||
|
||||
case 0xf4: //CPUIO0
|
||||
case 0xf5: //CPUIO1
|
||||
case 0xf6: //CPUIO2
|
||||
case 0xf7: { //CPUIO3
|
||||
scheduler.sync_smpcpu();
|
||||
r = cpu.port_read(addr & 3);
|
||||
} break;
|
||||
|
||||
case 0xf8: { //???
|
||||
r = status.smp_f8;
|
||||
} break;
|
||||
|
||||
case 0xf9: { //???
|
||||
r = status.smp_f9;
|
||||
} break;
|
||||
|
||||
case 0xfa: //T0TARGET
|
||||
case 0xfb: //T1TARGET
|
||||
case 0xfc: { //T2TARGET -- write-only registers
|
||||
r = 0x00;
|
||||
} break;
|
||||
|
||||
case 0xfd: { //T0OUT -- 4-bit counter value
|
||||
r = t0.stage3_ticks & 15;
|
||||
t0.stage3_ticks = 0;
|
||||
} break;
|
||||
|
||||
case 0xfe: { //T1OUT -- 4-bit counter value
|
||||
r = t1.stage3_ticks & 15;
|
||||
t1.stage3_ticks = 0;
|
||||
} break;
|
||||
|
||||
case 0xff: { //T2OUT -- 4-bit counter value
|
||||
r = t2.stage3_ticks & 15;
|
||||
t2.stage3_ticks = 0;
|
||||
} break;
|
||||
}
|
||||
} else {
|
||||
r = ram_read(addr);
|
||||
}
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
alwaysinline
|
||||
void sSMP::op_buswrite(uint16 addr, uint8 data) {
|
||||
if((addr & 0xfff0) == 0x00f0) {
|
||||
//addr >= 0x00f0 && addr >= 0x00ff
|
||||
if(status.mmio_disabled == true) return;
|
||||
|
||||
switch(addr) {
|
||||
case 0xf0: { //TEST
|
||||
if(regs.p.p) break; //writes only valid when P flag is clear
|
||||
|
||||
//multiplier table may not be 100% accurate, some settings crash
|
||||
//the processor due to S-SMP <> S-DSP bus access misalignment
|
||||
//static uint8 clock_speed_tbl[16] =
|
||||
//{ 3, 5, 9, 17, 4, 6, 10, 18, 6, 8, 12, 20, 10, 12, 16, 24 };
|
||||
|
||||
//status.clock_speed = 24 * clock_speed_tbl[data >> 4] / 3;
|
||||
status.mmio_disabled = !!(data & 0x04);
|
||||
status.ram_writable = !!(data & 0x02);
|
||||
|
||||
//if((data >> 4) != 0) {
|
||||
//dprintf("* S-SMP critical warning: $00f0 (TEST) clock speed control modified!");
|
||||
//dprintf("* S-SMP may crash on hardware as a result!");
|
||||
//}
|
||||
} break;
|
||||
|
||||
case 0xf1: { //CONTROL
|
||||
status.iplrom_enabled = !!(data & 0x80);
|
||||
|
||||
if(data & 0x30) {
|
||||
//one-time clearing of APU port read registers,
|
||||
//emulated by simulating CPU writes of 0x00
|
||||
scheduler.sync_smpcpu();
|
||||
if(data & 0x20) {
|
||||
cpu.port_write(2, 0x00);
|
||||
cpu.port_write(3, 0x00);
|
||||
}
|
||||
if(data & 0x10) {
|
||||
cpu.port_write(0, 0x00);
|
||||
cpu.port_write(1, 0x00);
|
||||
}
|
||||
}
|
||||
|
||||
//0->1 transistion resets timers
|
||||
if(t2.enabled == false && (data & 0x04)) {
|
||||
t2.stage2_ticks = 0;
|
||||
t2.stage3_ticks = 0;
|
||||
}
|
||||
t2.enabled = !!(data & 0x04);
|
||||
|
||||
if(t1.enabled == false && (data & 0x02)) {
|
||||
t1.stage2_ticks = 0;
|
||||
t1.stage3_ticks = 0;
|
||||
}
|
||||
t1.enabled = !!(data & 0x02);
|
||||
|
||||
if(t0.enabled == false && (data & 0x01)) {
|
||||
t0.stage2_ticks = 0;
|
||||
t0.stage3_ticks = 0;
|
||||
}
|
||||
t0.enabled = !!(data & 0x01);
|
||||
} break;
|
||||
|
||||
case 0xf2: { //DSPADDR
|
||||
status.dsp_addr = data;
|
||||
} break;
|
||||
|
||||
case 0xf3: { //DSPDATA
|
||||
//0x80-0xff is a read-only mirror of 0x00-0x7f
|
||||
if(!(status.dsp_addr & 0x80)) {
|
||||
dsp.write(status.dsp_addr & 0x7f, data);
|
||||
}
|
||||
} break;
|
||||
|
||||
case 0xf4: //CPUIO0
|
||||
case 0xf5: //CPUIO1
|
||||
case 0xf6: //CPUIO2
|
||||
case 0xf7: { //CPUIO3
|
||||
scheduler.sync_smpcpu();
|
||||
port_write(addr & 3, data);
|
||||
} break;
|
||||
|
||||
case 0xf8: { //???
|
||||
status.smp_f8 = data;
|
||||
} break;
|
||||
|
||||
case 0xf9: { //???
|
||||
status.smp_f9 = data;
|
||||
} break;
|
||||
|
||||
case 0xfa: { //T0TARGET
|
||||
t0.target = data;
|
||||
} break;
|
||||
|
||||
case 0xfb: { //T1TARGET
|
||||
t1.target = data;
|
||||
} break;
|
||||
|
||||
case 0xfc: { //T2TARGET
|
||||
t2.target = data;
|
||||
} break;
|
||||
|
||||
case 0xfd: //T0OUT
|
||||
case 0xfe: //T1OUT
|
||||
case 0xff: { //T2OUT -- read-only registers
|
||||
} break;
|
||||
}
|
||||
}
|
||||
|
||||
//all writes, even to MMIO registers, appear on bus
|
||||
if(status.ram_writable == true) {
|
||||
ram_write(addr, data);
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
|
||||
void sSMP::op_io() {
|
||||
add_clocks(24);
|
||||
tick_timers();
|
||||
}
|
||||
|
||||
uint8 sSMP::op_read(uint16 addr) {
|
||||
add_clocks(12);
|
||||
uint8 r = op_busread(addr);
|
||||
add_clocks(12);
|
||||
tick_timers();
|
||||
return r;
|
||||
}
|
||||
|
||||
void sSMP::op_write(uint16 addr, uint8 data) {
|
||||
add_clocks(24);
|
||||
op_buswrite(addr, data);
|
||||
tick_timers();
|
||||
}
|
||||
|
||||
//
|
||||
|
||||
alwaysinline
|
||||
uint8 sSMP::op_readpc() {
|
||||
return op_read(regs.pc++);
|
||||
}
|
||||
|
||||
alwaysinline
|
||||
uint8 sSMP::op_readstack() {
|
||||
return op_read(0x0100 | ++regs.sp);
|
||||
}
|
||||
|
||||
alwaysinline
|
||||
void sSMP::op_writestack(uint8 data) {
|
||||
op_write(0x0100 | regs.sp--, data);
|
||||
}
|
||||
|
||||
alwaysinline
|
||||
uint8 sSMP::op_readaddr(uint16 addr) {
|
||||
return op_read(addr);
|
||||
}
|
||||
|
||||
alwaysinline
|
||||
void sSMP::op_writeaddr(uint16 addr, uint8 data) {
|
||||
op_write(addr, data);
|
||||
}
|
||||
|
||||
alwaysinline
|
||||
uint8 sSMP::op_readdp(uint8 addr) {
|
||||
return op_read((unsigned(regs.p.p) << 8) + addr);
|
||||
}
|
||||
|
||||
alwaysinline
|
||||
void sSMP::op_writedp(uint8 addr, uint8 data) {
|
||||
op_write((unsigned(regs.p.p) << 8) + addr, data);
|
||||
}
|
||||
|
||||
#endif //ifdef SSMP_CPP
|
||||
Reference in New Issue
Block a user