quickerNES/core/Nes_Core.h

117 lines
3.0 KiB
C++

// Internal NES emulator
// Nes_Emu 0.7.0
#ifndef NES_CORE_H
#define NES_CORE_H
#include "blargg_common.h"
#include "Nes_Apu.h"
#include "Nes_Cpu.h"
#include "Nes_Ppu.h"
class Nes_Mapper;
class Nes_Cart;
class Nes_State;
class Nes_Core : private Nes_Cpu {
typedef Nes_Cpu cpu;
public:
Nes_Core();
~Nes_Core();
const char * init();
const char * open( Nes_Cart const* );
void reset( bool full_reset = true, bool erase_battery_ram = false );
blip_time_t emulate_frame();
void close();
void save_state( Nes_State* ) const;
void save_state( Nes_State_* ) const;
void load_state( Nes_State_ const& );
void irq_changed();
void event_changed();
public: private: friend class Nes_Emu;
struct impl_t
{
enum { sram_size = 0x2000 };
uint8_t sram [sram_size];
Nes_Apu apu;
// extra byte allows CPU to always read operand of instruction, which
// might go past end of data
uint8_t unmapped_page [::Nes_Cpu::page_size + 1];
};
impl_t* impl; // keep large arrays separate
unsigned long error_count;
bool sram_present;
public:
unsigned long current_joypad [2];
int joypad_read_count;
Nes_Cart const* cart;
Nes_Mapper* mapper;
nes_state_t nes;
Nes_Ppu ppu;
private:
// noncopyable
Nes_Core( const Nes_Core& );
Nes_Core& operator = ( const Nes_Core& );
// Timing
nes_time_t ppu_2002_time;
void disable_rendering() { clock_ = 0; }
nes_time_t earliest_irq( nes_time_t present );
nes_time_t ppu_frame_length( nes_time_t present );
nes_time_t earliest_event( nes_time_t present );
// APU and Joypad
joypad_state_t joypad;
int read_io( nes_addr_t );
void write_io( nes_addr_t, int data );
static int read_dmc( void* emu, nes_addr_t );
static void apu_irq_changed( void* emu );
// CPU
unsigned sram_readable;
unsigned sram_writable;
unsigned lrom_readable;
nes_time_t clock_;
nes_time_t cpu_time_offset;
nes_time_t emulate_frame_();
nes_addr_t read_vector( nes_addr_t );
void vector_interrupt( nes_addr_t );
static void log_unmapped( nes_addr_t addr, int data = -1 );
void cpu_set_irq_time( nes_time_t t ) { cpu::set_irq_time_( t - 1 - cpu_time_offset ); }
void cpu_set_end_time( nes_time_t t ) { cpu::set_end_time_( t - 1 - cpu_time_offset ); }
nes_time_t cpu_time() const { return clock_ + 1; }
void cpu_adjust_time( int offset );
public: private: friend class Nes_Ppu;
void set_ppu_2002_time( nes_time_t t ) { ppu_2002_time = t - 1 - cpu_time_offset; }
public: private: friend class Nes_Mapper;
void enable_prg_6000();
void enable_sram( bool enabled, bool read_only = false );
nes_time_t clock() const { return clock_; }
void add_mapper_intercept( nes_addr_t start, unsigned size, bool read, bool write );
public: private: friend class Nes_Cpu;
int cpu_read_ppu( nes_addr_t, nes_time_t );
int cpu_read( nes_addr_t, nes_time_t );
void cpu_write( nes_addr_t, int data, nes_time_t );
void cpu_write_2007( int data );
private:
unsigned char data_reader_mapped [page_count + 1]; // extra entry for overflow
unsigned char data_writer_mapped [page_count + 1];
};
int mem_differs( void const* p, int cmp, unsigned long s );
#endif