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:
Tim Allen 2010-08-09 23:33:44 +10:00
parent 94675634c1
commit 973ef89d4a
41 changed files with 205 additions and 283 deletions

View File

@ -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;

View File

@ -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() {

View File

@ -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;
}; };

View File

@ -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);

View File

@ -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();

View File

@ -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);

View File

@ -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;
}; };

View File

@ -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

View File

@ -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;

View File

@ -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);

View File

@ -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

View File

@ -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() {

View File

@ -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)

View File

@ -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);

View File

@ -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);

View File

@ -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);

View File

@ -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;
}; };

View File

@ -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>

View File

@ -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];

View File

@ -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;

View File

@ -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() {

View File

@ -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;
}; };

View File

@ -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);

View File

@ -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();

View File

@ -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);

View File

@ -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

View File

@ -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;

View File

@ -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);

View File

@ -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++) {

View File

@ -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;

View File

@ -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);

View File

@ -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);

View File

@ -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);

View File

@ -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;
}; };

View File

@ -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"

View File

@ -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>

View File

@ -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];

View File

@ -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) {

View File

@ -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;

View File

@ -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
View File

@ -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