LMMS
Loading...
Searching...
No Matches
Snes_Spc.h
Go to the documentation of this file.
1// SNES SPC-700 APU emulator
2
3// Game_Music_Emu https://bitbucket.org/mpyne/game-music-emu/
4#ifndef SNES_SPC_H
5#define SNES_SPC_H
6
7#include "Spc_Dsp.h"
8#include "blargg_endian.h"
9
10#include <stdint.h>
11
12struct Snes_Spc {
13public:
14 // Must be called once before using
15 blargg_err_t init();
16
17 // Sample pairs generated per second
18 enum { sample_rate = 32000 };
19
20// Emulator use
21
22 // Sets IPL ROM data. Library does not include ROM data. Most SPC music files
23 // don't need ROM, but a full emulator must provide this.
24 enum { rom_size = 0x40 };
25 void init_rom( uint8_t const rom [rom_size] );
26
27 // Sets destination for output samples
28 typedef short sample_t;
29 void set_output( sample_t* out, int out_size );
30
31 // Number of samples written to output since last set
32 int sample_count() const;
33
34 // Resets SPC to power-on state. This resets your output buffer, so you must
35 // call set_output() after this.
36 void reset();
37
38 // Emulates pressing reset switch on SNES. This resets your output buffer, so
39 // you must call set_output() after this.
40 void soft_reset();
41
42 // 1024000 SPC clocks per second, sample pair every 32 clocks
43 typedef int time_t;
44 enum { clock_rate = 1024000 };
45 enum { clocks_per_sample = 32 };
46
47 // Emulated port read/write at specified time
48 enum { port_count = 4 };
49 int read_port ( time_t, int port );
50 void write_port( time_t, int port, int data );
51
52 // Runs SPC to end_time and starts a new time frame at 0
53 void end_frame( time_t end_time );
54
55// Sound control
56
57 // Mutes voices corresponding to non-zero bits in mask (issues repeated KOFF events).
58 // Reduces emulation accuracy.
59 enum { voice_count = 8 };
60 void mute_voices( int mask );
61
62 // If true, prevents channels and global volumes from being phase-negated.
63 // Only supported by fast DSP.
64 void disable_surround( bool disable = true );
65
66 // Sets tempo, where tempo_unit = normal, tempo_unit / 2 = half speed, etc.
67 enum { tempo_unit = 0x100 };
68 void set_tempo( int );
69
70// SPC music files
71
72 // Loads SPC data into emulator
73 enum { spc_min_file_size = 0x10180 };
74 enum { spc_file_size = 0x10200 };
75 blargg_err_t load_spc( void const* in, long size );
76
77 // Clears echo region. Useful after loading an SPC as many have garbage in echo.
78 void clear_echo();
79
80 // Plays for count samples and write samples to out. Discards samples if out
81 // is NULL. Count must be a multiple of 2 since output is stereo.
82 blargg_err_t play( int count, sample_t* out );
83
84 // Skips count samples. Several times faster than play() when using fast DSP.
85 blargg_err_t skip( int count );
86
87// State save/load (only available with accurate DSP)
88
89#if !SPC_NO_COPY_STATE_FUNCS
90 // Saves/loads state
91 enum { state_size = 67 * 1024L }; // maximum space needed when saving
92 typedef Spc_Dsp::copy_func_t copy_func_t;
93 void copy_state( unsigned char** io, copy_func_t );
94
95 // Writes minimal header to spc_out
96 static void init_header( void* spc_out );
97
98 // Saves emulator state as SPC file data. Writes spc_file_size bytes to spc_out.
99 // Does not set up SPC header; use init_header() for that.
100 void save_spc( void* spc_out );
101
102 // Returns true if new key-on events occurred since last check. Useful for
103 // trimming silence while saving an SPC.
104 bool check_kon();
105#endif
106
107public:
108 // TODO: document
118 regs_t& smp_regs() { return m.cpu_regs; }
119
120 uint8_t* smp_ram() { return m.ram.ram; }
121
122 void run_until( time_t t ) { run_until_( t ); }
123public:
124 BLARGG_DISABLE_NOTHROW
125
126 // Time relative to m_spc_time. Speeds up code a bit by eliminating need to
127 // constantly add m_spc_time to time from CPU. CPU uses time that ends at
128 // 0 to eliminate reloading end time every instruction. It pays off.
129 typedef int rel_time_t;
130
131 struct Timer
132 {
133 rel_time_t next_time; // time of next event
139 };
140 enum { reg_count = 0x10 };
141 enum { timer_count = 3 };
143
144 enum { signature_size = 35 };
145
146private:
148
149 #if SPC_LESS_ACCURATE
150 static signed char const reg_times_ [256];
151 signed char reg_times [256];
152 #endif
153
154 struct state_t
155 {
157
159
161
165
166 int tempo;
169 const char* cpu_error;
170
176
180
181 unsigned char cycle_table [256];
182
183 struct
184 {
185 // padding to neutralize address overflow
186 union {
188 uint16_t align; // makes compiler align data for 16-bit access
189 } padding1 [1];
190 uint8_t ram [0x10000];
193 };
195
196 enum { rom_addr = 0xFFC0 };
197
198 enum { skipping_time = 127 };
199
200 // Value that padding should be filled with
201 enum { cpu_pad_fill = 0xFF };
202
203 enum {
204 r_test = 0x0, r_control = 0x1,
205 r_dspaddr = 0x2, r_dspdata = 0x3,
206 r_cpuio0 = 0x4, r_cpuio1 = 0x5,
207 r_cpuio2 = 0x6, r_cpuio3 = 0x7,
208 r_f8 = 0x8, r_f9 = 0x9,
209 r_t0target = 0xA, r_t1target = 0xB, r_t2target = 0xC,
210 r_t0out = 0xD, r_t1out = 0xE, r_t2out = 0xF
211 };
212
213 void timers_loaded();
214 void enable_rom( int enable );
215 void reset_buf();
216 void save_extra();
217 void load_regs( uint8_t const in [reg_count] );
218 void ram_loaded();
219 void regs_loaded();
220 void reset_time_regs();
221 void reset_common( int timer_counter_init );
222
223 Timer* run_timer_ ( Timer* t, rel_time_t );
224 Timer* run_timer ( Timer* t, rel_time_t );
225 int dsp_read ( rel_time_t );
226 void dsp_write ( int data, rel_time_t );
227 void cpu_write_smp_reg_( int data, rel_time_t, uint16_t addr );
228 void cpu_write_smp_reg ( int data, rel_time_t, uint16_t addr );
229 void cpu_write_high ( int data, uint8_t i );
230 void cpu_write ( int data, uint16_t addr, rel_time_t );
231 int cpu_read_smp_reg ( int i, rel_time_t );
232 int cpu_read ( uint16_t addr, rel_time_t );
233 unsigned CPU_mem_bit ( uint16_t pc, rel_time_t );
234
235 bool check_echo_access ( int addr );
237
255
256 static char const signature [signature_size + 1];
257
259};
260
261#include <assert.h>
262
263inline int Snes_Spc::sample_count() const { return (m.extra_clocks >> 5) * 2; }
264
265inline int Snes_Spc::read_port( time_t t, int port )
266{
267 assert( (unsigned) port < port_count );
268 return run_until_( t ) [port];
269}
270
271inline void Snes_Spc::write_port( time_t t, int port, int data )
272{
273 assert( (unsigned) port < port_count );
274 run_until_( t ) [0x10 + port] = data;
275}
276
277inline void Snes_Spc::mute_voices( int mask ) { dsp.mute_voices( mask ); }
278
279inline void Snes_Spc::disable_surround( bool disable ) { dsp.disable_surround( disable ); }
280
281#if !SPC_NO_COPY_STATE_FUNCS
282inline bool Snes_Spc::check_kon() { return dsp.check_kon(); }
283#endif
284
285#endif
assert(0)
uint16_t pc
Definition Spc_Cpu.h:144
LADSPA_Data sample_t
Definition basics.h:100
static const unsigned long mask[]
Definition bitwise.c:31
struct huft * t
Definition inflate.c:943
register unsigned i
Definition inflate.c:1575
JSAMPIMAGE data
Definition jpeglib.h:945
float in
Definition lilv_test.c:1460
float out
Definition lilv_test.c:1461
unsigned short uint16_t
Definition mid.cpp:99
unsigned char uint8_t
Definition mid.cpp:98
Definition audio_fx.h:36
Definition Snes_Spc.h:132
int counter
Definition Snes_Spc.h:138
int prescaler
Definition Snes_Spc.h:134
int period
Definition Snes_Spc.h:135
int divider
Definition Snes_Spc.h:136
int enabled
Definition Snes_Spc.h:137
rel_time_t next_time
Definition Snes_Spc.h:133
Definition Snes_Spc.h:110
uint8_t psw
Definition Snes_Spc.h:115
uint16_t pc
Definition Snes_Spc.h:111
uint8_t sp
Definition Snes_Spc.h:116
uint8_t x
Definition Snes_Spc.h:113
uint8_t y
Definition Snes_Spc.h:114
uint8_t a
Definition Snes_Spc.h:112
Definition Snes_Spc.h:239
uint8_t a
Definition Snes_Spc.h:244
uint8_t ipl_rom[0x40]
Definition Snes_Spc.h:253
uint8_t sp
Definition Snes_Spc.h:248
uint8_t ram[0x10000]
Definition Snes_Spc.h:250
uint8_t y
Definition Snes_Spc.h:246
uint8_t unused[0x40]
Definition Snes_Spc.h:252
uint8_t x
Definition Snes_Spc.h:245
char signature[signature_size]
Definition Snes_Spc.h:240
uint8_t pcl
Definition Snes_Spc.h:243
char text[212]
Definition Snes_Spc.h:249
uint8_t pch
Definition Snes_Spc.h:243
uint8_t psw
Definition Snes_Spc.h:247
uint8_t has_id666
Definition Snes_Spc.h:241
uint8_t version
Definition Snes_Spc.h:242
Definition Snes_Spc.h:155
sample_t * extra_pos
Definition Snes_Spc.h:174
uint8_t smp_regs[2][reg_count]
Definition Snes_Spc.h:158
int skipped_koff
Definition Snes_Spc.h:168
uint8_t ram[0x10000]
Definition Snes_Spc.h:190
int rom_enabled
Definition Snes_Spc.h:177
time_t spc_time
Definition Snes_Spc.h:163
int tempo
Definition Snes_Spc.h:166
rel_time_t dsp_time
Definition Snes_Spc.h:162
Timer timers[timer_count]
Definition Snes_Spc.h:156
uint8_t hi_ram[rom_size]
Definition Snes_Spc.h:179
sample_t const * buf_end
Definition Snes_Spc.h:173
uint8_t padding2[0x100]
Definition Snes_Spc.h:191
sample_t extra_buf[extra_size]
Definition Snes_Spc.h:175
unsigned char cycle_table[256]
Definition Snes_Spc.h:181
uint8_t padding1[0x100]
Definition Snes_Spc.h:187
uint8_t rom[rom_size]
Definition Snes_Spc.h:178
regs_t cpu_regs
Definition Snes_Spc.h:160
int extra_clocks
Definition Snes_Spc.h:171
int skipped_kon
Definition Snes_Spc.h:167
const char * cpu_error
Definition Snes_Spc.h:169
sample_t * buf_begin
Definition Snes_Spc.h:172
bool echo_accessed
Definition Snes_Spc.h:164
uint16_t align
Definition Snes_Spc.h:188
Definition Snes_Spc.h:12
@ rom_size
Definition Snes_Spc.h:24
void reset_common(int timer_counter_init)
Definition Snes_Spc.cpp:180
void regs_loaded()
Definition Snes_Spc.cpp:151
@ port_count
Definition Snes_Spc.h:48
state_t m
Definition Snes_Spc.h:194
void cpu_write(int data, uint16_t addr, rel_time_t)
Definition Spc_Cpu.cpp:404
void write_port(time_t, int port, int data)
Definition Snes_Spc.h:271
void reset_buf()
Definition Snes_Spc.cpp:264
void reset_time_regs()
Definition Snes_Spc.cpp:157
uint8_t * run_until_(time_t end_time)
void save_extra()
Definition Snes_Spc.cpp:314
@ r_dspaddr
Definition Snes_Spc.h:205
@ r_cpuio3
Definition Snes_Spc.h:207
@ r_t2target
Definition Snes_Spc.h:209
@ r_cpuio1
Definition Snes_Spc.h:206
@ r_t2out
Definition Snes_Spc.h:210
@ r_f8
Definition Snes_Spc.h:208
@ r_t0out
Definition Snes_Spc.h:210
@ r_dspdata
Definition Snes_Spc.h:205
@ r_f9
Definition Snes_Spc.h:208
@ r_t1out
Definition Snes_Spc.h:210
@ r_t1target
Definition Snes_Spc.h:209
@ r_cpuio0
Definition Snes_Spc.h:206
@ r_control
Definition Snes_Spc.h:204
@ r_t0target
Definition Snes_Spc.h:209
@ r_cpuio2
Definition Snes_Spc.h:207
@ r_test
Definition Snes_Spc.h:204
void ram_loaded()
Definition Snes_Spc.cpp:140
void cpu_write_smp_reg_(int data, rel_time_t, uint16_t addr)
Definition Spc_Cpu.cpp:287
int dsp_read(rel_time_t)
Definition Spc_Cpu.cpp:141
void reset()
Definition Snes_Spc.cpp:204
void set_output(sample_t *out, int out_size)
Definition Snes_Spc.cpp:277
static signed char const reg_times_[256]
Definition Snes_Spc.h:99
@ timer_count
Definition Snes_Spc.h:141
@ clock_rate
Definition Snes_Spc.h:44
short sample_t
Definition Snes_Spc.h:28
void end_frame(time_t end_time)
Definition Spc_Cpu.cpp:518
void soft_reset()
Definition Snes_Spc.cpp:198
@ rom_addr
Definition Snes_Spc.h:196
@ signature_size
Definition Snes_Spc.h:144
@ cpu_pad_fill
Definition Snes_Spc.h:201
void timers_loaded()
Definition Snes_Spc.cpp:110
signed char reg_times[256]
Definition Snes_Spc.h:151
blargg_err_t play(int count, sample_t *out)
Definition Snes_Spc.cpp:337
void cpu_write_smp_reg(int data, rel_time_t, uint16_t addr)
Definition Spc_Cpu.cpp:388
@ tempo_unit
Definition Snes_Spc.h:67
@ sample_rate
Definition Snes_Spc.h:18
static char const signature[signature_size+1]
Definition Snes_Spc.h:256
Timer * run_timer_(Timer *t, rel_time_t)
Definition Spc_Cpu.cpp:50
void mute_voices(int mask)
Definition Snes_Spc.h:277
bool check_echo_access(int addr)
Definition Spc_Cpu.cpp:197
void enable_rom(int enable)
Definition Spc_Cpu.cpp:81
uint8_t * smp_ram()
Definition Snes_Spc.h:120
int read_port(time_t, int port)
Definition Snes_Spc.h:265
@ skipping_time
Definition Snes_Spc.h:198
int sample_count() const
Definition Snes_Spc.h:263
@ clocks_per_sample
Definition Snes_Spc.h:45
int cpu_read_smp_reg(int i, rel_time_t)
Definition Spc_Cpu.cpp:438
int time_t
Definition Snes_Spc.h:43
Timer * run_timer(Timer *t, rel_time_t)
Definition Spc_Cpu.cpp:71
@ spc_min_file_size
Definition Snes_Spc.h:73
int cpu_read(uint16_t addr, rel_time_t)
Definition Spc_Cpu.cpp:452
void clear_echo()
Definition Snes_Spc.cpp:249
void run_until(time_t t)
Definition Snes_Spc.h:122
void init_rom(uint8_t const rom[rom_size])
Definition Snes_Spc.cpp:80
blargg_err_t skip(int count)
Definition Snes_Spc.cpp:351
blargg_err_t init()
Definition Snes_Spc.cpp:32
@ spc_file_size
Definition Snes_Spc.h:74
void set_tempo(int)
Definition Snes_Spc.cpp:85
@ voice_count
Definition Snes_Spc.h:59
@ extra_size
Definition Snes_Spc.h:142
blargg_err_t load_spc(void const *in, long size)
Definition Snes_Spc.cpp:215
BLARGG_DISABLE_NOTHROW typedef int rel_time_t
Definition Snes_Spc.h:129
@ reg_count
Definition Snes_Spc.h:140
regs_t & smp_regs()
Definition Snes_Spc.h:118
void load_regs(uint8_t const in[reg_count])
Definition Snes_Spc.cpp:125
void disable_surround(bool disable=true)
Definition Snes_Spc.h:279
void cpu_write_high(int data, uint8_t i)
Definition Spc_Cpu.cpp:396
unsigned CPU_mem_bit(uint16_t pc, rel_time_t)
Definition Spc_Cpu.h:99
void dsp_write(int data, rel_time_t)
Definition Spc_Cpu.cpp:154
void save_regs(uint8_t out[reg_count])
Definition Spc_Dsp.h:9
@ extra_size
Definition Spc_Dsp.h:84
ulg size
Definition extract.c:2350
_WDL_CSTRING_PREFIX void INT_PTR count
Definition wdlcstring.h:263