cog/Frameworks/GME/higan/smp/smp.hpp

132 lines
2.8 KiB
C++
Executable File

#ifndef _higan_smp_h_
#define _higan_smp_h_
#include "../../gme/blargg_common.h"
#include "../processor/spc700/spc700.hpp"
#include "../dsp/dsp.hpp"
namespace SuperFamicom {
struct SMP : Processor::SPC700 {
long clock;
uint8_t iplrom[64];
uint8_t apuram[64 * 1024];
int64_t dsp_clock_step;
SuperFamicom::DSP dsp;
inline void step(unsigned clocks);
inline void synchronize_dsp();
uint8_t port_read(uint8_t port) const;
void port_write(uint8_t port, uint8_t data);
void enter();
void power();
void reset();
void set_tempo(double);
void render(int16_t * buffer, unsigned count);
void skip(unsigned count);
uint8_t sfm_last[4];
private:
uint8_t const* sfm_queue;
uint8_t const* sfm_queue_end;
uint8_t const* sfm_queue_repeat;
public:
void set_sfm_queue(const uint8_t* queue, const uint8_t* queue_end, const uint8_t* queue_repeat);
const uint8_t* get_sfm_queue() const;
size_t get_sfm_queue_remain() const;
private:
int16_t * sample_buffer;
int16_t const* sample_buffer_end;
public:
bool sample( int16_t, int16_t );
SMP();
~SMP();
struct {
//timing
unsigned clock_counter;
unsigned dsp_counter;
unsigned timer_step;
//$00f0
uint8_t clock_speed;
uint8_t timer_speed;
bool timers_enable;
bool ram_disable;
bool ram_writable;
bool timers_disable;
//$00f1
bool iplrom_enable;
//$00f2
uint8_t dsp_addr;
//$00f8,$00f9
uint8_t ram00f8;
uint8_t ram00f9;
} status;
friend class SMPcore;
//memory.cpp
uint8_t ram_read(uint16_t addr);
void ram_write(uint16_t addr, uint8_t data);
uint8_t op_busread(uint16_t addr);
void op_buswrite(uint16_t addr, uint8_t data);
void op_io();
uint8_t op_read(uint16_t addr);
void op_write(uint16_t addr, uint8_t data);
uint8_t disassembler_read(uint16_t addr);
//timing.cpp
template<unsigned frequency>
struct Timer {
SMP &smp;
uint8_t stage0_ticks;
uint8_t stage1_ticks;
uint8_t stage2_ticks;
uint8_t stage3_ticks;
bool current_line;
bool enable;
uint8_t target;
Timer(SMP &p_smp) : smp( p_smp ) { }
void tick();
void synchronize_stage1();
};
Timer<192> timer0;
Timer<192> timer1;
Timer< 24> timer2;
inline void add_clocks(unsigned clocks);
inline void cycle_edge();
};
inline void SMP::set_tempo(double speed) { dsp_clock_step = (int64_t)(4096.0 / speed); }
inline void SMP::set_sfm_queue(const uint8_t *queue, const uint8_t *queue_end, const uint8_t *queue_repeat) { sfm_queue = queue; sfm_queue_end = queue_end; sfm_queue_repeat = queue_repeat; sfm_last[0] = 0; sfm_last[1] = 0; sfm_last[2] = 0; sfm_last[3] = 0; }
inline const uint8_t* SMP::get_sfm_queue() const { return sfm_queue; }
inline size_t SMP::get_sfm_queue_remain() const { return sfm_queue_end - sfm_queue; }
};
#endif