diff options
Diffstat (limited to 'plugins/gme/Game_Music_Emu-0.5.2/gme/Snes_Spc.h')
-rw-r--r-- | plugins/gme/Game_Music_Emu-0.5.2/gme/Snes_Spc.h | 121 |
1 files changed, 121 insertions, 0 deletions
diff --git a/plugins/gme/Game_Music_Emu-0.5.2/gme/Snes_Spc.h b/plugins/gme/Game_Music_Emu-0.5.2/gme/Snes_Spc.h new file mode 100644 index 00000000..b558fb71 --- /dev/null +++ b/plugins/gme/Game_Music_Emu-0.5.2/gme/Snes_Spc.h @@ -0,0 +1,121 @@ +// Super Nintendo (SNES) SPC-700 APU Emulator + +// Game_Music_Emu 0.5.2 +#ifndef SNES_SPC_H +#define SNES_SPC_H + +#include "blargg_common.h" +#include "Spc_Cpu.h" +#include "Spc_Dsp.h" + +class Snes_Spc { +public: + + // Load copy of SPC data into emulator. Clear echo buffer if 'clear_echo' is true. + enum { spc_file_size = 0x10180 }; + blargg_err_t load_spc( const void* spc, long spc_size ); + + // Generate 'count' samples and optionally write to 'buf'. Count must be even. + // Sample output is 16-bit 32kHz, signed stereo pairs with the left channel first. + typedef short sample_t; + blargg_err_t play( long count, sample_t* buf = NULL ); + +// Optional functionality + + // Load copy of state into emulator. + typedef Spc_Cpu::registers_t registers_t; + blargg_err_t load_state( const registers_t& cpu_state, const void* ram_64k, + const void* dsp_regs_128 ); + + // Clear echo buffer, useful because many tracks have junk in the buffer. + void clear_echo(); + + // Mute voice n if bit n (1 << n) of mask is set + enum { voice_count = Spc_Dsp::voice_count }; + void mute_voices( int mask ); + + // Skip forward by the specified number of samples (64000 samples = 1 second) + blargg_err_t skip( long count ); + + // Set gain, where 1.0 is normal. When greater than 1.0, output is clamped the + // 16-bit sample range. + void set_gain( double ); + + // If true, prevent channels and global volumes from being phase-negated + void disable_surround( bool disable = true ); + + // Set 128 bytes to use for IPL boot ROM. Makes copy. Default is zero filled, + // to avoid including copyrighted code from the SPC-700. + void set_ipl_rom( const void* ); + + void set_tempo( double ); + +public: + Snes_Spc(); + typedef BOOST::uint8_t uint8_t; +private: + // timers + struct Timer + { + spc_time_t next_tick; + int period; + int count; + int divisor; + int enabled; + int counter; + + void run_until_( spc_time_t ); + void run_until( spc_time_t time ) + { + if ( time >= next_tick ) + run_until_( time ); + } + }; + enum { timer_count = 3 }; + Timer timer [timer_count]; + + // hardware + int extra_cycles; + spc_time_t time() const; + int read( spc_addr_t ); + void write( spc_addr_t, int ); + friend class Spc_Cpu; + + // dsp + sample_t* sample_buf; + sample_t* buf_end; // to do: remove this once possible bug resolved + spc_time_t next_dsp; + Spc_Dsp dsp; + int keys_pressed; + int keys_released; + sample_t skip_sentinel [1]; // special value for play() passed by skip() + void run_dsp( spc_time_t ); + void run_dsp_( spc_time_t ); + bool echo_accessed; + void check_for_echo_access( spc_addr_t ); + + // boot rom + enum { rom_size = 64 }; + enum { rom_addr = 0xFFC0 }; + bool rom_enabled; + void enable_rom( bool ); + + // CPU and RAM (at end because it's large) + Spc_Cpu cpu; + uint8_t extra_ram [rom_size]; + struct { + // padding to catch jumps before beginning or past end + uint8_t padding1 [0x100]; + uint8_t ram [0x10000]; + uint8_t padding2 [0x100]; + } mem; + uint8_t boot_rom [rom_size]; +}; + +inline void Snes_Spc::disable_surround( bool disable ) { dsp.disable_surround( disable ); } + +inline void Snes_Spc::mute_voices( int mask ) { dsp.mute_voices( mask ); } + +inline void Snes_Spc::set_gain( double v ) { dsp.set_gain( v ); } + +#endif |