132 lines
2.8 KiB
C++
132 lines
2.8 KiB
C++
|
#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
|