Browse code

Update snes9x code from 1.53 to 1.6.0.

Notable differences from upstream:
* Did not use the same #include setup for the new byuu apu and instead chose to do things more traditionally, as the latter is also much easier to deal with in Visual Studio than just including .cpp files into other .cpp files...
* MSU1 support not included (I see no need for this in a plugin meant to be used for original SNES music).
* The dynamic rate control on the APU not included (I also see no need for it in this plugin).
* The extra resamplers I added in were removed as the original hermite resampler was folded into a single non-inhertiable resampler.
* Bits of cleanup.

Naram Qashat authored on 2021/04/19 21:20:36
Showing 1 changed files
1 1
deleted file mode 100644
... ...
@@ -1,285 +0,0 @@
1
-// Highly accurate SNES SPC-700 DSP emulator
2
-
3
-// snes_spc 0.9.0
4
-#pragma once
5
-
6
-#include "blargg_common.h"
7
-
8
-class SPC_DSP
9
-{
10
-public:
11
-	// Setup
12
-
13
-	// Initializes DSP and has it use the 64K RAM provided
14
-	void init(uint8_t *ram_64k);
15
-
16
-	// Sets destination for output samples. If out is NULL or out_size is 0,
17
-	// doesn't generate any.
18
-	typedef short sample_t;
19
-	void set_output(sample_t *out, int out_size);
20
-
21
-	// Number of samples written to output since it was last set, always
22
-	// a multiple of 2. Undefined if more samples were generated than
23
-	// output buffer could hold.
24
-	int sample_count() const;
25
-
26
-	// Emulation
27
-
28
-	// Resets DSP to power-on state
29
-	void reset();
30
-
31
-	// Emulates pressing reset switch on SNES
32
-	void soft_reset();
33
-
34
-	// Reads/writes DSP registers. For accuracy, you must first call run()
35
-	// to catch the DSP up to present.
36
-	int  read(int addr) const;
37
-	void write(int addr, int data);
38
-
39
-	// Runs DSP for specified number of clocks (~1024000 per second). Every 32 clocks
40
-	// a pair of samples is be generated.
41
-	void run(int clock_count);
42
-
43
-	// Sound control
44
-
45
-	// Mutes voices corresponding to non-zero bits in mask (issues repeated KOFF events).
46
-	// Reduces emulation accuracy.
47
-	enum { voice_count = 8 };
48
-	void mute_voices(int mask);
49
-
50
-	// State
51
-
52
-	// Resets DSP and uses supplied values to initialize registers
53
-	enum { register_count = 128 };
54
-	void load(const uint8_t regs[register_count]);
55
-
56
-	// Snes9x Accessor
57
-
58
-	int stereo_switch;
59
-	bool rom_enabled; // mirror
60
-	uint8_t *rom, *hi_ram; // mirror
61
-
62
-	void set_stereo_switch(int);
63
-	uint8_t reg_value(int, int);
64
-	int envx_value(int);
65
-
66
-	// DSP register addresses
67
-
68
-	// Global registers
69
-	enum
70
-	{
71
-		r_mvoll = 0x0C,
72
-		r_mvolr = 0x1C,
73
-		r_evoll = 0x2C,
74
-		r_evolr = 0x3C,
75
-		r_kon = 0x4C,
76
-		r_koff = 0x5C,
77
-		r_flg = 0x6C,
78
-		r_endx = 0x7C,
79
-		r_efb = 0x0D,
80
-		r_pmon = 0x2D,
81
-		r_non = 0x3D,
82
-		r_eon = 0x4D,
83
-		r_dir = 0x5D,
84
-		r_esa = 0x6D,
85
-		r_edl = 0x7D,
86
-		r_fir = 0x0F // 8 coefficients at 0x0F, 0x1F ... 0x7F
87
-	};
88
-
89
-	// Voice registers
90
-	enum
91
-	{
92
-		v_voll = 0x00,
93
-		v_volr = 0x01,
94
-		v_pitchl = 0x02,
95
-		v_pitchh = 0x03,
96
-		v_srcn = 0x04,
97
-		v_adsr0 = 0x05,
98
-		v_adsr1 = 0x06,
99
-		v_gain = 0x07,
100
-		v_envx = 0x08,
101
-		v_outx = 0x09
102
-	};
103
-
104
-public:
105
-	enum { extra_size = 16 };
106
-	sample_t *extra() { return this->m.extra; }
107
-	const sample_t *out_pos() const { return this->m.out; }
108
-	void disable_surround(bool) { } // not supported
109
-public:
110
-	enum { echo_hist_size = 8 };
111
-
112
-	enum env_mode_t { env_release, env_attack, env_decay, env_sustain };
113
-	enum { brr_buf_size = 12 };
114
-	struct voice_t
115
-	{
116
-		int buf[brr_buf_size * 2]; // decoded samples (twice the size to simplify wrap handling)
117
-		int buf_pos; // place in buffer where next samples will be decoded
118
-		int interp_pos; // relative fractional position in sample (0x1000 = 1.0)
119
-		int brr_addr; // address of current BRR block
120
-		int brr_offset; // current decoding offset in BRR block
121
-		uint8_t *regs; // pointer to voice's DSP registers
122
-		int vbit; // bitmask for voice: 0x01 for voice 0, 0x02 for voice 1, etc.
123
-		int kon_delay; // KON delay/current setup phase
124
-		env_mode_t env_mode;
125
-		int env; // current envelope level
126
-		int hidden_env; // used by GAIN mode 7, very obscure quirk
127
-		uint8_t t_envx_out;
128
-		int voice_number;
129
-	};
130
-private:
131
-	enum { brr_block_size = 9 };
132
-
133
-	struct state_t
134
-	{
135
-		uint8_t regs[register_count];
136
-
137
-		// Echo history keeps most recent 8 samples (twice the size to simplify wrap handling)
138
-		int echo_hist[echo_hist_size * 2][2];
139
-		int (*echo_hist_pos)[2]; // &echo_hist [0 to 7]
140
-
141
-		bool every_other_sample; // toggles every sample
142
-		int kon; // KON value when last checked
143
-		int noise;
144
-		int counter;
145
-		int echo_offset; // offset from ESA in echo buffer
146
-		int echo_length; // number of bytes that echo_offset will stop at
147
-		int phase; // next clock cycle to run (0-31)
148
-
149
-		// Hidden registers also written to when main register is written to
150
-		int new_kon;
151
-		uint8_t endx_buf;
152
-		uint8_t envx_buf;
153
-		uint8_t outx_buf;
154
-
155
-		// Temporary state between clocks
156
-
157
-		// read once per sample
158
-		int t_pmon;
159
-		int t_non;
160
-		int t_eon;
161
-		int t_dir;
162
-		int t_koff;
163
-
164
-		// read a few clocks ahead then used
165
-		int t_brr_next_addr;
166
-		int t_adsr0;
167
-		int t_brr_header;
168
-		int t_brr_byte;
169
-		int t_srcn;
170
-		int t_esa;
171
-		int t_echo_enabled;
172
-
173
-		// internal state that is recalculated every sample
174
-		int t_dir_addr;
175
-		int t_pitch;
176
-		int t_output;
177
-		int t_looped;
178
-		int t_echo_ptr;
179
-
180
-		// left/right sums
181
-		int t_main_out[2];
182
-		int t_echo_out[2];
183
-		int t_echo_in[2];
184
-
185
-		voice_t voices[voice_count];
186
-
187
-		// non-emulation state
188
-		uint8_t *ram; // 64K shared RAM between DSP and SMP
189
-		int mute_mask;
190
-		sample_t *out;
191
-		sample_t *out_end;
192
-		sample_t *out_begin;
193
-		sample_t extra[extra_size];
194
-	};
195
-	state_t m;
196
-
197
-	void init_counter();
198
-	void run_counters();
199
-	unsigned read_counter(int rate);
200
-
201
-	int interpolate(const voice_t *v);
202
-	void run_envelope(voice_t *const v);
203
-	void decode_brr(voice_t *v);
204
-
205
-	void misc_27();
206
-	void misc_28();
207
-	void misc_29();
208
-	void misc_30();
209
-
210
-	void voice_output(const voice_t *v, int ch);
211
-	void voice_V1(voice_t *const);
212
-	void voice_V2(voice_t *const);
213
-	void voice_V3(voice_t *const);
214
-	void voice_V3a(voice_t *const);
215
-	void voice_V3b(voice_t *const);
216
-	void voice_V3c(voice_t *const);
217
-	void voice_V4(voice_t *const);
218
-	void voice_V5(voice_t *const);
219
-	void voice_V6(voice_t *const);
220
-	void voice_V7(voice_t *const);
221
-	void voice_V8(voice_t *const);
222
-	void voice_V9(voice_t *const);
223
-	void voice_V7_V4_V1(voice_t *const);
224
-	void voice_V8_V5_V2(voice_t *const);
225
-	void voice_V9_V6_V3(voice_t *const);
226
-
227
-	// Current echo buffer pointer for left/right channel
228
-	uint8_t *ECHO_PTR(int ch) { return &this->m.ram[this->m.t_echo_ptr + ch * 2]; }
229
-	// Sample in echo history buffer, where 0 is the oldest
230
-	int *ECHO_FIR(size_t i) { return this->m.echo_hist_pos[i]; }
231
-	// Calculate FIR point for left/right channel
232
-	int CALC_FIR(size_t i, int ch) { return (this->ECHO_FIR(i + 1)[ch] * static_cast<int8_t>(this->m.regs[r_fir + i * 0x10])) >> 6; }
233
-
234
-	void echo_read(int ch);
235
-	int echo_output(int ch);
236
-	void echo_write(int ch);
237
-	void echo_22();
238
-	void echo_23();
239
-	void echo_24();
240
-	void echo_25();
241
-	void echo_26();
242
-	void echo_27();
243
-	void echo_28();
244
-	void echo_29();
245
-	void echo_30();
246
-
247
-	void soft_reset_common();
248
-};
249
-
250
-inline int SPC_DSP::sample_count() const { return this->m.out - this->m.out_begin; }
251
-
252
-inline int SPC_DSP::read(int addr) const
253
-{
254
-	assert(static_cast<unsigned>(addr) < register_count);
255
-	return this->m.regs[addr];
256
-}
257
-
258
-inline void SPC_DSP::write(int addr, int data)
259
-{
260
-	assert(static_cast<unsigned>(addr) < register_count);
261
-
262
-	this->m.regs[addr] = static_cast<uint8_t>(data);
263
-	switch (addr & 0x0F)
264
-	{
265
-		case v_envx:
266
-			this->m.envx_buf = static_cast<uint8_t>(data);
267
-			break;
268
-
269
-		case v_outx:
270
-			this->m.outx_buf = static_cast<uint8_t>(data);
271
-			break;
272
-
273
-		case 0x0C:
274
-			if (addr == r_kon)
275
-				this->m.new_kon = static_cast<uint8_t>(data);
276
-
277
-			if (addr == r_endx) // always cleared, regardless of data written
278
-			{
279
-				this->m.endx_buf = 0;
280
-				this->m.regs[r_endx] = 0;
281
-			}
282
-	}
283
-}
284
-
285
-inline void SPC_DSP::mute_voices(int mask) { this->m.mute_mask = mask; }
Browse code

* Fixes for gcc and clang (while they can compile the code, the DLLs made aren't functional, but oh well).

* [2SF] Used more up-to-date asmjit, despite the ugly looking code.

Naram Qashat authored on 2014/09/17 19:51:45
Showing 1 changed files
... ...
@@ -243,7 +243,7 @@ private:
243 243
 	void echo_28();
244 244
 	void echo_29();
245 245
 	void echo_30();
246
-	
246
+
247 247
 	void soft_reset_common();
248 248
 };
249 249
 
Browse code

A few more cases of using #pragma once instead of include guards.

Naram Qashat authored on 2014/09/08 14:51:19
Showing 1 changed files
... ...
@@ -1,8 +1,7 @@
1 1
 // Highly accurate SNES SPC-700 DSP emulator
2 2
 
3 3
 // snes_spc 0.9.0
4
-#ifndef SPC_DSP_H
5
-#define SPC_DSP_H
4
+#pragma once
6 5
 
7 6
 #include "blargg_common.h"
8 7
 
... ...
@@ -284,5 +283,3 @@ inline void SPC_DSP::write(int addr, int data)
284 283
 }
285 284
 
286 285
 inline void SPC_DSP::mute_voices(int mask) { this->m.mute_mask = mask; }
287
-
288
-#endif
Browse code

[SNSF] Massive code cleanup, as well as removing as much unused code/variables as possible.

Naram Qashat authored on 2013/05/23 06:02:16
Showing 1 changed files
... ...
@@ -6,169 +6,162 @@
6 6
 
7 7
 #include "blargg_common.h"
8 8
 
9
-extern "C" { typedef void (*dsp_copy_func_t)( unsigned char** io, void* state, size_t ); }
10
-
11
-class SPC_DSP {
9
+class SPC_DSP
10
+{
12 11
 public:
13
-	typedef BOOST::uint8_t uint8_t;
14
-	
15
-// Setup
12
+	// Setup
16 13
 
17 14
 	// Initializes DSP and has it use the 64K RAM provided
18
-	void init( void* ram_64k );
15
+	void init(uint8_t *ram_64k);
19 16
 
20 17
 	// Sets destination for output samples. If out is NULL or out_size is 0,
21 18
 	// doesn't generate any.
22 19
 	typedef short sample_t;
23
-	void set_output( sample_t* out, int out_size );
20
+	void set_output(sample_t *out, int out_size);
24 21
 
25 22
 	// Number of samples written to output since it was last set, always
26 23
 	// a multiple of 2. Undefined if more samples were generated than
27 24
 	// output buffer could hold.
28 25
 	int sample_count() const;
29 26
 
30
-// Emulation
27
+	// Emulation
31 28
 
32 29
 	// Resets DSP to power-on state
33 30
 	void reset();
34 31
 
35 32
 	// Emulates pressing reset switch on SNES
36 33
 	void soft_reset();
37
-	
34
+
38 35
 	// Reads/writes DSP registers. For accuracy, you must first call run()
39 36
 	// to catch the DSP up to present.
40
-	int  read ( int addr ) const;
41
-	void write( int addr, int data );
37
+	int  read(int addr) const;
38
+	void write(int addr, int data);
42 39
 
43 40
 	// Runs DSP for specified number of clocks (~1024000 per second). Every 32 clocks
44 41
 	// a pair of samples is be generated.
45
-	void run( int clock_count );
46
-	
47
-// Sound control
42
+	void run(int clock_count);
43
+
44
+	// Sound control
48 45
 
49 46
 	// Mutes voices corresponding to non-zero bits in mask (issues repeated KOFF events).
50 47
 	// Reduces emulation accuracy.
51 48
 	enum { voice_count = 8 };
52
-	void mute_voices( int mask );
49
+	void mute_voices(int mask);
50
+
51
+	// State
53 52
 
54
-// State
55
-	
56 53
 	// Resets DSP and uses supplied values to initialize registers
57 54
 	enum { register_count = 128 };
58
-	void load( uint8_t const regs [register_count] );
55
+	void load(const uint8_t regs[register_count]);
59 56
 
60
-	// Saves/loads exact emulator state
61
-	enum { state_size = 640 }; // maximum space needed when saving
62
-	typedef dsp_copy_func_t copy_func_t;
63
-	void copy_state( unsigned char** io, copy_func_t );
57
+	// Snes9x Accessor
64 58
 
65
-	// Returns non-zero if new key-on events occurred since last call
66
-	bool check_kon();
67
-
68
-// Snes9x Accessor
69
-
70
-	int     stereo_switch;
71
-	int     take_spc_snapshot;
72
-	int     rom_enabled;   // mirror
59
+	int stereo_switch;
60
+	bool rom_enabled; // mirror
73 61
 	uint8_t *rom, *hi_ram; // mirror
74
-	void    (*spc_snapshot_callback)();
75 62
 
76
-	void    set_spc_snapshot_callback(void (*callback)());
77
-	void    dump_spc_snapshot();
78
-	void    set_stereo_switch( int );
79
-	uint8_t reg_value( int, int );
80
-	int     envx_value( int );
63
+	void set_stereo_switch(int);
64
+	uint8_t reg_value(int, int);
65
+	int envx_value(int);
81 66
 
82
-// DSP register addresses
67
+	// DSP register addresses
83 68
 
84 69
 	// Global registers
85
-	enum {
86
-	    r_mvoll = 0x0C, r_mvolr = 0x1C,
87
-	    r_evoll = 0x2C, r_evolr = 0x3C,
88
-	    r_kon   = 0x4C, r_koff  = 0x5C,
89
-	    r_flg   = 0x6C, r_endx  = 0x7C,
90
-	    r_efb   = 0x0D, r_pmon  = 0x2D,
91
-	    r_non   = 0x3D, r_eon   = 0x4D,
92
-	    r_dir   = 0x5D, r_esa   = 0x6D,
93
-	    r_edl   = 0x7D,
94
-	    r_fir   = 0x0F // 8 coefficients at 0x0F, 0x1F ... 0x7F
70
+	enum
71
+	{
72
+		r_mvoll = 0x0C,
73
+		r_mvolr = 0x1C,
74
+		r_evoll = 0x2C,
75
+		r_evolr = 0x3C,
76
+		r_kon = 0x4C,
77
+		r_koff = 0x5C,
78
+		r_flg = 0x6C,
79
+		r_endx = 0x7C,
80
+		r_efb = 0x0D,
81
+		r_pmon = 0x2D,
82
+		r_non = 0x3D,
83
+		r_eon = 0x4D,
84
+		r_dir = 0x5D,
85
+		r_esa = 0x6D,
86
+		r_edl = 0x7D,
87
+		r_fir = 0x0F // 8 coefficients at 0x0F, 0x1F ... 0x7F
95 88
 	};
96 89
 
97 90
 	// Voice registers
98
-	enum {
99
-		v_voll   = 0x00, v_volr   = 0x01,
100
-		v_pitchl = 0x02, v_pitchh = 0x03,
101
-		v_srcn   = 0x04, v_adsr0  = 0x05,
102
-		v_adsr1  = 0x06, v_gain   = 0x07,
103
-		v_envx   = 0x08, v_outx   = 0x09
91
+	enum
92
+	{
93
+		v_voll = 0x00,
94
+		v_volr = 0x01,
95
+		v_pitchl = 0x02,
96
+		v_pitchh = 0x03,
97
+		v_srcn = 0x04,
98
+		v_adsr0 = 0x05,
99
+		v_adsr1 = 0x06,
100
+		v_gain = 0x07,
101
+		v_envx = 0x08,
102
+		v_outx = 0x09
104 103
 	};
105 104
 
106 105
 public:
107 106
 	enum { extra_size = 16 };
108
-	sample_t* extra()               { return m.extra; }
109
-	sample_t const* out_pos() const { return m.out; }
110
-	void disable_surround( bool ) { } // not supported
107
+	sample_t *extra() { return this->m.extra; }
108
+	const sample_t *out_pos() const { return this->m.out; }
109
+	void disable_surround(bool) { } // not supported
111 110
 public:
112
-	BLARGG_DISABLE_NOTHROW
113
-	
114
-	typedef BOOST::int8_t   int8_t;
115
-	typedef BOOST::int16_t int16_t;
116
-	
117 111
 	enum { echo_hist_size = 8 };
118
-	
112
+
119 113
 	enum env_mode_t { env_release, env_attack, env_decay, env_sustain };
120 114
 	enum { brr_buf_size = 12 };
121 115
 	struct voice_t
122 116
 	{
123
-		int buf [brr_buf_size*2];// decoded samples (twice the size to simplify wrap handling)
124
-		int buf_pos;            // place in buffer where next samples will be decoded
125
-		int interp_pos;         // relative fractional position in sample (0x1000 = 1.0)
126
-		int brr_addr;           // address of current BRR block
127
-		int brr_offset;         // current decoding offset in BRR block
128
-		uint8_t* regs;          // pointer to voice's DSP registers
129
-		int vbit;               // bitmask for voice: 0x01 for voice 0, 0x02 for voice 1, etc.
130
-		int kon_delay;          // KON delay/current setup phase
117
+		int buf[brr_buf_size * 2]; // decoded samples (twice the size to simplify wrap handling)
118
+		int buf_pos; // place in buffer where next samples will be decoded
119
+		int interp_pos; // relative fractional position in sample (0x1000 = 1.0)
120
+		int brr_addr; // address of current BRR block
121
+		int brr_offset; // current decoding offset in BRR block
122
+		uint8_t *regs; // pointer to voice's DSP registers
123
+		int vbit; // bitmask for voice: 0x01 for voice 0, 0x02 for voice 1, etc.
124
+		int kon_delay; // KON delay/current setup phase
131 125
 		env_mode_t env_mode;
132
-		int env;                // current envelope level
133
-		int hidden_env;         // used by GAIN mode 7, very obscure quirk
126
+		int env; // current envelope level
127
+		int hidden_env; // used by GAIN mode 7, very obscure quirk
134 128
 		uint8_t t_envx_out;
135 129
 		int voice_number;
136 130
 	};
137 131
 private:
138 132
 	enum { brr_block_size = 9 };
139
-	
133
+
140 134
 	struct state_t
141 135
 	{
142
-		uint8_t regs [register_count];
143
-		
136
+		uint8_t regs[register_count];
137
+
144 138
 		// Echo history keeps most recent 8 samples (twice the size to simplify wrap handling)
145
-		int echo_hist [echo_hist_size * 2] [2];
146
-		int (*echo_hist_pos) [2]; // &echo_hist [0 to 7]
147
-		
148
-		int every_other_sample; // toggles every sample
149
-		int kon;                // KON value when last checked
139
+		int echo_hist[echo_hist_size * 2][2];
140
+		int (*echo_hist_pos)[2]; // &echo_hist [0 to 7]
141
+
142
+		bool every_other_sample; // toggles every sample
143
+		int kon; // KON value when last checked
150 144
 		int noise;
151 145
 		int counter;
152
-		int echo_offset;        // offset from ESA in echo buffer
153
-		int echo_length;        // number of bytes that echo_offset will stop at
154
-		int phase;              // next clock cycle to run (0-31)
155
-		bool kon_check;         // set when a new KON occurs
156
-		
146
+		int echo_offset; // offset from ESA in echo buffer
147
+		int echo_length; // number of bytes that echo_offset will stop at
148
+		int phase; // next clock cycle to run (0-31)
149
+
157 150
 		// Hidden registers also written to when main register is written to
158 151
 		int new_kon;
159 152
 		uint8_t endx_buf;
160 153
 		uint8_t envx_buf;
161 154
 		uint8_t outx_buf;
162
-		
155
+
163 156
 		// Temporary state between clocks
164
-		
157
+
165 158
 		// read once per sample
166 159
 		int t_pmon;
167 160
 		int t_non;
168 161
 		int t_eon;
169 162
 		int t_dir;
170 163
 		int t_koff;
171
-		
164
+
172 165
 		// read a few clocks ahead then used
173 166
 		int t_brr_next_addr;
174 167
 		int t_adsr0;
... ...
@@ -177,64 +170,71 @@ private:
177 170
 		int t_srcn;
178 171
 		int t_esa;
179 172
 		int t_echo_enabled;
180
-		
173
+
181 174
 		// internal state that is recalculated every sample
182 175
 		int t_dir_addr;
183 176
 		int t_pitch;
184 177
 		int t_output;
185 178
 		int t_looped;
186 179
 		int t_echo_ptr;
187
-		
180
+
188 181
 		// left/right sums
189
-		int t_main_out [2];
190
-		int t_echo_out [2];
191
-		int t_echo_in  [2];
192
-		
193
-		voice_t voices [voice_count];
194
-		
182
+		int t_main_out[2];
183
+		int t_echo_out[2];
184
+		int t_echo_in[2];
185
+
186
+		voice_t voices[voice_count];
187
+
195 188
 		// non-emulation state
196
-		uint8_t* ram; // 64K shared RAM between DSP and SMP
189
+		uint8_t *ram; // 64K shared RAM between DSP and SMP
197 190
 		int mute_mask;
198
-		sample_t* out;
199
-		sample_t* out_end;
200
-		sample_t* out_begin;
201
-		sample_t extra [extra_size];
191
+		sample_t *out;
192
+		sample_t *out_end;
193
+		sample_t *out_begin;
194
+		sample_t extra[extra_size];
202 195
 	};
203 196
 	state_t m;
204
-	
197
+
205 198
 	void init_counter();
206 199
 	void run_counters();
207
-	unsigned read_counter( int rate );
208
-	
209
-	int  interpolate( voice_t const* v );
210
-	void run_envelope( voice_t* const v );
211
-	void decode_brr( voice_t* v );
200
+	unsigned read_counter(int rate);
201
+
202
+	int interpolate(const voice_t *v);
203
+	void run_envelope(voice_t *const v);
204
+	void decode_brr(voice_t *v);
212 205
 
213 206
 	void misc_27();
214 207
 	void misc_28();
215 208
 	void misc_29();
216 209
 	void misc_30();
217 210
 
218
-	void voice_output( voice_t const* v, int ch );
219
-	void voice_V1( voice_t* const );
220
-	void voice_V2( voice_t* const );
221
-	void voice_V3( voice_t* const );
222
-	void voice_V3a( voice_t* const );
223
-	void voice_V3b( voice_t* const );
224
-	void voice_V3c( voice_t* const );
225
-	void voice_V4( voice_t* const );
226
-	void voice_V5( voice_t* const );
227
-	void voice_V6( voice_t* const );
228
-	void voice_V7( voice_t* const );
229
-	void voice_V8( voice_t* const );
230
-	void voice_V9( voice_t* const );
231
-	void voice_V7_V4_V1( voice_t* const );
232
-	void voice_V8_V5_V2( voice_t* const );
233
-	void voice_V9_V6_V3( voice_t* const );
234
-
235
-	void echo_read( int ch );
236
-	int  echo_output( int ch );
237
-	void echo_write( int ch );
211
+	void voice_output(const voice_t *v, int ch);
212
+	void voice_V1(voice_t *const);
213
+	void voice_V2(voice_t *const);
214
+	void voice_V3(voice_t *const);
215
+	void voice_V3a(voice_t *const);
216
+	void voice_V3b(voice_t *const);
217
+	void voice_V3c(voice_t *const);
218
+	void voice_V4(voice_t *const);
219
+	void voice_V5(voice_t *const);
220
+	void voice_V6(voice_t *const);
221
+	void voice_V7(voice_t *const);
222
+	void voice_V8(voice_t *const);
223
+	void voice_V9(voice_t *const);
224
+	void voice_V7_V4_V1(voice_t *const);
225
+	void voice_V8_V5_V2(voice_t *const);
226
+	void voice_V9_V6_V3(voice_t *const);
227
+
228
+	// Current echo buffer pointer for left/right channel
229
+	uint8_t *ECHO_PTR(int ch) { return &this->m.ram[this->m.t_echo_ptr + ch * 2]; }
230
+	// Sample in echo history buffer, where 0 is the oldest
231
+	int *ECHO_FIR(size_t i) { return this->m.echo_hist_pos[i]; }
232
+	// Calculate FIR point for left/right channel
233
+	int CALC_FIR(size_t i, int ch) { return (this->ECHO_FIR(i + 1)[ch] * static_cast<int8_t>(this->m.regs[r_fir + i * 0x10])) >> 6; }
234
+
235
+	void echo_read(int ch);
236
+	int echo_output(int ch);
237
+	void echo_write(int ch);
238 238
 	void echo_22();
239 239
 	void echo_23();
240 240
 	void echo_24();
... ...
@@ -248,72 +248,41 @@ private:
248 248
 	void soft_reset_common();
249 249
 };
250 250
 
251
-#include <assert.h>
251
+inline int SPC_DSP::sample_count() const { return this->m.out - this->m.out_begin; }
252 252
 
253
-inline int SPC_DSP::sample_count() const { return m.out - m.out_begin; }
254
-
255
-inline int SPC_DSP::read( int addr ) const
253
+inline int SPC_DSP::read(int addr) const
256 254
 {
257
-	assert( (unsigned) addr < register_count );
258
-	return m.regs [addr];
255
+	assert(static_cast<unsigned>(addr) < register_count);
256
+	return this->m.regs[addr];
259 257
 }
260 258
 
261
-inline void SPC_DSP::write( int addr, int data )
259
+inline void SPC_DSP::write(int addr, int data)
262 260
 {
263
-	assert( (unsigned) addr < register_count );
264
-	
265
-	m.regs [addr] = (uint8_t) data;
266
-	switch ( addr & 0x0F )
261
+	assert(static_cast<unsigned>(addr) < register_count);
262
+
263
+	this->m.regs[addr] = static_cast<uint8_t>(data);
264
+	switch (addr & 0x0F)
267 265
 	{
268
-	case v_envx:
269
-		m.envx_buf = (uint8_t) data;
270
-		break;
271
-		
272
-	case v_outx:
273
-		m.outx_buf = (uint8_t) data;
274
-		break;
275
-	
276
-	case 0x0C:
277
-		if ( addr == r_kon )
278
-			m.new_kon = (uint8_t) data;
279
-		
280
-		if ( addr == r_endx ) // always cleared, regardless of data written
281
-		{
282
-			m.endx_buf = 0;
283
-			m.regs [r_endx] = 0;
284
-		}
285
-		break;
266
+		case v_envx:
267
+			this->m.envx_buf = static_cast<uint8_t>(data);
268
+			break;
269
+
270
+		case v_outx:
271
+			this->m.outx_buf = static_cast<uint8_t>(data);
272
+			break;
273
+
274
+		case 0x0C:
275
+			if (addr == r_kon)
276
+				this->m.new_kon = static_cast<uint8_t>(data);
277
+
278
+			if (addr == r_endx) // always cleared, regardless of data written
279
+			{
280
+				this->m.endx_buf = 0;
281
+				this->m.regs[r_endx] = 0;
282
+			}
286 283
 	}
287 284
 }
288 285
 
289
-inline void SPC_DSP::mute_voices( int mask ) { m.mute_mask = mask; }
290
-
291
-inline bool SPC_DSP::check_kon()
292
-{
293
-	bool old = m.kon_check;
294
-	m.kon_check = 0;
295
-	return old;
296
-}
297
-
298
-#if !SPC_NO_COPY_STATE_FUNCS
299
-
300
-class SPC_State_Copier {
301
-	SPC_DSP::copy_func_t func;
302
-	unsigned char** buf;
303
-public:
304
-	SPC_State_Copier( unsigned char** p, SPC_DSP::copy_func_t f ) { func = f; buf = p; }
305
-	void copy( void* state, size_t size );
306
-	int copy_int( int state, int size );
307
-	void skip( int count );
308
-	void extra();
309
-};
310
-
311
-#define SPC_COPY( type, state )\
312
-{\
313
-	state = (BOOST::type) copier.copy_int( state, sizeof (BOOST::type) );\
314
-	assert( (BOOST::type) state == state );\
315
-}
316
-
317
-#endif
286
+inline void SPC_DSP::mute_voices(int mask) { this->m.mute_mask = mask; }
318 287
 
319 288
 #endif
Browse code

Import actual code.

Naram Qashat authored on 2013/03/26 02:41:19
Showing 1 changed files
1 1
new file mode 100644
... ...
@@ -0,0 +1,319 @@
1
+// Highly accurate SNES SPC-700 DSP emulator
2
+
3
+// snes_spc 0.9.0
4
+#ifndef SPC_DSP_H
5
+#define SPC_DSP_H
6
+
7
+#include "blargg_common.h"
8
+
9
+extern "C" { typedef void (*dsp_copy_func_t)( unsigned char** io, void* state, size_t ); }
10
+
11
+class SPC_DSP {
12
+public:
13
+	typedef BOOST::uint8_t uint8_t;
14
+	
15
+// Setup
16
+
17
+	// Initializes DSP and has it use the 64K RAM provided
18
+	void init( void* ram_64k );
19
+
20
+	// Sets destination for output samples. If out is NULL or out_size is 0,
21
+	// doesn't generate any.
22
+	typedef short sample_t;
23
+	void set_output( sample_t* out, int out_size );
24
+
25
+	// Number of samples written to output since it was last set, always
26
+	// a multiple of 2. Undefined if more samples were generated than
27
+	// output buffer could hold.
28
+	int sample_count() const;
29
+
30
+// Emulation
31
+
32
+	// Resets DSP to power-on state
33
+	void reset();
34
+
35
+	// Emulates pressing reset switch on SNES
36
+	void soft_reset();
37
+	
38
+	// Reads/writes DSP registers. For accuracy, you must first call run()
39
+	// to catch the DSP up to present.
40
+	int  read ( int addr ) const;
41
+	void write( int addr, int data );
42
+
43
+	// Runs DSP for specified number of clocks (~1024000 per second). Every 32 clocks
44
+	// a pair of samples is be generated.
45
+	void run( int clock_count );
46
+	
47
+// Sound control
48
+
49
+	// Mutes voices corresponding to non-zero bits in mask (issues repeated KOFF events).
50
+	// Reduces emulation accuracy.
51
+	enum { voice_count = 8 };
52
+	void mute_voices( int mask );
53
+
54
+// State
55
+	
56
+	// Resets DSP and uses supplied values to initialize registers
57
+	enum { register_count = 128 };
58
+	void load( uint8_t const regs [register_count] );
59
+
60
+	// Saves/loads exact emulator state
61
+	enum { state_size = 640 }; // maximum space needed when saving
62
+	typedef dsp_copy_func_t copy_func_t;
63
+	void copy_state( unsigned char** io, copy_func_t );
64
+
65
+	// Returns non-zero if new key-on events occurred since last call
66
+	bool check_kon();
67
+
68
+// Snes9x Accessor
69
+
70
+	int     stereo_switch;
71
+	int     take_spc_snapshot;
72
+	int     rom_enabled;   // mirror
73
+	uint8_t *rom, *hi_ram; // mirror
74
+	void    (*spc_snapshot_callback)();
75
+
76
+	void    set_spc_snapshot_callback(void (*callback)());
77
+	void    dump_spc_snapshot();
78
+	void    set_stereo_switch( int );
79
+	uint8_t reg_value( int, int );
80
+	int     envx_value( int );
81
+
82
+// DSP register addresses
83
+
84
+	// Global registers
85
+	enum {
86
+	    r_mvoll = 0x0C, r_mvolr = 0x1C,
87
+	    r_evoll = 0x2C, r_evolr = 0x3C,
88
+	    r_kon   = 0x4C, r_koff  = 0x5C,
89
+	    r_flg   = 0x6C, r_endx  = 0x7C,
90
+	    r_efb   = 0x0D, r_pmon  = 0x2D,
91
+	    r_non   = 0x3D, r_eon   = 0x4D,
92
+	    r_dir   = 0x5D, r_esa   = 0x6D,
93
+	    r_edl   = 0x7D,
94
+	    r_fir   = 0x0F // 8 coefficients at 0x0F, 0x1F ... 0x7F
95
+	};
96
+
97
+	// Voice registers
98
+	enum {
99
+		v_voll   = 0x00, v_volr   = 0x01,
100
+		v_pitchl = 0x02, v_pitchh = 0x03,
101
+		v_srcn   = 0x04, v_adsr0  = 0x05,
102
+		v_adsr1  = 0x06, v_gain   = 0x07,
103
+		v_envx   = 0x08, v_outx   = 0x09
104
+	};
105
+
106
+public:
107
+	enum { extra_size = 16 };
108
+	sample_t* extra()               { return m.extra; }
109
+	sample_t const* out_pos() const { return m.out; }
110
+	void disable_surround( bool ) { } // not supported
111
+public:
112
+	BLARGG_DISABLE_NOTHROW
113
+	
114
+	typedef BOOST::int8_t   int8_t;
115
+	typedef BOOST::int16_t int16_t;
116
+	
117
+	enum { echo_hist_size = 8 };
118
+	
119
+	enum env_mode_t { env_release, env_attack, env_decay, env_sustain };
120
+	enum { brr_buf_size = 12 };
121
+	struct voice_t
122
+	{
123
+		int buf [brr_buf_size*2];// decoded samples (twice the size to simplify wrap handling)
124
+		int buf_pos;            // place in buffer where next samples will be decoded
125
+		int interp_pos;         // relative fractional position in sample (0x1000 = 1.0)
126
+		int brr_addr;           // address of current BRR block
127
+		int brr_offset;         // current decoding offset in BRR block
128
+		uint8_t* regs;          // pointer to voice's DSP registers
129
+		int vbit;               // bitmask for voice: 0x01 for voice 0, 0x02 for voice 1, etc.
130
+		int kon_delay;          // KON delay/current setup phase
131
+		env_mode_t env_mode;
132
+		int env;                // current envelope level
133
+		int hidden_env;         // used by GAIN mode 7, very obscure quirk
134
+		uint8_t t_envx_out;
135
+		int voice_number;
136
+	};
137
+private:
138
+	enum { brr_block_size = 9 };
139
+	
140
+	struct state_t
141
+	{
142
+		uint8_t regs [register_count];
143
+		
144
+		// Echo history keeps most recent 8 samples (twice the size to simplify wrap handling)
145
+		int echo_hist [echo_hist_size * 2] [2];
146
+		int (*echo_hist_pos) [2]; // &echo_hist [0 to 7]
147
+		
148
+		int every_other_sample; // toggles every sample
149
+		int kon;                // KON value when last checked
150
+		int noise;
151
+		int counter;
152
+		int echo_offset;        // offset from ESA in echo buffer
153
+		int echo_length;        // number of bytes that echo_offset will stop at
154
+		int phase;              // next clock cycle to run (0-31)
155
+		bool kon_check;         // set when a new KON occurs
156
+		
157
+		// Hidden registers also written to when main register is written to
158
+		int new_kon;
159
+		uint8_t endx_buf;
160
+		uint8_t envx_buf;
161
+		uint8_t outx_buf;
162
+		
163
+		// Temporary state between clocks
164
+		
165
+		// read once per sample
166
+		int t_pmon;
167
+		int t_non;
168
+		int t_eon;
169
+		int t_dir;
170
+		int t_koff;
171
+		
172
+		// read a few clocks ahead then used
173
+		int t_brr_next_addr;
174
+		int t_adsr0;
175
+		int t_brr_header;
176
+		int t_brr_byte;
177
+		int t_srcn;
178
+		int t_esa;
179
+		int t_echo_enabled;
180
+		
181
+		// internal state that is recalculated every sample
182
+		int t_dir_addr;
183
+		int t_pitch;
184
+		int t_output;
185
+		int t_looped;
186
+		int t_echo_ptr;
187
+		
188
+		// left/right sums
189
+		int t_main_out [2];
190
+		int t_echo_out [2];
191
+		int t_echo_in  [2];
192
+		
193
+		voice_t voices [voice_count];
194
+		
195
+		// non-emulation state
196
+		uint8_t* ram; // 64K shared RAM between DSP and SMP
197
+		int mute_mask;
198
+		sample_t* out;
199
+		sample_t* out_end;
200
+		sample_t* out_begin;
201
+		sample_t extra [extra_size];
202
+	};
203
+	state_t m;
204
+	
205
+	void init_counter();
206
+	void run_counters();
207
+	unsigned read_counter( int rate );
208
+	
209
+	int  interpolate( voice_t const* v );
210
+	void run_envelope( voice_t* const v );
211
+	void decode_brr( voice_t* v );
212
+
213
+	void misc_27();
214
+	void misc_28();
215
+	void misc_29();
216
+	void misc_30();
217
+
218
+	void voice_output( voice_t const* v, int ch );
219
+	void voice_V1( voice_t* const );
220
+	void voice_V2( voice_t* const );
221
+	void voice_V3( voice_t* const );
222
+	void voice_V3a( voice_t* const );
223
+	void voice_V3b( voice_t* const );
224
+	void voice_V3c( voice_t* const );
225
+	void voice_V4( voice_t* const );
226
+	void voice_V5( voice_t* const );
227
+	void voice_V6( voice_t* const );
228
+	void voice_V7( voice_t* const );
229
+	void voice_V8( voice_t* const );
230
+	void voice_V9( voice_t* const );
231
+	void voice_V7_V4_V1( voice_t* const );
232
+	void voice_V8_V5_V2( voice_t* const );
233
+	void voice_V9_V6_V3( voice_t* const );
234
+
235
+	void echo_read( int ch );
236
+	int  echo_output( int ch );
237
+	void echo_write( int ch );
238
+	void echo_22();
239
+	void echo_23();
240
+	void echo_24();
241
+	void echo_25();
242
+	void echo_26();
243
+	void echo_27();
244
+	void echo_28();
245
+	void echo_29();
246
+	void echo_30();
247
+	
248
+	void soft_reset_common();
249
+};
250
+
251
+#include <assert.h>
252
+
253
+inline int SPC_DSP::sample_count() const { return m.out - m.out_begin; }
254
+
255
+inline int SPC_DSP::read( int addr ) const
256
+{
257
+	assert( (unsigned) addr < register_count );
258
+	return m.regs [addr];
259
+}
260
+
261
+inline void SPC_DSP::write( int addr, int data )
262
+{
263
+	assert( (unsigned) addr < register_count );
264
+	
265
+	m.regs [addr] = (uint8_t) data;
266
+	switch ( addr & 0x0F )
267
+	{
268
+	case v_envx:
269
+		m.envx_buf = (uint8_t) data;
270
+		break;
271
+		
272
+	case v_outx:
273
+		m.outx_buf = (uint8_t) data;
274
+		break;
275
+	
276
+	case 0x0C:
277
+		if ( addr == r_kon )
278
+			m.new_kon = (uint8_t) data;
279
+		
280
+		if ( addr == r_endx ) // always cleared, regardless of data written
281
+		{
282
+			m.endx_buf = 0;
283
+			m.regs [r_endx] = 0;
284
+		}
285
+		break;
286
+	}
287
+}
288
+
289
+inline void SPC_DSP::mute_voices( int mask ) { m.mute_mask = mask; }
290
+
291
+inline bool SPC_DSP::check_kon()
292
+{
293
+	bool old = m.kon_check;
294
+	m.kon_check = 0;
295
+	return old;
296
+}
297
+
298
+#if !SPC_NO_COPY_STATE_FUNCS
299
+
300
+class SPC_State_Copier {
301
+	SPC_DSP::copy_func_t func;
302
+	unsigned char** buf;
303
+public:
304
+	SPC_State_Copier( unsigned char** p, SPC_DSP::copy_func_t f ) { func = f; buf = p; }
305
+	void copy( void* state, size_t size );
306
+	int copy_int( int state, int size );
307
+	void skip( int count );
308
+	void extra();
309
+};
310
+
311
+#define SPC_COPY( type, state )\
312
+{\
313
+	state = (BOOST::type) copier.copy_int( state, sizeof (BOOST::type) );\
314
+	assert( (BOOST::type) state == state );\
315
+}
316
+
317
+#endif
318
+
319
+#endif