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,11 +9,11 @@ Configuration::Configuration() {
|
|||
region = System::Region::Autodetect;
|
||||
|
||||
cpu.version = 2;
|
||||
cpu.ntsc_frequency = 21477272;
|
||||
cpu.ntsc_frequency = 21477272; //315 / 88 * 6000000
|
||||
cpu.pal_frequency = 21281370;
|
||||
cpu.wram_init_value = 0x55;
|
||||
|
||||
smp.ntsc_frequency = 24607104; //32040.5 * 768
|
||||
smp.ntsc_frequency = 24607104; //32040.5 * 768
|
||||
smp.pal_frequency = 24607104;
|
||||
|
||||
ppu1.version = 1;
|
||||
|
|
|
@ -106,7 +106,7 @@ void CPU::power() {
|
|||
void CPU::reset() {
|
||||
create(Enter, system.cpu_frequency());
|
||||
coprocessors.reset();
|
||||
PPUCounter::reset();
|
||||
PPUcounter::reset();
|
||||
|
||||
//note: some registers are not fully reset by SNES
|
||||
regs.pc = 0x000000;
|
||||
|
@ -132,7 +132,7 @@ void CPU::reset() {
|
|||
}
|
||||
|
||||
CPU::CPU() {
|
||||
PPUCounter::scanline = { &CPU::scanline, this };
|
||||
PPUcounter::scanline = { &CPU::scanline, this };
|
||||
}
|
||||
|
||||
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:
|
||||
//synchronization
|
||||
array<Processor*> coprocessors;
|
||||
alwaysinline void step(unsigned clocks);
|
||||
alwaysinline void synchronize_smp();
|
||||
void synchronize_ppu();
|
||||
void synchronize_coprocessor();
|
||||
|
||||
static void Enter();
|
||||
void enter();
|
||||
debugvirtual void op_step();
|
||||
void op_irq();
|
||||
bool interrupt_pending() { return status.interrupt_pending; }
|
||||
uint8 pio();
|
||||
bool joylatch();
|
||||
alwaysinline bool interrupt_pending() { return status.interrupt_pending; }
|
||||
alwaysinline uint8 port_read(uint8 port) { return apu_port[port & 3]; }
|
||||
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 "memory/memory.hpp"
|
||||
#include "mmio/mmio.hpp"
|
||||
#include "timing/timing.hpp"
|
||||
|
||||
uint8 cpu_version;
|
||||
|
||||
struct Status {
|
||||
bool interrupt_pending;
|
||||
uint16 interrupt_vector;
|
||||
|
@ -27,10 +34,7 @@ public:
|
|||
unsigned clock_count;
|
||||
unsigned line_clocks;
|
||||
|
||||
//======
|
||||
//timing
|
||||
//======
|
||||
|
||||
bool irq_lock;
|
||||
|
||||
unsigned dram_refresh_position;
|
||||
|
@ -56,10 +60,7 @@ public:
|
|||
|
||||
bool reset_pending;
|
||||
|
||||
//===
|
||||
//DMA
|
||||
//===
|
||||
|
||||
bool dma_active;
|
||||
unsigned dma_counter;
|
||||
unsigned dma_clocks;
|
||||
|
@ -67,10 +68,7 @@ public:
|
|||
bool hdma_pending;
|
||||
bool hdma_mode; //0 = init, 1 = run
|
||||
|
||||
//====
|
||||
//MMIO
|
||||
//====
|
||||
|
||||
//$2181-$2183
|
||||
uint32 wram_addr;
|
||||
|
||||
|
@ -118,12 +116,10 @@ public:
|
|||
unsigned shift;
|
||||
} alu;
|
||||
|
||||
void power();
|
||||
void reset();
|
||||
|
||||
void serialize(serializer&);
|
||||
CPU();
|
||||
~CPU();
|
||||
static void Enter();
|
||||
void enter();
|
||||
void op_irq();
|
||||
debugvirtual void op_step();
|
||||
|
||||
friend class CPUDebugger;
|
||||
};
|
||||
|
|
|
@ -1,14 +1,4 @@
|
|||
//============================
|
||||
//CPU<>APU communication ports
|
||||
//============================
|
||||
|
||||
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();
|
||||
debugvirtual uint8 op_read(uint32 addr);
|
||||
|
|
|
@ -3,9 +3,6 @@ void mmio_reset();
|
|||
uint8 mmio_read(unsigned addr);
|
||||
void mmio_write(unsigned addr, uint8 data);
|
||||
|
||||
uint8 pio();
|
||||
bool joylatch();
|
||||
|
||||
uint8 mmio_r2180();
|
||||
uint8 mmio_r4016();
|
||||
uint8 mmio_r4017();
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
#ifdef CPU_CPP
|
||||
|
||||
void CPU::serialize(serializer &s) {
|
||||
CPUcore::core_serialize(s);
|
||||
Processor::serialize(s);
|
||||
PPUCounter::serialize(s);
|
||||
CPUcore::core_serialize(s);
|
||||
PPUcounter::serialize(s);
|
||||
s.integer(cpu_version);
|
||||
|
||||
s.integer(status.interrupt_pending);
|
||||
|
|
|
@ -1,13 +1,8 @@
|
|||
class DSP : public Processor {
|
||||
public:
|
||||
//synchronization
|
||||
alwaysinline void step(unsigned clocks);
|
||||
alwaysinline void synchronize_smp();
|
||||
|
||||
static void Enter();
|
||||
void enter();
|
||||
void tick();
|
||||
|
||||
uint8 read(uint8 addr);
|
||||
void write(uint8 addr, uint8 data);
|
||||
|
||||
|
@ -18,7 +13,7 @@ public:
|
|||
DSP();
|
||||
~DSP();
|
||||
|
||||
protected:
|
||||
private:
|
||||
//global registers
|
||||
enum global_reg_t {
|
||||
r_mvoll = 0x0c, r_mvolr = 0x1c,
|
||||
|
@ -168,6 +163,11 @@ protected:
|
|||
void echo_29();
|
||||
void echo_30();
|
||||
|
||||
//dsp
|
||||
static void Enter();
|
||||
void enter();
|
||||
void tick();
|
||||
|
||||
friend class DSPDebugger;
|
||||
};
|
||||
|
||||
|
|
|
@ -1,9 +1,10 @@
|
|||
namespace SNES {
|
||||
namespace Info {
|
||||
static const char Name[] = "asnes";
|
||||
static const char Version[] = "000.01";
|
||||
static const char Version[] = "000.02";
|
||||
static const unsigned SerializerVersion = 12;
|
||||
}
|
||||
}
|
||||
|
||||
//#define DEBUGGER
|
||||
#define CHEAT_SYSTEM
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
//this should only be called by CPU::PPUcounter::tick();
|
||||
//keeps track of previous counter positions in history table
|
||||
void PPUCounter::tick() {
|
||||
void PPUcounter::tick() {
|
||||
status.hcounter += 2; //increment by smallest unit of time
|
||||
if(status.hcounter >= 1360 && status.hcounter == lineclocks()) {
|
||||
status.hcounter = 0;
|
||||
|
@ -15,7 +15,7 @@ void PPUCounter::tick() {
|
|||
|
||||
//this should only be called by PPU::PPUcounter::tick(n);
|
||||
//allows stepping by more than the smallest unit of time
|
||||
void PPUCounter::tick(unsigned clocks) {
|
||||
void PPUcounter::tick(unsigned clocks) {
|
||||
status.hcounter += clocks;
|
||||
if(status.hcounter >= lineclocks()) {
|
||||
status.hcounter -= lineclocks();
|
||||
|
@ -24,7 +24,7 @@ void PPUCounter::tick(unsigned clocks) {
|
|||
}
|
||||
|
||||
//internal
|
||||
void PPUCounter::vcounter_tick() {
|
||||
void PPUcounter::vcounter_tick() {
|
||||
if(++status.vcounter == 128) status.interlace = ppu.interlace();
|
||||
|
||||
if((system.region() == System::Region::NTSC && status.interlace == false && status.vcounter == 262)
|
||||
|
@ -40,13 +40,13 @@ void PPUCounter::vcounter_tick() {
|
|||
if(scanline) scanline();
|
||||
}
|
||||
|
||||
bool PPUCounter::field () const { return status.field; }
|
||||
uint16 PPUCounter::vcounter() const { return status.vcounter; }
|
||||
uint16 PPUCounter::hcounter() const { return status.hcounter; }
|
||||
bool PPUcounter::field () const { return status.field; }
|
||||
uint16 PPUcounter::vcounter() const { return status.vcounter; }
|
||||
uint16 PPUcounter::hcounter() const { return status.hcounter; }
|
||||
|
||||
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::hcounter(unsigned offset) const { return history.hcounter[(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::hcounter(unsigned offset) const { return history.hcounter[(history.index - (offset >> 1)) & 2047]; }
|
||||
|
||||
//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 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) {
|
||||
return (hcounter() >> 2);
|
||||
} 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;
|
||||
return 1364;
|
||||
}
|
||||
|
||||
void PPUCounter::reset() {
|
||||
void PPUcounter::reset() {
|
||||
status.interlace = false;
|
||||
status.field = 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
|
||||
//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
|
||||
//V=128.
|
||||
|
||||
class PPUCounter {
|
||||
class PPUcounter {
|
||||
public:
|
||||
alwaysinline void tick();
|
||||
alwaysinline void tick(unsigned clocks);
|
||||
|
|
|
@ -82,7 +82,6 @@ struct {
|
|||
uint16 vcounter;
|
||||
} regs;
|
||||
|
||||
void latch_counters();
|
||||
uint16 get_vram_address();
|
||||
|
||||
uint8 vram_read(unsigned addr);
|
||||
|
@ -94,10 +93,6 @@ void oam_write(unsigned addr, uint8 data);
|
|||
uint8 cgram_read(unsigned addr);
|
||||
void cgram_write(unsigned addr, uint8 data);
|
||||
|
||||
bool interlace() const;
|
||||
bool overscan() const;
|
||||
bool hires() const;
|
||||
|
||||
void mmio_update_video_mode();
|
||||
|
||||
void mmio_w2100(uint8); //INIDISP
|
||||
|
|
|
@ -86,7 +86,7 @@ void PPU::power() {
|
|||
|
||||
void PPU::reset() {
|
||||
create(Enter, system.cpu_frequency());
|
||||
PPUCounter::reset();
|
||||
PPUcounter::reset();
|
||||
memset(surface, 0, 512 * 512 * sizeof(uint16));
|
||||
|
||||
mmio_reset();
|
||||
|
@ -118,19 +118,6 @@ void PPU::frame() {
|
|||
|
||||
display.interlace = regs.interlace;
|
||||
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() :
|
||||
|
@ -143,9 +130,6 @@ window(*this),
|
|||
screen(*this) {
|
||||
surface = new uint16[512 * 512];
|
||||
output = surface + 16 * 512;
|
||||
|
||||
status.frames_updated = false;
|
||||
status.frames_executed = 0;
|
||||
}
|
||||
|
||||
PPU::~PPU() {
|
||||
|
|
|
@ -1,7 +1,23 @@
|
|||
#include "counter/counter.hpp"
|
||||
|
||||
class PPU : public Processor, public PPUCounter, public MMIO {
|
||||
class PPU : public Processor, public PPUcounter, public MMIO {
|
||||
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 "mmio/mmio.hpp"
|
||||
#include "screen/screen.hpp"
|
||||
|
@ -19,11 +35,6 @@ public:
|
|||
uint16 *surface;
|
||||
uint16 *output;
|
||||
|
||||
struct {
|
||||
bool frames_updated;
|
||||
unsigned frames_executed;
|
||||
} status;
|
||||
|
||||
uint8 ppu1_version;
|
||||
uint8 ppu2_version;
|
||||
|
||||
|
@ -32,23 +43,18 @@ public:
|
|||
bool overscan;
|
||||
} display;
|
||||
|
||||
//synchronization
|
||||
alwaysinline void step(unsigned clocks);
|
||||
alwaysinline void synchronize_cpu();
|
||||
|
||||
static void Enter();
|
||||
void enter();
|
||||
void add_clocks(unsigned);
|
||||
|
||||
void power();
|
||||
void reset();
|
||||
|
||||
void scanline();
|
||||
void frame();
|
||||
|
||||
void serialize(serializer&);
|
||||
PPU();
|
||||
~PPU();
|
||||
friend class PPU::Background;
|
||||
friend class PPU::Sprite;
|
||||
friend class PPU::Window;
|
||||
friend class PPU::Screen;
|
||||
friend class Video;
|
||||
};
|
||||
|
||||
#if defined(DEBUGGER)
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
#ifdef PPU_CPP
|
||||
|
||||
void PPUCounter::serialize(serializer &s) {
|
||||
void PPUcounter::serialize(serializer &s) {
|
||||
s.integer(status.interlace);
|
||||
s.integer(status.field);
|
||||
s.integer(status.vcounter);
|
||||
|
@ -14,10 +14,7 @@ void PPUCounter::serialize(serializer &s) {
|
|||
|
||||
void PPU::serialize(serializer &s) {
|
||||
Processor::serialize(s);
|
||||
PPUCounter::serialize(s);
|
||||
|
||||
s.integer(status.frames_updated);
|
||||
s.integer(status.frames_executed);
|
||||
PPUcounter::serialize(s);
|
||||
|
||||
s.integer(ppu1_version);
|
||||
s.integer(ppu2_version);
|
||||
|
|
|
@ -1,9 +1,6 @@
|
|||
uint8 ram_read(uint16 addr);
|
||||
void ram_write(uint16 addr, uint8 data);
|
||||
|
||||
uint8 port_read(uint8 port);
|
||||
void port_write(uint8 port, uint8 data);
|
||||
|
||||
uint8 op_busread(uint16 addr);
|
||||
void op_buswrite(uint16 addr, uint8 data);
|
||||
|
||||
|
|
|
@ -4,8 +4,6 @@ void SMP::serialize(serializer &s) {
|
|||
Processor::serialize(s);
|
||||
SMPcore::core_serialize(s);
|
||||
|
||||
s.integer(status.opcode);
|
||||
|
||||
s.integer(status.clock_counter);
|
||||
s.integer(status.dsp_counter);
|
||||
s.integer(status.timer_step);
|
||||
|
|
|
@ -1,22 +1,26 @@
|
|||
class SMP : public Processor, public SMPcore {
|
||||
public:
|
||||
static const uint8 iplrom[64];
|
||||
|
||||
//synchronization
|
||||
alwaysinline void step(unsigned clocks);
|
||||
alwaysinline void synchronize_cpu();
|
||||
alwaysinline void synchronize_dsp();
|
||||
|
||||
static void Enter();
|
||||
void enter();
|
||||
debugvirtual void op_step();
|
||||
uint8 port_read(uint8 port);
|
||||
void port_write(uint8 port, uint8 data);
|
||||
|
||||
void power();
|
||||
void reset();
|
||||
|
||||
void serialize(serializer&);
|
||||
SMP();
|
||||
~SMP();
|
||||
|
||||
private:
|
||||
#include "memory/memory.hpp"
|
||||
#include "timing/timing.hpp"
|
||||
|
||||
struct {
|
||||
uint8 opcode;
|
||||
static const uint8 iplrom[64];
|
||||
|
||||
struct {
|
||||
//timing
|
||||
unsigned clock_counter;
|
||||
unsigned dsp_counter;
|
||||
|
@ -40,14 +44,11 @@ public:
|
|||
uint8 smp_f8, smp_f9;
|
||||
} status;
|
||||
|
||||
//ssmp.cpp
|
||||
void power();
|
||||
void reset();
|
||||
|
||||
void serialize(serializer&);
|
||||
SMP();
|
||||
~SMP();
|
||||
static void Enter();
|
||||
void enter();
|
||||
debugvirtual void op_step();
|
||||
|
||||
friend class SMPcore;
|
||||
friend class SMPDebugger;
|
||||
};
|
||||
|
||||
|
|
|
@ -28,7 +28,6 @@ public:
|
|||
bool unserialize(serializer&);
|
||||
|
||||
System();
|
||||
virtual ~System() {}
|
||||
|
||||
private:
|
||||
Interface *interface;
|
||||
|
@ -42,8 +41,6 @@ private:
|
|||
friend class Video;
|
||||
friend class Audio;
|
||||
friend class Input;
|
||||
friend class StateManager;
|
||||
friend void threadentry_cop();
|
||||
};
|
||||
|
||||
#include <video/video.hpp>
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
class Video {
|
||||
private:
|
||||
bool frame_hires;
|
||||
bool frame_interlace;
|
||||
unsigned line_width[240];
|
||||
|
|
|
@ -9,11 +9,11 @@ Configuration::Configuration() {
|
|||
region = System::Region::Autodetect;
|
||||
|
||||
cpu.version = 2;
|
||||
cpu.ntsc_frequency = 21477272;
|
||||
cpu.ntsc_frequency = 21477272; //315 / 88 * 6000000
|
||||
cpu.pal_frequency = 21281370;
|
||||
cpu.wram_init_value = 0x55;
|
||||
|
||||
smp.ntsc_frequency = 24607104; //32040.5 * 768
|
||||
smp.ntsc_frequency = 24607104; //32040.5 * 768
|
||||
smp.pal_frequency = 24607104;
|
||||
|
||||
ppu1.version = 1;
|
||||
|
|
|
@ -106,7 +106,7 @@ void CPU::power() {
|
|||
void CPU::reset() {
|
||||
create(Enter, system.cpu_frequency());
|
||||
coprocessors.reset();
|
||||
PPUCounter::reset();
|
||||
PPUcounter::reset();
|
||||
|
||||
//note: some registers are not fully reset by SNES
|
||||
regs.pc = 0x000000;
|
||||
|
@ -132,7 +132,7 @@ void CPU::reset() {
|
|||
}
|
||||
|
||||
CPU::CPU() {
|
||||
PPUCounter::scanline = { &CPU::scanline, this };
|
||||
PPUcounter::scanline = { &CPU::scanline, this };
|
||||
}
|
||||
|
||||
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:
|
||||
//synchronization
|
||||
array<Processor*> coprocessors;
|
||||
alwaysinline void step(unsigned clocks);
|
||||
alwaysinline void synchronize_smp();
|
||||
void synchronize_ppu();
|
||||
void synchronize_coprocessor();
|
||||
|
||||
static void Enter();
|
||||
void enter();
|
||||
debugvirtual void op_step();
|
||||
void op_irq();
|
||||
bool interrupt_pending() { return status.interrupt_pending; }
|
||||
uint8 pio();
|
||||
bool joylatch();
|
||||
alwaysinline bool interrupt_pending() { return status.interrupt_pending; }
|
||||
alwaysinline uint8 port_read(uint8 port) { return apu_port[port & 3]; }
|
||||
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 "memory/memory.hpp"
|
||||
#include "mmio/mmio.hpp"
|
||||
#include "timing/timing.hpp"
|
||||
|
||||
uint8 cpu_version;
|
||||
|
||||
struct Status {
|
||||
bool interrupt_pending;
|
||||
uint16 interrupt_vector;
|
||||
|
@ -27,10 +34,7 @@ public:
|
|||
unsigned clock_count;
|
||||
unsigned line_clocks;
|
||||
|
||||
//======
|
||||
//timing
|
||||
//======
|
||||
|
||||
bool irq_lock;
|
||||
|
||||
unsigned dram_refresh_position;
|
||||
|
@ -56,10 +60,7 @@ public:
|
|||
|
||||
bool reset_pending;
|
||||
|
||||
//===
|
||||
//DMA
|
||||
//===
|
||||
|
||||
bool dma_active;
|
||||
unsigned dma_counter;
|
||||
unsigned dma_clocks;
|
||||
|
@ -67,10 +68,7 @@ public:
|
|||
bool hdma_pending;
|
||||
bool hdma_mode; //0 = init, 1 = run
|
||||
|
||||
//====
|
||||
//MMIO
|
||||
//====
|
||||
|
||||
//$2181-$2183
|
||||
uint32 wram_addr;
|
||||
|
||||
|
@ -118,12 +116,10 @@ public:
|
|||
unsigned shift;
|
||||
} alu;
|
||||
|
||||
void power();
|
||||
void reset();
|
||||
|
||||
void serialize(serializer&);
|
||||
CPU();
|
||||
~CPU();
|
||||
static void Enter();
|
||||
void enter();
|
||||
void op_irq();
|
||||
debugvirtual void op_step();
|
||||
|
||||
friend class CPUDebugger;
|
||||
};
|
||||
|
|
|
@ -1,14 +1,4 @@
|
|||
//============================
|
||||
//CPU<>APU communication ports
|
||||
//============================
|
||||
|
||||
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();
|
||||
debugvirtual uint8 op_read(uint32 addr);
|
||||
|
|
|
@ -3,9 +3,6 @@ void mmio_reset();
|
|||
uint8 mmio_read(unsigned addr);
|
||||
void mmio_write(unsigned addr, uint8 data);
|
||||
|
||||
uint8 pio();
|
||||
bool joylatch();
|
||||
|
||||
uint8 mmio_r2180();
|
||||
uint8 mmio_r4016();
|
||||
uint8 mmio_r4017();
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
#ifdef CPU_CPP
|
||||
|
||||
void CPU::serialize(serializer &s) {
|
||||
CPUcore::core_serialize(s);
|
||||
Processor::serialize(s);
|
||||
PPUCounter::serialize(s);
|
||||
CPUcore::core_serialize(s);
|
||||
PPUcounter::serialize(s);
|
||||
s.integer(cpu_version);
|
||||
|
||||
s.integer(status.interrupt_pending);
|
||||
|
|
|
@ -1,10 +1,11 @@
|
|||
namespace SNES {
|
||||
namespace Info {
|
||||
static const char Name[] = "bsnes";
|
||||
static const char Version[] = "067.07";
|
||||
static const char Version[] = "067.08";
|
||||
static const unsigned SerializerVersion = 12;
|
||||
}
|
||||
}
|
||||
|
||||
#define DSP_STATE_MACHINE
|
||||
//#define DEBUGGER
|
||||
#define DSP_STATE_MACHINE
|
||||
#define CHEAT_SYSTEM
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
//this should only be called by CPU::PPUcounter::tick();
|
||||
//keeps track of previous counter positions in history table
|
||||
void PPUCounter::tick() {
|
||||
void PPUcounter::tick() {
|
||||
status.hcounter += 2; //increment by smallest unit of time
|
||||
if(status.hcounter >= 1360 && status.hcounter == lineclocks()) {
|
||||
status.hcounter = 0;
|
||||
|
@ -15,7 +15,7 @@ void PPUCounter::tick() {
|
|||
|
||||
//this should only be called by PPU::PPUcounter::tick(n);
|
||||
//allows stepping by more than the smallest unit of time
|
||||
void PPUCounter::tick(unsigned clocks) {
|
||||
void PPUcounter::tick(unsigned clocks) {
|
||||
status.hcounter += clocks;
|
||||
if(status.hcounter >= lineclocks()) {
|
||||
status.hcounter -= lineclocks();
|
||||
|
@ -24,7 +24,7 @@ void PPUCounter::tick(unsigned clocks) {
|
|||
}
|
||||
|
||||
//internal
|
||||
void PPUCounter::vcounter_tick() {
|
||||
void PPUcounter::vcounter_tick() {
|
||||
if(++status.vcounter == 128) status.interlace = ppu.interlace();
|
||||
|
||||
if((system.region() == System::Region::NTSC && status.interlace == false && status.vcounter == 262)
|
||||
|
@ -40,13 +40,13 @@ void PPUCounter::vcounter_tick() {
|
|||
if(scanline) scanline();
|
||||
}
|
||||
|
||||
bool PPUCounter::field () const { return status.field; }
|
||||
uint16 PPUCounter::vcounter() const { return status.vcounter; }
|
||||
uint16 PPUCounter::hcounter() const { return status.hcounter; }
|
||||
bool PPUcounter::field () const { return status.field; }
|
||||
uint16 PPUcounter::vcounter() const { return status.vcounter; }
|
||||
uint16 PPUcounter::hcounter() const { return status.hcounter; }
|
||||
|
||||
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::hcounter(unsigned offset) const { return history.hcounter[(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::hcounter(unsigned offset) const { return history.hcounter[(history.index - (offset >> 1)) & 2047]; }
|
||||
|
||||
//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 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) {
|
||||
return (hcounter() >> 2);
|
||||
} 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;
|
||||
return 1364;
|
||||
}
|
||||
|
||||
void PPUCounter::reset() {
|
||||
void PPUcounter::reset() {
|
||||
status.interlace = false;
|
||||
status.field = 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
|
||||
//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
|
||||
//V=128.
|
||||
|
||||
class PPUCounter {
|
||||
class PPUcounter {
|
||||
public:
|
||||
alwaysinline void tick();
|
||||
alwaysinline void tick(unsigned clocks);
|
||||
|
|
|
@ -112,19 +112,6 @@ void PPU::frame() {
|
|||
display.interlace = regs.interlace;
|
||||
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() {
|
||||
|
@ -347,7 +334,7 @@ void PPU::power() {
|
|||
|
||||
void PPU::reset() {
|
||||
create(Enter, system.cpu_frequency());
|
||||
PPUCounter::reset();
|
||||
PPUcounter::reset();
|
||||
memset(surface, 0, 512 * 512 * sizeof(uint16));
|
||||
|
||||
frame();
|
||||
|
@ -377,9 +364,6 @@ PPU::PPU() {
|
|||
surface = new uint16[512 * 512];
|
||||
output = surface + 16 * 512;
|
||||
|
||||
status.frames_updated = false;
|
||||
status.frames_executed = 0;
|
||||
|
||||
alloc_tiledata_cache();
|
||||
|
||||
for(unsigned l = 0; l < 16; l++) {
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
#include "counter/counter.hpp"
|
||||
|
||||
class PPU : public Processor, public PPUCounter, public MMIO {
|
||||
class PPU : public Processor, public PPUcounter, public MMIO {
|
||||
public:
|
||||
#include "memory/memory.hpp"
|
||||
#include "mmio/mmio.hpp"
|
||||
|
@ -9,11 +9,6 @@ public:
|
|||
uint16 *surface;
|
||||
uint16 *output;
|
||||
|
||||
struct {
|
||||
bool frames_updated;
|
||||
unsigned frames_executed;
|
||||
} status;
|
||||
|
||||
uint8 ppu1_version;
|
||||
uint8 ppu2_version;
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
#ifdef PPU_CPP
|
||||
|
||||
void PPUCounter::serialize(serializer &s) {
|
||||
void PPUcounter::serialize(serializer &s) {
|
||||
s.integer(status.interlace);
|
||||
s.integer(status.field);
|
||||
s.integer(status.vcounter);
|
||||
|
@ -14,10 +14,7 @@ void PPUCounter::serialize(serializer &s) {
|
|||
|
||||
void PPU::serialize(serializer &s) {
|
||||
Processor::serialize(s);
|
||||
PPUCounter::serialize(s);
|
||||
|
||||
s.integer(status.frames_updated);
|
||||
s.integer(status.frames_executed);
|
||||
PPUcounter::serialize(s);
|
||||
|
||||
s.integer(ppu1_version);
|
||||
s.integer(ppu2_version);
|
||||
|
|
|
@ -1,9 +1,6 @@
|
|||
uint8 ram_read(uint16 addr);
|
||||
void ram_write(uint16 addr, uint8 data);
|
||||
|
||||
uint8 port_read(uint8 port);
|
||||
void port_write(uint8 port, uint8 data);
|
||||
|
||||
uint8 op_busread(uint16 addr);
|
||||
void op_buswrite(uint16 addr, uint8 data);
|
||||
|
||||
|
|
|
@ -4,8 +4,6 @@ void SMP::serialize(serializer &s) {
|
|||
Processor::serialize(s);
|
||||
SMPcore::core_serialize(s);
|
||||
|
||||
s.integer(status.opcode);
|
||||
|
||||
s.integer(status.clock_counter);
|
||||
s.integer(status.dsp_counter);
|
||||
s.integer(status.timer_step);
|
||||
|
|
|
@ -1,22 +1,26 @@
|
|||
class SMP : public Processor, public SMPcore {
|
||||
public:
|
||||
static const uint8 iplrom[64];
|
||||
|
||||
//synchronization
|
||||
alwaysinline void step(unsigned clocks);
|
||||
alwaysinline void synchronize_cpu();
|
||||
alwaysinline void synchronize_dsp();
|
||||
|
||||
static void Enter();
|
||||
void enter();
|
||||
debugvirtual void op_step();
|
||||
uint8 port_read(uint8 port);
|
||||
void port_write(uint8 port, uint8 data);
|
||||
|
||||
void power();
|
||||
void reset();
|
||||
|
||||
void serialize(serializer&);
|
||||
SMP();
|
||||
~SMP();
|
||||
|
||||
private:
|
||||
#include "memory/memory.hpp"
|
||||
#include "timing/timing.hpp"
|
||||
|
||||
struct {
|
||||
uint8 opcode;
|
||||
static const uint8 iplrom[64];
|
||||
|
||||
struct {
|
||||
//timing
|
||||
unsigned clock_counter;
|
||||
unsigned dsp_counter;
|
||||
|
@ -40,14 +44,11 @@ public:
|
|||
uint8 smp_f8, smp_f9;
|
||||
} status;
|
||||
|
||||
//ssmp.cpp
|
||||
void power();
|
||||
void reset();
|
||||
|
||||
void serialize(serializer&);
|
||||
SMP();
|
||||
~SMP();
|
||||
static void Enter();
|
||||
void enter();
|
||||
debugvirtual void op_step();
|
||||
|
||||
friend class SMPcore;
|
||||
friend class SMPDebugger;
|
||||
};
|
||||
|
||||
|
|
|
@ -1,35 +1,25 @@
|
|||
rm -r audio
|
||||
rm -r cartridge
|
||||
rm -r cheat
|
||||
rm -r chip
|
||||
rm -r config
|
||||
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
|
||||
synchronize() {
|
||||
if [ -d ../asnes/"$1" ]; then
|
||||
test -d "$1" && rm -r "$1"
|
||||
cp -r ../asnes/"$1" ./"$1"
|
||||
fi
|
||||
}
|
||||
|
||||
cp -r ../asnes/audio ./audio
|
||||
cp -r ../asnes/cartridge ./cartridge
|
||||
cp -r ../asnes/cheat ./cheat
|
||||
cp -r ../asnes/chip ./chip
|
||||
cp -r ../asnes/config ./config
|
||||
cp -r ../asnes/cpu ./cpu
|
||||
cp -r ../asnes/debugger ./debugger
|
||||
cp -r ../asnes/input ./input
|
||||
cp -r ../asnes/interface ./interface
|
||||
cp -r ../asnes/libsnes ./libsnes
|
||||
cp -r ../asnes/memory ./memory
|
||||
cp -r ../asnes/scheduler ./scheduler
|
||||
cp -r ../asnes/smp ./smp
|
||||
cp -r ../asnes/system ./system
|
||||
cp -r ../asnes/video ./video
|
||||
cp -r ../asnes/snes.hpp ./snes.hpp
|
||||
cp -r ../asnes/Makefile ./Makefile
|
||||
synchronize "audio"
|
||||
synchronize "cartridge"
|
||||
synchronize "cheat"
|
||||
synchronize "chip"
|
||||
synchronize "config"
|
||||
synchronize "cpu"
|
||||
synchronize "debugger"
|
||||
synchronize "input"
|
||||
synchronize "interface"
|
||||
synchronize "libsnes"
|
||||
synchronize "memory"
|
||||
synchronize "ppu/counter"
|
||||
synchronize "scheduler"
|
||||
synchronize "smp"
|
||||
synchronize "system"
|
||||
synchronize "video"
|
||||
synchronize "snes.hpp"
|
||||
synchronize "Makefile"
|
||||
|
|
|
@ -28,7 +28,6 @@ public:
|
|||
bool unserialize(serializer&);
|
||||
|
||||
System();
|
||||
virtual ~System() {}
|
||||
|
||||
private:
|
||||
Interface *interface;
|
||||
|
@ -42,8 +41,6 @@ private:
|
|||
friend class Video;
|
||||
friend class Audio;
|
||||
friend class Input;
|
||||
friend class StateManager;
|
||||
friend void threadentry_cop();
|
||||
};
|
||||
|
||||
#include <video/video.hpp>
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
class Video {
|
||||
private:
|
||||
bool frame_hires;
|
||||
bool frame_interlace;
|
||||
unsigned line_width[240];
|
||||
|
|
|
@ -43,6 +43,19 @@ void Interface::video_refresh(const uint16_t *data, unsigned width, unsigned hei
|
|||
#if defined(DEBUGGER)
|
||||
debugger->frameTick();
|
||||
#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) {
|
||||
|
|
|
@ -8,6 +8,8 @@ public:
|
|||
Interface();
|
||||
void captureScreenshot(uint32_t*, unsigned, unsigned, unsigned);
|
||||
bool saveScreenshot;
|
||||
bool framesUpdated;
|
||||
unsigned framesExecuted;
|
||||
};
|
||||
|
||||
extern Interface interface;
|
||||
|
|
|
@ -30,9 +30,9 @@ void Utility::updateSystemState() {
|
|||
text = "Power off";
|
||||
} else if(application.pause == true || application.autopause == true) {
|
||||
text = "Paused";
|
||||
} else if(SNES::ppu.status.frames_updated == true) {
|
||||
SNES::ppu.status.frames_updated = false;
|
||||
text << SNES::ppu.status.frames_executed;
|
||||
} else if(interface.framesUpdated == true) {
|
||||
interface.framesUpdated = false;
|
||||
text << interface.framesExecuted;
|
||||
text << " fps";
|
||||
} else {
|
||||
//nothing to update
|
||||
|
|
19
sync.sh
19
sync.sh
|
@ -1,10 +1,13 @@
|
|||
rm -r libco
|
||||
rm -r nall
|
||||
rm -r ruby
|
||||
synchronize() {
|
||||
if [ -d ../"$1" ]; then
|
||||
test -d "$1" && rm -r "$1"
|
||||
cp -r ../"$1" ./"$1"
|
||||
fi
|
||||
}
|
||||
|
||||
cp -r ../libco ./libco
|
||||
cp -r ../nall ./nall
|
||||
cp -r ../ruby ./ruby
|
||||
synchronize "libco"
|
||||
synchronize "nall"
|
||||
synchronize "ruby"
|
||||
|
||||
rm -r libco/doc
|
||||
rm -r libco/test
|
||||
test -d libco/doc && rm -r libco/doc
|
||||
test -d libco/test && rm -r libco/test
|
||||
|
|
Loading…
Reference in New Issue