mirror of https://github.com/bsnes-emu/bsnes.git
Update to v074r11 release.
byuu says: Changelog: - debugger compiles on all three profiles - libsnes compiles on all three platforms (no API changes to libsnes) - memory.cpp : namespace memory removed (wram -> cpu, apuram -> smp, vram, oam, cgram -> ppu) - sa1.cpp : namespace memory removed (SA-1 specific functions merged inline to SA1::bus_read,write) - GameBoy: added serial link support with interrupts and proper 8192hz timing, but obviously it acts as if no other GB is connected to it - GameBoy: added STAT OAM interrupt, and better STAT d1,d0 mode values - UI: since Qt is dead, I've renamed the config files back to bsnes.cfg and bsnes-geometry.cfg - SA1: IRAM was not syncing to CPU on SA-1 side - PPU/Accuracy and PPU/Performance needed Sprite oam renamed to Sprite sprite; so that I could add uint8 oam[544] - makes more sense anyway, OAM = object attribute memory, obj or sprite are better names for Sprite rendering class - more cleanup
This commit is contained in:
parent
054bdd4094
commit
53fe43afd8
|
@ -120,12 +120,19 @@ void CPU::power() {
|
|||
status.timer1 = 0;
|
||||
status.timer2 = 0;
|
||||
status.timer3 = 0;
|
||||
status.timer4 = 0;
|
||||
|
||||
status.p15 = 0;
|
||||
status.p14 = 0;
|
||||
status.joyp = 0;
|
||||
status.mlt_req = 0;
|
||||
|
||||
status.serial_data = 0;
|
||||
status.serial_bits = 0;
|
||||
|
||||
status.serial_transfer = 0;
|
||||
status.serial_clock = 0;
|
||||
|
||||
status.div = 0;
|
||||
|
||||
status.tima = 0;
|
||||
|
|
|
@ -23,6 +23,7 @@ struct CPU : Processor, MMIO {
|
|||
unsigned timer1;
|
||||
unsigned timer2;
|
||||
unsigned timer3;
|
||||
unsigned timer4;
|
||||
|
||||
//$ff00 JOYP
|
||||
bool p15;
|
||||
|
@ -30,6 +31,14 @@ struct CPU : Processor, MMIO {
|
|||
uint8 joyp;
|
||||
uint8 mlt_req;
|
||||
|
||||
//$ff01 SB
|
||||
uint8 serial_data;
|
||||
unsigned serial_bits;
|
||||
|
||||
//$ff02 SC
|
||||
bool serial_transfer;
|
||||
bool serial_clock;
|
||||
|
||||
//$ff04 DIV
|
||||
uint8 div;
|
||||
|
||||
|
|
|
@ -31,6 +31,15 @@ uint8 CPU::mmio_read(uint16 addr) {
|
|||
| (status.joyp << 0);
|
||||
}
|
||||
|
||||
if(addr == 0xff01) { //SB
|
||||
return 0xff;
|
||||
}
|
||||
|
||||
if(addr == 0xff02) { //SC
|
||||
return (status.serial_transfer << 7)
|
||||
| (status.serial_clock << 0);
|
||||
}
|
||||
|
||||
if(addr == 0xff04) { //DIV
|
||||
return status.div;
|
||||
}
|
||||
|
@ -81,10 +90,14 @@ void CPU::mmio_write(uint16 addr, uint8 data) {
|
|||
}
|
||||
|
||||
if(addr == 0xff01) { //SB
|
||||
status.serial_data = data;
|
||||
return;
|
||||
}
|
||||
|
||||
if(addr == 0xff02) { //SC
|
||||
status.serial_transfer = data & 0x80;
|
||||
status.serial_clock = data & 0x01;
|
||||
if(status.serial_transfer) status.serial_bits = 8;
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
@ -27,12 +27,19 @@ void CPU::serialize(serializer &s) {
|
|||
s.integer(status.timer1);
|
||||
s.integer(status.timer2);
|
||||
s.integer(status.timer3);
|
||||
s.integer(status.timer4);
|
||||
|
||||
s.integer(status.p15);
|
||||
s.integer(status.p14);
|
||||
s.integer(status.joyp);
|
||||
s.integer(status.mlt_req);
|
||||
|
||||
s.integer(status.serial_data);
|
||||
s.integer(status.serial_bits);
|
||||
|
||||
s.integer(status.serial_transfer);
|
||||
s.integer(status.serial_clock);
|
||||
|
||||
s.integer(status.div);
|
||||
s.integer(status.tima);
|
||||
s.integer(status.tma);
|
||||
|
|
|
@ -64,10 +64,22 @@ void CPU::timer_stage2() { // 16384hz
|
|||
status.div++;
|
||||
|
||||
status.timer2 -= 4;
|
||||
if(++status.timer3 >= 4) timer_stage3();
|
||||
if(++status.timer3 >= 2) timer_stage3();
|
||||
}
|
||||
|
||||
void CPU::timer_stage3() { // 4096hz
|
||||
void CPU::timer_stage3() { // 8192hz
|
||||
if(status.serial_transfer && status.serial_clock) {
|
||||
if(--status.serial_bits == 0) {
|
||||
status.serial_transfer = 0;
|
||||
interrupt_raise(Interrupt::Serial);
|
||||
}
|
||||
}
|
||||
|
||||
status.timer3 -= 2;
|
||||
if(++status.timer4 >= 2) timer_stage4();
|
||||
}
|
||||
|
||||
void CPU::timer_stage4() { // 4096hz
|
||||
if(status.timer_enable && status.timer_clock == 0) {
|
||||
if(++status.tima == 0) {
|
||||
status.tima = status.tma;
|
||||
|
@ -75,7 +87,7 @@ void CPU::timer_stage3() { // 4096hz
|
|||
}
|
||||
}
|
||||
|
||||
status.timer3 -= 4;
|
||||
status.timer4 -= 2;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
@ -3,6 +3,7 @@ void timer_stage0();
|
|||
void timer_stage1();
|
||||
void timer_stage2();
|
||||
void timer_stage3();
|
||||
void timer_stage4();
|
||||
|
||||
//opcode.cpp
|
||||
void op_io();
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
namespace GameBoy {
|
||||
namespace Info {
|
||||
static const char Name[] = "bgameboy";
|
||||
static const char Version[] = "000.12";
|
||||
static const char Version[] = "000.13";
|
||||
static unsigned SerializerVersion = 1;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -19,7 +19,11 @@ void LCD::main() {
|
|||
|
||||
add_clocks(4);
|
||||
|
||||
if(status.lx == 320) {
|
||||
if(status.lx == 0) {
|
||||
if(status.interrupt_oam) cpu.interrupt_raise(CPU::Interrupt::Stat);
|
||||
}
|
||||
|
||||
if(status.lx == 252) {
|
||||
if(status.interrupt_hblank) cpu.interrupt_raise(CPU::Interrupt::Stat);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -17,9 +17,10 @@ uint8 LCD::mmio_read(uint16 addr) {
|
|||
|
||||
if(addr == 0xff41) { //STAT
|
||||
unsigned mode;
|
||||
if(status.ly >= 144) mode = 1; //Vblank
|
||||
else if(status.lx >= 320) mode = 0; //Hblank
|
||||
else mode = 3; //LCD transfer
|
||||
if(status.ly >= 144) mode = 1; //Vblank
|
||||
else if(status.lx < 80) mode = 2; //OAM
|
||||
else if(status.lx < 252) mode = 3; //LCD
|
||||
else mode = 0; //Hblank
|
||||
|
||||
return (status.interrupt_lyc << 6)
|
||||
| (status.interrupt_oam << 5)
|
||||
|
|
|
@ -91,32 +91,27 @@ void CPU::op_irq(uint16 vector) {
|
|||
}
|
||||
|
||||
void CPU::enable() {
|
||||
bus.map(Bus::MapMode::Direct, 0x00, 0x3f, 0x2140, 0x2183, { &CPU::mmio_read, &cpu }, { &CPU::mmio_write, &cpu });
|
||||
bus.map(Bus::MapMode::Direct, 0x80, 0xbf, 0x2140, 0x2183, { &CPU::mmio_read, &cpu }, { &CPU::mmio_write, &cpu });
|
||||
function<uint8 (unsigned)> read = { &CPU::mmio_read, (CPU*)&cpu };
|
||||
function<void (unsigned, uint8)> write = { &CPU::mmio_write, (CPU*)&cpu };
|
||||
|
||||
bus.map(Bus::MapMode::Direct, 0x00, 0x3f, 0x4016, 0x4017, { &CPU::mmio_read, &cpu }, { &CPU::mmio_write, &cpu });
|
||||
bus.map(Bus::MapMode::Direct, 0x80, 0xbf, 0x4016, 0x4017, { &CPU::mmio_read, &cpu }, { &CPU::mmio_write, &cpu });
|
||||
bus.map(Bus::MapMode::Direct, 0x00, 0x3f, 0x2140, 0x2183, read, write);
|
||||
bus.map(Bus::MapMode::Direct, 0x80, 0xbf, 0x2140, 0x2183, read, write);
|
||||
|
||||
bus.map(Bus::MapMode::Direct, 0x00, 0x3f, 0x4200, 0x421f, { &CPU::mmio_read, &cpu }, { &CPU::mmio_write, &cpu });
|
||||
bus.map(Bus::MapMode::Direct, 0x80, 0xbf, 0x4200, 0x421f, { &CPU::mmio_read, &cpu }, { &CPU::mmio_write, &cpu });
|
||||
bus.map(Bus::MapMode::Direct, 0x00, 0x3f, 0x4016, 0x4017, read, write);
|
||||
bus.map(Bus::MapMode::Direct, 0x80, 0xbf, 0x4016, 0x4017, read, write);
|
||||
|
||||
bus.map(Bus::MapMode::Direct, 0x00, 0x3f, 0x4300, 0x437f, { &CPU::mmio_read, &cpu }, { &CPU::mmio_write, &cpu });
|
||||
bus.map(Bus::MapMode::Direct, 0x80, 0xbf, 0x4300, 0x437f, { &CPU::mmio_read, &cpu }, { &CPU::mmio_write, &cpu });
|
||||
bus.map(Bus::MapMode::Direct, 0x00, 0x3f, 0x4200, 0x421f, read, write);
|
||||
bus.map(Bus::MapMode::Direct, 0x80, 0xbf, 0x4200, 0x421f, read, write);
|
||||
|
||||
bus.map(
|
||||
Bus::MapMode::Linear, 0x00, 0x3f, 0x0000, 0x1fff,
|
||||
{ &StaticRAM::read, &memory::wram }, { &StaticRAM::write, &memory::wram },
|
||||
0x000000, 0x002000
|
||||
);
|
||||
bus.map(
|
||||
Bus::MapMode::Linear, 0x80, 0xbf, 0x0000, 0x1fff,
|
||||
{ &StaticRAM::read, &memory::wram }, { &StaticRAM::write, &memory::wram },
|
||||
0x000000, 0x002000
|
||||
);
|
||||
bus.map(
|
||||
Bus::MapMode::Linear, 0x7e, 0x7f, 0x0000, 0xffff,
|
||||
{ &StaticRAM::read, &memory::wram }, { &StaticRAM::write, &memory::wram }
|
||||
);
|
||||
bus.map(Bus::MapMode::Direct, 0x00, 0x3f, 0x4300, 0x437f, read, write);
|
||||
bus.map(Bus::MapMode::Direct, 0x80, 0xbf, 0x4300, 0x437f, read, write);
|
||||
|
||||
read = [](unsigned addr) { return cpu.wram[addr]; };
|
||||
write = [](unsigned addr, uint8 data) { cpu.wram[addr] = data; };
|
||||
|
||||
bus.map(Bus::MapMode::Linear, 0x00, 0x3f, 0x0000, 0x1fff, read, write, 0x000000, 0x002000);
|
||||
bus.map(Bus::MapMode::Linear, 0x80, 0xbf, 0x0000, 0x1fff, read, write, 0x000000, 0x002000);
|
||||
bus.map(Bus::MapMode::Linear, 0x7e, 0x7f, 0x0000, 0xffff, read, write);
|
||||
}
|
||||
|
||||
void CPU::power() {
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
class CPU : public Processor, public CPUcore, public PPUcounter {
|
||||
public:
|
||||
uint8 wram[128 * 1024];
|
||||
|
||||
enum : bool { Threaded = true };
|
||||
array<Processor*> coprocessors;
|
||||
alwaysinline void step(unsigned clocks);
|
||||
|
|
|
@ -8,13 +8,11 @@ void CPUDebugger::op_step() {
|
|||
opcode_pc = regs.pc;
|
||||
|
||||
opcode_edge = true;
|
||||
if(debugger.step_cpu) {
|
||||
debugger.breakpoint_test(Debugger::Breakpoint::Source::CPUBus, Debugger::Breakpoint::Mode::Exec, regs.pc, 0x00);
|
||||
if(step_event && step_event()) {
|
||||
debugger.break_event = Debugger::BreakEvent::CPUStep;
|
||||
scheduler.exit(Scheduler::ExitReason::DebuggerEvent);
|
||||
} else {
|
||||
debugger.breakpoint_test(Debugger::Breakpoint::Source::CPUBus, Debugger::Breakpoint::Mode::Exec, regs.pc, 0x00);
|
||||
}
|
||||
if(step_event) step_event();
|
||||
opcode_edge = false;
|
||||
|
||||
CPU::op_step();
|
||||
|
|
|
@ -2,7 +2,7 @@ class CPUDebugger : public CPU, public ChipDebugger {
|
|||
public:
|
||||
bool property(unsigned id, string &name, string &value);
|
||||
|
||||
function<void ()> step_event;
|
||||
function<bool ()> step_event;
|
||||
|
||||
enum Usage {
|
||||
UsageRead = 0x80,
|
||||
|
|
|
@ -5,6 +5,8 @@ void CPU::serialize(serializer &s) {
|
|||
CPUcore::core_serialize(s);
|
||||
PPUcounter::serialize(s);
|
||||
|
||||
s.array(wram);
|
||||
|
||||
queue.serialize(s);
|
||||
s.array(port_data);
|
||||
|
||||
|
|
|
@ -40,7 +40,7 @@ void DSP::write(uint8 addr, uint8 data) {
|
|||
}
|
||||
|
||||
void DSP::power() {
|
||||
spc_dsp.init(memory::apuram.data());
|
||||
spc_dsp.init(smp.apuram);
|
||||
spc_dsp.reset();
|
||||
spc_dsp.set_output(samplebuffer, 8192);
|
||||
}
|
||||
|
|
|
@ -26,7 +26,7 @@ uint8 PPU::vram_mmio_read(uint16 addr) {
|
|||
uint8 data;
|
||||
|
||||
if(regs.display_disabled == true) {
|
||||
data = memory::vram[addr];
|
||||
data = vram[addr];
|
||||
} else {
|
||||
uint16 v = cpu.vcounter();
|
||||
uint16 h = cpu.hcounter();
|
||||
|
@ -39,12 +39,12 @@ uint8 PPU::vram_mmio_read(uint16 addr) {
|
|||
data = 0x00;
|
||||
} else if(v == (!overscan() ? 224 : 239)) {
|
||||
if(h == 1362) {
|
||||
data = memory::vram[addr];
|
||||
data = vram[addr];
|
||||
} else {
|
||||
data = 0x00;
|
||||
}
|
||||
} else {
|
||||
data = memory::vram[addr];
|
||||
data = vram[addr];
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -53,15 +53,15 @@ uint8 PPU::vram_mmio_read(uint16 addr) {
|
|||
|
||||
void PPU::vram_mmio_write(uint16 addr, uint8 data) {
|
||||
if(regs.display_disabled == true) {
|
||||
memory::vram[addr] = data;
|
||||
vram[addr] = data;
|
||||
} else {
|
||||
uint16 v = cpu.vcounter();
|
||||
uint16 h = cpu.hcounter();
|
||||
if(v == 0) {
|
||||
if(h <= 4) {
|
||||
memory::vram[addr] = data;
|
||||
vram[addr] = data;
|
||||
} else if(h == 6) {
|
||||
memory::vram[addr] = cpu.regs.mdr;
|
||||
vram[addr] = cpu.regs.mdr;
|
||||
} else {
|
||||
//no write
|
||||
}
|
||||
|
@ -71,10 +71,10 @@ void PPU::vram_mmio_write(uint16 addr, uint8 data) {
|
|||
if(h <= 4) {
|
||||
//no write
|
||||
} else {
|
||||
memory::vram[addr] = data;
|
||||
vram[addr] = data;
|
||||
}
|
||||
} else {
|
||||
memory::vram[addr] = data;
|
||||
vram[addr] = data;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -85,12 +85,12 @@ uint8 PPU::oam_mmio_read(uint16 addr) {
|
|||
uint8 data;
|
||||
|
||||
if(regs.display_disabled == true) {
|
||||
data = memory::oam[addr];
|
||||
data = oam[addr];
|
||||
} else {
|
||||
if(cpu.vcounter() < (!overscan() ? 225 : 240)) {
|
||||
data = memory::oam[regs.ioamaddr];
|
||||
data = oam[regs.ioamaddr];
|
||||
} else {
|
||||
data = memory::oam[addr];
|
||||
data = oam[addr];
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -104,14 +104,14 @@ void PPU::oam_mmio_write(uint16 addr, uint8 data) {
|
|||
sprite_list_valid = false;
|
||||
|
||||
if(regs.display_disabled == true) {
|
||||
memory::oam[addr] = data;
|
||||
oam[addr] = data;
|
||||
update_sprite_list(addr, data);
|
||||
} else {
|
||||
if(cpu.vcounter() < (!overscan() ? 225 : 240)) {
|
||||
memory::oam[regs.ioamaddr] = data;
|
||||
oam[regs.ioamaddr] = data;
|
||||
update_sprite_list(regs.ioamaddr, data);
|
||||
} else {
|
||||
memory::oam[addr] = data;
|
||||
oam[addr] = data;
|
||||
update_sprite_list(addr, data);
|
||||
}
|
||||
}
|
||||
|
@ -122,14 +122,14 @@ uint8 PPU::cgram_mmio_read(uint16 addr) {
|
|||
uint8 data;
|
||||
|
||||
if(1 || regs.display_disabled == true) {
|
||||
data = memory::cgram[addr];
|
||||
data = cgram[addr];
|
||||
} else {
|
||||
uint16 v = cpu.vcounter();
|
||||
uint16 h = cpu.hcounter();
|
||||
if(v < (!overscan() ? 225 : 240) && h >= 128 && h < 1096) {
|
||||
data = memory::cgram[regs.icgramaddr] & 0x7f;
|
||||
data = cgram[regs.icgramaddr] & 0x7f;
|
||||
} else {
|
||||
data = memory::cgram[addr];
|
||||
data = cgram[addr];
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -142,14 +142,14 @@ void PPU::cgram_mmio_write(uint16 addr, uint8 data) {
|
|||
if(addr & 1) data &= 0x7f;
|
||||
|
||||
if(1 || regs.display_disabled == true) {
|
||||
memory::cgram[addr] = data;
|
||||
cgram[addr] = data;
|
||||
} else {
|
||||
uint16 v = cpu.vcounter();
|
||||
uint16 h = cpu.hcounter();
|
||||
if(v < (!overscan() ? 225 : 240) && h >= 128 && h < 1096) {
|
||||
memory::cgram[regs.icgramaddr] = data & 0x7f;
|
||||
cgram[regs.icgramaddr] = data & 0x7f;
|
||||
} else {
|
||||
memory::cgram[addr] = data;
|
||||
cgram[addr] = data;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -123,17 +123,20 @@ void PPU::frame() {
|
|||
}
|
||||
|
||||
void PPU::enable() {
|
||||
bus.map(Bus::MapMode::Direct, 0x00, 0x3f, 0x2100, 0x213f, { &PPU::mmio_read, &ppu }, { &PPU::mmio_write, &ppu });
|
||||
bus.map(Bus::MapMode::Direct, 0x80, 0xbf, 0x2100, 0x213f, { &PPU::mmio_read, &ppu }, { &PPU::mmio_write, &ppu });
|
||||
function<uint8 (unsigned)> read = { &PPU::mmio_read, (PPU*)&ppu };
|
||||
function<void (unsigned, uint8)> write = { &PPU::mmio_write, (PPU*)&ppu };
|
||||
|
||||
bus.map(Bus::MapMode::Direct, 0x00, 0x3f, 0x2100, 0x213f, read, write);
|
||||
bus.map(Bus::MapMode::Direct, 0x80, 0xbf, 0x2100, 0x213f, read, write);
|
||||
}
|
||||
|
||||
void PPU::power() {
|
||||
ppu1_version = config.ppu1.version;
|
||||
ppu2_version = config.ppu2.version;
|
||||
|
||||
for(unsigned i = 0; i < memory::vram.size(); i++) memory::vram[i] = 0x00;
|
||||
for(unsigned i = 0; i < memory::oam.size(); i++) memory::oam[i] = 0x00;
|
||||
for(unsigned i = 0; i < memory::cgram.size(); i++) memory::cgram[i] = 0x00;
|
||||
foreach(n, vram) n = 0x00;
|
||||
foreach(n, oam) n = 0x00;
|
||||
foreach(n, cgram) n = 0x00;
|
||||
flush_tiledata_cache();
|
||||
|
||||
region = (system.region() == System::Region::NTSC ? 0 : 1); //0 = NTSC, 1 = PAL
|
||||
|
|
|
@ -1,5 +1,9 @@
|
|||
class PPU : public Processor, public PPUcounter {
|
||||
public:
|
||||
uint8 vram[128 * 1024];
|
||||
uint8 oam[544];
|
||||
uint8 cgram[512];
|
||||
|
||||
enum : bool { Threaded = true };
|
||||
alwaysinline void step(unsigned clocks);
|
||||
alwaysinline void synchronize_cpu();
|
||||
|
|
|
@ -32,7 +32,7 @@ uint16 PPU::bg_get_tile(uint16 x, uint16 y) {
|
|||
if(x & 0x20) pos += bg_info[bg].scx;
|
||||
|
||||
const uint16 addr = regs.bg_scaddr[bg] + (pos << 1);
|
||||
return memory::vram[addr] + (memory::vram[addr + 1] << 8);
|
||||
return vram[addr] + (vram[addr + 1] << 8);
|
||||
}
|
||||
|
||||
#define setpixel_main(x) \
|
||||
|
|
|
@ -32,8 +32,8 @@ void PPU::render_bg_tile(uint16 tile_num) {
|
|||
unsigned pos = tile_num * 16;
|
||||
unsigned y = 8;
|
||||
while(y--) {
|
||||
d0 = memory::vram[pos ];
|
||||
d1 = memory::vram[pos + 1];
|
||||
d0 = vram[pos ];
|
||||
d1 = vram[pos + 1];
|
||||
render_bg_tile_line_2bpp(0x80);
|
||||
render_bg_tile_line_2bpp(0x40);
|
||||
render_bg_tile_line_2bpp(0x20);
|
||||
|
@ -52,10 +52,10 @@ void PPU::render_bg_tile(uint16 tile_num) {
|
|||
unsigned pos = tile_num * 32;
|
||||
unsigned y = 8;
|
||||
while(y--) {
|
||||
d0 = memory::vram[pos ];
|
||||
d1 = memory::vram[pos + 1];
|
||||
d2 = memory::vram[pos + 16];
|
||||
d3 = memory::vram[pos + 17];
|
||||
d0 = vram[pos ];
|
||||
d1 = vram[pos + 1];
|
||||
d2 = vram[pos + 16];
|
||||
d3 = vram[pos + 17];
|
||||
render_bg_tile_line_4bpp(0x80);
|
||||
render_bg_tile_line_4bpp(0x40);
|
||||
render_bg_tile_line_4bpp(0x20);
|
||||
|
@ -74,14 +74,14 @@ void PPU::render_bg_tile(uint16 tile_num) {
|
|||
unsigned pos = tile_num * 64;
|
||||
unsigned y = 8;
|
||||
while(y--) {
|
||||
d0 = memory::vram[pos ];
|
||||
d1 = memory::vram[pos + 1];
|
||||
d2 = memory::vram[pos + 16];
|
||||
d3 = memory::vram[pos + 17];
|
||||
d4 = memory::vram[pos + 32];
|
||||
d5 = memory::vram[pos + 33];
|
||||
d6 = memory::vram[pos + 48];
|
||||
d7 = memory::vram[pos + 49];
|
||||
d0 = vram[pos ];
|
||||
d1 = vram[pos + 1];
|
||||
d2 = vram[pos + 16];
|
||||
d3 = vram[pos + 17];
|
||||
d4 = vram[pos + 32];
|
||||
d5 = vram[pos + 33];
|
||||
d6 = vram[pos + 48];
|
||||
d7 = vram[pos + 49];
|
||||
render_bg_tile_line_8bpp(0x80);
|
||||
render_bg_tile_line_8bpp(0x40);
|
||||
render_bg_tile_line_8bpp(0x20);
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
inline uint16 PPU::get_palette(uint8 index) {
|
||||
const unsigned addr = index << 1;
|
||||
return memory::cgram[addr] + (memory::cgram[addr + 1] << 8);
|
||||
return cgram[addr] + (cgram[addr + 1] << 8);
|
||||
}
|
||||
|
||||
//p = 00000bgr <palette data>
|
||||
|
|
|
@ -71,8 +71,8 @@ void PPU::render_line_mode7(uint8 pri0_pos, uint8 pri1_pos) {
|
|||
py &= 1023;
|
||||
tx = ((px >> 3) & 127);
|
||||
ty = ((py >> 3) & 127);
|
||||
tile = memory::vram[(ty * 128 + tx) << 1];
|
||||
palette = memory::vram[(((tile << 6) + ((py & 7) << 3) + (px & 7)) << 1) + 1];
|
||||
tile = vram[(ty * 128 + tx) << 1];
|
||||
palette = vram[(((tile << 6) + ((py & 7) << 3) + (px & 7)) << 1) + 1];
|
||||
} break;
|
||||
case 2: { //palette color 0 outside of screen area
|
||||
if((px | py) & ~1023) {
|
||||
|
@ -82,8 +82,8 @@ void PPU::render_line_mode7(uint8 pri0_pos, uint8 pri1_pos) {
|
|||
py &= 1023;
|
||||
tx = ((px >> 3) & 127);
|
||||
ty = ((py >> 3) & 127);
|
||||
tile = memory::vram[(ty * 128 + tx) << 1];
|
||||
palette = memory::vram[(((tile << 6) + ((py & 7) << 3) + (px & 7)) << 1) + 1];
|
||||
tile = vram[(ty * 128 + tx) << 1];
|
||||
palette = vram[(((tile << 6) + ((py & 7) << 3) + (px & 7)) << 1) + 1];
|
||||
}
|
||||
} break;
|
||||
case 3: { //character 0 repetition outside of screen area
|
||||
|
@ -94,9 +94,9 @@ void PPU::render_line_mode7(uint8 pri0_pos, uint8 pri1_pos) {
|
|||
py &= 1023;
|
||||
tx = ((px >> 3) & 127);
|
||||
ty = ((py >> 3) & 127);
|
||||
tile = memory::vram[(ty * 128 + tx) << 1];
|
||||
tile = vram[(ty * 128 + tx) << 1];
|
||||
}
|
||||
palette = memory::vram[(((tile << 6) + ((py & 7) << 3) + (px & 7)) << 1) + 1];
|
||||
palette = vram[(((tile << 6) + ((py & 7) << 3) + (px & 7)) << 1) + 1];
|
||||
} break;
|
||||
}
|
||||
|
||||
|
|
|
@ -16,6 +16,10 @@ void PPU::serialize(serializer &s) {
|
|||
Processor::serialize(s);
|
||||
PPUcounter::serialize(s);
|
||||
|
||||
s.array(vram);
|
||||
s.array(oam);
|
||||
s.array(cgram);
|
||||
|
||||
s.integer(ppu1_version);
|
||||
s.integer(ppu2_version);
|
||||
|
||||
|
|
|
@ -11,7 +11,7 @@ unsigned PPU::Background::get_tile(unsigned hoffset, unsigned voffset) {
|
|||
if(tile_x & 0x20) tile_pos += scx;
|
||||
|
||||
const uint16 tiledata_addr = regs.screen_addr + (tile_pos << 1);
|
||||
return (memory::vram[tiledata_addr + 0] << 0) + (memory::vram[tiledata_addr + 1] << 8);
|
||||
return (ppu.vram[tiledata_addr + 0] << 0) + (ppu.vram[tiledata_addr + 1] << 8);
|
||||
}
|
||||
|
||||
void PPU::Background::offset_per_tile(unsigned x, unsigned y, unsigned &hoffset, unsigned &voffset) {
|
||||
|
|
|
@ -43,8 +43,8 @@ void PPU::Background::render_mode7() {
|
|||
py &= 1023;
|
||||
tx = ((px >> 3) & 127);
|
||||
ty = ((py >> 3) & 127);
|
||||
tile = memory::vram[(ty * 128 + tx) << 1];
|
||||
palette = memory::vram[(((tile << 6) + ((py & 7) << 3) + (px & 7)) << 1) + 1];
|
||||
tile = ppu.vram[(ty * 128 + tx) << 1];
|
||||
palette = ppu.vram[(((tile << 6) + ((py & 7) << 3) + (px & 7)) << 1) + 1];
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -56,8 +56,8 @@ void PPU::Background::render_mode7() {
|
|||
py &= 1023;
|
||||
tx = ((px >> 3) & 127);
|
||||
ty = ((py >> 3) & 127);
|
||||
tile = memory::vram[(ty * 128 + tx) << 1];
|
||||
palette = memory::vram[(((tile << 6) + ((py & 7) << 3) + (px & 7)) << 1) + 1];
|
||||
tile = ppu.vram[(ty * 128 + tx) << 1];
|
||||
palette = ppu.vram[(((tile << 6) + ((py & 7) << 3) + (px & 7)) << 1) + 1];
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
@ -70,9 +70,9 @@ void PPU::Background::render_mode7() {
|
|||
py &= 1023;
|
||||
tx = ((px >> 3) & 127);
|
||||
ty = ((py >> 3) & 127);
|
||||
tile = memory::vram[(ty * 128 + tx) << 1];
|
||||
tile = ppu.vram[(ty * 128 + tx) << 1];
|
||||
}
|
||||
palette = memory::vram[(((tile << 6) + ((py & 7) << 3) + (px & 7)) << 1) + 1];
|
||||
palette = ppu.vram[(((tile << 6) + ((py & 7) << 3) + (px & 7)) << 1) + 1];
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -8,8 +8,8 @@ uint8* PPU::Cache::tile_2bpp(unsigned tile) {
|
|||
unsigned y = 8;
|
||||
unsigned color, d0, d1;
|
||||
while(y--) {
|
||||
d0 = memory::vram[offset + 0];
|
||||
d1 = memory::vram[offset + 1];
|
||||
d0 = ppu.vram[offset + 0];
|
||||
d1 = ppu.vram[offset + 1];
|
||||
#define render_line(mask) \
|
||||
color = !!(d0 & mask) << 0; \
|
||||
color |= !!(d1 & mask) << 1; \
|
||||
|
@ -37,10 +37,10 @@ uint8* PPU::Cache::tile_4bpp(unsigned tile) {
|
|||
unsigned y = 8;
|
||||
unsigned color, d0, d1, d2, d3;
|
||||
while(y--) {
|
||||
d0 = memory::vram[offset + 0];
|
||||
d1 = memory::vram[offset + 1];
|
||||
d2 = memory::vram[offset + 16];
|
||||
d3 = memory::vram[offset + 17];
|
||||
d0 = ppu.vram[offset + 0];
|
||||
d1 = ppu.vram[offset + 1];
|
||||
d2 = ppu.vram[offset + 16];
|
||||
d3 = ppu.vram[offset + 17];
|
||||
#define render_line(mask) \
|
||||
color = !!(d0 & mask) << 0; \
|
||||
color |= !!(d1 & mask) << 1; \
|
||||
|
@ -70,14 +70,14 @@ uint8* PPU::Cache::tile_8bpp(unsigned tile) {
|
|||
unsigned y = 8;
|
||||
unsigned color, d0, d1, d2, d3, d4, d5, d6, d7;
|
||||
while(y--) {
|
||||
d0 = memory::vram[offset + 0];
|
||||
d1 = memory::vram[offset + 1];
|
||||
d2 = memory::vram[offset + 16];
|
||||
d3 = memory::vram[offset + 17];
|
||||
d4 = memory::vram[offset + 32];
|
||||
d5 = memory::vram[offset + 33];
|
||||
d6 = memory::vram[offset + 48];
|
||||
d7 = memory::vram[offset + 49];
|
||||
d0 = ppu.vram[offset + 0];
|
||||
d1 = ppu.vram[offset + 1];
|
||||
d2 = ppu.vram[offset + 16];
|
||||
d3 = ppu.vram[offset + 17];
|
||||
d4 = ppu.vram[offset + 32];
|
||||
d5 = ppu.vram[offset + 33];
|
||||
d6 = ppu.vram[offset + 48];
|
||||
d7 = ppu.vram[offset + 49];
|
||||
#define render_line(mask) \
|
||||
color = !!(d0 & mask) << 0; \
|
||||
color |= !!(d1 & mask) << 1; \
|
||||
|
|
|
@ -22,14 +22,14 @@ uint16 PPU::get_vram_addr() {
|
|||
}
|
||||
|
||||
uint8 PPU::vram_read(unsigned addr) {
|
||||
if(regs.display_disable) return memory::vram[addr];
|
||||
if(cpu.vcounter() >= display.height) return memory::vram[addr];
|
||||
if(regs.display_disable) return vram[addr];
|
||||
if(cpu.vcounter() >= display.height) return vram[addr];
|
||||
return 0x00;
|
||||
}
|
||||
|
||||
void PPU::vram_write(unsigned addr, uint8 data) {
|
||||
if(regs.display_disable || cpu.vcounter() >= display.height) {
|
||||
memory::vram[addr] = data;
|
||||
vram[addr] = data;
|
||||
cache.tilevalid[0][addr >> 4] = false;
|
||||
cache.tilevalid[1][addr >> 5] = false;
|
||||
cache.tilevalid[2][addr >> 6] = false;
|
||||
|
@ -39,24 +39,24 @@ void PPU::vram_write(unsigned addr, uint8 data) {
|
|||
|
||||
uint8 PPU::oam_read(unsigned addr) {
|
||||
if(addr & 0x0200) addr &= 0x021f;
|
||||
if(regs.display_disable) return memory::oam[addr];
|
||||
if(cpu.vcounter() >= display.height) return memory::oam[addr];
|
||||
return memory::oam[0x0218];
|
||||
if(regs.display_disable) return oam[addr];
|
||||
if(cpu.vcounter() >= display.height) return oam[addr];
|
||||
return oam[0x0218];
|
||||
}
|
||||
|
||||
void PPU::oam_write(unsigned addr, uint8 data) {
|
||||
if(addr & 0x0200) addr &= 0x021f;
|
||||
if(!regs.display_disable && cpu.vcounter() < display.height) addr = 0x0218;
|
||||
memory::oam[addr] = data;
|
||||
oam.update_list(addr, data);
|
||||
oam[addr] = data;
|
||||
sprite.update_list(addr, data);
|
||||
}
|
||||
|
||||
uint8 PPU::cgram_read(unsigned addr) {
|
||||
return memory::cgram[addr];
|
||||
return cgram[addr];
|
||||
}
|
||||
|
||||
void PPU::cgram_write(unsigned addr, uint8 data) {
|
||||
memory::cgram[addr] = data;
|
||||
cgram[addr] = data;
|
||||
}
|
||||
|
||||
void PPU::mmio_update_video_mode() {
|
||||
|
@ -66,7 +66,7 @@ void PPU::mmio_update_video_mode() {
|
|||
bg2.regs.mode = Background::Mode::BPP2; bg2.regs.priority0 = 7; bg2.regs.priority1 = 10;
|
||||
bg3.regs.mode = Background::Mode::BPP2; bg3.regs.priority0 = 2; bg3.regs.priority1 = 5;
|
||||
bg4.regs.mode = Background::Mode::BPP2; bg4.regs.priority0 = 1; bg4.regs.priority1 = 4;
|
||||
oam.regs.priority0 = 3; oam.regs.priority1 = 6; oam.regs.priority2 = 9; oam.regs.priority3 = 12;
|
||||
sprite.regs.priority0 = 3; sprite.regs.priority1 = 6; sprite.regs.priority2 = 9; sprite.regs.priority3 = 12;
|
||||
} break;
|
||||
|
||||
case 1: {
|
||||
|
@ -78,12 +78,12 @@ void PPU::mmio_update_video_mode() {
|
|||
bg1.regs.priority0 = 5; bg1.regs.priority1 = 8;
|
||||
bg2.regs.priority0 = 4; bg2.regs.priority1 = 7;
|
||||
bg3.regs.priority0 = 1; bg3.regs.priority1 = 10;
|
||||
oam.regs.priority0 = 2; oam.regs.priority1 = 3; oam.regs.priority2 = 6; oam.regs.priority3 = 9;
|
||||
sprite.regs.priority0 = 2; sprite.regs.priority1 = 3; sprite.regs.priority2 = 6; sprite.regs.priority3 = 9;
|
||||
} else {
|
||||
bg1.regs.priority0 = 6; bg1.regs.priority1 = 9;
|
||||
bg2.regs.priority0 = 5; bg2.regs.priority1 = 8;
|
||||
bg3.regs.priority0 = 1; bg3.regs.priority1 = 3;
|
||||
oam.regs.priority0 = 2; oam.regs.priority1 = 4; oam.regs.priority2 = 7; oam.regs.priority3 = 10;
|
||||
sprite.regs.priority0 = 2; sprite.regs.priority1 = 4; sprite.regs.priority2 = 7; sprite.regs.priority3 = 10;
|
||||
}
|
||||
} break;
|
||||
|
||||
|
@ -94,7 +94,7 @@ void PPU::mmio_update_video_mode() {
|
|||
bg4.regs.mode = Background::Mode::Inactive;
|
||||
bg1.regs.priority0 = 3; bg1.regs.priority1 = 7;
|
||||
bg2.regs.priority0 = 1; bg2.regs.priority1 = 5;
|
||||
oam.regs.priority0 = 2; oam.regs.priority1 = 4; oam.regs.priority2 = 6; oam.regs.priority3 = 8;
|
||||
sprite.regs.priority0 = 2; sprite.regs.priority1 = 4; sprite.regs.priority2 = 6; sprite.regs.priority3 = 8;
|
||||
} break;
|
||||
|
||||
case 3: {
|
||||
|
@ -104,7 +104,7 @@ void PPU::mmio_update_video_mode() {
|
|||
bg4.regs.mode = Background::Mode::Inactive;
|
||||
bg1.regs.priority0 = 3; bg1.regs.priority1 = 7;
|
||||
bg2.regs.priority0 = 1; bg2.regs.priority1 = 5;
|
||||
oam.regs.priority0 = 2; oam.regs.priority1 = 4; oam.regs.priority2 = 6; oam.regs.priority3 = 8;
|
||||
sprite.regs.priority0 = 2; sprite.regs.priority1 = 4; sprite.regs.priority2 = 6; sprite.regs.priority3 = 8;
|
||||
} break;
|
||||
|
||||
case 4: {
|
||||
|
@ -114,7 +114,7 @@ void PPU::mmio_update_video_mode() {
|
|||
bg4.regs.mode = Background::Mode::Inactive;
|
||||
bg1.regs.priority0 = 3; bg1.regs.priority1 = 7;
|
||||
bg2.regs.priority0 = 1; bg2.regs.priority1 = 5;
|
||||
oam.regs.priority0 = 2; oam.regs.priority1 = 4; oam.regs.priority2 = 6; oam.regs.priority3 = 8;
|
||||
sprite.regs.priority0 = 2; sprite.regs.priority1 = 4; sprite.regs.priority2 = 6; sprite.regs.priority3 = 8;
|
||||
} break;
|
||||
|
||||
case 5: {
|
||||
|
@ -124,7 +124,7 @@ void PPU::mmio_update_video_mode() {
|
|||
bg4.regs.mode = Background::Mode::Inactive;
|
||||
bg1.regs.priority0 = 3; bg1.regs.priority1 = 7;
|
||||
bg2.regs.priority0 = 1; bg2.regs.priority1 = 5;
|
||||
oam.regs.priority0 = 2; oam.regs.priority1 = 4; oam.regs.priority2 = 6; oam.regs.priority3 = 8;
|
||||
sprite.regs.priority0 = 2; sprite.regs.priority1 = 4; sprite.regs.priority2 = 6; sprite.regs.priority3 = 8;
|
||||
} break;
|
||||
|
||||
case 6: {
|
||||
|
@ -133,7 +133,7 @@ void PPU::mmio_update_video_mode() {
|
|||
bg3.regs.mode = Background::Mode::Inactive;
|
||||
bg4.regs.mode = Background::Mode::Inactive;
|
||||
bg1.regs.priority0 = 2; bg1.regs.priority1 = 5;
|
||||
oam.regs.priority0 = 1; oam.regs.priority1 = 3; oam.regs.priority2 = 4; oam.regs.priority3 = 6;
|
||||
sprite.regs.priority0 = 1; sprite.regs.priority1 = 3; sprite.regs.priority2 = 4; sprite.regs.priority3 = 6;
|
||||
} break;
|
||||
|
||||
case 7: {
|
||||
|
@ -143,7 +143,7 @@ void PPU::mmio_update_video_mode() {
|
|||
bg3.regs.mode = Background::Mode::Inactive;
|
||||
bg4.regs.mode = Background::Mode::Inactive;
|
||||
bg1.regs.priority0 = 2; bg1.regs.priority1 = 2;
|
||||
oam.regs.priority0 = 1; oam.regs.priority1 = 3; oam.regs.priority2 = 4; oam.regs.priority3 = 5;
|
||||
sprite.regs.priority0 = 1; sprite.regs.priority1 = 3; sprite.regs.priority2 = 4; sprite.regs.priority3 = 5;
|
||||
} else {
|
||||
bg1.regs.mode = Background::Mode::Mode7;
|
||||
bg2.regs.mode = Background::Mode::Mode7;
|
||||
|
@ -151,7 +151,7 @@ void PPU::mmio_update_video_mode() {
|
|||
bg4.regs.mode = Background::Mode::Inactive;
|
||||
bg1.regs.priority0 = 3; bg1.regs.priority1 = 3;
|
||||
bg2.regs.priority0 = 1; bg2.regs.priority1 = 5;
|
||||
oam.regs.priority0 = 2; oam.regs.priority1 = 4; oam.regs.priority2 = 6; oam.regs.priority3 = 7;
|
||||
sprite.regs.priority0 = 2; sprite.regs.priority1 = 4; sprite.regs.priority2 = 6; sprite.regs.priority3 = 7;
|
||||
}
|
||||
} break;
|
||||
}
|
||||
|
@ -193,7 +193,7 @@ uint8 PPU::mmio_read(unsigned addr) {
|
|||
case 0x2138: { //OAMDATAREAD
|
||||
regs.ppu1_mdr = oam_read(regs.oam_addr);
|
||||
regs.oam_addr = (regs.oam_addr + 1) & 0x03ff;
|
||||
oam.set_first();
|
||||
sprite.set_first();
|
||||
return regs.ppu1_mdr;
|
||||
}
|
||||
|
||||
|
@ -251,8 +251,8 @@ uint8 PPU::mmio_read(unsigned addr) {
|
|||
|
||||
case 0x213e: { //STAT77
|
||||
regs.ppu1_mdr &= 0x10;
|
||||
regs.ppu1_mdr |= oam.regs.time_over << 7;
|
||||
regs.ppu1_mdr |= oam.regs.range_over << 6;
|
||||
regs.ppu1_mdr |= sprite.regs.time_over << 7;
|
||||
regs.ppu1_mdr |= sprite.regs.range_over << 6;
|
||||
regs.ppu1_mdr |= 0x01; //version
|
||||
return regs.ppu1_mdr;
|
||||
}
|
||||
|
@ -283,30 +283,30 @@ void PPU::mmio_write(unsigned addr, uint8 data) {
|
|||
|
||||
switch(addr & 0xffff) {
|
||||
case 0x2100: { //INIDISP
|
||||
if(regs.display_disable && cpu.vcounter() == display.height) oam.address_reset();
|
||||
if(regs.display_disable && cpu.vcounter() == display.height) sprite.address_reset();
|
||||
regs.display_disable = data & 0x80;
|
||||
regs.display_brightness = data & 0x0f;
|
||||
return;
|
||||
}
|
||||
|
||||
case 0x2101: { //OBSEL
|
||||
oam.regs.base_size = (data >> 5) & 7;
|
||||
oam.regs.nameselect = (data >> 3) & 3;
|
||||
oam.regs.tiledata_addr = (data & 3) << 14;
|
||||
oam.list_valid = false;
|
||||
sprite.regs.base_size = (data >> 5) & 7;
|
||||
sprite.regs.nameselect = (data >> 3) & 3;
|
||||
sprite.regs.tiledata_addr = (data & 3) << 14;
|
||||
sprite.list_valid = false;
|
||||
return;
|
||||
}
|
||||
|
||||
case 0x2102: { //OAMADDL
|
||||
regs.oam_baseaddr = (regs.oam_baseaddr & 0x0100) | (data << 0);
|
||||
oam.address_reset();
|
||||
sprite.address_reset();
|
||||
return;
|
||||
}
|
||||
|
||||
case 0x2103: { //OAMADDH
|
||||
regs.oam_priority = data & 0x80;
|
||||
regs.oam_baseaddr = ((data & 1) << 8) | (regs.oam_baseaddr & 0x00ff);
|
||||
oam.address_reset();
|
||||
sprite.address_reset();
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -319,7 +319,7 @@ void PPU::mmio_write(unsigned addr, uint8 data) {
|
|||
oam_write((regs.oam_addr & ~1) + 1, data);
|
||||
}
|
||||
regs.oam_addr = (regs.oam_addr + 1) & 0x03ff;
|
||||
oam.set_first();
|
||||
sprite.set_first();
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -561,10 +561,10 @@ void PPU::mmio_write(unsigned addr, uint8 data) {
|
|||
screen.window.two_invert = data & 0x40;
|
||||
screen.window.one_enable = data & 0x20;
|
||||
screen.window.one_invert = data & 0x10;
|
||||
oam.window.two_enable = data & 0x08;
|
||||
oam.window.two_invert = data & 0x04;
|
||||
oam.window.one_enable = data & 0x02;
|
||||
oam.window.one_invert = data & 0x01;
|
||||
sprite.window.two_enable = data & 0x08;
|
||||
sprite.window.two_invert = data & 0x04;
|
||||
sprite.window.one_enable = data & 0x02;
|
||||
sprite.window.one_invert = data & 0x01;
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -598,12 +598,12 @@ void PPU::mmio_write(unsigned addr, uint8 data) {
|
|||
|
||||
case 0x212b: { //WOBJLOG
|
||||
screen.window.mask = (data >> 2) & 3;
|
||||
oam.window.mask = (data >> 0) & 3;
|
||||
sprite.window.mask = (data >> 0) & 3;
|
||||
return;
|
||||
}
|
||||
|
||||
case 0x212c: { //TM
|
||||
oam.regs.main_enable = data & 0x10;
|
||||
sprite.regs.main_enable = data & 0x10;
|
||||
bg4.regs.main_enable = data & 0x08;
|
||||
bg3.regs.main_enable = data & 0x04;
|
||||
bg2.regs.main_enable = data & 0x02;
|
||||
|
@ -612,7 +612,7 @@ void PPU::mmio_write(unsigned addr, uint8 data) {
|
|||
}
|
||||
|
||||
case 0x212d: { //TS
|
||||
oam.regs.sub_enable = data & 0x10;
|
||||
sprite.regs.sub_enable = data & 0x10;
|
||||
bg4.regs.sub_enable = data & 0x08;
|
||||
bg3.regs.sub_enable = data & 0x04;
|
||||
bg2.regs.sub_enable = data & 0x02;
|
||||
|
@ -621,7 +621,7 @@ void PPU::mmio_write(unsigned addr, uint8 data) {
|
|||
}
|
||||
|
||||
case 0x212e: { //TMW
|
||||
oam.window.main_enable = data & 0x10;
|
||||
sprite.window.main_enable = data & 0x10;
|
||||
bg4.window.main_enable = data & 0x08;
|
||||
bg3.window.main_enable = data & 0x04;
|
||||
bg2.window.main_enable = data & 0x02;
|
||||
|
@ -630,7 +630,7 @@ void PPU::mmio_write(unsigned addr, uint8 data) {
|
|||
}
|
||||
|
||||
case 0x212f: { //TSW
|
||||
oam.window.sub_enable = data & 0x10;
|
||||
sprite.window.sub_enable = data & 0x10;
|
||||
bg4.window.sub_enable = data & 0x08;
|
||||
bg3.window.sub_enable = data & 0x04;
|
||||
bg2.window.sub_enable = data & 0x02;
|
||||
|
@ -671,10 +671,10 @@ void PPU::mmio_write(unsigned addr, uint8 data) {
|
|||
regs.mode7_extbg = data & 0x40;
|
||||
regs.pseudo_hires = data & 0x08;
|
||||
regs.overscan = data & 0x04;
|
||||
oam.regs.interlace = data & 0x02;
|
||||
sprite.regs.interlace = data & 0x02;
|
||||
regs.interlace = data & 0x01;
|
||||
mmio_update_video_mode();
|
||||
oam.list_valid = false;
|
||||
sprite.list_valid = false;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
@ -695,17 +695,17 @@ void PPU::mmio_reset() {
|
|||
regs.latch_hcounter = 0;
|
||||
regs.latch_vcounter = 0;
|
||||
|
||||
oam.regs.first_sprite = 0;
|
||||
oam.list_valid = false;
|
||||
sprite.regs.first_sprite = 0;
|
||||
sprite.list_valid = false;
|
||||
|
||||
//$2100
|
||||
regs.display_disable = true;
|
||||
regs.display_brightness = 0;
|
||||
|
||||
//$2101
|
||||
oam.regs.base_size = 0;
|
||||
oam.regs.nameselect = 0;
|
||||
oam.regs.tiledata_addr = 0;
|
||||
sprite.regs.base_size = 0;
|
||||
sprite.regs.nameselect = 0;
|
||||
sprite.regs.tiledata_addr = 0;
|
||||
|
||||
//$2102-$2103
|
||||
regs.oam_baseaddr = 0;
|
||||
|
@ -799,10 +799,10 @@ void PPU::mmio_reset() {
|
|||
bg4.window.two_enable = 0;
|
||||
bg4.window.two_invert = 0;
|
||||
|
||||
oam.window.one_enable = 0;
|
||||
oam.window.one_invert = 0;
|
||||
oam.window.two_enable = 0;
|
||||
oam.window.two_invert = 0;
|
||||
sprite.window.one_enable = 0;
|
||||
sprite.window.one_invert = 0;
|
||||
sprite.window.two_enable = 0;
|
||||
sprite.window.two_invert = 0;
|
||||
|
||||
screen.window.one_enable = 0;
|
||||
screen.window.one_invert = 0;
|
||||
|
@ -820,7 +820,7 @@ void PPU::mmio_reset() {
|
|||
bg2.window.mask = 0;
|
||||
bg3.window.mask = 0;
|
||||
bg4.window.mask = 0;
|
||||
oam.window.mask = 0;
|
||||
sprite.window.mask = 0;
|
||||
screen.window.mask = 0;
|
||||
|
||||
//$212c
|
||||
|
@ -828,28 +828,28 @@ void PPU::mmio_reset() {
|
|||
bg2.regs.main_enable = 0;
|
||||
bg3.regs.main_enable = 0;
|
||||
bg4.regs.main_enable = 0;
|
||||
oam.regs.main_enable = 0;
|
||||
sprite.regs.main_enable = 0;
|
||||
|
||||
//$212d
|
||||
bg1.regs.sub_enable = 0;
|
||||
bg2.regs.sub_enable = 0;
|
||||
bg3.regs.sub_enable = 0;
|
||||
bg4.regs.sub_enable = 0;
|
||||
oam.regs.sub_enable = 0;
|
||||
sprite.regs.sub_enable = 0;
|
||||
|
||||
//$212e
|
||||
bg1.window.main_enable = 0;
|
||||
bg2.window.main_enable = 0;
|
||||
bg3.window.main_enable = 0;
|
||||
bg4.window.main_enable = 0;
|
||||
oam.window.main_enable = 0;
|
||||
sprite.window.main_enable = 0;
|
||||
|
||||
//$212f
|
||||
bg1.window.sub_enable = 0;
|
||||
bg2.window.sub_enable = 0;
|
||||
bg3.window.sub_enable = 0;
|
||||
bg4.window.sub_enable = 0;
|
||||
oam.window.sub_enable = 0;
|
||||
sprite.window.sub_enable = 0;
|
||||
|
||||
//$2130
|
||||
screen.window.main_mask = 0;
|
||||
|
@ -878,12 +878,12 @@ void PPU::mmio_reset() {
|
|||
regs.mode7_extbg = 0;
|
||||
regs.pseudo_hires = 0;
|
||||
regs.overscan = 0;
|
||||
oam.regs.interlace = 0;
|
||||
sprite.regs.interlace = 0;
|
||||
regs.interlace = 0;
|
||||
|
||||
//$213e
|
||||
oam.regs.time_over = 0;
|
||||
oam.regs.range_over = 0;
|
||||
sprite.regs.time_over = 0;
|
||||
sprite.regs.range_over = 0;
|
||||
|
||||
mmio_update_video_mode();
|
||||
}
|
||||
|
|
|
@ -67,7 +67,7 @@ void PPU::render_scanline() {
|
|||
bg2.render();
|
||||
bg3.render();
|
||||
bg4.render();
|
||||
oam.render();
|
||||
sprite.render();
|
||||
screen.render();
|
||||
}
|
||||
|
||||
|
@ -75,11 +75,11 @@ void PPU::scanline() {
|
|||
display.width = !hires() ? 256 : 512;
|
||||
display.height = !overscan() ? 225 : 240;
|
||||
if(vcounter() == 0) frame();
|
||||
if(vcounter() == display.height && regs.display_disable == false) oam.address_reset();
|
||||
if(vcounter() == display.height && regs.display_disable == false) sprite.address_reset();
|
||||
}
|
||||
|
||||
void PPU::frame() {
|
||||
oam.frame();
|
||||
sprite.frame();
|
||||
system.frame();
|
||||
display.interlace = regs.interlace;
|
||||
display.overscan = regs.overscan;
|
||||
|
@ -87,14 +87,17 @@ void PPU::frame() {
|
|||
}
|
||||
|
||||
void PPU::enable() {
|
||||
bus.map(Bus::MapMode::Direct, 0x00, 0x3f, 0x2100, 0x213f, { &PPU::mmio_read, &ppu }, { &PPU::mmio_write, &ppu });
|
||||
bus.map(Bus::MapMode::Direct, 0x80, 0xbf, 0x2100, 0x213f, { &PPU::mmio_read, &ppu }, { &PPU::mmio_write, &ppu });
|
||||
function<uint8 (unsigned)> read = { &PPU::mmio_read, (PPU*)&ppu };
|
||||
function<void (unsigned, uint8)> write = { &PPU::mmio_write, (PPU*)&ppu };
|
||||
|
||||
bus.map(Bus::MapMode::Direct, 0x00, 0x3f, 0x2100, 0x213f, read, write);
|
||||
bus.map(Bus::MapMode::Direct, 0x80, 0xbf, 0x2100, 0x213f, read, write);
|
||||
}
|
||||
|
||||
void PPU::power() {
|
||||
foreach(n, memory::vram) n = 0;
|
||||
foreach(n, memory::oam) n = 0;
|
||||
foreach(n, memory::cgram) n = 0;
|
||||
foreach(n, vram) n = 0;
|
||||
foreach(n, oam) n = 0;
|
||||
foreach(n, cgram) n = 0;
|
||||
reset();
|
||||
}
|
||||
|
||||
|
@ -117,10 +120,10 @@ void PPU::layer_enable(unsigned layer, unsigned priority, bool enable) {
|
|||
case 9: bg3.priority1_enable = enable; break;
|
||||
case 12: bg4.priority0_enable = enable; break;
|
||||
case 13: bg4.priority1_enable = enable; break;
|
||||
case 16: oam.priority0_enable = enable; break;
|
||||
case 17: oam.priority1_enable = enable; break;
|
||||
case 18: oam.priority2_enable = enable; break;
|
||||
case 19: oam.priority3_enable = enable; break;
|
||||
case 16: sprite.priority0_enable = enable; break;
|
||||
case 17: sprite.priority1_enable = enable; break;
|
||||
case 18: sprite.priority2_enable = enable; break;
|
||||
case 19: sprite.priority3_enable = enable; break;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -135,7 +138,7 @@ bg1(*this, Background::ID::BG1),
|
|||
bg2(*this, Background::ID::BG2),
|
||||
bg3(*this, Background::ID::BG3),
|
||||
bg4(*this, Background::ID::BG4),
|
||||
oam(*this),
|
||||
sprite(*this),
|
||||
screen(*this) {
|
||||
surface = new uint16[512 * 512];
|
||||
output = surface + 16 * 512;
|
||||
|
|
|
@ -1,5 +1,9 @@
|
|||
class PPU : public Processor, public PPUcounter {
|
||||
public:
|
||||
uint8 vram[64 * 1024];
|
||||
uint8 oam[544];
|
||||
uint8 cgram[512];
|
||||
|
||||
enum : bool { Threaded = true };
|
||||
alwaysinline void step(unsigned clocks);
|
||||
alwaysinline void synchronize_cpu();
|
||||
|
@ -39,7 +43,7 @@ private:
|
|||
Background bg2;
|
||||
Background bg3;
|
||||
Background bg4;
|
||||
Sprite oam;
|
||||
Sprite sprite;
|
||||
Screen screen;
|
||||
|
||||
struct Display {
|
||||
|
|
|
@ -2,11 +2,10 @@
|
|||
|
||||
unsigned PPU::Screen::get_palette(unsigned color) {
|
||||
#if defined(ARCH_LSB)
|
||||
static uint16 *cgram = (uint16*)memory::cgram.data();
|
||||
return cgram[color];
|
||||
return ((uint16*)ppu.cgram)[color];
|
||||
#else
|
||||
color <<= 1;
|
||||
return (memory::cgram[color + 0] << 0) + (memory::cgram[color + 1] << 8);
|
||||
return (ppu.cgram[color + 0] << 0) + (ppu.cgram[color + 1] << 8);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
|
|
@ -16,12 +16,16 @@ void PPU::serialize(serializer &s) {
|
|||
Processor::serialize(s);
|
||||
PPUcounter::serialize(s);
|
||||
|
||||
s.array(vram);
|
||||
s.array(oam);
|
||||
s.array(cgram);
|
||||
|
||||
cache.serialize(s);
|
||||
bg1.serialize(s);
|
||||
bg2.serialize(s);
|
||||
bg3.serialize(s);
|
||||
bg4.serialize(s);
|
||||
oam.serialize(s);
|
||||
sprite.serialize(s);
|
||||
screen.serialize(s);
|
||||
|
||||
s.integer(display.interlace);
|
||||
|
|
|
@ -125,7 +125,7 @@ void Cartridge::xml_parse_superfx(xml_element &root) {
|
|||
if(node.name == "rom") {
|
||||
foreach(leaf, node.element) {
|
||||
if(leaf.name == "map") {
|
||||
Mapping m(memory::fxrom);
|
||||
Mapping m(superfx.rom);
|
||||
foreach(attr, leaf.attribute) {
|
||||
if(attr.name == "address") xml_parse_address(m, attr.content);
|
||||
if(attr.name == "mode") xml_parse_mode(m, attr.content);
|
||||
|
@ -142,7 +142,7 @@ void Cartridge::xml_parse_superfx(xml_element &root) {
|
|||
|
||||
foreach(leaf, node.element) {
|
||||
if(leaf.name == "map") {
|
||||
Mapping m(memory::fxram);
|
||||
Mapping m(superfx.ram);
|
||||
foreach(attr, leaf.attribute) {
|
||||
if(attr.name == "address") xml_parse_address(m, attr.content);
|
||||
if(attr.name == "mode") xml_parse_mode(m, attr.content);
|
||||
|
@ -201,7 +201,7 @@ void Cartridge::xml_parse_sa1(xml_element &root) {
|
|||
} else if(node.name == "iram") {
|
||||
foreach(leaf, node.element) {
|
||||
if(leaf.name == "map") {
|
||||
Mapping m(memory::cpuiram);
|
||||
Mapping m(sa1.cpuiram);
|
||||
foreach(attr, leaf.attribute) {
|
||||
if(attr.name == "address") xml_parse_address(m, attr.content);
|
||||
if(attr.name == "mode") xml_parse_mode(m, attr.content);
|
||||
|
@ -219,7 +219,7 @@ void Cartridge::xml_parse_sa1(xml_element &root) {
|
|||
|
||||
foreach(leaf, node.element) {
|
||||
if(leaf.name == "map") {
|
||||
Mapping m(memory::cc1bwram);
|
||||
Mapping m(sa1.cpubwram);
|
||||
foreach(attr, leaf.attribute) {
|
||||
if(attr.name == "address") xml_parse_address(m, attr.content);
|
||||
if(attr.name == "mode") xml_parse_mode(m, attr.content);
|
||||
|
|
|
@ -1,144 +1,34 @@
|
|||
#ifdef SA1_CPP
|
||||
|
||||
namespace memory {
|
||||
StaticRAM iram(2048);
|
||||
//accessed by:
|
||||
CPUIRAM cpuiram; //S-CPU
|
||||
SA1IRAM sa1iram; //SA-1
|
||||
SA1BWRAM sa1bwram; //SA-1
|
||||
CC1BWRAM cc1bwram; //S-CPU
|
||||
BitmapRAM bitmapram; //SA-1
|
||||
//ROM / RAM access from the S-CPU
|
||||
|
||||
unsigned SA1::CPUIRAM::size() const {
|
||||
return sa1.iram.size();
|
||||
}
|
||||
|
||||
//=======
|
||||
//SA1IRAM
|
||||
//=======
|
||||
|
||||
unsigned SA1IRAM::size() const {
|
||||
return memory::iram.size();
|
||||
}
|
||||
|
||||
uint8 SA1IRAM::read(unsigned addr) {
|
||||
sa1.synchronize_cpu();
|
||||
return memory::iram.read(addr);
|
||||
}
|
||||
|
||||
void SA1IRAM::write(unsigned addr, uint8 data) {
|
||||
sa1.synchronize_cpu();
|
||||
memory::iram.write(addr, data);
|
||||
}
|
||||
|
||||
//=======
|
||||
//CPUIRAM
|
||||
//=======
|
||||
|
||||
unsigned CPUIRAM::size() const {
|
||||
return memory::iram.size();
|
||||
}
|
||||
|
||||
uint8 CPUIRAM::read(unsigned addr) {
|
||||
uint8 SA1::CPUIRAM::read(unsigned addr) {
|
||||
cpu.synchronize_coprocessor();
|
||||
return memory::iram.read(addr);
|
||||
return sa1.iram.read(addr);
|
||||
}
|
||||
|
||||
void CPUIRAM::write(unsigned addr, uint8 data) {
|
||||
void SA1::CPUIRAM::write(unsigned addr, uint8 data) {
|
||||
cpu.synchronize_coprocessor();
|
||||
memory::iram.write(addr, data);
|
||||
sa1.iram.write(addr, data);
|
||||
}
|
||||
|
||||
//========
|
||||
//SA1BWRAM
|
||||
//========
|
||||
|
||||
unsigned SA1BWRAM::size() const {
|
||||
unsigned SA1::CPUBWRAM::size() const {
|
||||
return cartridge.ram.size();
|
||||
}
|
||||
|
||||
uint8 SA1BWRAM::read(unsigned addr) {
|
||||
sa1.synchronize_cpu();
|
||||
return cartridge.ram.read(addr);
|
||||
}
|
||||
|
||||
void SA1BWRAM::write(unsigned addr, uint8 data) {
|
||||
sa1.synchronize_cpu();
|
||||
cartridge.ram.write(addr, data);
|
||||
}
|
||||
|
||||
//========
|
||||
//CC1BWRAM
|
||||
//========
|
||||
|
||||
unsigned CC1BWRAM::size() const {
|
||||
return cartridge.ram.size();
|
||||
}
|
||||
|
||||
uint8 CC1BWRAM::read(unsigned addr) {
|
||||
uint8 SA1::CPUBWRAM::read(unsigned addr) {
|
||||
cpu.synchronize_coprocessor();
|
||||
if(dma) return sa1.dma_cc1_read(addr);
|
||||
return cartridge.ram.read(addr);
|
||||
}
|
||||
|
||||
void CC1BWRAM::write(unsigned addr, uint8 data) {
|
||||
void SA1::CPUBWRAM::write(unsigned addr, uint8 data) {
|
||||
cpu.synchronize_coprocessor();
|
||||
cartridge.ram.write(addr, data);
|
||||
}
|
||||
|
||||
//=========
|
||||
//BitmapRAM
|
||||
//=========
|
||||
|
||||
unsigned BitmapRAM::size() const {
|
||||
return 0x100000;
|
||||
}
|
||||
|
||||
uint8 BitmapRAM::read(unsigned addr) {
|
||||
sa1.synchronize_cpu();
|
||||
|
||||
if(sa1.mmio.bbf == 0) {
|
||||
//4bpp
|
||||
unsigned shift = addr & 1;
|
||||
addr = (addr >> 1) & (cartridge.ram.size() - 1);
|
||||
switch(shift) { default:
|
||||
case 0: return (cartridge.ram.read(addr) >> 0) & 15;
|
||||
case 1: return (cartridge.ram.read(addr) >> 4) & 15;
|
||||
}
|
||||
} else {
|
||||
//2bpp
|
||||
unsigned shift = addr & 3;
|
||||
addr = (addr >> 2) & (cartridge.ram.size() - 1);
|
||||
switch(shift) { default:
|
||||
case 0: return (cartridge.ram.read(addr) >> 0) & 3;
|
||||
case 1: return (cartridge.ram.read(addr) >> 2) & 3;
|
||||
case 2: return (cartridge.ram.read(addr) >> 4) & 3;
|
||||
case 3: return (cartridge.ram.read(addr) >> 6) & 3;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void BitmapRAM::write(unsigned addr, uint8 data) {
|
||||
sa1.synchronize_cpu();
|
||||
|
||||
if(sa1.mmio.bbf == 0) {
|
||||
//4bpp
|
||||
unsigned shift = addr & 1;
|
||||
addr = (addr >> 1) & (cartridge.ram.size() - 1);
|
||||
switch(shift) { default:
|
||||
case 0: data = (cartridge.ram.read(addr) & 0xf0) | ((data & 15) << 0); break;
|
||||
case 1: data = (cartridge.ram.read(addr) & 0x0f) | ((data & 15) << 4); break;
|
||||
}
|
||||
} else {
|
||||
//2bpp
|
||||
unsigned shift = addr & 3;
|
||||
addr = (addr >> 2) & (cartridge.ram.size() - 1);
|
||||
switch(shift) { default:
|
||||
case 0: data = (cartridge.ram.read(addr) & 0xfc) | ((data & 3) << 0); break;
|
||||
case 1: data = (cartridge.ram.read(addr) & 0xf3) | ((data & 3) << 2); break;
|
||||
case 2: data = (cartridge.ram.read(addr) & 0xcf) | ((data & 3) << 4); break;
|
||||
case 3: data = (cartridge.ram.read(addr) & 0x3f) | ((data & 3) << 6); break;
|
||||
}
|
||||
}
|
||||
|
||||
cartridge.ram.write(addr, data);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
@ -1,40 +1,14 @@
|
|||
StaticRAM iram;
|
||||
|
||||
struct CPUIRAM : Memory {
|
||||
unsigned size() const;
|
||||
alwaysinline uint8 read(unsigned);
|
||||
alwaysinline void write(unsigned, uint8);
|
||||
};
|
||||
} cpuiram;
|
||||
|
||||
struct SA1IRAM : Memory {
|
||||
unsigned size() const;
|
||||
alwaysinline uint8 read(unsigned);
|
||||
alwaysinline void write(unsigned, uint8);
|
||||
};
|
||||
|
||||
struct SA1BWRAM : Memory {
|
||||
unsigned size() const;
|
||||
alwaysinline uint8 read(unsigned);
|
||||
alwaysinline void write(unsigned, uint8);
|
||||
};
|
||||
|
||||
struct CC1BWRAM : Memory {
|
||||
struct CPUBWRAM : Memory {
|
||||
unsigned size() const;
|
||||
alwaysinline uint8 read(unsigned);
|
||||
alwaysinline void write(unsigned, uint8);
|
||||
bool dma;
|
||||
};
|
||||
|
||||
struct BitmapRAM : Memory {
|
||||
unsigned size() const;
|
||||
alwaysinline uint8 read(unsigned);
|
||||
alwaysinline void write(unsigned, uint8);
|
||||
};
|
||||
|
||||
namespace memory {
|
||||
extern StaticRAM iram;
|
||||
|
||||
extern CPUIRAM cpuiram;
|
||||
extern SA1IRAM sa1iram;
|
||||
extern SA1BWRAM sa1bwram;
|
||||
extern CC1BWRAM cc1bwram;
|
||||
extern BitmapRAM bitmapram;
|
||||
};
|
||||
} cpubwram;
|
||||
|
|
|
@ -28,7 +28,7 @@ void SA1::dma_normal() {
|
|||
} break;
|
||||
|
||||
case DMA::SourceIRAM: {
|
||||
data = memory::iram.read(dsa & 0x07ff);
|
||||
data = iram.read(dsa & 0x07ff);
|
||||
} break;
|
||||
}
|
||||
|
||||
|
@ -40,7 +40,7 @@ void SA1::dma_normal() {
|
|||
} break;
|
||||
|
||||
case DMA::DestIRAM: {
|
||||
memory::iram.write(dda & 0x07ff, data);
|
||||
iram.write(dda & 0x07ff, data);
|
||||
} break;
|
||||
}
|
||||
}
|
||||
|
@ -59,7 +59,7 @@ void SA1::dma_normal() {
|
|||
//===========================
|
||||
|
||||
void SA1::dma_cc1() {
|
||||
memory::cc1bwram.dma = true;
|
||||
cpubwram.dma = true;
|
||||
mmio.chdma_irqfl = true;
|
||||
if(mmio.chdma_irqen) {
|
||||
mmio.chdma_irqcl = 0;
|
||||
|
@ -104,12 +104,12 @@ uint8 SA1::dma_cc1_read(unsigned addr) {
|
|||
|
||||
for(unsigned byte = 0; byte < bpp; byte++) {
|
||||
unsigned p = mmio.dda + (y << 1) + ((byte & 6) << 3) + (byte & 1);
|
||||
memory::iram.write(p & 0x07ff, out[byte]);
|
||||
iram.write(p & 0x07ff, out[byte]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return memory::iram.read((mmio.dda + (addr & charmask)) & 0x07ff);
|
||||
return iram.read((mmio.dda + (addr & charmask)) & 0x07ff);
|
||||
}
|
||||
|
||||
//===========================
|
||||
|
@ -130,7 +130,7 @@ void SA1::dma_cc2() {
|
|||
for(unsigned bit = 0; bit < 8; bit++) {
|
||||
output |= ((brf[bit] >> byte) & 1) << (7 - bit);
|
||||
}
|
||||
memory::iram.write(addr + ((byte & 6) << 3) + (byte & 1), output);
|
||||
iram.write(addr + ((byte & 6) << 3) + (byte & 1), output);
|
||||
}
|
||||
|
||||
dma.line = (dma.line + 1) & 15;
|
||||
|
|
|
@ -18,19 +18,23 @@ uint8 SA1::bus_read(unsigned addr) {
|
|||
}
|
||||
|
||||
if((addr & 0x40f800) == 0x000000) { //$00-3f|80-bf:0000-07ff
|
||||
return memory::iram.read(addr & 2047);
|
||||
synchronize_cpu();
|
||||
return iram.read(addr & 2047);
|
||||
}
|
||||
|
||||
if((addr & 0x40f800) == 0x003000) { //$00-3f|80-bf:3000-37ff
|
||||
return memory::iram.read(addr & 2047);
|
||||
synchronize_cpu();
|
||||
return iram.read(addr & 2047);
|
||||
}
|
||||
|
||||
if((addr & 0xf00000) == 0x400000) { //$40-4f:0000-ffff
|
||||
return memory::sa1bwram.read(addr & (memory::sa1bwram.size() - 1));
|
||||
synchronize_cpu();
|
||||
return cartridge.ram.read(addr & (cartridge.ram.size() - 1));
|
||||
}
|
||||
|
||||
if((addr & 0xf00000) == 0x600000) { //$60-6f:0000-ffff
|
||||
return memory::bitmapram.read(addr & (memory::bitmapram.size() - 1));
|
||||
synchronize_cpu();
|
||||
return bitmap_read(addr & 0x0fffff);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -44,19 +48,23 @@ void SA1::bus_write(unsigned addr, uint8 data) {
|
|||
}
|
||||
|
||||
if((addr & 0x40f800) == 0x000000) { //$00-3f|80-bf:0000-07ff
|
||||
return memory::iram.write(addr & 2047, data);
|
||||
synchronize_cpu();
|
||||
return iram.write(addr & 2047, data);
|
||||
}
|
||||
|
||||
if((addr & 0x40f800) == 0x003000) { //$00-3f|80-bf:3000-37ff
|
||||
return memory::iram.write(addr & 2047, data);
|
||||
synchronize_cpu();
|
||||
return iram.write(addr & 2047, data);
|
||||
}
|
||||
|
||||
if((addr & 0xf00000) == 0x400000) { //$40-4f:0000-ffff
|
||||
return memory::sa1bwram.write(addr & (memory::sa1bwram.size() - 1), data);
|
||||
synchronize_cpu();
|
||||
return cartridge.ram.write(addr & (cartridge.ram.size() - 1), data);
|
||||
}
|
||||
|
||||
if((addr & 0xf00000) == 0x600000) { //$60-6f:0000-ffff
|
||||
return memory::bitmapram.write(addr & (memory::bitmapram.size() - 1), data);
|
||||
synchronize_cpu();
|
||||
return bitmap_write(addr & 0x0fffff, data);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -64,7 +72,6 @@ void SA1::bus_write(unsigned addr, uint8 data) {
|
|||
//this is used both to keep VBR-reads from accessing MMIO registers, and
|
||||
//to avoid syncing the S-CPU and SA-1*; as both chips are able to access
|
||||
//these ports.
|
||||
//(* eg, cartridge.ram is used directly, as memory::sa1bwram syncs to the S-CPU)
|
||||
uint8 SA1::vbr_read(unsigned addr) {
|
||||
if((addr & 0x408000) == 0x008000) { //$00-3f|80-bf:8000-ffff
|
||||
return mmc_read(addr);
|
||||
|
@ -83,11 +90,11 @@ uint8 SA1::vbr_read(unsigned addr) {
|
|||
}
|
||||
|
||||
if((addr & 0x40f800) == 0x000000) { //$00-3f|80-bf:0000-07ff
|
||||
return memory::iram.read(addr & 2047);
|
||||
return iram.read(addr & 2047);
|
||||
}
|
||||
|
||||
if((addr & 0x40f800) == 0x003000) { //$00-3f|80-bf:3000-37ff
|
||||
return memory::iram.read(addr & 0x2047);
|
||||
return iram.read(addr & 0x2047);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -172,26 +179,26 @@ void SA1::mmc_write(unsigned addr, uint8 data) {
|
|||
|
||||
uint8 SA1::mmc_cpu_read(unsigned addr) {
|
||||
cpu.synchronize_coprocessor();
|
||||
addr = bus.mirror(mmio.sbm * 0x2000 + (addr & 0x1fff), memory::cc1bwram.size());
|
||||
return memory::cc1bwram.read(addr);
|
||||
addr = bus.mirror(mmio.sbm * 0x2000 + (addr & 0x1fff), cpubwram.size());
|
||||
return cpubwram.read(addr);
|
||||
}
|
||||
|
||||
void SA1::mmc_cpu_write(unsigned addr, uint8 data) {
|
||||
cpu.synchronize_coprocessor();
|
||||
addr = bus.mirror(mmio.sbm * 0x2000 + (addr & 0x1fff), memory::cc1bwram.size());
|
||||
memory::cc1bwram.write(addr, data);
|
||||
addr = bus.mirror(mmio.sbm * 0x2000 + (addr & 0x1fff), cpubwram.size());
|
||||
cpubwram.write(addr, data);
|
||||
}
|
||||
|
||||
uint8 SA1::mmc_sa1_read(unsigned addr) {
|
||||
synchronize_cpu();
|
||||
if(mmio.sw46 == 0) {
|
||||
//$40-43:0000-ffff x 32 projection
|
||||
addr = bus.mirror((mmio.cbm & 0x1f) * 0x2000 + (addr & 0x1fff), memory::sa1bwram.size());
|
||||
return memory::sa1bwram.read(addr);
|
||||
addr = bus.mirror((mmio.cbm & 0x1f) * 0x2000 + (addr & 0x1fff), cartridge.ram.size());
|
||||
return cartridge.ram.read(addr);
|
||||
} else {
|
||||
//$60-6f:0000-ffff x 128 projection
|
||||
addr = bus.mirror(mmio.cbm * 0x2000 + (addr & 0x1fff), memory::bitmapram.size());
|
||||
return memory::bitmapram.read(addr);
|
||||
addr = bus.mirror(mmio.cbm * 0x2000 + (addr & 0x1fff), 0x100000);
|
||||
return bitmap_read(addr);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -199,13 +206,59 @@ void SA1::mmc_sa1_write(unsigned addr, uint8 data) {
|
|||
synchronize_cpu();
|
||||
if(mmio.sw46 == 0) {
|
||||
//$40-43:0000-ffff x 32 projection
|
||||
addr = bus.mirror((mmio.cbm & 0x1f) * 0x2000 + (addr & 0x1fff), memory::sa1bwram.size());
|
||||
memory::sa1bwram.write(addr, data);
|
||||
addr = bus.mirror((mmio.cbm & 0x1f) * 0x2000 + (addr & 0x1fff), cartridge.ram.size());
|
||||
cartridge.ram.write(addr, data);
|
||||
} else {
|
||||
//$60-6f:0000-ffff x 128 projection
|
||||
addr = bus.mirror(mmio.cbm * 0x2000 + (addr & 0x1fff), memory::bitmapram.size());
|
||||
memory::bitmapram.write(addr, data);
|
||||
addr = bus.mirror(mmio.cbm * 0x2000 + (addr & 0x1fff), 0x100000);
|
||||
bitmap_write(addr, data);
|
||||
}
|
||||
}
|
||||
|
||||
uint8 SA1::bitmap_read(unsigned addr) {
|
||||
if(mmio.bbf == 0) {
|
||||
//4bpp
|
||||
unsigned shift = addr & 1;
|
||||
addr = (addr >> 1) & (cartridge.ram.size() - 1);
|
||||
switch(shift) { default:
|
||||
case 0: return (cartridge.ram.read(addr) >> 0) & 15;
|
||||
case 1: return (cartridge.ram.read(addr) >> 4) & 15;
|
||||
}
|
||||
} else {
|
||||
//2bpp
|
||||
unsigned shift = addr & 3;
|
||||
addr = (addr >> 2) & (cartridge.ram.size() - 1);
|
||||
switch(shift) { default:
|
||||
case 0: return (cartridge.ram.read(addr) >> 0) & 3;
|
||||
case 1: return (cartridge.ram.read(addr) >> 2) & 3;
|
||||
case 2: return (cartridge.ram.read(addr) >> 4) & 3;
|
||||
case 3: return (cartridge.ram.read(addr) >> 6) & 3;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void SA1::bitmap_write(unsigned addr, uint8 data) {
|
||||
if(mmio.bbf == 0) {
|
||||
//4bpp
|
||||
unsigned shift = addr & 1;
|
||||
addr = (addr >> 1) & (cartridge.ram.size() - 1);
|
||||
switch(shift) { default:
|
||||
case 0: data = (cartridge.ram.read(addr) & 0xf0) | ((data & 15) << 0); break;
|
||||
case 1: data = (cartridge.ram.read(addr) & 0x0f) | ((data & 15) << 4); break;
|
||||
}
|
||||
} else {
|
||||
//2bpp
|
||||
unsigned shift = addr & 3;
|
||||
addr = (addr >> 2) & (cartridge.ram.size() - 1);
|
||||
switch(shift) { default:
|
||||
case 0: data = (cartridge.ram.read(addr) & 0xfc) | ((data & 3) << 0); break;
|
||||
case 1: data = (cartridge.ram.read(addr) & 0xf3) | ((data & 3) << 2); break;
|
||||
case 2: data = (cartridge.ram.read(addr) & 0xcf) | ((data & 3) << 4); break;
|
||||
case 3: data = (cartridge.ram.read(addr) & 0x3f) | ((data & 3) << 6); break;
|
||||
}
|
||||
}
|
||||
|
||||
cartridge.ram.write(addr, data);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
@ -14,3 +14,6 @@ void mmc_cpu_write(unsigned addr, uint8 data);
|
|||
|
||||
uint8 mmc_sa1_read(unsigned addr);
|
||||
void mmc_sa1_write(unsigned addr, uint8 data);
|
||||
|
||||
uint8 bitmap_read(unsigned addr);
|
||||
void bitmap_write(unsigned addr, uint8 data);
|
||||
|
|
|
@ -217,7 +217,7 @@ void SA1::mmio_w2231(uint8 data) {
|
|||
mmio.dmasize = (data >> 2) & 7;
|
||||
mmio.dmacb = (data & 0x03);
|
||||
|
||||
if(mmio.chdend) memory::cc1bwram.dma = false;
|
||||
if(mmio.chdend) cpubwram.dma = false;
|
||||
if(mmio.dmasize > 5) mmio.dmasize = 5;
|
||||
if(mmio.dmacb > 2) mmio.dmacb = 2;
|
||||
}
|
||||
|
|
|
@ -130,9 +130,9 @@ void SA1::power() {
|
|||
void SA1::reset() {
|
||||
create(SA1::Enter, system.cpu_frequency());
|
||||
|
||||
memory::cc1bwram.dma = false;
|
||||
for(unsigned addr = 0; addr < memory::iram.size(); addr++) {
|
||||
memory::iram.write(addr, 0x00);
|
||||
cpubwram.dma = false;
|
||||
for(unsigned addr = 0; addr < iram.size(); addr++) {
|
||||
iram.write(addr, 0x00);
|
||||
}
|
||||
|
||||
regs.pc.d = 0x000000;
|
||||
|
@ -321,7 +321,7 @@ void SA1::reset() {
|
|||
mmio.overflow = false;
|
||||
}
|
||||
|
||||
SA1::SA1() {
|
||||
SA1::SA1() : iram(2048) {
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
#include "bus/bus.hpp"
|
||||
|
||||
class SA1 : public Coprocessor, public CPUcore {
|
||||
public:
|
||||
#include "bus/bus.hpp"
|
||||
#include "dma/dma.hpp"
|
||||
#include "memory/memory.hpp"
|
||||
#include "mmio/mmio.hpp"
|
||||
|
|
|
@ -15,9 +15,9 @@ void SA1::serialize(serializer &s) {
|
|||
s.integer(status.hcounter);
|
||||
|
||||
//bus/bus.hpp
|
||||
s.array(memory::iram.data(), memory::iram.size());
|
||||
s.array(iram.data(), iram.size());
|
||||
|
||||
s.integer(memory::cc1bwram.dma);
|
||||
s.integer(cpubwram.dma);
|
||||
|
||||
//dma/dma.hpp
|
||||
s.integer(dma.line);
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
|
||||
class SPC7110 {
|
||||
public:
|
||||
uint8 rtc[20];
|
||||
unsigned data_rom_offset;
|
||||
|
||||
void init();
|
||||
|
@ -134,7 +135,6 @@ private:
|
|||
|
||||
enum RTC_State { RTCS_Inactive, RTCS_ModeSelect, RTCS_IndexSelect, RTCS_Write };
|
||||
enum RTC_Mode { RTCM_Linear = 0x03, RTCM_Indexed = 0x0c };
|
||||
uint8 rtc[20];
|
||||
unsigned rtc_state;
|
||||
unsigned rtc_mode;
|
||||
unsigned rtc_index;
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
class SRTC {
|
||||
public:
|
||||
uint8 rtc[20];
|
||||
|
||||
void init();
|
||||
void enable();
|
||||
void power();
|
||||
|
@ -14,7 +16,6 @@ public:
|
|||
private:
|
||||
static const unsigned months[12];
|
||||
enum RtcMode { RtcReady, RtcCommand, RtcRead, RtcWrite };
|
||||
uint8 rtc[20];
|
||||
unsigned rtc_mode;
|
||||
signed rtc_index;
|
||||
|
||||
|
|
|
@ -1,17 +1,12 @@
|
|||
#ifdef SUPERFX_CPP
|
||||
|
||||
namespace memory {
|
||||
SuperFXCPUROM fxrom;
|
||||
SuperFXCPURAM fxram;
|
||||
}
|
||||
|
||||
//ROM / RAM access from the S-CPU
|
||||
|
||||
unsigned SuperFXCPUROM::size() const {
|
||||
unsigned SuperFX::ROM::size() const {
|
||||
return cartridge.rom.size();
|
||||
}
|
||||
|
||||
uint8 SuperFXCPUROM::read(unsigned addr) {
|
||||
uint8 SuperFX::ROM::read(unsigned addr) {
|
||||
if(superfx.regs.sfr.g && superfx.regs.scmr.ron) {
|
||||
static const uint8_t data[16] = {
|
||||
0x00, 0x01, 0x00, 0x01, 0x04, 0x01, 0x00, 0x01,
|
||||
|
@ -22,20 +17,20 @@ uint8 SuperFXCPUROM::read(unsigned addr) {
|
|||
return cartridge.rom.read(addr);
|
||||
}
|
||||
|
||||
void SuperFXCPUROM::write(unsigned addr, uint8 data) {
|
||||
void SuperFX::ROM::write(unsigned addr, uint8 data) {
|
||||
cartridge.rom.write(addr, data);
|
||||
}
|
||||
|
||||
unsigned SuperFXCPURAM::size() const {
|
||||
unsigned SuperFX::RAM::size() const {
|
||||
return cartridge.ram.size();
|
||||
}
|
||||
|
||||
uint8 SuperFXCPURAM::read(unsigned addr) {
|
||||
uint8 SuperFX::RAM::read(unsigned addr) {
|
||||
if(superfx.regs.sfr.g && superfx.regs.scmr.ran) return cpu.regs.mdr;
|
||||
return cartridge.ram.read(addr);
|
||||
}
|
||||
|
||||
void SuperFXCPURAM::write(unsigned addr, uint8 data) {
|
||||
void SuperFX::RAM::write(unsigned addr, uint8 data) {
|
||||
cartridge.ram.write(addr, data);
|
||||
}
|
||||
|
||||
|
|
|
@ -1,16 +1,11 @@
|
|||
struct SuperFXCPUROM : Memory {
|
||||
struct ROM : Memory {
|
||||
unsigned size() const;
|
||||
uint8 read(unsigned);
|
||||
void write(unsigned, uint8);
|
||||
};
|
||||
} rom;
|
||||
|
||||
struct SuperFXCPURAM : Memory {
|
||||
struct RAM : Memory {
|
||||
unsigned size() const;
|
||||
uint8 read(unsigned);
|
||||
void write(unsigned, uint8);
|
||||
};
|
||||
|
||||
namespace memory {
|
||||
extern SuperFXCPUROM fxrom;
|
||||
extern SuperFXCPURAM fxram;
|
||||
}
|
||||
} ram;
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
#include "bus/bus.hpp"
|
||||
|
||||
class SuperFX : public Coprocessor {
|
||||
public:
|
||||
#include "bus/bus.hpp"
|
||||
#include "core/core.hpp"
|
||||
#include "memory/memory.hpp"
|
||||
#include "mmio/mmio.hpp"
|
||||
|
|
|
@ -99,37 +99,32 @@ void CPU::op_irq() {
|
|||
}
|
||||
|
||||
void CPU::enable() {
|
||||
bus.map(Bus::MapMode::Direct, 0x00, 0x3f, 0x2140, 0x2183, { &CPU::mmio_read, &cpu }, { &CPU::mmio_write, &cpu });
|
||||
bus.map(Bus::MapMode::Direct, 0x80, 0xbf, 0x2140, 0x2183, { &CPU::mmio_read, &cpu }, { &CPU::mmio_write, &cpu });
|
||||
function<uint8 (unsigned)> read = { &CPU::mmio_read, (CPU*)&cpu };
|
||||
function<void (unsigned, uint8)> write = { &CPU::mmio_write, (CPU*)&cpu };
|
||||
|
||||
bus.map(Bus::MapMode::Direct, 0x00, 0x3f, 0x4016, 0x4017, { &CPU::mmio_read, &cpu }, { &CPU::mmio_write, &cpu });
|
||||
bus.map(Bus::MapMode::Direct, 0x80, 0xbf, 0x4016, 0x4017, { &CPU::mmio_read, &cpu }, { &CPU::mmio_write, &cpu });
|
||||
bus.map(Bus::MapMode::Direct, 0x00, 0x3f, 0x2140, 0x2183, read, write);
|
||||
bus.map(Bus::MapMode::Direct, 0x80, 0xbf, 0x2140, 0x2183, read, write);
|
||||
|
||||
bus.map(Bus::MapMode::Direct, 0x00, 0x3f, 0x4200, 0x421f, { &CPU::mmio_read, &cpu }, { &CPU::mmio_write, &cpu });
|
||||
bus.map(Bus::MapMode::Direct, 0x80, 0xbf, 0x4200, 0x421f, { &CPU::mmio_read, &cpu }, { &CPU::mmio_write, &cpu });
|
||||
bus.map(Bus::MapMode::Direct, 0x00, 0x3f, 0x4016, 0x4017, read, write);
|
||||
bus.map(Bus::MapMode::Direct, 0x80, 0xbf, 0x4016, 0x4017, read, write);
|
||||
|
||||
bus.map(Bus::MapMode::Direct, 0x00, 0x3f, 0x4300, 0x437f, { &CPU::mmio_read, &cpu }, { &CPU::mmio_write, &cpu });
|
||||
bus.map(Bus::MapMode::Direct, 0x80, 0xbf, 0x4300, 0x437f, { &CPU::mmio_read, &cpu }, { &CPU::mmio_write, &cpu });
|
||||
bus.map(Bus::MapMode::Direct, 0x00, 0x3f, 0x4200, 0x421f, read, write);
|
||||
bus.map(Bus::MapMode::Direct, 0x80, 0xbf, 0x4200, 0x421f, read, write);
|
||||
|
||||
bus.map(
|
||||
Bus::MapMode::Linear, 0x00, 0x3f, 0x0000, 0x1fff,
|
||||
{ &StaticRAM::read, &memory::wram }, { &StaticRAM::write, &memory::wram },
|
||||
0x000000, 0x002000
|
||||
);
|
||||
bus.map(
|
||||
Bus::MapMode::Linear, 0x80, 0xbf, 0x0000, 0x1fff,
|
||||
{ &StaticRAM::read, &memory::wram }, { &StaticRAM::write, &memory::wram },
|
||||
0x000000, 0x002000
|
||||
);
|
||||
bus.map(
|
||||
Bus::MapMode::Linear, 0x7e, 0x7f, 0x0000, 0xffff,
|
||||
{ &StaticRAM::read, &memory::wram }, { &StaticRAM::write, &memory::wram }
|
||||
);
|
||||
bus.map(Bus::MapMode::Direct, 0x00, 0x3f, 0x4300, 0x437f, read, write);
|
||||
bus.map(Bus::MapMode::Direct, 0x80, 0xbf, 0x4300, 0x437f, read, write);
|
||||
|
||||
read = [](unsigned addr) { return cpu.wram[addr]; };
|
||||
write = [](unsigned addr, uint8 data) { cpu.wram[addr] = data; };
|
||||
|
||||
bus.map(Bus::MapMode::Linear, 0x00, 0x3f, 0x0000, 0x1fff, read, write, 0x000000, 0x002000);
|
||||
bus.map(Bus::MapMode::Linear, 0x80, 0xbf, 0x0000, 0x1fff, read, write, 0x000000, 0x002000);
|
||||
bus.map(Bus::MapMode::Linear, 0x7e, 0x7f, 0x0000, 0xffff, read, write);
|
||||
}
|
||||
|
||||
void CPU::power() {
|
||||
cpu_version = config.cpu.version;
|
||||
foreach(n, memory::wram) n = config.cpu.wram_init_value;
|
||||
foreach(n, wram) n = config.cpu.wram_init_value;
|
||||
|
||||
regs.a = regs.x = regs.y = 0x0000;
|
||||
regs.s = 0x01ff;
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
class CPU : public Processor, public CPUcore, public PPUcounter {
|
||||
public:
|
||||
uint8 wram[128 * 1024];
|
||||
|
||||
enum : bool { Threaded = true };
|
||||
array<Processor*> coprocessors;
|
||||
alwaysinline void step(unsigned clocks);
|
||||
|
|
|
@ -4,6 +4,9 @@ void CPU::serialize(serializer &s) {
|
|||
Processor::serialize(s);
|
||||
CPUcore::core_serialize(s);
|
||||
PPUcounter::serialize(s);
|
||||
|
||||
s.array(wram);
|
||||
|
||||
s.integer(cpu_version);
|
||||
|
||||
s.integer(status.interrupt_pending);
|
||||
|
|
|
@ -38,24 +38,24 @@ uint8 Debugger::read(Debugger::MemorySource source, unsigned addr) {
|
|||
|
||||
case MemorySource::APUBus: {
|
||||
if((addr & 0xffc0) == 0xffc0) return smp.iplrom[addr & 0x3f];
|
||||
return memory::apuram.read(addr & 0xffff);
|
||||
return smp.apuram[addr & 0xffff];
|
||||
} break;
|
||||
|
||||
case MemorySource::APURAM: {
|
||||
return memory::apuram.read(addr & 0xffff);
|
||||
return smp.apuram[addr & 0xffff];
|
||||
} break;
|
||||
|
||||
case MemorySource::VRAM: {
|
||||
return memory::vram.read(addr & 0xffff);
|
||||
return ppu.vram[addr & 0xffff];
|
||||
} break;
|
||||
|
||||
case MemorySource::OAM: {
|
||||
if(addr & 0x0200) return memory::oam.read(0x0200 + (addr & 0x1f));
|
||||
return memory::oam.read(addr & 0x01ff);
|
||||
if(addr & 0x0200) return ppu.oam[0x0200 + (addr & 0x1f)];
|
||||
return ppu.oam[addr & 0x01ff];
|
||||
} break;
|
||||
|
||||
case MemorySource::CGRAM: {
|
||||
return memory::cgram.read(addr & 0x01ff);
|
||||
return ppu.cgram[addr & 0x01ff];
|
||||
} break;
|
||||
}
|
||||
|
||||
|
@ -73,20 +73,20 @@ void Debugger::write(Debugger::MemorySource source, unsigned addr, uint8 data) {
|
|||
} break;
|
||||
|
||||
case MemorySource::APURAM: {
|
||||
memory::apuram.write(addr & 0xffff, data);
|
||||
smp.apuram[addr & 0xffff] = data;
|
||||
} break;
|
||||
|
||||
case MemorySource::VRAM: {
|
||||
memory::vram.write(addr & 0xffff, data);
|
||||
ppu.vram[addr & 0xffff] = data;
|
||||
} break;
|
||||
|
||||
case MemorySource::OAM: {
|
||||
if(addr & 0x0200) memory::oam.write(0x0200 + (addr & 0x1f), data);
|
||||
else memory::oam.write(addr & 0x01ff, data);
|
||||
if(addr & 0x0200) ppu.oam[0x0200 + (addr & 0x1f)] = data;
|
||||
else ppu.oam[addr & 0x01ff] = data;
|
||||
} break;
|
||||
|
||||
case MemorySource::CGRAM: {
|
||||
memory::cgram.write(addr & 0x01ff, data);
|
||||
ppu.cgram[addr & 0x01ff] = data;
|
||||
} break;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
void DSP::brr_decode(voice_t &v) {
|
||||
//state.t_brr_byte = ram[v.brr_addr + v.brr_offset] cached from previous clock cycle
|
||||
int nybbles = (state.t_brr_byte << 8) + memory::apuram[(uint16)(v.brr_addr + v.brr_offset + 1)];
|
||||
int nybbles = (state.t_brr_byte << 8) + smp.apuram[(uint16)(v.brr_addr + v.brr_offset + 1)];
|
||||
|
||||
const int filter = (state.t_brr_header >> 2) & 3;
|
||||
const int scale = (state.t_brr_header >> 4);
|
||||
|
|
|
@ -13,8 +13,8 @@ int DSP::echo_output(bool channel) {
|
|||
|
||||
void DSP::echo_read(bool channel) {
|
||||
unsigned addr = state.t_echo_ptr + channel * 2;
|
||||
uint8 lo = memory::apuram[(uint16)(addr + 0)];
|
||||
uint8 hi = memory::apuram[(uint16)(addr + 1)];
|
||||
uint8 lo = smp.apuram[(uint16)(addr + 0)];
|
||||
uint8 hi = smp.apuram[(uint16)(addr + 1)];
|
||||
int s = (int16)((hi << 8) + lo);
|
||||
state.echo_hist[channel].write(state.echo_hist_pos, s >> 1);
|
||||
}
|
||||
|
@ -23,8 +23,8 @@ void DSP::echo_write(bool channel) {
|
|||
if(!(state.t_echo_disabled & 0x20)) {
|
||||
unsigned addr = state.t_echo_ptr + channel * 2;
|
||||
int s = state.t_echo_out[channel];
|
||||
memory::apuram[(uint16)(addr + 0)] = s;
|
||||
memory::apuram[(uint16)(addr + 1)] = s >> 8;
|
||||
smp.apuram[(uint16)(addr + 0)] = s;
|
||||
smp.apuram[(uint16)(addr + 1)] = s >> 8;
|
||||
}
|
||||
|
||||
state.t_echo_out[channel] = 0;
|
||||
|
|
|
@ -24,8 +24,8 @@ void DSP::voice_2(voice_t &v) {
|
|||
//read sample pointer (ignored if not needed)
|
||||
uint16 addr = state.t_dir_addr;
|
||||
if(!v.kon_delay) addr += 2;
|
||||
uint8 lo = memory::apuram[(uint16)(addr + 0)];
|
||||
uint8 hi = memory::apuram[(uint16)(addr + 1)];
|
||||
uint8 lo = smp.apuram[(uint16)(addr + 0)];
|
||||
uint8 hi = smp.apuram[(uint16)(addr + 1)];
|
||||
state.t_brr_next_addr = ((hi << 8) + lo);
|
||||
|
||||
state.t_adsr0 = VREG(adsr0);
|
||||
|
@ -45,8 +45,8 @@ void DSP::voice_3a(voice_t &v) {
|
|||
}
|
||||
|
||||
void DSP::voice_3b(voice_t &v) {
|
||||
state.t_brr_byte = memory::apuram[(uint16)(v.brr_addr + v.brr_offset)];
|
||||
state.t_brr_header = memory::apuram[(uint16)(v.brr_addr)];
|
||||
state.t_brr_byte = smp.apuram[(uint16)(v.brr_addr + v.brr_offset)];
|
||||
state.t_brr_header = smp.apuram[(uint16)(v.brr_addr)];
|
||||
}
|
||||
|
||||
void DSP::voice_3c(voice_t &v) {
|
||||
|
|
|
@ -120,7 +120,7 @@ bool snes_load_cartridge_normal(
|
|||
const char *rom_xml, const uint8_t *rom_data, unsigned rom_size
|
||||
) {
|
||||
snes_cheat_reset();
|
||||
if(rom_data) SNES::memory::cartrom.copy(rom_data, rom_size);
|
||||
if(rom_data) SNES::cartridge.rom.copy(rom_data, rom_size);
|
||||
string xmlrom = (rom_xml && *rom_xml) ? string(rom_xml) : SNESCartridge(rom_data, rom_size).xmlMemoryMap;
|
||||
SNES::cartridge.load(SNES::Cartridge::Mode::Normal, { xmlrom });
|
||||
SNES::system.power();
|
||||
|
@ -132,9 +132,9 @@ bool snes_load_cartridge_bsx_slotted(
|
|||
const char *bsx_xml, const uint8_t *bsx_data, unsigned bsx_size
|
||||
) {
|
||||
snes_cheat_reset();
|
||||
if(rom_data) SNES::memory::cartrom.copy(rom_data, rom_size);
|
||||
if(rom_data) SNES::cartridge.rom.copy(rom_data, rom_size);
|
||||
string xmlrom = (rom_xml && *rom_xml) ? string(rom_xml) : SNESCartridge(rom_data, rom_size).xmlMemoryMap;
|
||||
if(bsx_data) SNES::memory::bsxflash.copy(bsx_data, bsx_size);
|
||||
if(bsx_data) SNES::bsxflash.memory.copy(bsx_data, bsx_size);
|
||||
string xmlbsx = (bsx_xml && *bsx_xml) ? string(bsx_xml) : SNESCartridge(bsx_data, bsx_size).xmlMemoryMap;
|
||||
SNES::cartridge.load(SNES::Cartridge::Mode::BsxSlotted, { xmlrom, xmlbsx });
|
||||
SNES::system.power();
|
||||
|
@ -146,9 +146,9 @@ bool snes_load_cartridge_bsx(
|
|||
const char *bsx_xml, const uint8_t *bsx_data, unsigned bsx_size
|
||||
) {
|
||||
snes_cheat_reset();
|
||||
if(rom_data) SNES::memory::cartrom.copy(rom_data, rom_size);
|
||||
if(rom_data) SNES::cartridge.rom.copy(rom_data, rom_size);
|
||||
string xmlrom = (rom_xml && *rom_xml) ? string(rom_xml) : SNESCartridge(rom_data, rom_size).xmlMemoryMap;
|
||||
if(bsx_data) SNES::memory::bsxflash.copy(bsx_data, bsx_size);
|
||||
if(bsx_data) SNES::bsxflash.memory.copy(bsx_data, bsx_size);
|
||||
string xmlbsx = (bsx_xml && *bsx_xml) ? string(bsx_xml) : SNESCartridge(bsx_data, bsx_size).xmlMemoryMap;
|
||||
SNES::cartridge.load(SNES::Cartridge::Mode::Bsx, { xmlrom, xmlbsx });
|
||||
SNES::system.power();
|
||||
|
@ -161,11 +161,11 @@ bool snes_load_cartridge_sufami_turbo(
|
|||
const char *stb_xml, const uint8_t *stb_data, unsigned stb_size
|
||||
) {
|
||||
snes_cheat_reset();
|
||||
if(rom_data) SNES::memory::cartrom.copy(rom_data, rom_size);
|
||||
if(rom_data) SNES::cartridge.rom.copy(rom_data, rom_size);
|
||||
string xmlrom = (rom_xml && *rom_xml) ? string(rom_xml) : SNESCartridge(rom_data, rom_size).xmlMemoryMap;
|
||||
if(sta_data) SNES::memory::stArom.copy(sta_data, sta_size);
|
||||
if(sta_data) SNES::sufamiturbo.slotA.rom.copy(sta_data, sta_size);
|
||||
string xmlsta = (sta_xml && *sta_xml) ? string(sta_xml) : SNESCartridge(sta_data, sta_size).xmlMemoryMap;
|
||||
if(stb_data) SNES::memory::stBrom.copy(stb_data, stb_size);
|
||||
if(stb_data) SNES::sufamiturbo.slotB.rom.copy(stb_data, stb_size);
|
||||
string xmlstb = (stb_xml && *stb_xml) ? string(stb_xml) : SNESCartridge(stb_data, stb_size).xmlMemoryMap;
|
||||
SNES::cartridge.load(SNES::Cartridge::Mode::SufamiTurbo, { xmlrom, xmlsta, xmlstb });
|
||||
SNES::system.power();
|
||||
|
@ -177,7 +177,7 @@ bool snes_load_cartridge_super_game_boy(
|
|||
const char *dmg_xml, const uint8_t *dmg_data, unsigned dmg_size
|
||||
) {
|
||||
snes_cheat_reset();
|
||||
if(rom_data) SNES::memory::cartrom.copy(rom_data, rom_size);
|
||||
if(rom_data) SNES::cartridge.rom.copy(rom_data, rom_size);
|
||||
string xmlrom = (rom_xml && *rom_xml) ? string(rom_xml) : SNESCartridge(rom_data, rom_size).xmlMemoryMap;
|
||||
if(dmg_data) {
|
||||
string xmldmg = (dmg_xml && *dmg_xml) ? string(dmg_xml) : GameBoyCartridge(dmg_data, dmg_size).xml;
|
||||
|
@ -201,21 +201,23 @@ uint8_t* snes_get_memory_data(unsigned id) {
|
|||
|
||||
switch(id) {
|
||||
case SNES_MEMORY_CARTRIDGE_RAM:
|
||||
return SNES::memory::cartram.data();
|
||||
return SNES::cartridge.ram.data();
|
||||
case SNES_MEMORY_CARTRIDGE_RTC:
|
||||
return SNES::memory::cartrtc.data();
|
||||
if(SNES::cartridge.has_srtc()) return SNES::srtc.rtc;
|
||||
if(SNES::cartridge.has_spc7110rtc()) return SNES::spc7110.rtc;
|
||||
return 0;
|
||||
case SNES_MEMORY_BSX_RAM:
|
||||
if(SNES::cartridge.mode() != SNES::Cartridge::Mode::Bsx) break;
|
||||
return SNES::memory::bsxram.data();
|
||||
return SNES::bsxcartridge.sram.data();
|
||||
case SNES_MEMORY_BSX_PRAM:
|
||||
if(SNES::cartridge.mode() != SNES::Cartridge::Mode::Bsx) break;
|
||||
return SNES::memory::bsxpram.data();
|
||||
return SNES::bsxcartridge.psram.data();
|
||||
case SNES_MEMORY_SUFAMI_TURBO_A_RAM:
|
||||
if(SNES::cartridge.mode() != SNES::Cartridge::Mode::SufamiTurbo) break;
|
||||
return SNES::memory::stAram.data();
|
||||
return SNES::sufamiturbo.slotA.ram.data();
|
||||
case SNES_MEMORY_SUFAMI_TURBO_B_RAM:
|
||||
if(SNES::cartridge.mode() != SNES::Cartridge::Mode::SufamiTurbo) break;
|
||||
return SNES::memory::stBram.data();
|
||||
return SNES::sufamiturbo.slotB.ram.data();
|
||||
case SNES_MEMORY_GAME_BOY_RAM:
|
||||
if(SNES::cartridge.mode() != SNES::Cartridge::Mode::SuperGameBoy) break;
|
||||
return GameBoy::cartridge.ramdata;
|
||||
|
@ -224,15 +226,15 @@ uint8_t* snes_get_memory_data(unsigned id) {
|
|||
// return GameBoy::cartridge.rtcdata;
|
||||
|
||||
case SNES_MEMORY_WRAM:
|
||||
return SNES::memory::wram.data();
|
||||
return SNES::cpu.wram;
|
||||
case SNES_MEMORY_APURAM:
|
||||
return SNES::memory::apuram.data();
|
||||
return SNES::smp.apuram;
|
||||
case SNES_MEMORY_VRAM:
|
||||
return SNES::memory::vram.data();
|
||||
return SNES::ppu.vram;
|
||||
case SNES_MEMORY_OAM:
|
||||
return SNES::memory::oam.data();
|
||||
return SNES::ppu.oam;
|
||||
case SNES_MEMORY_CGRAM:
|
||||
return SNES::memory::cgram.data();
|
||||
return SNES::ppu.cgram;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
@ -244,26 +246,26 @@ unsigned snes_get_memory_size(unsigned id) {
|
|||
|
||||
switch(id) {
|
||||
case SNES_MEMORY_CARTRIDGE_RAM:
|
||||
size = SNES::memory::cartram.size();
|
||||
size = SNES::cartridge.ram.size();
|
||||
break;
|
||||
case SNES_MEMORY_CARTRIDGE_RTC:
|
||||
size = SNES::memory::cartrtc.size();
|
||||
if(SNES::cartridge.has_srtc() || SNES::cartridge.has_spc7110rtc()) size = 20;
|
||||
break;
|
||||
case SNES_MEMORY_BSX_RAM:
|
||||
if(SNES::cartridge.mode() != SNES::Cartridge::Mode::Bsx) break;
|
||||
size = SNES::memory::bsxram.size();
|
||||
size = SNES::bsxcartridge.sram.size();
|
||||
break;
|
||||
case SNES_MEMORY_BSX_PRAM:
|
||||
if(SNES::cartridge.mode() != SNES::Cartridge::Mode::Bsx) break;
|
||||
size = SNES::memory::bsxpram.size();
|
||||
size = SNES::bsxcartridge.psram.size();
|
||||
break;
|
||||
case SNES_MEMORY_SUFAMI_TURBO_A_RAM:
|
||||
if(SNES::cartridge.mode() != SNES::Cartridge::Mode::SufamiTurbo) break;
|
||||
size = SNES::memory::stAram.size();
|
||||
size = SNES::sufamiturbo.slotA.ram.size();
|
||||
break;
|
||||
case SNES_MEMORY_SUFAMI_TURBO_B_RAM:
|
||||
if(SNES::cartridge.mode() != SNES::Cartridge::Mode::SufamiTurbo) break;
|
||||
size = SNES::memory::stBram.size();
|
||||
size = SNES::sufamiturbo.slotB.ram.size();
|
||||
break;
|
||||
case SNES_MEMORY_GAME_BOY_RAM:
|
||||
if(SNES::cartridge.mode() != SNES::Cartridge::Mode::SuperGameBoy) break;
|
||||
|
@ -275,19 +277,19 @@ unsigned snes_get_memory_size(unsigned id) {
|
|||
// break;
|
||||
|
||||
case SNES_MEMORY_WRAM:
|
||||
size = SNES::memory::wram.size();
|
||||
size = 128 * 1024;
|
||||
break;
|
||||
case SNES_MEMORY_APURAM:
|
||||
size = SNES::memory::apuram.size();
|
||||
size = 64 * 1024;
|
||||
break;
|
||||
case SNES_MEMORY_VRAM:
|
||||
size = SNES::memory::vram.size();
|
||||
size = 64 * 1024;
|
||||
break;
|
||||
case SNES_MEMORY_OAM:
|
||||
size = SNES::memory::oam.size();
|
||||
size = 544;
|
||||
break;
|
||||
case SNES_MEMORY_CGRAM:
|
||||
size = SNES::memory::cgram.size();
|
||||
size = 512;
|
||||
break;
|
||||
}
|
||||
|
||||
|
|
|
@ -5,16 +5,6 @@ namespace SNES {
|
|||
|
||||
Bus bus;
|
||||
|
||||
#include "serialization.cpp"
|
||||
|
||||
namespace memory {
|
||||
StaticRAM wram(128 * 1024);
|
||||
StaticRAM apuram(64 * 1024);
|
||||
StaticRAM vram(64 * 1024);
|
||||
StaticRAM oam(544);
|
||||
StaticRAM cgram(512);
|
||||
};
|
||||
|
||||
unsigned Bus::mirror(unsigned addr, unsigned size) {
|
||||
unsigned base = 0;
|
||||
if(size) {
|
||||
|
|
|
@ -67,17 +67,8 @@ struct Bus {
|
|||
void map_reset();
|
||||
void map_xml();
|
||||
|
||||
void serialize(serializer&);
|
||||
Bus();
|
||||
~Bus();
|
||||
};
|
||||
|
||||
namespace memory {
|
||||
extern StaticRAM wram; //S-CPU
|
||||
extern StaticRAM apuram; //S-SMP, S-DSP
|
||||
extern StaticRAM vram; //S-PPU
|
||||
extern StaticRAM oam; //S-PPU
|
||||
extern StaticRAM cgram; //S-PPU
|
||||
};
|
||||
|
||||
extern Bus bus;
|
||||
|
|
|
@ -1,11 +0,0 @@
|
|||
#ifdef MEMORY_CPP
|
||||
|
||||
void Bus::serialize(serializer &s) {
|
||||
s.array(memory::wram.data(), memory::wram.size());
|
||||
s.array(memory::apuram.data(), memory::apuram.size());
|
||||
s.array(memory::vram.data(), memory::vram.size());
|
||||
s.array(memory::oam.data(), memory::oam.size());
|
||||
s.array(memory::cgram.data(), memory::cgram.size());
|
||||
}
|
||||
|
||||
#endif
|
|
@ -96,7 +96,7 @@ void PPU::Background::get_tile() {
|
|||
if(ty & 0x20) offset += screen_y;
|
||||
|
||||
uint16 addr = regs.screen_addr + (offset << 1);
|
||||
tile = (memory::vram[addr + 0] << 0) + (memory::vram[addr + 1] << 8);
|
||||
tile = (ppu.vram[addr + 0] << 0) + (ppu.vram[addr + 1] << 8);
|
||||
bool mirror_y = tile & 0x8000;
|
||||
bool mirror_x = tile & 0x4000;
|
||||
priority = (tile & 0x2000 ? regs.priority1 : regs.priority0);
|
||||
|
@ -111,18 +111,18 @@ void PPU::Background::get_tile() {
|
|||
offset = (character << (4 + color_depth)) + ((voffset & 7) << 1);
|
||||
|
||||
if(regs.mode >= Mode::BPP2) {
|
||||
data[0] = memory::vram[offset + 0];
|
||||
data[1] = memory::vram[offset + 1];
|
||||
data[0] = ppu.vram[offset + 0];
|
||||
data[1] = ppu.vram[offset + 1];
|
||||
}
|
||||
if(regs.mode >= Mode::BPP4) {
|
||||
data[2] = memory::vram[offset + 16];
|
||||
data[3] = memory::vram[offset + 17];
|
||||
data[2] = ppu.vram[offset + 16];
|
||||
data[3] = ppu.vram[offset + 17];
|
||||
}
|
||||
if(regs.mode >= Mode::BPP8) {
|
||||
data[4] = memory::vram[offset + 32];
|
||||
data[5] = memory::vram[offset + 33];
|
||||
data[6] = memory::vram[offset + 48];
|
||||
data[7] = memory::vram[offset + 49];
|
||||
data[4] = ppu.vram[offset + 32];
|
||||
data[5] = ppu.vram[offset + 33];
|
||||
data[6] = ppu.vram[offset + 48];
|
||||
data[7] = ppu.vram[offset + 49];
|
||||
}
|
||||
|
||||
if(mirror_x) for(unsigned n = 0; n < 8; n++) {
|
||||
|
@ -273,7 +273,7 @@ unsigned PPU::Background::get_tile(unsigned x, unsigned y) {
|
|||
if(y & 0x20) offset += screen_y;
|
||||
|
||||
uint16 addr = regs.screen_addr + (offset << 1);
|
||||
return (memory::vram[addr + 0] << 0) + (memory::vram[addr + 1] << 8);
|
||||
return (ppu.vram[addr + 0] << 0) + (ppu.vram[addr + 1] << 8);
|
||||
}
|
||||
|
||||
PPU::Background::Background(PPU &self, unsigned id) : self(self), id(id) {
|
||||
|
|
|
@ -46,8 +46,8 @@ void PPU::Background::run_mode7() {
|
|||
case 1: {
|
||||
px &= 1023;
|
||||
py &= 1023;
|
||||
tile = memory::vram[((py >> 3) * 128 + (px >> 3)) << 1];
|
||||
palette = memory::vram[(((tile << 6) + ((py & 7) << 3) + (px & 7)) << 1) + 1];
|
||||
tile = ppu.vram[((py >> 3) * 128 + (px >> 3)) << 1];
|
||||
palette = ppu.vram[(((tile << 6) + ((py & 7) << 3) + (px & 7)) << 1) + 1];
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -58,8 +58,8 @@ void PPU::Background::run_mode7() {
|
|||
} else {
|
||||
px &= 1023;
|
||||
py &= 1023;
|
||||
tile = memory::vram[((py >> 3) * 128 + (px >> 3)) << 1];
|
||||
palette = memory::vram[(((tile << 6) + ((py & 7) << 3) + (px & 7)) << 1) + 1];
|
||||
tile = ppu.vram[((py >> 3) * 128 + (px >> 3)) << 1];
|
||||
palette = ppu.vram[(((tile << 6) + ((py & 7) << 3) + (px & 7)) << 1) + 1];
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
@ -71,9 +71,9 @@ void PPU::Background::run_mode7() {
|
|||
} else {
|
||||
px &= 1023;
|
||||
py &= 1023;
|
||||
tile = memory::vram[((py >> 3) * 128 + (px >> 3)) << 1];
|
||||
tile = ppu.vram[((py >> 3) * 128 + (px >> 3)) << 1];
|
||||
}
|
||||
palette = memory::vram[(((tile << 6) + ((py & 7) << 3) + (px & 7)) << 1) + 1];
|
||||
palette = ppu.vram[(((tile << 6) + ((py & 7) << 3) + (px & 7)) << 1) + 1];
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -32,14 +32,14 @@ uint16 PPU::get_vram_address() {
|
|||
|
||||
uint8 PPU::vram_read(unsigned addr) {
|
||||
if(regs.display_disable || vcounter() >= (!regs.overscan ? 225 : 240)) {
|
||||
return memory::vram[addr];
|
||||
return vram[addr];
|
||||
}
|
||||
return 0x00;
|
||||
}
|
||||
|
||||
void PPU::vram_write(unsigned addr, uint8 data) {
|
||||
if(regs.display_disable || vcounter() >= (!regs.overscan ? 225 : 240)) {
|
||||
memory::vram[addr] = data;
|
||||
vram[addr] = data;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -50,7 +50,7 @@ void PPU::mmio_update_video_mode() {
|
|||
bg2.regs.mode = Background::Mode::BPP2; bg2.regs.priority0 = 7; bg2.regs.priority1 = 10;
|
||||
bg3.regs.mode = Background::Mode::BPP2; bg3.regs.priority0 = 2; bg3.regs.priority1 = 5;
|
||||
bg4.regs.mode = Background::Mode::BPP2; bg4.regs.priority0 = 1; bg4.regs.priority1 = 4;
|
||||
oam.regs.priority0 = 3; oam.regs.priority1 = 6; oam.regs.priority2 = 9; oam.regs.priority3 = 12;
|
||||
sprite.regs.priority0 = 3; sprite.regs.priority1 = 6; sprite.regs.priority2 = 9; sprite.regs.priority3 = 12;
|
||||
} break;
|
||||
|
||||
case 1: {
|
||||
|
@ -62,12 +62,12 @@ void PPU::mmio_update_video_mode() {
|
|||
bg1.regs.priority0 = 5; bg1.regs.priority1 = 8;
|
||||
bg2.regs.priority0 = 4; bg2.regs.priority1 = 7;
|
||||
bg3.regs.priority0 = 1; bg3.regs.priority1 = 10;
|
||||
oam.regs.priority0 = 2; oam.regs.priority1 = 3; oam.regs.priority2 = 6; oam.regs.priority3 = 9;
|
||||
sprite.regs.priority0 = 2; sprite.regs.priority1 = 3; sprite.regs.priority2 = 6; sprite.regs.priority3 = 9;
|
||||
} else {
|
||||
bg1.regs.priority0 = 6; bg1.regs.priority1 = 9;
|
||||
bg2.regs.priority0 = 5; bg2.regs.priority1 = 8;
|
||||
bg3.regs.priority0 = 1; bg3.regs.priority1 = 3;
|
||||
oam.regs.priority0 = 2; oam.regs.priority1 = 4; oam.regs.priority2 = 7; oam.regs.priority3 = 10;
|
||||
sprite.regs.priority0 = 2; sprite.regs.priority1 = 4; sprite.regs.priority2 = 7; sprite.regs.priority3 = 10;
|
||||
}
|
||||
} break;
|
||||
|
||||
|
@ -78,7 +78,7 @@ void PPU::mmio_update_video_mode() {
|
|||
bg4.regs.mode = Background::Mode::Inactive;
|
||||
bg1.regs.priority0 = 3; bg1.regs.priority1 = 7;
|
||||
bg2.regs.priority0 = 1; bg2.regs.priority1 = 5;
|
||||
oam.regs.priority0 = 2; oam.regs.priority1 = 4; oam.regs.priority2 = 6; oam.regs.priority3 = 8;
|
||||
sprite.regs.priority0 = 2; sprite.regs.priority1 = 4; sprite.regs.priority2 = 6; sprite.regs.priority3 = 8;
|
||||
} break;
|
||||
|
||||
case 3: {
|
||||
|
@ -88,7 +88,7 @@ void PPU::mmio_update_video_mode() {
|
|||
bg4.regs.mode = Background::Mode::Inactive;
|
||||
bg1.regs.priority0 = 3; bg1.regs.priority1 = 7;
|
||||
bg2.regs.priority0 = 1; bg2.regs.priority1 = 5;
|
||||
oam.regs.priority0 = 2; oam.regs.priority1 = 4; oam.regs.priority2 = 6; oam.regs.priority3 = 8;
|
||||
sprite.regs.priority0 = 2; sprite.regs.priority1 = 4; sprite.regs.priority2 = 6; sprite.regs.priority3 = 8;
|
||||
} break;
|
||||
|
||||
case 4: {
|
||||
|
@ -98,7 +98,7 @@ void PPU::mmio_update_video_mode() {
|
|||
bg4.regs.mode = Background::Mode::Inactive;
|
||||
bg1.regs.priority0 = 3; bg1.regs.priority1 = 7;
|
||||
bg2.regs.priority0 = 1; bg2.regs.priority1 = 5;
|
||||
oam.regs.priority0 = 2; oam.regs.priority1 = 4; oam.regs.priority2 = 6; oam.regs.priority3 = 8;
|
||||
sprite.regs.priority0 = 2; sprite.regs.priority1 = 4; sprite.regs.priority2 = 6; sprite.regs.priority3 = 8;
|
||||
} break;
|
||||
|
||||
case 5: {
|
||||
|
@ -108,7 +108,7 @@ void PPU::mmio_update_video_mode() {
|
|||
bg4.regs.mode = Background::Mode::Inactive;
|
||||
bg1.regs.priority0 = 3; bg1.regs.priority1 = 7;
|
||||
bg2.regs.priority0 = 1; bg2.regs.priority1 = 5;
|
||||
oam.regs.priority0 = 2; oam.regs.priority1 = 4; oam.regs.priority2 = 6; oam.regs.priority3 = 8;
|
||||
sprite.regs.priority0 = 2; sprite.regs.priority1 = 4; sprite.regs.priority2 = 6; sprite.regs.priority3 = 8;
|
||||
} break;
|
||||
|
||||
case 6: {
|
||||
|
@ -117,7 +117,7 @@ void PPU::mmio_update_video_mode() {
|
|||
bg3.regs.mode = Background::Mode::Inactive;
|
||||
bg4.regs.mode = Background::Mode::Inactive;
|
||||
bg1.regs.priority0 = 2; bg1.regs.priority1 = 5;
|
||||
oam.regs.priority0 = 1; oam.regs.priority1 = 3; oam.regs.priority2 = 4; oam.regs.priority3 = 6;
|
||||
sprite.regs.priority0 = 1; sprite.regs.priority1 = 3; sprite.regs.priority2 = 4; sprite.regs.priority3 = 6;
|
||||
} break;
|
||||
|
||||
case 7: {
|
||||
|
@ -127,7 +127,7 @@ void PPU::mmio_update_video_mode() {
|
|||
bg3.regs.mode = Background::Mode::Inactive;
|
||||
bg4.regs.mode = Background::Mode::Inactive;
|
||||
bg1.regs.priority0 = 2; bg1.regs.priority1 = 2;
|
||||
oam.regs.priority0 = 1; oam.regs.priority1 = 3; oam.regs.priority2 = 4; oam.regs.priority3 = 5;
|
||||
sprite.regs.priority0 = 1; sprite.regs.priority1 = 3; sprite.regs.priority2 = 4; sprite.regs.priority3 = 5;
|
||||
} else {
|
||||
bg1.regs.mode = Background::Mode::Mode7;
|
||||
bg2.regs.mode = Background::Mode::Mode7;
|
||||
|
@ -135,7 +135,7 @@ void PPU::mmio_update_video_mode() {
|
|||
bg4.regs.mode = Background::Mode::Inactive;
|
||||
bg1.regs.priority0 = 3; bg1.regs.priority1 = 3;
|
||||
bg2.regs.priority0 = 1; bg2.regs.priority1 = 5;
|
||||
oam.regs.priority0 = 2; oam.regs.priority1 = 4; oam.regs.priority2 = 6; oam.regs.priority3 = 7;
|
||||
sprite.regs.priority0 = 2; sprite.regs.priority1 = 4; sprite.regs.priority2 = 6; sprite.regs.priority3 = 7;
|
||||
}
|
||||
} break;
|
||||
}
|
||||
|
@ -143,29 +143,29 @@ void PPU::mmio_update_video_mode() {
|
|||
|
||||
//INIDISP
|
||||
void PPU::mmio_w2100(uint8 data) {
|
||||
if(regs.display_disable && vcounter() == (!regs.overscan ? 225 : 240)) oam.address_reset();
|
||||
if(regs.display_disable && vcounter() == (!regs.overscan ? 225 : 240)) sprite.address_reset();
|
||||
regs.display_disable = data & 0x80;
|
||||
regs.display_brightness = data & 0x0f;
|
||||
}
|
||||
|
||||
//OBSEL
|
||||
void PPU::mmio_w2101(uint8 data) {
|
||||
oam.regs.base_size = (data >> 5) & 7;
|
||||
oam.regs.nameselect = (data >> 3) & 3;
|
||||
oam.regs.tiledata_addr = (data & 3) << 14;
|
||||
sprite.regs.base_size = (data >> 5) & 7;
|
||||
sprite.regs.nameselect = (data >> 3) & 3;
|
||||
sprite.regs.tiledata_addr = (data & 3) << 14;
|
||||
}
|
||||
|
||||
//OAMADDL
|
||||
void PPU::mmio_w2102(uint8 data) {
|
||||
regs.oam_baseaddr = (regs.oam_baseaddr & 0x0200) | (data << 1);
|
||||
oam.address_reset();
|
||||
sprite.address_reset();
|
||||
}
|
||||
|
||||
//OAMADDH
|
||||
void PPU::mmio_w2103(uint8 data) {
|
||||
regs.oam_priority = data & 0x80;
|
||||
regs.oam_baseaddr = ((data & 0x01) << 9) | (regs.oam_baseaddr & 0x01fe);
|
||||
oam.address_reset();
|
||||
sprite.address_reset();
|
||||
}
|
||||
|
||||
//OAMDATA
|
||||
|
@ -177,12 +177,12 @@ void PPU::mmio_w2104(uint8 data) {
|
|||
|
||||
if(latch == 0) regs.oam_latchdata = data;
|
||||
if(addr & 0x0200) {
|
||||
oam.update(addr, data);
|
||||
sprite.update(addr, data);
|
||||
} else if(latch == 1) {
|
||||
oam.update((addr & ~1) + 0, regs.oam_latchdata);
|
||||
oam.update((addr & ~1) + 1, data);
|
||||
sprite.update((addr & ~1) + 0, regs.oam_latchdata);
|
||||
sprite.update((addr & ~1) + 1, data);
|
||||
}
|
||||
oam.set_first_sprite();
|
||||
sprite.set_first_sprite();
|
||||
}
|
||||
|
||||
//BGMODE
|
||||
|
@ -399,8 +399,8 @@ void PPU::mmio_w2122(uint8 data) {
|
|||
if(latch == 0) {
|
||||
regs.cgram_latchdata = data;
|
||||
} else {
|
||||
memory::cgram[(addr & ~1) + 0] = regs.cgram_latchdata;
|
||||
memory::cgram[(addr & ~1) + 1] = data & 0x7f;
|
||||
cgram[(addr & ~1) + 0] = regs.cgram_latchdata;
|
||||
cgram[(addr & ~1) + 1] = data & 0x7f;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -476,7 +476,7 @@ void PPU::mmio_w212b(uint8 data) {
|
|||
|
||||
//TM
|
||||
void PPU::mmio_w212c(uint8 data) {
|
||||
oam.regs.main_enable = data & 0x10;
|
||||
sprite.regs.main_enable = data & 0x10;
|
||||
bg4.regs.main_enable = data & 0x08;
|
||||
bg3.regs.main_enable = data & 0x04;
|
||||
bg2.regs.main_enable = data & 0x02;
|
||||
|
@ -485,7 +485,7 @@ void PPU::mmio_w212c(uint8 data) {
|
|||
|
||||
//TS
|
||||
void PPU::mmio_w212d(uint8 data) {
|
||||
oam.regs.sub_enable = data & 0x10;
|
||||
sprite.regs.sub_enable = data & 0x10;
|
||||
bg4.regs.sub_enable = data & 0x08;
|
||||
bg3.regs.sub_enable = data & 0x04;
|
||||
bg2.regs.sub_enable = data & 0x02;
|
||||
|
@ -542,7 +542,7 @@ void PPU::mmio_w2133(uint8 data) {
|
|||
regs.mode7_extbg = data & 0x40;
|
||||
regs.pseudo_hires = data & 0x08;
|
||||
regs.overscan = data & 0x04;
|
||||
oam.regs.interlace = data & 0x02;
|
||||
sprite.regs.interlace = data & 0x02;
|
||||
regs.interlace = data & 0x01;
|
||||
mmio_update_video_mode();
|
||||
}
|
||||
|
@ -580,8 +580,8 @@ uint8 PPU::mmio_r2138() {
|
|||
if(regs.display_disable == false && vcounter() < (!regs.overscan ? 225 : 240)) addr = regs.oam_iaddr;
|
||||
if(addr & 0x0200) addr &= 0x021f;
|
||||
|
||||
regs.ppu1_mdr = memory::oam[addr];
|
||||
oam.set_first_sprite();
|
||||
regs.ppu1_mdr = oam[addr];
|
||||
sprite.set_first_sprite();
|
||||
return regs.ppu1_mdr;
|
||||
}
|
||||
|
||||
|
@ -621,10 +621,10 @@ uint8 PPU::mmio_r213b() {
|
|||
) addr = regs.cgram_iaddr;
|
||||
|
||||
if(latch == 0) {
|
||||
regs.ppu2_mdr = memory::cgram[addr];
|
||||
regs.ppu2_mdr = cgram[addr];
|
||||
} else {
|
||||
regs.ppu2_mdr &= 0x80;
|
||||
regs.ppu2_mdr |= memory::cgram[addr];
|
||||
regs.ppu2_mdr |= cgram[addr];
|
||||
}
|
||||
return regs.ppu2_mdr;
|
||||
}
|
||||
|
@ -656,8 +656,8 @@ uint8 PPU::mmio_r213d() {
|
|||
//STAT77
|
||||
uint8 PPU::mmio_r213e() {
|
||||
regs.ppu1_mdr &= 0x10;
|
||||
regs.ppu1_mdr |= oam.regs.time_over << 7;
|
||||
regs.ppu1_mdr |= oam.regs.range_over << 6;
|
||||
regs.ppu1_mdr |= sprite.regs.time_over << 7;
|
||||
regs.ppu1_mdr |= sprite.regs.range_over << 6;
|
||||
regs.ppu1_mdr |= ppu1_version & 0x0f;
|
||||
return regs.ppu1_mdr;
|
||||
}
|
||||
|
|
|
@ -53,7 +53,7 @@ void PPU::enter() {
|
|||
bg3.run(0);
|
||||
bg4.run(0);
|
||||
if(pixel >= 0) {
|
||||
oam.run();
|
||||
sprite.run();
|
||||
window.run();
|
||||
screen.run();
|
||||
}
|
||||
|
@ -61,7 +61,7 @@ void PPU::enter() {
|
|||
}
|
||||
|
||||
add_clocks(22);
|
||||
oam.tilefetch();
|
||||
sprite.tilefetch();
|
||||
} else {
|
||||
add_clocks(1052 + 22 + 136);
|
||||
}
|
||||
|
@ -80,17 +80,20 @@ void PPU::add_clocks(unsigned clocks) {
|
|||
}
|
||||
|
||||
void PPU::enable() {
|
||||
bus.map(Bus::MapMode::Direct, 0x00, 0x3f, 0x2100, 0x213f, { &PPU::mmio_read, &ppu }, { &PPU::mmio_write, &ppu });
|
||||
bus.map(Bus::MapMode::Direct, 0x80, 0xbf, 0x2100, 0x213f, { &PPU::mmio_read, &ppu }, { &PPU::mmio_write, &ppu });
|
||||
function<uint8 (unsigned)> read = { &PPU::mmio_read, (PPU*)&ppu };
|
||||
function<void (unsigned, uint8)> write = { &PPU::mmio_write, (PPU*)&ppu };
|
||||
|
||||
bus.map(Bus::MapMode::Direct, 0x00, 0x3f, 0x2100, 0x213f, read, write);
|
||||
bus.map(Bus::MapMode::Direct, 0x80, 0xbf, 0x2100, 0x213f, read, write);
|
||||
}
|
||||
|
||||
void PPU::power() {
|
||||
ppu1_version = config.ppu1.version;
|
||||
ppu2_version = config.ppu2.version;
|
||||
|
||||
memset(memory::vram.data(), 0x00, memory::vram.size());
|
||||
memset(memory::oam.data(), 0x00, memory::oam.size());
|
||||
memset(memory::cgram.data(), 0x00, memory::cgram.size());
|
||||
foreach(n, vram) n = 0x00;
|
||||
foreach(n, oam) n = 0x00;
|
||||
foreach(n, cgram) n = 0x00;
|
||||
|
||||
reset();
|
||||
}
|
||||
|
@ -105,7 +108,7 @@ void PPU::reset() {
|
|||
bg2.reset();
|
||||
bg3.reset();
|
||||
bg4.reset();
|
||||
oam.reset();
|
||||
sprite.reset();
|
||||
window.reset();
|
||||
screen.reset();
|
||||
|
||||
|
@ -125,14 +128,14 @@ void PPU::scanline() {
|
|||
bg2.scanline();
|
||||
bg3.scanline();
|
||||
bg4.scanline();
|
||||
oam.scanline();
|
||||
sprite.scanline();
|
||||
window.scanline();
|
||||
screen.scanline();
|
||||
}
|
||||
|
||||
void PPU::frame() {
|
||||
system.frame();
|
||||
oam.frame();
|
||||
sprite.frame();
|
||||
|
||||
display.interlace = regs.interlace;
|
||||
display.overscan = regs.overscan;
|
||||
|
@ -143,7 +146,7 @@ bg1(*this, Background::ID::BG1),
|
|||
bg2(*this, Background::ID::BG2),
|
||||
bg3(*this, Background::ID::BG3),
|
||||
bg4(*this, Background::ID::BG4),
|
||||
oam(*this),
|
||||
sprite(*this),
|
||||
window(*this),
|
||||
screen(*this) {
|
||||
surface = new uint16[512 * 512];
|
||||
|
|
|
@ -1,5 +1,9 @@
|
|||
class PPU : public Processor, public PPUcounter {
|
||||
public:
|
||||
uint8 vram[64 * 1024];
|
||||
uint8 oam[544];
|
||||
uint8 cgram[512];
|
||||
|
||||
enum : bool { Threaded = true };
|
||||
alwaysinline void step(unsigned clocks);
|
||||
alwaysinline void synchronize_cpu();
|
||||
|
@ -40,7 +44,7 @@ private:
|
|||
Background bg2;
|
||||
Background bg3;
|
||||
Background bg4;
|
||||
Sprite oam;
|
||||
Sprite sprite;
|
||||
Window window;
|
||||
Screen screen;
|
||||
|
||||
|
|
|
@ -55,9 +55,9 @@ uint16 PPU::Screen::get_pixel(bool swap) {
|
|||
color_main = get_color(self.bg4.output.main.palette);
|
||||
source_main = BG4;
|
||||
}
|
||||
if(self.oam.output.main.priority > priority_main) {
|
||||
priority_main = self.oam.output.main.priority;
|
||||
color_main = get_color(self.oam.output.main.palette);
|
||||
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) {
|
||||
|
@ -97,9 +97,9 @@ uint16 PPU::Screen::get_pixel(bool swap) {
|
|||
color_sub = get_color(self.bg4.output.sub.palette);
|
||||
source_sub = BG4;
|
||||
}
|
||||
if(self.oam.output.sub.priority > priority_sub) {
|
||||
priority_sub = self.oam.output.sub.priority;
|
||||
color_sub = get_color(self.oam.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) {
|
||||
|
@ -130,7 +130,7 @@ uint16 PPU::Screen::get_pixel(bool swap) {
|
|||
color_main = 0x0000;
|
||||
}
|
||||
|
||||
bool color_exempt = (source_main == OAM && self.oam.output.main.palette < 192);
|
||||
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) {
|
||||
|
@ -173,7 +173,7 @@ uint16 PPU::Screen::addsub(unsigned x, unsigned y, bool halve) {
|
|||
uint16 PPU::Screen::get_color(unsigned palette) {
|
||||
palette <<= 1;
|
||||
self.regs.cgram_iaddr = palette;
|
||||
return memory::cgram[palette + 0] + (memory::cgram[palette + 1] << 8);
|
||||
return ppu.cgram[palette + 0] + (ppu.cgram[palette + 1] << 8);
|
||||
}
|
||||
|
||||
uint16 PPU::Screen::get_direct_color(unsigned palette, unsigned tile) {
|
||||
|
|
|
@ -16,6 +16,10 @@ void PPU::serialize(serializer &s) {
|
|||
Processor::serialize(s);
|
||||
PPUcounter::serialize(s);
|
||||
|
||||
s.array(vram);
|
||||
s.array(oam);
|
||||
s.array(cgram);
|
||||
|
||||
s.integer(ppu1_version);
|
||||
s.integer(ppu2_version);
|
||||
|
||||
|
@ -81,7 +85,7 @@ void PPU::serialize(serializer &s) {
|
|||
bg2.serialize(s);
|
||||
bg3.serialize(s);
|
||||
bg4.serialize(s);
|
||||
oam.serialize(s);
|
||||
sprite.serialize(s);
|
||||
window.serialize(s);
|
||||
screen.serialize(s);
|
||||
}
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
#ifdef PPU_CPP
|
||||
|
||||
void PPU::Sprite::update(unsigned addr, uint8 data) {
|
||||
memory::oam[addr] = data;
|
||||
ppu.oam[addr] = data;
|
||||
|
||||
if(addr < 0x0200) {
|
||||
unsigned n = addr >> 2;
|
||||
|
@ -35,21 +35,21 @@ void PPU::Sprite::update(unsigned addr, uint8 data) {
|
|||
unsigned PPU::Sprite::SpriteItem::width() const {
|
||||
if(size == 0) {
|
||||
static unsigned width[] = { 8, 8, 8, 16, 16, 32, 16, 16 };
|
||||
return width[ppu.oam.regs.base_size];
|
||||
return width[ppu.sprite.regs.base_size];
|
||||
} else {
|
||||
static unsigned width[] = { 16, 32, 64, 32, 64, 64, 32, 32 };
|
||||
return width[ppu.oam.regs.base_size];
|
||||
return width[ppu.sprite.regs.base_size];
|
||||
}
|
||||
}
|
||||
|
||||
unsigned PPU::Sprite::SpriteItem::height() const {
|
||||
if(size == 0) {
|
||||
if(ppu.oam.regs.interlace && ppu.oam.regs.base_size >= 6) return 16;
|
||||
if(ppu.sprite.regs.interlace && ppu.sprite.regs.base_size >= 6) return 16;
|
||||
static unsigned height[] = { 8, 8, 8, 16, 16, 32, 32, 32 };
|
||||
return height[ppu.oam.regs.base_size];
|
||||
return height[ppu.sprite.regs.base_size];
|
||||
} else {
|
||||
static unsigned height[] = { 16, 32, 64, 32, 64, 64, 64, 32 };
|
||||
return height[ppu.oam.regs.base_size];
|
||||
return height[ppu.sprite.regs.base_size];
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -144,12 +144,12 @@ void PPU::Sprite::tilefetch() {
|
|||
unsigned pos = tiledata_addr + ((chry + ((chrx + mx) & 15)) << 5);
|
||||
uint16 addr = (pos & 0xffe0) + ((y & 7) * 2);
|
||||
|
||||
oam_tile[n].d0 = memory::vram[addr + 0];
|
||||
oam_tile[n].d1 = memory::vram[addr + 1];
|
||||
oam_tile[n].d0 = ppu.vram[addr + 0];
|
||||
oam_tile[n].d1 = ppu.vram[addr + 1];
|
||||
self.add_clocks(2);
|
||||
|
||||
oam_tile[n].d2 = memory::vram[addr + 16];
|
||||
oam_tile[n].d3 = memory::vram[addr + 17];
|
||||
oam_tile[n].d2 = ppu.vram[addr + 16];
|
||||
oam_tile[n].d3 = ppu.vram[addr + 17];
|
||||
self.add_clocks(2);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -52,8 +52,8 @@ void PPU::Window::run() {
|
|||
regs.oam_two_enable, regs.oam_two_invert,
|
||||
regs.oam_mask, regs.oam_main_enable, regs.oam_sub_enable
|
||||
);
|
||||
if(main) self.oam.output.main.priority = 0;
|
||||
if(sub) self.oam.output.sub.priority = 0;
|
||||
if(main) self.sprite.output.main.priority = 0;
|
||||
if(sub) self.sprite.output.sub.priority = 0;
|
||||
|
||||
test(
|
||||
main, sub,
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
uint8 SMPcore::disassemble_read(uint16 addr) {
|
||||
if(addr >= 0xffc0) return smp.iplrom[addr & 0x3f];
|
||||
return memory::apuram[addr];
|
||||
return smp.apuram[addr];
|
||||
}
|
||||
|
||||
uint16 SMPcore::relb(int8 offset, int op_len) {
|
||||
|
|
|
@ -3,20 +3,20 @@
|
|||
alwaysinline uint8 SMP::ram_read(uint16 addr) {
|
||||
if(addr >= 0xffc0 && status.iplrom_enabled) return iplrom[addr & 0x3f];
|
||||
if(status.ram_disabled) return 0x5a; //0xff on mini-SNES
|
||||
return memory::apuram[addr];
|
||||
return apuram[addr];
|
||||
}
|
||||
|
||||
alwaysinline void SMP::ram_write(uint16 addr, uint8 data) {
|
||||
//writes to $ffc0-$ffff always go to apuram, even if the iplrom is enabled
|
||||
if(status.ram_writable && !status.ram_disabled) memory::apuram[addr] = data;
|
||||
if(status.ram_writable && !status.ram_disabled) apuram[addr] = data;
|
||||
}
|
||||
|
||||
uint8 SMP::port_read(uint2 port) const {
|
||||
return memory::apuram[0xf4 + port];
|
||||
return apuram[0xf4 + port];
|
||||
}
|
||||
|
||||
void SMP::port_write(uint2 port, uint8 data) {
|
||||
memory::apuram[0xf4 + port] = data;
|
||||
apuram[0xf4 + port] = data;
|
||||
}
|
||||
|
||||
alwaysinline uint8 SMP::op_busread(uint16 addr) {
|
||||
|
|
|
@ -4,6 +4,8 @@ void SMP::serialize(serializer &s) {
|
|||
Processor::serialize(s);
|
||||
SMPcore::core_serialize(s);
|
||||
|
||||
s.array(apuram);
|
||||
|
||||
s.integer(status.clock_counter);
|
||||
s.integer(status.dsp_counter);
|
||||
s.integer(status.timer_step);
|
||||
|
|
|
@ -71,9 +71,7 @@ void SMP::reset() {
|
|||
regs.sp = 0xef;
|
||||
regs.p = 0x02;
|
||||
|
||||
for(unsigned i = 0; i < memory::apuram.size(); i++) {
|
||||
memory::apuram.write(i, 0x00);
|
||||
}
|
||||
foreach(n, apuram) n = 0x00;
|
||||
|
||||
status.clock_counter = 0;
|
||||
status.dsp_counter = 0;
|
||||
|
|
|
@ -1,5 +1,8 @@
|
|||
class SMP : public Processor, public SMPcore {
|
||||
public:
|
||||
static const uint8 iplrom[64];
|
||||
uint8 apuram[64 * 1024];
|
||||
|
||||
enum : bool { Threaded = true };
|
||||
alwaysinline void step(unsigned clocks);
|
||||
alwaysinline void synchronize_cpu();
|
||||
|
@ -16,8 +19,6 @@ public:
|
|||
SMP();
|
||||
~SMP();
|
||||
|
||||
static const uint8 iplrom[64];
|
||||
|
||||
private:
|
||||
#include "memory/memory.hpp"
|
||||
#include "timing/timing.hpp"
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
namespace SNES {
|
||||
namespace Info {
|
||||
static const char Name[] = "bsnes";
|
||||
static const char Version[] = "074.10";
|
||||
static const char Version[] = "074.11";
|
||||
static const unsigned SerializerVersion = 17;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -49,7 +49,6 @@ void System::serialize(serializer &s) {
|
|||
}
|
||||
|
||||
void System::serialize_all(serializer &s) {
|
||||
bus.serialize(s);
|
||||
cartridge.serialize(s);
|
||||
system.serialize(s);
|
||||
cpu.serialize(s);
|
||||
|
|
|
@ -1,12 +1,12 @@
|
|||
Configuration config;
|
||||
|
||||
void Configuration::load() {
|
||||
configuration::load(string(path.user, "bsnes-phoenix.cfg"));
|
||||
configuration::load(string(path.user, "bsnes.cfg"));
|
||||
}
|
||||
|
||||
void Configuration::save() {
|
||||
mkdir(path.user, 0755);
|
||||
configuration::save(string(path.user, "bsnes-phoenix.cfg"));
|
||||
configuration::save(string(path.user, "bsnes.cfg"));
|
||||
}
|
||||
|
||||
void Configuration::create() {
|
||||
|
|
|
@ -146,7 +146,7 @@ int main(int argc, char **argv) {
|
|||
}
|
||||
|
||||
void Application::loadGeometry() {
|
||||
geometryConfig.load(string(config.path.user, "bsnes-phoenix-geometry.cfg"));
|
||||
geometryConfig.load(string(config.path.user, "bsnes-geometry.cfg"));
|
||||
foreach(window, windows) {
|
||||
lstring position;
|
||||
position.split(",", window->position);
|
||||
|
@ -160,5 +160,5 @@ void Application::saveGeometry() {
|
|||
Geometry geom = window->geometry();
|
||||
window->position = { geom.x, ",", geom.y };
|
||||
}
|
||||
geometryConfig.save(string(config.path.user, "bsnes-phoenix-geometry.cfg"));
|
||||
geometryConfig.save(string(config.path.user, "bsnes-geometry.cfg"));
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue