mirror of https://github.com/bsnes-emu/bsnes.git
Update to 20100809 release.
byuu says: This adds some sync.sh improvements to make it handle errors more gracefully. It also updates asnes a good bit. All of the four base processors now have all publicly accessible functions right at the top of the main headers, and everything else is private. This is to allow these headers to essentially take the place of the previous base classes in the old bsnes-merged format. So if there's something public there, you need to implement that exact function to make your own module. I removed the frame counter from the PPU, as it has nothing to do with emulation. That now resides inside the Qt -> SNES interface code. Quite amazing, I was actually saving the frame counter into the save state files before, yuck. Removed some baggage in the System class: it was friending a bunch of long-dead functions and classes. Forgot to re-add the CHEAT_SYSTEM define to info.hpp, so that's been put back.
This commit is contained in:
parent
94675634c1
commit
973ef89d4a
|
@ -9,7 +9,7 @@ Configuration::Configuration() {
|
||||||
region = System::Region::Autodetect;
|
region = System::Region::Autodetect;
|
||||||
|
|
||||||
cpu.version = 2;
|
cpu.version = 2;
|
||||||
cpu.ntsc_frequency = 21477272;
|
cpu.ntsc_frequency = 21477272; //315 / 88 * 6000000
|
||||||
cpu.pal_frequency = 21281370;
|
cpu.pal_frequency = 21281370;
|
||||||
cpu.wram_init_value = 0x55;
|
cpu.wram_init_value = 0x55;
|
||||||
|
|
||||||
|
|
|
@ -106,7 +106,7 @@ void CPU::power() {
|
||||||
void CPU::reset() {
|
void CPU::reset() {
|
||||||
create(Enter, system.cpu_frequency());
|
create(Enter, system.cpu_frequency());
|
||||||
coprocessors.reset();
|
coprocessors.reset();
|
||||||
PPUCounter::reset();
|
PPUcounter::reset();
|
||||||
|
|
||||||
//note: some registers are not fully reset by SNES
|
//note: some registers are not fully reset by SNES
|
||||||
regs.pc = 0x000000;
|
regs.pc = 0x000000;
|
||||||
|
@ -132,7 +132,7 @@ void CPU::reset() {
|
||||||
}
|
}
|
||||||
|
|
||||||
CPU::CPU() {
|
CPU::CPU() {
|
||||||
PPUCounter::scanline = { &CPU::scanline, this };
|
PPUcounter::scanline = { &CPU::scanline, this };
|
||||||
}
|
}
|
||||||
|
|
||||||
CPU::~CPU() {
|
CPU::~CPU() {
|
||||||
|
|
|
@ -1,25 +1,32 @@
|
||||||
class CPU : public Processor, public PPUCounter, public MMIO, public CPUcore {
|
class CPU : public Processor, public CPUcore, public PPUcounter, public MMIO {
|
||||||
public:
|
public:
|
||||||
//synchronization
|
|
||||||
array<Processor*> coprocessors;
|
array<Processor*> coprocessors;
|
||||||
alwaysinline void step(unsigned clocks);
|
alwaysinline void step(unsigned clocks);
|
||||||
alwaysinline void synchronize_smp();
|
alwaysinline void synchronize_smp();
|
||||||
void synchronize_ppu();
|
void synchronize_ppu();
|
||||||
void synchronize_coprocessor();
|
void synchronize_coprocessor();
|
||||||
|
|
||||||
static void Enter();
|
uint8 pio();
|
||||||
void enter();
|
bool joylatch();
|
||||||
debugvirtual void op_step();
|
alwaysinline bool interrupt_pending() { return status.interrupt_pending; }
|
||||||
void op_irq();
|
alwaysinline uint8 port_read(uint8 port) { return apu_port[port & 3]; }
|
||||||
bool interrupt_pending() { return status.interrupt_pending; }
|
alwaysinline void port_write(uint8 port, uint8 data) { apu_port[port & 3] = data; }
|
||||||
|
|
||||||
uint8 cpu_version;
|
void power();
|
||||||
|
void reset();
|
||||||
|
|
||||||
|
void serialize(serializer&);
|
||||||
|
CPU();
|
||||||
|
~CPU();
|
||||||
|
|
||||||
|
private:
|
||||||
#include "dma/dma.hpp"
|
#include "dma/dma.hpp"
|
||||||
#include "memory/memory.hpp"
|
#include "memory/memory.hpp"
|
||||||
#include "mmio/mmio.hpp"
|
#include "mmio/mmio.hpp"
|
||||||
#include "timing/timing.hpp"
|
#include "timing/timing.hpp"
|
||||||
|
|
||||||
|
uint8 cpu_version;
|
||||||
|
|
||||||
struct Status {
|
struct Status {
|
||||||
bool interrupt_pending;
|
bool interrupt_pending;
|
||||||
uint16 interrupt_vector;
|
uint16 interrupt_vector;
|
||||||
|
@ -27,10 +34,7 @@ public:
|
||||||
unsigned clock_count;
|
unsigned clock_count;
|
||||||
unsigned line_clocks;
|
unsigned line_clocks;
|
||||||
|
|
||||||
//======
|
|
||||||
//timing
|
//timing
|
||||||
//======
|
|
||||||
|
|
||||||
bool irq_lock;
|
bool irq_lock;
|
||||||
|
|
||||||
unsigned dram_refresh_position;
|
unsigned dram_refresh_position;
|
||||||
|
@ -56,10 +60,7 @@ public:
|
||||||
|
|
||||||
bool reset_pending;
|
bool reset_pending;
|
||||||
|
|
||||||
//===
|
|
||||||
//DMA
|
//DMA
|
||||||
//===
|
|
||||||
|
|
||||||
bool dma_active;
|
bool dma_active;
|
||||||
unsigned dma_counter;
|
unsigned dma_counter;
|
||||||
unsigned dma_clocks;
|
unsigned dma_clocks;
|
||||||
|
@ -67,10 +68,7 @@ public:
|
||||||
bool hdma_pending;
|
bool hdma_pending;
|
||||||
bool hdma_mode; //0 = init, 1 = run
|
bool hdma_mode; //0 = init, 1 = run
|
||||||
|
|
||||||
//====
|
|
||||||
//MMIO
|
//MMIO
|
||||||
//====
|
|
||||||
|
|
||||||
//$2181-$2183
|
//$2181-$2183
|
||||||
uint32 wram_addr;
|
uint32 wram_addr;
|
||||||
|
|
||||||
|
@ -118,12 +116,10 @@ public:
|
||||||
unsigned shift;
|
unsigned shift;
|
||||||
} alu;
|
} alu;
|
||||||
|
|
||||||
void power();
|
static void Enter();
|
||||||
void reset();
|
void enter();
|
||||||
|
void op_irq();
|
||||||
void serialize(serializer&);
|
debugvirtual void op_step();
|
||||||
CPU();
|
|
||||||
~CPU();
|
|
||||||
|
|
||||||
friend class CPUDebugger;
|
friend class CPUDebugger;
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,14 +1,4 @@
|
||||||
//============================
|
|
||||||
//CPU<>APU communication ports
|
|
||||||
//============================
|
|
||||||
|
|
||||||
uint8 apu_port[4];
|
uint8 apu_port[4];
|
||||||
uint8 port_read(uint8 port) { return apu_port[port & 3]; }
|
|
||||||
void port_write(uint8 port, uint8 data) { apu_port[port & 3] = data; }
|
|
||||||
|
|
||||||
//======================
|
|
||||||
//core CPU bus functions
|
|
||||||
//======================
|
|
||||||
|
|
||||||
void op_io();
|
void op_io();
|
||||||
debugvirtual uint8 op_read(uint32 addr);
|
debugvirtual uint8 op_read(uint32 addr);
|
||||||
|
|
|
@ -3,9 +3,6 @@ void mmio_reset();
|
||||||
uint8 mmio_read(unsigned addr);
|
uint8 mmio_read(unsigned addr);
|
||||||
void mmio_write(unsigned addr, uint8 data);
|
void mmio_write(unsigned addr, uint8 data);
|
||||||
|
|
||||||
uint8 pio();
|
|
||||||
bool joylatch();
|
|
||||||
|
|
||||||
uint8 mmio_r2180();
|
uint8 mmio_r2180();
|
||||||
uint8 mmio_r4016();
|
uint8 mmio_r4016();
|
||||||
uint8 mmio_r4017();
|
uint8 mmio_r4017();
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
#ifdef CPU_CPP
|
#ifdef CPU_CPP
|
||||||
|
|
||||||
void CPU::serialize(serializer &s) {
|
void CPU::serialize(serializer &s) {
|
||||||
CPUcore::core_serialize(s);
|
|
||||||
Processor::serialize(s);
|
Processor::serialize(s);
|
||||||
PPUCounter::serialize(s);
|
CPUcore::core_serialize(s);
|
||||||
|
PPUcounter::serialize(s);
|
||||||
s.integer(cpu_version);
|
s.integer(cpu_version);
|
||||||
|
|
||||||
s.integer(status.interrupt_pending);
|
s.integer(status.interrupt_pending);
|
||||||
|
|
|
@ -1,13 +1,8 @@
|
||||||
class DSP : public Processor {
|
class DSP : public Processor {
|
||||||
public:
|
public:
|
||||||
//synchronization
|
|
||||||
alwaysinline void step(unsigned clocks);
|
alwaysinline void step(unsigned clocks);
|
||||||
alwaysinline void synchronize_smp();
|
alwaysinline void synchronize_smp();
|
||||||
|
|
||||||
static void Enter();
|
|
||||||
void enter();
|
|
||||||
void tick();
|
|
||||||
|
|
||||||
uint8 read(uint8 addr);
|
uint8 read(uint8 addr);
|
||||||
void write(uint8 addr, uint8 data);
|
void write(uint8 addr, uint8 data);
|
||||||
|
|
||||||
|
@ -18,7 +13,7 @@ public:
|
||||||
DSP();
|
DSP();
|
||||||
~DSP();
|
~DSP();
|
||||||
|
|
||||||
protected:
|
private:
|
||||||
//global registers
|
//global registers
|
||||||
enum global_reg_t {
|
enum global_reg_t {
|
||||||
r_mvoll = 0x0c, r_mvolr = 0x1c,
|
r_mvoll = 0x0c, r_mvolr = 0x1c,
|
||||||
|
@ -168,6 +163,11 @@ protected:
|
||||||
void echo_29();
|
void echo_29();
|
||||||
void echo_30();
|
void echo_30();
|
||||||
|
|
||||||
|
//dsp
|
||||||
|
static void Enter();
|
||||||
|
void enter();
|
||||||
|
void tick();
|
||||||
|
|
||||||
friend class DSPDebugger;
|
friend class DSPDebugger;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -1,9 +1,10 @@
|
||||||
namespace SNES {
|
namespace SNES {
|
||||||
namespace Info {
|
namespace Info {
|
||||||
static const char Name[] = "asnes";
|
static const char Name[] = "asnes";
|
||||||
static const char Version[] = "000.01";
|
static const char Version[] = "000.02";
|
||||||
static const unsigned SerializerVersion = 12;
|
static const unsigned SerializerVersion = 12;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//#define DEBUGGER
|
//#define DEBUGGER
|
||||||
|
#define CHEAT_SYSTEM
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
//this should only be called by CPU::PPUcounter::tick();
|
//this should only be called by CPU::PPUcounter::tick();
|
||||||
//keeps track of previous counter positions in history table
|
//keeps track of previous counter positions in history table
|
||||||
void PPUCounter::tick() {
|
void PPUcounter::tick() {
|
||||||
status.hcounter += 2; //increment by smallest unit of time
|
status.hcounter += 2; //increment by smallest unit of time
|
||||||
if(status.hcounter >= 1360 && status.hcounter == lineclocks()) {
|
if(status.hcounter >= 1360 && status.hcounter == lineclocks()) {
|
||||||
status.hcounter = 0;
|
status.hcounter = 0;
|
||||||
|
@ -15,7 +15,7 @@ void PPUCounter::tick() {
|
||||||
|
|
||||||
//this should only be called by PPU::PPUcounter::tick(n);
|
//this should only be called by PPU::PPUcounter::tick(n);
|
||||||
//allows stepping by more than the smallest unit of time
|
//allows stepping by more than the smallest unit of time
|
||||||
void PPUCounter::tick(unsigned clocks) {
|
void PPUcounter::tick(unsigned clocks) {
|
||||||
status.hcounter += clocks;
|
status.hcounter += clocks;
|
||||||
if(status.hcounter >= lineclocks()) {
|
if(status.hcounter >= lineclocks()) {
|
||||||
status.hcounter -= lineclocks();
|
status.hcounter -= lineclocks();
|
||||||
|
@ -24,7 +24,7 @@ void PPUCounter::tick(unsigned clocks) {
|
||||||
}
|
}
|
||||||
|
|
||||||
//internal
|
//internal
|
||||||
void PPUCounter::vcounter_tick() {
|
void PPUcounter::vcounter_tick() {
|
||||||
if(++status.vcounter == 128) status.interlace = ppu.interlace();
|
if(++status.vcounter == 128) status.interlace = ppu.interlace();
|
||||||
|
|
||||||
if((system.region() == System::Region::NTSC && status.interlace == false && status.vcounter == 262)
|
if((system.region() == System::Region::NTSC && status.interlace == false && status.vcounter == 262)
|
||||||
|
@ -40,13 +40,13 @@ void PPUCounter::vcounter_tick() {
|
||||||
if(scanline) scanline();
|
if(scanline) scanline();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool PPUCounter::field () const { return status.field; }
|
bool PPUcounter::field () const { return status.field; }
|
||||||
uint16 PPUCounter::vcounter() const { return status.vcounter; }
|
uint16 PPUcounter::vcounter() const { return status.vcounter; }
|
||||||
uint16 PPUCounter::hcounter() const { return status.hcounter; }
|
uint16 PPUcounter::hcounter() const { return status.hcounter; }
|
||||||
|
|
||||||
bool PPUCounter::field (unsigned offset) const { return history.field [(history.index - (offset >> 1)) & 2047]; }
|
bool PPUcounter::field (unsigned offset) const { return history.field [(history.index - (offset >> 1)) & 2047]; }
|
||||||
uint16 PPUCounter::vcounter(unsigned offset) const { return history.vcounter[(history.index - (offset >> 1)) & 2047]; }
|
uint16 PPUcounter::vcounter(unsigned offset) const { return history.vcounter[(history.index - (offset >> 1)) & 2047]; }
|
||||||
uint16 PPUCounter::hcounter(unsigned offset) const { return history.hcounter[(history.index - (offset >> 1)) & 2047]; }
|
uint16 PPUcounter::hcounter(unsigned offset) const { return history.hcounter[(history.index - (offset >> 1)) & 2047]; }
|
||||||
|
|
||||||
//one PPU dot = 4 CPU clocks
|
//one PPU dot = 4 CPU clocks
|
||||||
//
|
//
|
||||||
|
@ -57,7 +57,7 @@ uint16 PPUCounter::hcounter(unsigned offset) const { return history.hcounter[(hi
|
||||||
//dot 323 range = { 1292, 1294, 1296 }
|
//dot 323 range = { 1292, 1294, 1296 }
|
||||||
//dot 327 range = { 1310, 1312, 1314 }
|
//dot 327 range = { 1310, 1312, 1314 }
|
||||||
|
|
||||||
uint16 PPUCounter::hdot() const {
|
uint16 PPUcounter::hdot() const {
|
||||||
if(system.region() == System::Region::NTSC && status.interlace == false && vcounter() == 240 && field() == 1) {
|
if(system.region() == System::Region::NTSC && status.interlace == false && vcounter() == 240 && field() == 1) {
|
||||||
return (hcounter() >> 2);
|
return (hcounter() >> 2);
|
||||||
} else {
|
} else {
|
||||||
|
@ -65,12 +65,12 @@ uint16 PPUCounter::hdot() const {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
uint16 PPUCounter::lineclocks() const {
|
uint16 PPUcounter::lineclocks() const {
|
||||||
if(system.region() == System::Region::NTSC && status.interlace == false && vcounter() == 240 && field() == 1) return 1360;
|
if(system.region() == System::Region::NTSC && status.interlace == false && vcounter() == 240 && field() == 1) return 1360;
|
||||||
return 1364;
|
return 1364;
|
||||||
}
|
}
|
||||||
|
|
||||||
void PPUCounter::reset() {
|
void PPUcounter::reset() {
|
||||||
status.interlace = false;
|
status.interlace = false;
|
||||||
status.field = 0;
|
status.field = 0;
|
||||||
status.vcounter = 0;
|
status.vcounter = 0;
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
//PPUCounter emulates the H/V latch counters of the S-PPU2.
|
//PPUcounter emulates the H/V latch counters of the S-PPU2.
|
||||||
//
|
//
|
||||||
//real hardware has the S-CPU maintain its own copy of these counters that are
|
//real hardware has the S-CPU maintain its own copy of these counters that are
|
||||||
//updated based on the state of the S-PPU Vblank and Hblank pins. emulating this
|
//updated based on the state of the S-PPU Vblank and Hblank pins. emulating this
|
||||||
|
@ -10,7 +10,7 @@
|
||||||
//point before this in the frame, which is handled internally by this class at
|
//point before this in the frame, which is handled internally by this class at
|
||||||
//V=128.
|
//V=128.
|
||||||
|
|
||||||
class PPUCounter {
|
class PPUcounter {
|
||||||
public:
|
public:
|
||||||
alwaysinline void tick();
|
alwaysinline void tick();
|
||||||
alwaysinline void tick(unsigned clocks);
|
alwaysinline void tick(unsigned clocks);
|
||||||
|
|
|
@ -82,7 +82,6 @@ struct {
|
||||||
uint16 vcounter;
|
uint16 vcounter;
|
||||||
} regs;
|
} regs;
|
||||||
|
|
||||||
void latch_counters();
|
|
||||||
uint16 get_vram_address();
|
uint16 get_vram_address();
|
||||||
|
|
||||||
uint8 vram_read(unsigned addr);
|
uint8 vram_read(unsigned addr);
|
||||||
|
@ -94,10 +93,6 @@ void oam_write(unsigned addr, uint8 data);
|
||||||
uint8 cgram_read(unsigned addr);
|
uint8 cgram_read(unsigned addr);
|
||||||
void cgram_write(unsigned addr, uint8 data);
|
void cgram_write(unsigned addr, uint8 data);
|
||||||
|
|
||||||
bool interlace() const;
|
|
||||||
bool overscan() const;
|
|
||||||
bool hires() const;
|
|
||||||
|
|
||||||
void mmio_update_video_mode();
|
void mmio_update_video_mode();
|
||||||
|
|
||||||
void mmio_w2100(uint8); //INIDISP
|
void mmio_w2100(uint8); //INIDISP
|
||||||
|
|
|
@ -86,7 +86,7 @@ void PPU::power() {
|
||||||
|
|
||||||
void PPU::reset() {
|
void PPU::reset() {
|
||||||
create(Enter, system.cpu_frequency());
|
create(Enter, system.cpu_frequency());
|
||||||
PPUCounter::reset();
|
PPUcounter::reset();
|
||||||
memset(surface, 0, 512 * 512 * sizeof(uint16));
|
memset(surface, 0, 512 * 512 * sizeof(uint16));
|
||||||
|
|
||||||
mmio_reset();
|
mmio_reset();
|
||||||
|
@ -118,19 +118,6 @@ void PPU::frame() {
|
||||||
|
|
||||||
display.interlace = regs.interlace;
|
display.interlace = regs.interlace;
|
||||||
display.overscan = regs.overscan;
|
display.overscan = regs.overscan;
|
||||||
|
|
||||||
//frame counter
|
|
||||||
static signed framecount = 0;
|
|
||||||
static time_t prev, curr;
|
|
||||||
framecount++;
|
|
||||||
|
|
||||||
time(&curr);
|
|
||||||
if(curr != prev) {
|
|
||||||
status.frames_updated = true;
|
|
||||||
status.frames_executed = framecount;
|
|
||||||
framecount = 0;
|
|
||||||
prev = curr;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
PPU::PPU() :
|
PPU::PPU() :
|
||||||
|
@ -143,9 +130,6 @@ window(*this),
|
||||||
screen(*this) {
|
screen(*this) {
|
||||||
surface = new uint16[512 * 512];
|
surface = new uint16[512 * 512];
|
||||||
output = surface + 16 * 512;
|
output = surface + 16 * 512;
|
||||||
|
|
||||||
status.frames_updated = false;
|
|
||||||
status.frames_executed = 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
PPU::~PPU() {
|
PPU::~PPU() {
|
||||||
|
|
|
@ -1,7 +1,23 @@
|
||||||
#include "counter/counter.hpp"
|
#include "counter/counter.hpp"
|
||||||
|
|
||||||
class PPU : public Processor, public PPUCounter, public MMIO {
|
class PPU : public Processor, public PPUcounter, public MMIO {
|
||||||
public:
|
public:
|
||||||
|
alwaysinline void step(unsigned clocks);
|
||||||
|
alwaysinline void synchronize_cpu();
|
||||||
|
|
||||||
|
void latch_counters();
|
||||||
|
bool interlace() const;
|
||||||
|
bool overscan() const;
|
||||||
|
bool hires() const;
|
||||||
|
|
||||||
|
void power();
|
||||||
|
void reset();
|
||||||
|
|
||||||
|
void serialize(serializer&);
|
||||||
|
PPU();
|
||||||
|
~PPU();
|
||||||
|
|
||||||
|
private:
|
||||||
#include "background/background.hpp"
|
#include "background/background.hpp"
|
||||||
#include "mmio/mmio.hpp"
|
#include "mmio/mmio.hpp"
|
||||||
#include "screen/screen.hpp"
|
#include "screen/screen.hpp"
|
||||||
|
@ -19,11 +35,6 @@ public:
|
||||||
uint16 *surface;
|
uint16 *surface;
|
||||||
uint16 *output;
|
uint16 *output;
|
||||||
|
|
||||||
struct {
|
|
||||||
bool frames_updated;
|
|
||||||
unsigned frames_executed;
|
|
||||||
} status;
|
|
||||||
|
|
||||||
uint8 ppu1_version;
|
uint8 ppu1_version;
|
||||||
uint8 ppu2_version;
|
uint8 ppu2_version;
|
||||||
|
|
||||||
|
@ -32,23 +43,18 @@ public:
|
||||||
bool overscan;
|
bool overscan;
|
||||||
} display;
|
} display;
|
||||||
|
|
||||||
//synchronization
|
|
||||||
alwaysinline void step(unsigned clocks);
|
|
||||||
alwaysinline void synchronize_cpu();
|
|
||||||
|
|
||||||
static void Enter();
|
static void Enter();
|
||||||
void enter();
|
void enter();
|
||||||
void add_clocks(unsigned);
|
void add_clocks(unsigned);
|
||||||
|
|
||||||
void power();
|
|
||||||
void reset();
|
|
||||||
|
|
||||||
void scanline();
|
void scanline();
|
||||||
void frame();
|
void frame();
|
||||||
|
|
||||||
void serialize(serializer&);
|
friend class PPU::Background;
|
||||||
PPU();
|
friend class PPU::Sprite;
|
||||||
~PPU();
|
friend class PPU::Window;
|
||||||
|
friend class PPU::Screen;
|
||||||
|
friend class Video;
|
||||||
};
|
};
|
||||||
|
|
||||||
#if defined(DEBUGGER)
|
#if defined(DEBUGGER)
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
#ifdef PPU_CPP
|
#ifdef PPU_CPP
|
||||||
|
|
||||||
void PPUCounter::serialize(serializer &s) {
|
void PPUcounter::serialize(serializer &s) {
|
||||||
s.integer(status.interlace);
|
s.integer(status.interlace);
|
||||||
s.integer(status.field);
|
s.integer(status.field);
|
||||||
s.integer(status.vcounter);
|
s.integer(status.vcounter);
|
||||||
|
@ -14,10 +14,7 @@ void PPUCounter::serialize(serializer &s) {
|
||||||
|
|
||||||
void PPU::serialize(serializer &s) {
|
void PPU::serialize(serializer &s) {
|
||||||
Processor::serialize(s);
|
Processor::serialize(s);
|
||||||
PPUCounter::serialize(s);
|
PPUcounter::serialize(s);
|
||||||
|
|
||||||
s.integer(status.frames_updated);
|
|
||||||
s.integer(status.frames_executed);
|
|
||||||
|
|
||||||
s.integer(ppu1_version);
|
s.integer(ppu1_version);
|
||||||
s.integer(ppu2_version);
|
s.integer(ppu2_version);
|
||||||
|
|
|
@ -1,9 +1,6 @@
|
||||||
uint8 ram_read(uint16 addr);
|
uint8 ram_read(uint16 addr);
|
||||||
void ram_write(uint16 addr, uint8 data);
|
void ram_write(uint16 addr, uint8 data);
|
||||||
|
|
||||||
uint8 port_read(uint8 port);
|
|
||||||
void port_write(uint8 port, uint8 data);
|
|
||||||
|
|
||||||
uint8 op_busread(uint16 addr);
|
uint8 op_busread(uint16 addr);
|
||||||
void op_buswrite(uint16 addr, uint8 data);
|
void op_buswrite(uint16 addr, uint8 data);
|
||||||
|
|
||||||
|
|
|
@ -4,8 +4,6 @@ void SMP::serialize(serializer &s) {
|
||||||
Processor::serialize(s);
|
Processor::serialize(s);
|
||||||
SMPcore::core_serialize(s);
|
SMPcore::core_serialize(s);
|
||||||
|
|
||||||
s.integer(status.opcode);
|
|
||||||
|
|
||||||
s.integer(status.clock_counter);
|
s.integer(status.clock_counter);
|
||||||
s.integer(status.dsp_counter);
|
s.integer(status.dsp_counter);
|
||||||
s.integer(status.timer_step);
|
s.integer(status.timer_step);
|
||||||
|
|
|
@ -1,22 +1,26 @@
|
||||||
class SMP : public Processor, public SMPcore {
|
class SMP : public Processor, public SMPcore {
|
||||||
public:
|
public:
|
||||||
static const uint8 iplrom[64];
|
|
||||||
|
|
||||||
//synchronization
|
|
||||||
alwaysinline void step(unsigned clocks);
|
alwaysinline void step(unsigned clocks);
|
||||||
alwaysinline void synchronize_cpu();
|
alwaysinline void synchronize_cpu();
|
||||||
alwaysinline void synchronize_dsp();
|
alwaysinline void synchronize_dsp();
|
||||||
|
|
||||||
static void Enter();
|
uint8 port_read(uint8 port);
|
||||||
void enter();
|
void port_write(uint8 port, uint8 data);
|
||||||
debugvirtual void op_step();
|
|
||||||
|
|
||||||
|
void power();
|
||||||
|
void reset();
|
||||||
|
|
||||||
|
void serialize(serializer&);
|
||||||
|
SMP();
|
||||||
|
~SMP();
|
||||||
|
|
||||||
|
private:
|
||||||
#include "memory/memory.hpp"
|
#include "memory/memory.hpp"
|
||||||
#include "timing/timing.hpp"
|
#include "timing/timing.hpp"
|
||||||
|
|
||||||
struct {
|
static const uint8 iplrom[64];
|
||||||
uint8 opcode;
|
|
||||||
|
|
||||||
|
struct {
|
||||||
//timing
|
//timing
|
||||||
unsigned clock_counter;
|
unsigned clock_counter;
|
||||||
unsigned dsp_counter;
|
unsigned dsp_counter;
|
||||||
|
@ -40,14 +44,11 @@ public:
|
||||||
uint8 smp_f8, smp_f9;
|
uint8 smp_f8, smp_f9;
|
||||||
} status;
|
} status;
|
||||||
|
|
||||||
//ssmp.cpp
|
static void Enter();
|
||||||
void power();
|
void enter();
|
||||||
void reset();
|
debugvirtual void op_step();
|
||||||
|
|
||||||
void serialize(serializer&);
|
|
||||||
SMP();
|
|
||||||
~SMP();
|
|
||||||
|
|
||||||
|
friend class SMPcore;
|
||||||
friend class SMPDebugger;
|
friend class SMPDebugger;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -28,7 +28,6 @@ public:
|
||||||
bool unserialize(serializer&);
|
bool unserialize(serializer&);
|
||||||
|
|
||||||
System();
|
System();
|
||||||
virtual ~System() {}
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Interface *interface;
|
Interface *interface;
|
||||||
|
@ -42,8 +41,6 @@ private:
|
||||||
friend class Video;
|
friend class Video;
|
||||||
friend class Audio;
|
friend class Audio;
|
||||||
friend class Input;
|
friend class Input;
|
||||||
friend class StateManager;
|
|
||||||
friend void threadentry_cop();
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#include <video/video.hpp>
|
#include <video/video.hpp>
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
class Video {
|
class Video {
|
||||||
|
private:
|
||||||
bool frame_hires;
|
bool frame_hires;
|
||||||
bool frame_interlace;
|
bool frame_interlace;
|
||||||
unsigned line_width[240];
|
unsigned line_width[240];
|
||||||
|
|
|
@ -9,7 +9,7 @@ Configuration::Configuration() {
|
||||||
region = System::Region::Autodetect;
|
region = System::Region::Autodetect;
|
||||||
|
|
||||||
cpu.version = 2;
|
cpu.version = 2;
|
||||||
cpu.ntsc_frequency = 21477272;
|
cpu.ntsc_frequency = 21477272; //315 / 88 * 6000000
|
||||||
cpu.pal_frequency = 21281370;
|
cpu.pal_frequency = 21281370;
|
||||||
cpu.wram_init_value = 0x55;
|
cpu.wram_init_value = 0x55;
|
||||||
|
|
||||||
|
|
|
@ -106,7 +106,7 @@ void CPU::power() {
|
||||||
void CPU::reset() {
|
void CPU::reset() {
|
||||||
create(Enter, system.cpu_frequency());
|
create(Enter, system.cpu_frequency());
|
||||||
coprocessors.reset();
|
coprocessors.reset();
|
||||||
PPUCounter::reset();
|
PPUcounter::reset();
|
||||||
|
|
||||||
//note: some registers are not fully reset by SNES
|
//note: some registers are not fully reset by SNES
|
||||||
regs.pc = 0x000000;
|
regs.pc = 0x000000;
|
||||||
|
@ -132,7 +132,7 @@ void CPU::reset() {
|
||||||
}
|
}
|
||||||
|
|
||||||
CPU::CPU() {
|
CPU::CPU() {
|
||||||
PPUCounter::scanline = { &CPU::scanline, this };
|
PPUcounter::scanline = { &CPU::scanline, this };
|
||||||
}
|
}
|
||||||
|
|
||||||
CPU::~CPU() {
|
CPU::~CPU() {
|
||||||
|
|
|
@ -1,25 +1,32 @@
|
||||||
class CPU : public Processor, public PPUCounter, public MMIO, public CPUcore {
|
class CPU : public Processor, public CPUcore, public PPUcounter, public MMIO {
|
||||||
public:
|
public:
|
||||||
//synchronization
|
|
||||||
array<Processor*> coprocessors;
|
array<Processor*> coprocessors;
|
||||||
alwaysinline void step(unsigned clocks);
|
alwaysinline void step(unsigned clocks);
|
||||||
alwaysinline void synchronize_smp();
|
alwaysinline void synchronize_smp();
|
||||||
void synchronize_ppu();
|
void synchronize_ppu();
|
||||||
void synchronize_coprocessor();
|
void synchronize_coprocessor();
|
||||||
|
|
||||||
static void Enter();
|
uint8 pio();
|
||||||
void enter();
|
bool joylatch();
|
||||||
debugvirtual void op_step();
|
alwaysinline bool interrupt_pending() { return status.interrupt_pending; }
|
||||||
void op_irq();
|
alwaysinline uint8 port_read(uint8 port) { return apu_port[port & 3]; }
|
||||||
bool interrupt_pending() { return status.interrupt_pending; }
|
alwaysinline void port_write(uint8 port, uint8 data) { apu_port[port & 3] = data; }
|
||||||
|
|
||||||
uint8 cpu_version;
|
void power();
|
||||||
|
void reset();
|
||||||
|
|
||||||
|
void serialize(serializer&);
|
||||||
|
CPU();
|
||||||
|
~CPU();
|
||||||
|
|
||||||
|
private:
|
||||||
#include "dma/dma.hpp"
|
#include "dma/dma.hpp"
|
||||||
#include "memory/memory.hpp"
|
#include "memory/memory.hpp"
|
||||||
#include "mmio/mmio.hpp"
|
#include "mmio/mmio.hpp"
|
||||||
#include "timing/timing.hpp"
|
#include "timing/timing.hpp"
|
||||||
|
|
||||||
|
uint8 cpu_version;
|
||||||
|
|
||||||
struct Status {
|
struct Status {
|
||||||
bool interrupt_pending;
|
bool interrupt_pending;
|
||||||
uint16 interrupt_vector;
|
uint16 interrupt_vector;
|
||||||
|
@ -27,10 +34,7 @@ public:
|
||||||
unsigned clock_count;
|
unsigned clock_count;
|
||||||
unsigned line_clocks;
|
unsigned line_clocks;
|
||||||
|
|
||||||
//======
|
|
||||||
//timing
|
//timing
|
||||||
//======
|
|
||||||
|
|
||||||
bool irq_lock;
|
bool irq_lock;
|
||||||
|
|
||||||
unsigned dram_refresh_position;
|
unsigned dram_refresh_position;
|
||||||
|
@ -56,10 +60,7 @@ public:
|
||||||
|
|
||||||
bool reset_pending;
|
bool reset_pending;
|
||||||
|
|
||||||
//===
|
|
||||||
//DMA
|
//DMA
|
||||||
//===
|
|
||||||
|
|
||||||
bool dma_active;
|
bool dma_active;
|
||||||
unsigned dma_counter;
|
unsigned dma_counter;
|
||||||
unsigned dma_clocks;
|
unsigned dma_clocks;
|
||||||
|
@ -67,10 +68,7 @@ public:
|
||||||
bool hdma_pending;
|
bool hdma_pending;
|
||||||
bool hdma_mode; //0 = init, 1 = run
|
bool hdma_mode; //0 = init, 1 = run
|
||||||
|
|
||||||
//====
|
|
||||||
//MMIO
|
//MMIO
|
||||||
//====
|
|
||||||
|
|
||||||
//$2181-$2183
|
//$2181-$2183
|
||||||
uint32 wram_addr;
|
uint32 wram_addr;
|
||||||
|
|
||||||
|
@ -118,12 +116,10 @@ public:
|
||||||
unsigned shift;
|
unsigned shift;
|
||||||
} alu;
|
} alu;
|
||||||
|
|
||||||
void power();
|
static void Enter();
|
||||||
void reset();
|
void enter();
|
||||||
|
void op_irq();
|
||||||
void serialize(serializer&);
|
debugvirtual void op_step();
|
||||||
CPU();
|
|
||||||
~CPU();
|
|
||||||
|
|
||||||
friend class CPUDebugger;
|
friend class CPUDebugger;
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,14 +1,4 @@
|
||||||
//============================
|
|
||||||
//CPU<>APU communication ports
|
|
||||||
//============================
|
|
||||||
|
|
||||||
uint8 apu_port[4];
|
uint8 apu_port[4];
|
||||||
uint8 port_read(uint8 port) { return apu_port[port & 3]; }
|
|
||||||
void port_write(uint8 port, uint8 data) { apu_port[port & 3] = data; }
|
|
||||||
|
|
||||||
//======================
|
|
||||||
//core CPU bus functions
|
|
||||||
//======================
|
|
||||||
|
|
||||||
void op_io();
|
void op_io();
|
||||||
debugvirtual uint8 op_read(uint32 addr);
|
debugvirtual uint8 op_read(uint32 addr);
|
||||||
|
|
|
@ -3,9 +3,6 @@ void mmio_reset();
|
||||||
uint8 mmio_read(unsigned addr);
|
uint8 mmio_read(unsigned addr);
|
||||||
void mmio_write(unsigned addr, uint8 data);
|
void mmio_write(unsigned addr, uint8 data);
|
||||||
|
|
||||||
uint8 pio();
|
|
||||||
bool joylatch();
|
|
||||||
|
|
||||||
uint8 mmio_r2180();
|
uint8 mmio_r2180();
|
||||||
uint8 mmio_r4016();
|
uint8 mmio_r4016();
|
||||||
uint8 mmio_r4017();
|
uint8 mmio_r4017();
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
#ifdef CPU_CPP
|
#ifdef CPU_CPP
|
||||||
|
|
||||||
void CPU::serialize(serializer &s) {
|
void CPU::serialize(serializer &s) {
|
||||||
CPUcore::core_serialize(s);
|
|
||||||
Processor::serialize(s);
|
Processor::serialize(s);
|
||||||
PPUCounter::serialize(s);
|
CPUcore::core_serialize(s);
|
||||||
|
PPUcounter::serialize(s);
|
||||||
s.integer(cpu_version);
|
s.integer(cpu_version);
|
||||||
|
|
||||||
s.integer(status.interrupt_pending);
|
s.integer(status.interrupt_pending);
|
||||||
|
|
|
@ -1,10 +1,11 @@
|
||||||
namespace SNES {
|
namespace SNES {
|
||||||
namespace Info {
|
namespace Info {
|
||||||
static const char Name[] = "bsnes";
|
static const char Name[] = "bsnes";
|
||||||
static const char Version[] = "067.07";
|
static const char Version[] = "067.08";
|
||||||
static const unsigned SerializerVersion = 12;
|
static const unsigned SerializerVersion = 12;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#define DSP_STATE_MACHINE
|
|
||||||
//#define DEBUGGER
|
//#define DEBUGGER
|
||||||
|
#define DSP_STATE_MACHINE
|
||||||
|
#define CHEAT_SYSTEM
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
//this should only be called by CPU::PPUcounter::tick();
|
//this should only be called by CPU::PPUcounter::tick();
|
||||||
//keeps track of previous counter positions in history table
|
//keeps track of previous counter positions in history table
|
||||||
void PPUCounter::tick() {
|
void PPUcounter::tick() {
|
||||||
status.hcounter += 2; //increment by smallest unit of time
|
status.hcounter += 2; //increment by smallest unit of time
|
||||||
if(status.hcounter >= 1360 && status.hcounter == lineclocks()) {
|
if(status.hcounter >= 1360 && status.hcounter == lineclocks()) {
|
||||||
status.hcounter = 0;
|
status.hcounter = 0;
|
||||||
|
@ -15,7 +15,7 @@ void PPUCounter::tick() {
|
||||||
|
|
||||||
//this should only be called by PPU::PPUcounter::tick(n);
|
//this should only be called by PPU::PPUcounter::tick(n);
|
||||||
//allows stepping by more than the smallest unit of time
|
//allows stepping by more than the smallest unit of time
|
||||||
void PPUCounter::tick(unsigned clocks) {
|
void PPUcounter::tick(unsigned clocks) {
|
||||||
status.hcounter += clocks;
|
status.hcounter += clocks;
|
||||||
if(status.hcounter >= lineclocks()) {
|
if(status.hcounter >= lineclocks()) {
|
||||||
status.hcounter -= lineclocks();
|
status.hcounter -= lineclocks();
|
||||||
|
@ -24,7 +24,7 @@ void PPUCounter::tick(unsigned clocks) {
|
||||||
}
|
}
|
||||||
|
|
||||||
//internal
|
//internal
|
||||||
void PPUCounter::vcounter_tick() {
|
void PPUcounter::vcounter_tick() {
|
||||||
if(++status.vcounter == 128) status.interlace = ppu.interlace();
|
if(++status.vcounter == 128) status.interlace = ppu.interlace();
|
||||||
|
|
||||||
if((system.region() == System::Region::NTSC && status.interlace == false && status.vcounter == 262)
|
if((system.region() == System::Region::NTSC && status.interlace == false && status.vcounter == 262)
|
||||||
|
@ -40,13 +40,13 @@ void PPUCounter::vcounter_tick() {
|
||||||
if(scanline) scanline();
|
if(scanline) scanline();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool PPUCounter::field () const { return status.field; }
|
bool PPUcounter::field () const { return status.field; }
|
||||||
uint16 PPUCounter::vcounter() const { return status.vcounter; }
|
uint16 PPUcounter::vcounter() const { return status.vcounter; }
|
||||||
uint16 PPUCounter::hcounter() const { return status.hcounter; }
|
uint16 PPUcounter::hcounter() const { return status.hcounter; }
|
||||||
|
|
||||||
bool PPUCounter::field (unsigned offset) const { return history.field [(history.index - (offset >> 1)) & 2047]; }
|
bool PPUcounter::field (unsigned offset) const { return history.field [(history.index - (offset >> 1)) & 2047]; }
|
||||||
uint16 PPUCounter::vcounter(unsigned offset) const { return history.vcounter[(history.index - (offset >> 1)) & 2047]; }
|
uint16 PPUcounter::vcounter(unsigned offset) const { return history.vcounter[(history.index - (offset >> 1)) & 2047]; }
|
||||||
uint16 PPUCounter::hcounter(unsigned offset) const { return history.hcounter[(history.index - (offset >> 1)) & 2047]; }
|
uint16 PPUcounter::hcounter(unsigned offset) const { return history.hcounter[(history.index - (offset >> 1)) & 2047]; }
|
||||||
|
|
||||||
//one PPU dot = 4 CPU clocks
|
//one PPU dot = 4 CPU clocks
|
||||||
//
|
//
|
||||||
|
@ -57,7 +57,7 @@ uint16 PPUCounter::hcounter(unsigned offset) const { return history.hcounter[(hi
|
||||||
//dot 323 range = { 1292, 1294, 1296 }
|
//dot 323 range = { 1292, 1294, 1296 }
|
||||||
//dot 327 range = { 1310, 1312, 1314 }
|
//dot 327 range = { 1310, 1312, 1314 }
|
||||||
|
|
||||||
uint16 PPUCounter::hdot() const {
|
uint16 PPUcounter::hdot() const {
|
||||||
if(system.region() == System::Region::NTSC && status.interlace == false && vcounter() == 240 && field() == 1) {
|
if(system.region() == System::Region::NTSC && status.interlace == false && vcounter() == 240 && field() == 1) {
|
||||||
return (hcounter() >> 2);
|
return (hcounter() >> 2);
|
||||||
} else {
|
} else {
|
||||||
|
@ -65,12 +65,12 @@ uint16 PPUCounter::hdot() const {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
uint16 PPUCounter::lineclocks() const {
|
uint16 PPUcounter::lineclocks() const {
|
||||||
if(system.region() == System::Region::NTSC && status.interlace == false && vcounter() == 240 && field() == 1) return 1360;
|
if(system.region() == System::Region::NTSC && status.interlace == false && vcounter() == 240 && field() == 1) return 1360;
|
||||||
return 1364;
|
return 1364;
|
||||||
}
|
}
|
||||||
|
|
||||||
void PPUCounter::reset() {
|
void PPUcounter::reset() {
|
||||||
status.interlace = false;
|
status.interlace = false;
|
||||||
status.field = 0;
|
status.field = 0;
|
||||||
status.vcounter = 0;
|
status.vcounter = 0;
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
//PPUCounter emulates the H/V latch counters of the S-PPU2.
|
//PPUcounter emulates the H/V latch counters of the S-PPU2.
|
||||||
//
|
//
|
||||||
//real hardware has the S-CPU maintain its own copy of these counters that are
|
//real hardware has the S-CPU maintain its own copy of these counters that are
|
||||||
//updated based on the state of the S-PPU Vblank and Hblank pins. emulating this
|
//updated based on the state of the S-PPU Vblank and Hblank pins. emulating this
|
||||||
|
@ -10,7 +10,7 @@
|
||||||
//point before this in the frame, which is handled internally by this class at
|
//point before this in the frame, which is handled internally by this class at
|
||||||
//V=128.
|
//V=128.
|
||||||
|
|
||||||
class PPUCounter {
|
class PPUcounter {
|
||||||
public:
|
public:
|
||||||
alwaysinline void tick();
|
alwaysinline void tick();
|
||||||
alwaysinline void tick(unsigned clocks);
|
alwaysinline void tick(unsigned clocks);
|
||||||
|
|
|
@ -112,19 +112,6 @@ void PPU::frame() {
|
||||||
display.interlace = regs.interlace;
|
display.interlace = regs.interlace;
|
||||||
regs.scanlines = (regs.overscan == false) ? 224 : 239;
|
regs.scanlines = (regs.overscan == false) ? 224 : 239;
|
||||||
}
|
}
|
||||||
|
|
||||||
//frame counter
|
|
||||||
static signed framecount = 0;
|
|
||||||
static time_t prev, curr;
|
|
||||||
framecount++;
|
|
||||||
|
|
||||||
time(&curr);
|
|
||||||
if(curr != prev) {
|
|
||||||
status.frames_updated = true;
|
|
||||||
status.frames_executed = framecount;
|
|
||||||
framecount = 0;
|
|
||||||
prev = curr;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void PPU::power() {
|
void PPU::power() {
|
||||||
|
@ -347,7 +334,7 @@ void PPU::power() {
|
||||||
|
|
||||||
void PPU::reset() {
|
void PPU::reset() {
|
||||||
create(Enter, system.cpu_frequency());
|
create(Enter, system.cpu_frequency());
|
||||||
PPUCounter::reset();
|
PPUcounter::reset();
|
||||||
memset(surface, 0, 512 * 512 * sizeof(uint16));
|
memset(surface, 0, 512 * 512 * sizeof(uint16));
|
||||||
|
|
||||||
frame();
|
frame();
|
||||||
|
@ -377,9 +364,6 @@ PPU::PPU() {
|
||||||
surface = new uint16[512 * 512];
|
surface = new uint16[512 * 512];
|
||||||
output = surface + 16 * 512;
|
output = surface + 16 * 512;
|
||||||
|
|
||||||
status.frames_updated = false;
|
|
||||||
status.frames_executed = 0;
|
|
||||||
|
|
||||||
alloc_tiledata_cache();
|
alloc_tiledata_cache();
|
||||||
|
|
||||||
for(unsigned l = 0; l < 16; l++) {
|
for(unsigned l = 0; l < 16; l++) {
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
#include "counter/counter.hpp"
|
#include "counter/counter.hpp"
|
||||||
|
|
||||||
class PPU : public Processor, public PPUCounter, public MMIO {
|
class PPU : public Processor, public PPUcounter, public MMIO {
|
||||||
public:
|
public:
|
||||||
#include "memory/memory.hpp"
|
#include "memory/memory.hpp"
|
||||||
#include "mmio/mmio.hpp"
|
#include "mmio/mmio.hpp"
|
||||||
|
@ -9,11 +9,6 @@ public:
|
||||||
uint16 *surface;
|
uint16 *surface;
|
||||||
uint16 *output;
|
uint16 *output;
|
||||||
|
|
||||||
struct {
|
|
||||||
bool frames_updated;
|
|
||||||
unsigned frames_executed;
|
|
||||||
} status;
|
|
||||||
|
|
||||||
uint8 ppu1_version;
|
uint8 ppu1_version;
|
||||||
uint8 ppu2_version;
|
uint8 ppu2_version;
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
#ifdef PPU_CPP
|
#ifdef PPU_CPP
|
||||||
|
|
||||||
void PPUCounter::serialize(serializer &s) {
|
void PPUcounter::serialize(serializer &s) {
|
||||||
s.integer(status.interlace);
|
s.integer(status.interlace);
|
||||||
s.integer(status.field);
|
s.integer(status.field);
|
||||||
s.integer(status.vcounter);
|
s.integer(status.vcounter);
|
||||||
|
@ -14,10 +14,7 @@ void PPUCounter::serialize(serializer &s) {
|
||||||
|
|
||||||
void PPU::serialize(serializer &s) {
|
void PPU::serialize(serializer &s) {
|
||||||
Processor::serialize(s);
|
Processor::serialize(s);
|
||||||
PPUCounter::serialize(s);
|
PPUcounter::serialize(s);
|
||||||
|
|
||||||
s.integer(status.frames_updated);
|
|
||||||
s.integer(status.frames_executed);
|
|
||||||
|
|
||||||
s.integer(ppu1_version);
|
s.integer(ppu1_version);
|
||||||
s.integer(ppu2_version);
|
s.integer(ppu2_version);
|
||||||
|
|
|
@ -1,9 +1,6 @@
|
||||||
uint8 ram_read(uint16 addr);
|
uint8 ram_read(uint16 addr);
|
||||||
void ram_write(uint16 addr, uint8 data);
|
void ram_write(uint16 addr, uint8 data);
|
||||||
|
|
||||||
uint8 port_read(uint8 port);
|
|
||||||
void port_write(uint8 port, uint8 data);
|
|
||||||
|
|
||||||
uint8 op_busread(uint16 addr);
|
uint8 op_busread(uint16 addr);
|
||||||
void op_buswrite(uint16 addr, uint8 data);
|
void op_buswrite(uint16 addr, uint8 data);
|
||||||
|
|
||||||
|
|
|
@ -4,8 +4,6 @@ void SMP::serialize(serializer &s) {
|
||||||
Processor::serialize(s);
|
Processor::serialize(s);
|
||||||
SMPcore::core_serialize(s);
|
SMPcore::core_serialize(s);
|
||||||
|
|
||||||
s.integer(status.opcode);
|
|
||||||
|
|
||||||
s.integer(status.clock_counter);
|
s.integer(status.clock_counter);
|
||||||
s.integer(status.dsp_counter);
|
s.integer(status.dsp_counter);
|
||||||
s.integer(status.timer_step);
|
s.integer(status.timer_step);
|
||||||
|
|
|
@ -1,22 +1,26 @@
|
||||||
class SMP : public Processor, public SMPcore {
|
class SMP : public Processor, public SMPcore {
|
||||||
public:
|
public:
|
||||||
static const uint8 iplrom[64];
|
|
||||||
|
|
||||||
//synchronization
|
|
||||||
alwaysinline void step(unsigned clocks);
|
alwaysinline void step(unsigned clocks);
|
||||||
alwaysinline void synchronize_cpu();
|
alwaysinline void synchronize_cpu();
|
||||||
alwaysinline void synchronize_dsp();
|
alwaysinline void synchronize_dsp();
|
||||||
|
|
||||||
static void Enter();
|
uint8 port_read(uint8 port);
|
||||||
void enter();
|
void port_write(uint8 port, uint8 data);
|
||||||
debugvirtual void op_step();
|
|
||||||
|
|
||||||
|
void power();
|
||||||
|
void reset();
|
||||||
|
|
||||||
|
void serialize(serializer&);
|
||||||
|
SMP();
|
||||||
|
~SMP();
|
||||||
|
|
||||||
|
private:
|
||||||
#include "memory/memory.hpp"
|
#include "memory/memory.hpp"
|
||||||
#include "timing/timing.hpp"
|
#include "timing/timing.hpp"
|
||||||
|
|
||||||
struct {
|
static const uint8 iplrom[64];
|
||||||
uint8 opcode;
|
|
||||||
|
|
||||||
|
struct {
|
||||||
//timing
|
//timing
|
||||||
unsigned clock_counter;
|
unsigned clock_counter;
|
||||||
unsigned dsp_counter;
|
unsigned dsp_counter;
|
||||||
|
@ -40,14 +44,11 @@ public:
|
||||||
uint8 smp_f8, smp_f9;
|
uint8 smp_f8, smp_f9;
|
||||||
} status;
|
} status;
|
||||||
|
|
||||||
//ssmp.cpp
|
static void Enter();
|
||||||
void power();
|
void enter();
|
||||||
void reset();
|
debugvirtual void op_step();
|
||||||
|
|
||||||
void serialize(serializer&);
|
|
||||||
SMP();
|
|
||||||
~SMP();
|
|
||||||
|
|
||||||
|
friend class SMPcore;
|
||||||
friend class SMPDebugger;
|
friend class SMPDebugger;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -1,35 +1,25 @@
|
||||||
rm -r audio
|
synchronize() {
|
||||||
rm -r cartridge
|
if [ -d ../asnes/"$1" ]; then
|
||||||
rm -r cheat
|
test -d "$1" && rm -r "$1"
|
||||||
rm -r chip
|
cp -r ../asnes/"$1" ./"$1"
|
||||||
rm -r config
|
fi
|
||||||
rm -r cpu
|
}
|
||||||
rm -r debugger
|
|
||||||
rm -r input
|
|
||||||
rm -r interface
|
|
||||||
rm -r libsnes
|
|
||||||
rm -r memory
|
|
||||||
rm -r scheduler
|
|
||||||
rm -r smp
|
|
||||||
rm -r system
|
|
||||||
rm -r video
|
|
||||||
rm -r snes.hpp
|
|
||||||
rm -r Makefile
|
|
||||||
|
|
||||||
cp -r ../asnes/audio ./audio
|
synchronize "audio"
|
||||||
cp -r ../asnes/cartridge ./cartridge
|
synchronize "cartridge"
|
||||||
cp -r ../asnes/cheat ./cheat
|
synchronize "cheat"
|
||||||
cp -r ../asnes/chip ./chip
|
synchronize "chip"
|
||||||
cp -r ../asnes/config ./config
|
synchronize "config"
|
||||||
cp -r ../asnes/cpu ./cpu
|
synchronize "cpu"
|
||||||
cp -r ../asnes/debugger ./debugger
|
synchronize "debugger"
|
||||||
cp -r ../asnes/input ./input
|
synchronize "input"
|
||||||
cp -r ../asnes/interface ./interface
|
synchronize "interface"
|
||||||
cp -r ../asnes/libsnes ./libsnes
|
synchronize "libsnes"
|
||||||
cp -r ../asnes/memory ./memory
|
synchronize "memory"
|
||||||
cp -r ../asnes/scheduler ./scheduler
|
synchronize "ppu/counter"
|
||||||
cp -r ../asnes/smp ./smp
|
synchronize "scheduler"
|
||||||
cp -r ../asnes/system ./system
|
synchronize "smp"
|
||||||
cp -r ../asnes/video ./video
|
synchronize "system"
|
||||||
cp -r ../asnes/snes.hpp ./snes.hpp
|
synchronize "video"
|
||||||
cp -r ../asnes/Makefile ./Makefile
|
synchronize "snes.hpp"
|
||||||
|
synchronize "Makefile"
|
||||||
|
|
|
@ -28,7 +28,6 @@ public:
|
||||||
bool unserialize(serializer&);
|
bool unserialize(serializer&);
|
||||||
|
|
||||||
System();
|
System();
|
||||||
virtual ~System() {}
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Interface *interface;
|
Interface *interface;
|
||||||
|
@ -42,8 +41,6 @@ private:
|
||||||
friend class Video;
|
friend class Video;
|
||||||
friend class Audio;
|
friend class Audio;
|
||||||
friend class Input;
|
friend class Input;
|
||||||
friend class StateManager;
|
|
||||||
friend void threadentry_cop();
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#include <video/video.hpp>
|
#include <video/video.hpp>
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
class Video {
|
class Video {
|
||||||
|
private:
|
||||||
bool frame_hires;
|
bool frame_hires;
|
||||||
bool frame_interlace;
|
bool frame_interlace;
|
||||||
unsigned line_width[240];
|
unsigned line_width[240];
|
||||||
|
|
|
@ -43,6 +43,19 @@ void Interface::video_refresh(const uint16_t *data, unsigned width, unsigned hei
|
||||||
#if defined(DEBUGGER)
|
#if defined(DEBUGGER)
|
||||||
debugger->frameTick();
|
debugger->frameTick();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
//frame counter
|
||||||
|
static signed frameCount = 0;
|
||||||
|
static time_t prev, curr;
|
||||||
|
frameCount++;
|
||||||
|
|
||||||
|
time(&curr);
|
||||||
|
if(curr != prev) {
|
||||||
|
framesUpdated = true;
|
||||||
|
framesExecuted = frameCount;
|
||||||
|
frameCount = 0;
|
||||||
|
prev = curr;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Interface::audio_sample(uint16_t left, uint16_t right) {
|
void Interface::audio_sample(uint16_t left, uint16_t right) {
|
||||||
|
|
|
@ -8,6 +8,8 @@ public:
|
||||||
Interface();
|
Interface();
|
||||||
void captureScreenshot(uint32_t*, unsigned, unsigned, unsigned);
|
void captureScreenshot(uint32_t*, unsigned, unsigned, unsigned);
|
||||||
bool saveScreenshot;
|
bool saveScreenshot;
|
||||||
|
bool framesUpdated;
|
||||||
|
unsigned framesExecuted;
|
||||||
};
|
};
|
||||||
|
|
||||||
extern Interface interface;
|
extern Interface interface;
|
||||||
|
|
|
@ -30,9 +30,9 @@ void Utility::updateSystemState() {
|
||||||
text = "Power off";
|
text = "Power off";
|
||||||
} else if(application.pause == true || application.autopause == true) {
|
} else if(application.pause == true || application.autopause == true) {
|
||||||
text = "Paused";
|
text = "Paused";
|
||||||
} else if(SNES::ppu.status.frames_updated == true) {
|
} else if(interface.framesUpdated == true) {
|
||||||
SNES::ppu.status.frames_updated = false;
|
interface.framesUpdated = false;
|
||||||
text << SNES::ppu.status.frames_executed;
|
text << interface.framesExecuted;
|
||||||
text << " fps";
|
text << " fps";
|
||||||
} else {
|
} else {
|
||||||
//nothing to update
|
//nothing to update
|
||||||
|
|
19
sync.sh
19
sync.sh
|
@ -1,10 +1,13 @@
|
||||||
rm -r libco
|
synchronize() {
|
||||||
rm -r nall
|
if [ -d ../"$1" ]; then
|
||||||
rm -r ruby
|
test -d "$1" && rm -r "$1"
|
||||||
|
cp -r ../"$1" ./"$1"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
cp -r ../libco ./libco
|
synchronize "libco"
|
||||||
cp -r ../nall ./nall
|
synchronize "nall"
|
||||||
cp -r ../ruby ./ruby
|
synchronize "ruby"
|
||||||
|
|
||||||
rm -r libco/doc
|
test -d libco/doc && rm -r libco/doc
|
||||||
rm -r libco/test
|
test -d libco/test && rm -r libco/test
|
||||||
|
|
Loading…
Reference in New Issue