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,848 +0,0 @@
1
-// snes_spc 0.9.0. http://www.slack.net/~ant/
2
-
3
-#include <algorithm>
4
-#include <cstring>
5
-#include "SPC_DSP.h"
6
-
7
-#include "blargg_endian.h"
8
-
9
-/* Copyright (C) 2007 Shay Green. This module is free software; you
10
-can redistribute it and/or modify it under the terms of the GNU Lesser
11
-General Public License as published by the Free Software Foundation; either
12
-version 2.1 of the License, or (at your option) any later version. This
13
-module is distributed in the hope that it will be useful, but WITHOUT ANY
14
-WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
15
-FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
16
-details. You should have received a copy of the GNU Lesser General Public
17
-License along with this module; if not, write to the Free Software Foundation,
18
-Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
19
-
20
-#if INT_MAX < 0x7FFFFFFF
21
-# error "Requires that int type have at least 32 bits"
22
-#endif
23
-
24
-static const uint8_t initial_regs[] =
25
-{
26
-	0x45, 0x8B, 0x5A, 0x9A, 0xE4, 0x82, 0x1B, 0x78, 0x00, 0x00, 0xAA, 0x96, 0x89, 0x0E, 0xE0, 0x80,
27
-	0x2A, 0x49, 0x3D, 0xBA, 0x14, 0xA0, 0xAC, 0xC5, 0x00, 0x00, 0x51, 0xBB, 0x9C, 0x4E, 0x7B, 0xFF,
28
-	0xF4, 0xFD, 0x57, 0x32, 0x37, 0xD9, 0x42, 0x22, 0x00, 0x00, 0x5B, 0x3C, 0x9F, 0x1B, 0x87, 0x9A,
29
-	0x6F, 0x27, 0xAF, 0x7B, 0xE5, 0x68, 0x0A, 0xD9, 0x00, 0x00, 0x9A, 0xC5, 0x9C, 0x4E, 0x7B, 0xFF,
30
-	0xEA, 0x21, 0x78, 0x4F, 0xDD, 0xED, 0x24, 0x14, 0x00, 0x00, 0x77, 0xB1, 0xD1, 0x36, 0xC1, 0x67,
31
-	0x52, 0x57, 0x46, 0x3D, 0x59, 0xF4, 0x87, 0xA4, 0x00, 0x00, 0x7E, 0x44, 0x00, 0x4E, 0x7B, 0xFF,
32
-	0x75, 0xF5, 0x06, 0x97, 0x10, 0xC3, 0x24, 0xBB, 0x00, 0x00, 0x7B, 0x7A, 0xE0, 0x60, 0x12, 0x0F,
33
-	0xF7, 0x74, 0x1C, 0xE5, 0x39, 0x3D, 0x73, 0xC1, 0x00, 0x00, 0x7A, 0xB3, 0xFF, 0x4E, 0x7B, 0xFF
34
-};
35
-
36
-// if ( io < -32768 ) io = -32768;
37
-// if ( io >  32767 ) io =  32767;
38
-template<typename T> static inline void CLAMP16(T &io)
39
-{
40
-	if (static_cast<int16_t>(io) != io)
41
-		io = (io >> 31) ^ 0x7FFF;
42
-}
43
-
44
-void SPC_DSP::set_output(sample_t *out, int size)
45
-{
46
-	assert(!(size & 1)); // must be even
47
-	if (!out)
48
-	{
49
-		out = this->m.extra;
50
-		size = extra_size;
51
-	}
52
-	this->m.out_begin = this->m.out = out;
53
-	this->m.out_end = out + size;
54
-}
55
-
56
-// Volume registers and efb are signed! Easy to forget int8_t cast.
57
-// Prefixes are to avoid accidental use of locals with same names.
58
-
59
-// Gaussian interpolation
60
-
61
-static const short gauss[] =
62
-{
63
-	   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
64
-	   1,   1,   1,   1,   1,   1,   1,   1,   1,   1,   1,   2,   2,   2,   2,   2,
65
-	   2,   2,   3,   3,   3,   3,   3,   4,   4,   4,   4,   4,   5,   5,   5,   5,
66
-	   6,   6,   6,   6,   7,   7,   7,   8,   8,   8,   9,   9,   9,  10,  10,  10,
67
-	  11,  11,  11,  12,  12,  13,  13,  14,  14,  15,  15,  15,  16,  16,  17,  17,
68
-	  18,  19,  19,  20,  20,  21,  21,  22,  23,  23,  24,  24,  25,  26,  27,  27,
69
-	  28,  29,  29,  30,  31,  32,  32,  33,  34,  35,  36,  36,  37,  38,  39,  40,
70
-	  41,  42,  43,  44,  45,  46,  47,  48,  49,  50,  51,  52,  53,  54,  55,  56,
71
-	  58,  59,  60,  61,  62,  64,  65,  66,  67,  69,  70,  71,  73,  74,  76,  77,
72
-	  78,  80,  81,  83,  84,  86,  87,  89,  90,  92,  94,  95,  97,  99, 100, 102,
73
-	 104, 106, 107, 109, 111, 113, 115, 117, 118, 120, 122, 124, 126, 128, 130, 132,
74
-	 134, 137, 139, 141, 143, 145, 147, 150, 152, 154, 156, 159, 161, 163, 166, 168,
75
-	 171, 173, 175, 178, 180, 183, 186, 188, 191, 193, 196, 199, 201, 204, 207, 210,
76
-	 212, 215, 218, 221, 224, 227, 230, 233, 236, 239, 242, 245, 248, 251, 254, 257,
77
-	 260, 263, 267, 270, 273, 276, 280, 283, 286, 290, 293, 297, 300, 304, 307, 311,
78
-	 314, 318, 321, 325, 328, 332, 336, 339, 343, 347, 351, 354, 358, 362, 366, 370,
79
-	 374, 378, 381, 385, 389, 393, 397, 401, 405, 410, 414, 418, 422, 426, 430, 434,
80
-	 439, 443, 447, 451, 456, 460, 464, 469, 473, 477, 482, 486, 491, 495, 499, 504,
81
-	 508, 513, 517, 522, 527, 531, 536, 540, 545, 550, 554, 559, 563, 568, 573, 577,
82
-	 582, 587, 592, 596, 601, 606, 611, 615, 620, 625, 630, 635, 640, 644, 649, 654,
83
-	 659, 664, 669, 674, 678, 683, 688, 693, 698, 703, 708, 713, 718, 723, 728, 732,
84
-	 737, 742, 747, 752, 757, 762, 767, 772, 777, 782, 787, 792, 797, 802, 806, 811,
85
-	 816, 821, 826, 831, 836, 841, 846, 851, 855, 860, 865, 870, 875, 880, 884, 889,
86
-	 894, 899, 904, 908, 913, 918, 923, 927, 932, 937, 941, 946, 951, 955, 960, 965,
87
-	 969, 974, 978, 983, 988, 992, 997,1001,1005,1010,1014,1019,1023,1027,1032,1036,
88
-	1040,1045,1049,1053,1057,1061,1066,1070,1074,1078,1082,1086,1090,1094,1098,1102,
89
-	1106,1109,1113,1117,1121,1125,1128,1132,1136,1139,1143,1146,1150,1153,1157,1160,
90
-	1164,1167,1170,1174,1177,1180,1183,1186,1190,1193,1196,1199,1202,1205,1207,1210,
91
-	1213,1216,1219,1221,1224,1227,1229,1232,1234,1237,1239,1241,1244,1246,1248,1251,
92
-	1253,1255,1257,1259,1261,1263,1265,1267,1269,1270,1272,1274,1275,1277,1279,1280,
93
-	1282,1283,1284,1286,1287,1288,1290,1291,1292,1293,1294,1295,1296,1297,1297,1298,
94
-	1299,1300,1300,1301,1302,1302,1303,1303,1303,1304,1304,1304,1304,1304,1305,1305,
95
-};
96
-
97
-int SPC_DSP::interpolate(const voice_t *v)
98
-{
99
-	// Make pointers into gaussian based on fractional position between samples
100
-	int offset = (v->interp_pos >> 4) & 0xFF;
101
-	auto fwd = gauss + 255 - offset;
102
-	auto rev = gauss + offset; // mirror left half of gaussian
103
-
104
-	auto in = &v->buf[(v->interp_pos >> 12) + v->buf_pos];
105
-	int out = (fwd[0] * in[0]) >> 11;
106
-	out += (fwd[256] * in[1]) >> 11;
107
-	out += (rev[256] * in[2]) >> 11;
108
-	out = static_cast<int16_t>(out);
109
-	out += (rev[0] * in[3]) >> 11;
110
-
111
-	CLAMP16(out);
112
-	out &= ~1;
113
-	return out;
114
-}
115
-
116
-//// Counters
117
-
118
-static const int simple_counter_range = 2048 * 5 * 3; // 30720
119
-
120
-static const unsigned counter_rates[] =
121
-{
122
-	simple_counter_range + 1, // never fires
123
-	2048, 1536,
124
-	1280, 1024, 768,
125
-	640, 512, 384,
126
-	320, 256, 192,
127
-	160, 128, 96,
128
-	80, 64, 48,
129
-	40, 32, 24,
130
-	20, 16, 12,
131
-	10, 8, 6,
132
-	5, 4, 3,
133
-	2,
134
-	1
135
-};
136
-
137
-static const unsigned counter_offsets[] =
138
-{
139
-	1, 0, 1040,
140
-	536, 0, 1040,
141
-	536, 0, 1040,
142
-	536, 0, 1040,
143
-	536, 0, 1040,
144
-	536, 0, 1040,
145
-	536, 0, 1040,
146
-	536, 0, 1040,
147
-	536, 0, 1040,
148
-	536, 0, 1040,
149
-	0,
150
-	0
151
-};
152
-
153
-void SPC_DSP::init_counter()
154
-{
155
-	this->m.counter = 0;
156
-}
157
-
158
-void SPC_DSP::run_counters()
159
-{
160
-	if (--this->m.counter < 0)
161
-		this->m.counter = simple_counter_range - 1;
162
-}
163
-
164
-unsigned SPC_DSP::read_counter(int rate)
165
-{
166
-	return (static_cast<unsigned>(this->m.counter) + counter_offsets[rate]) % counter_rates[rate];
167
-}
168
-
169
-//// Envelope
170
-
171
-void SPC_DSP::run_envelope(voice_t *const v)
172
-{
173
-	int env = v->env;
174
-	if (v->env_mode == env_release) // 60%
175
-	{
176
-		if ((env -= 0x8) < 0)
177
-			env = 0;
178
-		v->env = env;
179
-	}
180
-	else
181
-	{
182
-		int rate;
183
-		int env_data = v->regs[v_adsr1];
184
-		if (this->m.t_adsr0 & 0x80) // 99% ADSR
185
-		{
186
-			if (v->env_mode >= env_decay) // 99%
187
-			{
188
-				--env;
189
-				env -= env >> 8;
190
-				rate = env_data & 0x1F;
191
-				if (v->env_mode == env_decay) // 1%
192
-					rate = ((this->m.t_adsr0 >> 3) & 0x0E) + 0x10;
193
-			}
194
-			else // env_attack
195
-			{
196
-				rate = (this->m.t_adsr0 & 0x0F) * 2 + 1;
197
-				env += rate < 31 ? 0x20 : 0x400;
198
-			}
199
-		}
200
-		else // GAIN
201
-		{
202
-			env_data = v->regs[v_gain];
203
-			int mode = env_data >> 5;
204
-			if (mode < 4) // direct
205
-			{
206
-				env = env_data * 0x10;
207
-				rate = 31;
208
-			}
209
-			else
210
-			{
211
-				rate = env_data & 0x1F;
212
-				if (mode == 4) // 4: linear decrease
213
-					env -= 0x20;
214
-				else if (mode < 6) // 5: exponential decrease
215
-				{
216
-					--env;
217
-					env -= env >> 8;
218
-				}
219
-				else // 6,7: linear increase
220
-				{
221
-					env += 0x20;
222
-					if (mode > 6 && static_cast<unsigned>(v->hidden_env) >= 0x600)
223
-						env += 0x8 - 0x20; // 7: two-slope linear increase
224
-				}
225
-			}
226
-		}
227
-
228
-		// Sustain level
229
-		if ((env >> 8) == (env_data >> 5) && v->env_mode == env_decay)
230
-			v->env_mode = env_sustain;
231
-
232
-		v->hidden_env = env;
233
-
234
-		// unsigned cast because linear decrease going negative also triggers this
235
-		if (static_cast<unsigned>(env) > 0x7FF)
236
-		{
237
-			env = env < 0 ? 0 : 0x7FF;
238
-			if (v->env_mode == env_attack)
239
-				v->env_mode = env_decay;
240
-		}
241
-
242
-		if (!this->read_counter(rate))
243
-			v->env = env; // nothing else is controlled by the counter
244
-	}
245
-}
246
-
247
-//// BRR Decoding
248
-
249
-void SPC_DSP::decode_brr(voice_t *v)
250
-{
251
-	// Arrange the four input nybbles in 0xABCD order for easy decoding
252
-	int nybbles = this->m.t_brr_byte * 0x100 + this->m.ram[(v->brr_addr + v->brr_offset + 1) & 0xFFFF];
253
-
254
-	int header = this->m.t_brr_header;
255
-
256
-	// Write to next four samples in circular buffer
257
-	int *pos = &v->buf[v->buf_pos];
258
-	int *end;
259
-	if ((v->buf_pos += 4) >= brr_buf_size)
260
-		v->buf_pos = 0;
261
-
262
-	// Decode four samples
263
-	for (end = pos + 4; pos < end; ++pos, nybbles <<= 4)
264
-	{
265
-		// Extract nybble and sign-extend
266
-		int s = static_cast<int16_t>(nybbles) >> 12;
267
-
268
-		// Shift sample based on header
269
-		int shift = header >> 4;
270
-		s = (s << shift) >> 1;
271
-		if (shift >= 0xD) // handle invalid range
272
-			s = (s >> 25) << 11; // same as: s = (s < 0 ? -0x800 : 0)
273
-
274
-		// Apply IIR filter (8 is the most commonly used)
275
-		int filter = header & 0x0C;
276
-		int p1 = pos[brr_buf_size - 1];
277
-		int p2 = pos[brr_buf_size - 2] >> 1;
278
-		if (filter >= 8)
279
-		{
280
-			s += p1;
281
-			s -= p2;
282
-			if (filter == 8) // s += p1 * 0.953125 - p2 * 0.46875
283
-			{
284
-				s += p2 >> 4;
285
-				s += (p1 * -3) >> 6;
286
-			}
287
-			else // s += p1 * 0.8984375 - p2 * 0.40625
288
-			{
289
-				s += (p1 * -13) >> 7;
290
-				s += (p2 * 3) >> 4;
291
-			}
292
-		}
293
-		else if (filter) // s += p1 * 0.46875
294
-		{
295
-			s += p1 >> 1;
296
-			s += -p1 >> 5;
297
-		}
298
-
299
-		// Adjust and write sample
300
-		CLAMP16(s);
301
-		s = static_cast<int16_t>(s * 2);
302
-		pos[brr_buf_size] = pos[0] = s; // second copy simplifies wrap-around
303
-	}
304
-}
305
-
306
-//// Misc
307
-
308
-void SPC_DSP::misc_27()
309
-{
310
-	this->m.t_pmon = this->m.regs[r_pmon] & 0xFE; // voice 0 doesn't support PMON
311
-}
312
-void SPC_DSP::misc_28()
313
-{
314
-	this->m.t_non = this->m.regs[r_non];
315
-	this->m.t_eon = this->m.regs[r_eon];
316
-	this->m.t_dir = this->m.regs[r_dir];
317
-}
318
-void SPC_DSP::misc_29()
319
-{
320
-	this->m.every_other_sample = !this->m.every_other_sample;
321
-	if (this->m.every_other_sample)
322
-		this->m.new_kon &= ~this->m.kon; // clears KON 63 clocks after it was last read
323
-}
324
-void SPC_DSP::misc_30()
325
-{
326
-	if (this->m.every_other_sample)
327
-	{
328
-		this->m.kon = this->m.new_kon;
329
-		this->m.t_koff = this->m.regs[r_koff] | this->m.mute_mask;
330
-	}
331
-
332
-	this->run_counters();
333
-
334
-	// Noise
335
-	if (!this->read_counter(this->m.regs[r_flg] & 0x1F))
336
-	{
337
-		int feedback = (this->m.noise << 13) ^ (this->m.noise << 14);
338
-		this->m.noise = (feedback & 0x4000) ^ (this->m.noise >> 1);
339
-	}
340
-}
341
-
342
-//// Voices
343
-
344
-void SPC_DSP::voice_V1(voice_t *const v)
345
-{
346
-	this->m.t_dir_addr = this->m.t_dir * 0x100 + this->m.t_srcn * 4;
347
-	this->m.t_srcn = v->regs[v_srcn];
348
-}
349
-void SPC_DSP::voice_V2(voice_t *const v)
350
-{
351
-	// Read sample pointer (ignored if not needed)
352
-	auto entry = &this->m.ram[m.t_dir_addr];
353
-	if (!v->kon_delay)
354
-		entry += 2;
355
-	this->m.t_brr_next_addr = get_le16(entry);
356
-
357
-	this->m.t_adsr0 = v->regs[v_adsr0];
358
-
359
-	// Read pitch, spread over two clocks
360
-	this->m.t_pitch = v->regs[v_pitchl];
361
-}
362
-void SPC_DSP::voice_V3a(voice_t *const v)
363
-{
364
-	this->m.t_pitch += (v->regs[v_pitchh] & 0x3F) << 8;
365
-}
366
-void SPC_DSP::voice_V3b(voice_t *const v)
367
-{
368
-	// Read BRR header and byte
369
-	this->m.t_brr_byte = this->m.ram[(v->brr_addr + v->brr_offset) & 0xFFFF];
370
-	this->m.t_brr_header = this->m.ram[v->brr_addr]; // brr_addr doesn't need masking
371
-}
372
-void SPC_DSP::voice_V3c(voice_t *const v)
373
-{
374
-	// Pitch modulation using previous voice's output
375
-	if (this->m.t_pmon & v->vbit)
376
-		this->m.t_pitch += ((this->m.t_output >> 5) * this->m.t_pitch) >> 10;
377
-
378
-	if (v->kon_delay)
379
-	{
380
-		// Get ready to start BRR decoding on next sample
381
-		if (v->kon_delay == 5)
382
-		{
383
-			v->brr_addr = this->m.t_brr_next_addr;
384
-			v->brr_offset = 1;
385
-			v->buf_pos = 0;
386
-			this->m.t_brr_header = 0; // header is ignored on this sample
387
-		}
388
-
389
-		// Envelope is never run during KON
390
-		v->env = 0;
391
-		v->hidden_env = 0;
392
-
393
-		// Disable BRR decoding until last three samples
394
-		v->interp_pos = 0;
395
-		if (--v->kon_delay & 3)
396
-			v->interp_pos = 0x4000;
397
-
398
-		// Pitch is never added during KON
399
-		this->m.t_pitch = 0;
400
-	}
401
-
402
-	// Gaussian interpolation
403
-	int output = this->interpolate(v);
404
-
405
-	// Noise
406
-	if (this->m.t_non & v->vbit)
407
-		output = static_cast<int16_t>(this->m.noise * 2);
408
-
409
-	// Apply envelope
410
-	this->m.t_output = (output * v->env) >> 11 & ~1;
411
-	v->t_envx_out = static_cast<uint8_t>(v->env >> 4);
412
-
413
-	// Immediate silence due to end of sample or soft reset
414
-	if (this->m.regs[r_flg] & 0x80 || (this->m.t_brr_header & 3) == 1)
415
-	{
416
-		v->env_mode = env_release;
417
-		v->env = 0;
418
-	}
419
-
420
-	if (this->m.every_other_sample)
421
-	{
422
-		// KOFF
423
-		if (this->m.t_koff & v->vbit)
424
-			v->env_mode = env_release;
425
-
426
-		// KON
427
-		if (this->m.kon & v->vbit)
428
-		{
429
-			v->kon_delay = 5;
430
-			v->env_mode  = env_attack;
431
-		}
432
-	}
433
-
434
-	// Run envelope for next sample
435
-	if (!v->kon_delay)
436
-		this->run_envelope(v);
437
-}
438
-
439
-void SPC_DSP::voice_output(const voice_t *v, int ch)
440
-{
441
-	// Apply left/right volume
442
-	int amp = (this->m.t_output * static_cast<int8_t>(v->regs[v_voll + ch])) >> 7;
443
-	amp *= (this->stereo_switch & (1 << (v->voice_number + ch * voice_count))) ? 1 : 0;
444
-
445
-	// Add to output total
446
-	this->m.t_main_out[ch] += amp;
447
-	CLAMP16(this->m.t_main_out[ch]);
448
-
449
-	// Optionally add to echo total
450
-	if (this->m.t_eon & v->vbit)
451
-	{
452
-		this->m.t_echo_out[ch] += amp;
453
-		CLAMP16(this->m.t_echo_out[ch]);
454
-	}
455
-}
456
-void SPC_DSP::voice_V4(voice_t *const v)
457
-{
458
-	// Decode BRR
459
-	this->m.t_looped = 0;
460
-	if (v->interp_pos >= 0x4000)
461
-	{
462
-		this->decode_brr(v);
463
-
464
-		if ((v->brr_offset += 2) >= brr_block_size)
465
-		{
466
-			// Start decoding next BRR block
467
-			assert(v->brr_offset == brr_block_size);
468
-			v->brr_addr = (v->brr_addr + brr_block_size) & 0xFFFF;
469
-			if (this->m.t_brr_header & 1)
470
-			{
471
-				v->brr_addr = this->m.t_brr_next_addr;
472
-				this->m.t_looped = v->vbit;
473
-			}
474
-			v->brr_offset = 1;
475
-		}
476
-	}
477
-
478
-	// Apply pitch
479
-	v->interp_pos = (v->interp_pos & 0x3FFF) + m.t_pitch;
480
-
481
-	// Keep from getting too far ahead (when using pitch modulation)
482
-	if (v->interp_pos > 0x7FFF)
483
-		v->interp_pos = 0x7FFF;
484
-
485
-	// Output left
486
-	this->voice_output(v, 0);
487
-}
488
-void SPC_DSP::voice_V5(voice_t *const v)
489
-{
490
-	// Output right
491
-	this->voice_output(v, 1);
492
-
493
-	// ENDX, OUTX, and ENVX won't update if you wrote to them 1-2 clocks earlier
494
-	int endx_buf = this->m.regs[r_endx] | this->m.t_looped;
495
-
496
-	// Clear bit in ENDX if KON just began
497
-	if (v->kon_delay == 5)
498
-		endx_buf &= ~v->vbit;
499
-	this->m.endx_buf = static_cast<uint8_t>(endx_buf);
500
-}
501
-void SPC_DSP::voice_V6(voice_t *const)
502
-{
503
-	this->m.outx_buf = static_cast<uint8_t>(this->m.t_output >> 8);
504
-}
505
-void SPC_DSP::voice_V7(voice_t *const v)
506
-{
507
-	// Update ENDX
508
-	this->m.regs[r_endx] = this->m.endx_buf;
509
-
510
-	this->m.envx_buf = v->t_envx_out;
511
-}
512
-void SPC_DSP::voice_V8(voice_t *const v)
513
-{
514
-	// Update OUTX
515
-	v->regs[v_outx] = this->m.outx_buf;
516
-}
517
-void SPC_DSP::voice_V9(voice_t *const v)
518
-{
519
-	// Update ENVX
520
-	v->regs[v_envx] = this->m.envx_buf;
521
-}
522
-
523
-// Most voices do all these in one clock, so make a handy composite
524
-void SPC_DSP::voice_V3(voice_t *const v)
525
-{
526
-	this->voice_V3a(v);
527
-	this->voice_V3b(v);
528
-	this->voice_V3c(v);
529
-}
530
-
531
-// Common combinations of voice steps on different voices. This greatly reduces
532
-// code size and allows everything to be inlined in these functions.
533
-void SPC_DSP::voice_V7_V4_V1(voice_t *const v) { this->voice_V7(v); this->voice_V1(v + 3); this->voice_V4(v + 1); }
534
-void SPC_DSP::voice_V8_V5_V2(voice_t *const v) { this->voice_V8(v); this->voice_V5(v + 1); this->voice_V2(v + 2); }
535
-void SPC_DSP::voice_V9_V6_V3(voice_t *const v) { this->voice_V9(v); this->voice_V6(v + 1); this->voice_V3(v + 2); }
536
-
537
-//// Echo
538
-
539
-void SPC_DSP::echo_read(int ch)
540
-{
541
-	int s = static_cast<int16_t>(get_le16(this->ECHO_PTR(ch)));
542
-	// second copy simplifies wrap-around handling
543
-	this->ECHO_FIR(0)[ch] = this->ECHO_FIR(8)[ch] = s >> 1;
544
-}
545
-
546
-void SPC_DSP::echo_22()
547
-{
548
-	// History
549
-	if (++this->m.echo_hist_pos >= &this->m.echo_hist[echo_hist_size])
550
-		this->m.echo_hist_pos = this->m.echo_hist;
551
-
552
-	this->m.t_echo_ptr = (this->m.t_esa * 0x100 + this->m.echo_offset) & 0xFFFF;
553
-	this->echo_read(0);
554
-
555
-	// FIR (using l and r temporaries below helps compiler optimize)
556
-	int l = this->CALC_FIR(0, 0);
557
-	int r = this->CALC_FIR(0, 1);
558
-
559
-	this->m.t_echo_in[0] = l;
560
-	this->m.t_echo_in[1] = r;
561
-}
562
-void SPC_DSP::echo_23()
563
-{
564
-	int l = this->CALC_FIR(1, 0) + this->CALC_FIR(2, 0);
565
-	int r = this->CALC_FIR(1, 1) + this->CALC_FIR(2, 1);
566
-
567
-	this->m.t_echo_in[0] += l;
568
-	this->m.t_echo_in[1] += r;
569
-
570
-	echo_read(1);
571
-}
572
-void SPC_DSP::echo_24()
573
-{
574
-	int l = this->CALC_FIR(3, 0) + this->CALC_FIR(4, 0) + this->CALC_FIR(5, 0);
575
-	int r = this->CALC_FIR(3, 1) + this->CALC_FIR(4, 1) + this->CALC_FIR(5, 1);
576
-
577
-	this->m.t_echo_in[0] += l;
578
-	this->m.t_echo_in[1] += r;
579
-}
580
-void SPC_DSP::echo_25()
581
-{
582
-	int l = this->m.t_echo_in[0] + this->CALC_FIR(6, 0);
583
-	int r = this->m.t_echo_in[1] + this->CALC_FIR(6, 1);
584
-
585
-	l = static_cast<int16_t>(l);
586
-	r = static_cast<int16_t>(r);
587
-
588
-	l += static_cast<int16_t>(this->CALC_FIR(7, 0));
589
-	r += static_cast<int16_t>(this->CALC_FIR(7, 1));
590
-
591
-	CLAMP16(l);
592
-	CLAMP16(r);
593
-
594
-	this->m.t_echo_in[0] = l & ~1;
595
-	this->m.t_echo_in[1] = r & ~1;
596
-}
597
-int SPC_DSP::echo_output(int ch)
598
-{
599
-	int out = static_cast<int16_t>((this->m.t_main_out [ch] * static_cast<int8_t>(this->m.regs[r_mvoll + ch * 0x10])) >> 7) +
600
-		static_cast<int16_t>((this->m.t_echo_in [ch] * static_cast<int8_t>(this->m.regs[r_evoll + ch * 0x10])) >> 7);
601
-	CLAMP16(out);
602
-	return out;
603
-}
604
-void SPC_DSP::echo_26()
605
-{
606
-	// Left output volumes
607
-	// (save sample for next clock so we can output both together)
608
-	this->m.t_main_out[0] = echo_output(0);
609
-
610
-	// Echo feedback
611
-	int l = this->m.t_echo_out[0] + static_cast<int16_t>((this->m.t_echo_in[0] * static_cast<int8_t>(this->m.regs[r_efb])) >> 7);
612
-	int r = this->m.t_echo_out[1] + static_cast<int16_t>((this->m.t_echo_in[1] * static_cast<int8_t>(this->m.regs[r_efb])) >> 7);
613
-
614
-	CLAMP16(l);
615
-	CLAMP16(r);
616
-
617
-	this->m.t_echo_out[0] = l & ~1;
618
-	this->m.t_echo_out[1] = r & ~1;
619
-}
620
-void SPC_DSP::echo_27()
621
-{
622
-	// Output
623
-	int l = this->m.t_main_out[0];
624
-	int r = echo_output(1);
625
-	this->m.t_main_out[0] = this->m.t_main_out[1] = 0;
626
-
627
-	// TODO: global muting isn't this simple (turns DAC on and off
628
-	// or something, causing small ~37-sample pulse when first muted)
629
-	if (this->m.regs[r_flg] & 0x40)
630
-		l = r = 0;
631
-
632
-	// Output sample to DAC
633
-#ifdef SPC_DSP_OUT_HOOK
634
-	SPC_DSP_OUT_HOOK(l, r);
635
-#else
636
-	sample_t *out = this->m.out;
637
-	out[0] = l;
638
-	out[1] = r;
639
-	out += 2;
640
-	if (out >= m.out_end)
641
-	{
642
-		out = this->m.extra;
643
-		this->m.out_end = &this->m.extra[extra_size];
644
-	}
645
-	this->m.out = out;
646
-#endif
647
-}
648
-void SPC_DSP::echo_28()
649
-{
650
-	this->m.t_echo_enabled = this->m.regs[r_flg];
651
-}
652
-void SPC_DSP::echo_write(int ch)
653
-{
654
-	if (!(this->m.t_echo_enabled & 0x20))
655
-	{
656
-		if (this->m.t_echo_ptr >= 0xffc0 && this->rom_enabled)
657
-			set_le16(&this->hi_ram[this->m.t_echo_ptr + ch * 2 - 0xffc0], this->m.t_echo_out [ch]);
658
-		else
659
-			set_le16(this->ECHO_PTR(ch), this->m.t_echo_out[ch]);
660
-	}
661
-
662
-	this->m.t_echo_out[ch] = 0;
663
-}
664
-void SPC_DSP::echo_29()
665
-{
666
-	this->m.t_esa = this->m.regs[r_esa];
667
-
668
-	if (!this->m.echo_offset)
669
-		this->m.echo_length = (this->m.regs[r_edl] & 0x0F) * 0x800;
670
-
671
-	this->m.echo_offset += 4;
672
-	if (this->m.echo_offset >= this->m.echo_length)
673
-		this->m.echo_offset = 0;
674
-
675
-	// Write left echo
676
-	this->echo_write(0);
677
-
678
-	this->m.t_echo_enabled = this->m.regs[r_flg];
679
-}
680
-void SPC_DSP::echo_30()
681
-{
682
-	// Write right echo
683
-	this->echo_write(1);
684
-}
685
-
686
-//// Timing
687
-
688
-// Execute clock for a particular voice
689
-#define V(clock, voice) voice_##clock(&this->m.voices[voice]);
690
-
691
-/* The most common sequence of clocks uses composite operations
692
-for efficiency. For example, the following are equivalent to the
693
-individual steps on the right:
694
-
695
-V(V7_V4_V1,2) -> V(V7,2) V(V4,3) V(V1,5)
696
-V(V8_V5_V2,2) -> V(V8,2) V(V5,3) V(V2,4)
697
-V(V9_V6_V3,2) -> V(V9,2) V(V6,3) V(V3,4) */
698
-
699
-// Voice      0      1      2      3      4      5      6      7
700
-#define GEN_DSP_TIMING \
701
-PHASE(0) V(V5, 0) V(V2, 1) \
702
-PHASE(1) V(V6, 0) V(V3, 1) \
703
-PHASE(2) V(V7_V4_V1, 0) \
704
-PHASE(3) V(V8_V5_V2, 0) \
705
-PHASE(4) V(V9_V6_V3, 0) \
706
-PHASE(5) V(V7_V4_V1, 1) \
707
-PHASE(6) V(V8_V5_V2, 1) \
708
-PHASE(7) V(V9_V6_V3, 1) \
709
-PHASE(8) V(V7_V4_V1, 2) \
710
-PHASE(9) V(V8_V5_V2, 2) \
711
-PHASE(10) V(V9_V6_V3, 2) \
712
-PHASE(11) V(V7_V4_V1, 3) \
713
-PHASE(12) V(V8_V5_V2, 3) \
714
-PHASE(13) V(V9_V6_V3, 3) \
715
-PHASE(14) V(V7_V4_V1, 4) \
716
-PHASE(15) V(V8_V5_V2, 4) \
717
-PHASE(16) V(V9_V6_V3, 4) \
718
-PHASE(17) V(V1, 0) V(V7, 5) V(V4, 6) \
719
-PHASE(18) V(V8_V5_V2, 5) \
720
-PHASE(19) V(V9_V6_V3, 5) \
721
-PHASE(20) V(V1, 1) V(V7, 6) V(V4, 7) \
722
-PHASE(21) V(V8, 6) V(V5, 7) V(V2, 0) /* t_brr_next_addr order dependency */ \
723
-PHASE(22) V(V3a, 0) V(V9, 6) V(V6, 7) echo_22(); \
724
-PHASE(23) V(V7, 7) echo_23(); \
725
-PHASE(24) V(V8, 7) echo_24(); \
726
-PHASE(25) V(V3b, 0) V(V9, 7) echo_25(); \
727
-PHASE(26) echo_26(); \
728
-PHASE(27) misc_27(); echo_27(); \
729
-PHASE(28) misc_28(); echo_28(); \
730
-PHASE(29) misc_29(); echo_29(); \
731
-PHASE(30) misc_30(); V(V3c, 0) echo_30(); \
732
-PHASE(31) V(V4, 0) V(V1, 2)
733
-
734
-#ifndef SPC_DSP_CUSTOM_RUN
735
-void SPC_DSP::run(int clocks_remain)
736
-{
737
-	assert(clocks_remain > 0);
738
-
739
-	int phase = this->m.phase;
740
-	this->m.phase = (phase + clocks_remain) & 31;
741
-	switch (phase)
742
-	{
743
-		loop:
744
-#define PHASE(n) if (n && !--clocks_remain) break; case n:
745
-		GEN_DSP_TIMING
746
-#undef PHASE
747
-
748
-		if (--clocks_remain)
749
-			goto loop;
750
-	}
751
-}
752
-#endif
753
-
754
-//// Setup
755
-
756
-void SPC_DSP::init(uint8_t *ram_64k)
757
-{
758
-	this->m.ram = ram_64k;
759
-	this->mute_voices(0);
760
-	this->disable_surround(false);
761
-	this->set_output(nullptr, 0);
762
-	this->reset();
763
-
764
-	this->stereo_switch = 0xffff;
765
-
766
-#ifndef NDEBUG
767
-	// be sure this sign-extends
768
-	assert(static_cast<int16_t>(0x8000) == -0x8000);
769
-
770
-	// be sure right shift preserves sign
771
-	assert((-1 >> 1) == -1);
772
-
773
-	// check clamp macro
774
-	int i = 0x8000;
775
-	CLAMP16(i);
776
-	assert(i == 0x7FFF);
777
-
778
-	i = -0x8001;
779
-	CLAMP16(i);
780
-	assert(i == -0x8000);
781
-
782
-	blargg_verify_byte_order();
783
-#endif
784
-}
785
-
786
-void SPC_DSP::soft_reset_common()
787
-{
788
-	assert(this->m.ram); // init() must have been called already
789
-
790
-	this->m.noise = 0x4000;
791
-	this->m.echo_hist_pos = this->m.echo_hist;
792
-	this->m.every_other_sample = true;
793
-	this->m.echo_offset = 0;
794
-	this->m.phase = 0;
795
-
796
-	this->init_counter();
797
-
798
-	for (int i = 0; i < voice_count; ++i)
799
-		this->m.voices[i].voice_number = i;
800
-}
801
-
802
-void SPC_DSP::soft_reset()
803
-{
804
-	this->m.regs[r_flg] = 0xE0;
805
-	this->soft_reset_common();
806
-}
807
-
808
-void SPC_DSP::load(const uint8_t regs[register_count])
809
-{
810
-	std::copy_n(&regs[0], static_cast<int>(register_count), &this->m.regs[0]);
811
-	memset(&this->m.regs[register_count], 0, offsetof(state_t, ram) - register_count);
812
-
813
-	// Internal state
814
-	for (int i = voice_count; --i >= 0;)
815
-	{
816
-		auto &v = this->m.voices[i];
817
-		v.brr_offset = 1;
818
-		v.vbit = 1 << i;
819
-		v.regs = &this->m.regs[i * 0x10];
820
-	}
821
-	this->m.new_kon = this->m.regs[r_kon];
822
-	this->m.t_dir = this->m.regs[r_dir];
823
-	this->m.t_esa = this->m.regs[r_esa];
824
-
825
-	this->soft_reset_common();
826
-}
827
-
828
-void SPC_DSP::reset()
829
-{
830
-	this->load(initial_regs);
831
-}
832
-
833
-//// Snes9x Accessor
834
-
835
-void SPC_DSP::set_stereo_switch(int value)
836
-{
837
-	this->stereo_switch = value;
838
-}
839
-
840
-uint8_t SPC_DSP::reg_value(int ch, int addr)
841
-{
842
-	return this->m.voices[ch].regs[addr];
843
-}
844
-
845
-int SPC_DSP::envx_value(int ch)
846
-{
847
-	return this->m.voices[ch].env;
848
-}
Browse code

* Small Makefile changes.

* Removed a couple files that were not being used.
* Cleanups found with clang's -Weverything (and shutting it up about a
lot of things that were ridiculous, as well as ignoring some of the
warnings still coming up).

Naram Qashat authored on 2014/09/25 12:28:21
Showing 1 changed files
... ...
@@ -731,7 +731,7 @@ PHASE(29) misc_29(); echo_29(); \
731 731
 PHASE(30) misc_30(); V(V3c, 0) echo_30(); \
732 732
 PHASE(31) V(V4, 0) V(V1, 2)
733 733
 
734
-#if !SPC_DSP_CUSTOM_RUN
734
+#ifndef SPC_DSP_CUSTOM_RUN
735 735
 void SPC_DSP::run(int clocks_remain)
736 736
 {
737 737
 	assert(clocks_remain > 0);
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
... ...
@@ -238,7 +238,7 @@ void SPC_DSP::run_envelope(voice_t *const v)
238 238
 			if (v->env_mode == env_attack)
239 239
 				v->env_mode = env_decay;
240 240
 		}
241
-		
241
+
242 242
 		if (!this->read_counter(rate))
243 243
 			v->env = env; // nothing else is controlled by the counter
244 244
 	}
... ...
@@ -326,7 +326,7 @@ void SPC_DSP::misc_30()
326 326
 	if (this->m.every_other_sample)
327 327
 	{
328 328
 		this->m.kon = this->m.new_kon;
329
-		this->m.t_koff = this->m.regs[r_koff] | this->m.mute_mask; 
329
+		this->m.t_koff = this->m.regs[r_koff] | this->m.mute_mask;
330 330
 	}
331 331
 
332 332
 	this->run_counters();
... ...
@@ -606,7 +606,7 @@ void SPC_DSP::echo_26()
606 606
 	// Left output volumes
607 607
 	// (save sample for next clock so we can output both together)
608 608
 	this->m.t_main_out[0] = echo_output(0);
609
-	
609
+
610 610
 	// Echo feedback
611 611
 	int l = this->m.t_echo_out[0] + static_cast<int16_t>((this->m.t_echo_in[0] * static_cast<int8_t>(this->m.regs[r_efb])) >> 7);
612 612
 	int r = this->m.t_echo_out[1] + static_cast<int16_t>((this->m.t_echo_in[1] * static_cast<int8_t>(this->m.regs[r_efb])) >> 7);
... ...
@@ -744,7 +744,7 @@ void SPC_DSP::run(int clocks_remain)
744 744
 #define PHASE(n) if (n && !--clocks_remain) break; case n:
745 745
 		GEN_DSP_TIMING
746 746
 #undef PHASE
747
-	
747
+
748 748
 		if (--clocks_remain)
749 749
 			goto loop;
750 750
 	}
Browse code

[SNSF] Replaced most uses of fill/copy with fill_n/copy_n, and a few other minor code cleanups.

Naram Qashat authored on 2013/05/27 22:34:22
Showing 1 changed files
... ...
@@ -317,7 +317,8 @@ void SPC_DSP::misc_28()
317 317
 }
318 318
 void SPC_DSP::misc_29()
319 319
 {
320
-	if ((this->m.every_other_sample = !this->m.every_other_sample))
320
+	this->m.every_other_sample = !this->m.every_other_sample;
321
+	if (this->m.every_other_sample)
321 322
 		this->m.new_kon &= ~this->m.kon; // clears KON 63 clocks after it was last read
322 323
 }
323 324
 void SPC_DSP::misc_30()
... ...
@@ -697,38 +698,38 @@ V(V9_V6_V3,2) -> V(V9,2) V(V6,3) V(V3,4) */
697 698
 
698 699
 // Voice      0      1      2      3      4      5      6      7
699 700
 #define GEN_DSP_TIMING \
700
-PHASE( 0)  V(V5,0)V(V2,1)\
701
-PHASE( 1)  V(V6,0)V(V3,1)\
702
-PHASE( 2)  V(V7_V4_V1,0)\
703
-PHASE( 3)  V(V8_V5_V2,0)\
704
-PHASE( 4)  V(V9_V6_V3,0)\
705
-PHASE( 5)         V(V7_V4_V1,1)\
706
-PHASE( 6)         V(V8_V5_V2,1)\
707
-PHASE( 7)         V(V9_V6_V3,1)\
708
-PHASE( 8)                V(V7_V4_V1,2)\
709
-PHASE( 9)                V(V8_V5_V2,2)\
710
-PHASE(10)                V(V9_V6_V3,2)\
711
-PHASE(11)                       V(V7_V4_V1,3)\
712
-PHASE(12)                       V(V8_V5_V2,3)\
713
-PHASE(13)                       V(V9_V6_V3,3)\
714
-PHASE(14)                              V(V7_V4_V1,4)\
715
-PHASE(15)                              V(V8_V5_V2,4)\
716
-PHASE(16)                              V(V9_V6_V3,4)\
717
-PHASE(17)  V(V1,0)                            V(V7,5)V(V4,6)\
718
-PHASE(18)                                     V(V8_V5_V2,5)\
719
-PHASE(19)                                     V(V9_V6_V3,5)\
720
-PHASE(20)         V(V1,1)                            V(V7,6)V(V4,7)\
721
-PHASE(21)                                            V(V8,6)V(V5,7)  V(V2,0)  /* t_brr_next_addr order dependency */\
722
-PHASE(22)  V(V3a,0)                                  V(V9,6)V(V6,7)  echo_22();\
723
-PHASE(23)                                                   V(V7,7)  echo_23();\
724
-PHASE(24)                                                   V(V8,7)  echo_24();\
725
-PHASE(25)  V(V3b,0)                                         V(V9,7)  echo_25();\
726
-PHASE(26)                                                            echo_26();\
727
-PHASE(27) misc_27();                                                 echo_27();\
728
-PHASE(28) misc_28();                                                 echo_28();\
729
-PHASE(29) misc_29();                                                 echo_29();\
730
-PHASE(30) misc_30();V(V3c,0)                                         echo_30();\
731
-PHASE(31)  V(V4,0)       V(V1,2)\
701
+PHASE(0) V(V5, 0) V(V2, 1) \
702
+PHASE(1) V(V6, 0) V(V3, 1) \
703
+PHASE(2) V(V7_V4_V1, 0) \
704
+PHASE(3) V(V8_V5_V2, 0) \
705
+PHASE(4) V(V9_V6_V3, 0) \
706
+PHASE(5) V(V7_V4_V1, 1) \
707
+PHASE(6) V(V8_V5_V2, 1) \
708
+PHASE(7) V(V9_V6_V3, 1) \
709
+PHASE(8) V(V7_V4_V1, 2) \
710
+PHASE(9) V(V8_V5_V2, 2) \
711
+PHASE(10) V(V9_V6_V3, 2) \
712
+PHASE(11) V(V7_V4_V1, 3) \
713
+PHASE(12) V(V8_V5_V2, 3) \
714
+PHASE(13) V(V9_V6_V3, 3) \
715
+PHASE(14) V(V7_V4_V1, 4) \
716
+PHASE(15) V(V8_V5_V2, 4) \
717
+PHASE(16) V(V9_V6_V3, 4) \
718
+PHASE(17) V(V1, 0) V(V7, 5) V(V4, 6) \
719
+PHASE(18) V(V8_V5_V2, 5) \
720
+PHASE(19) V(V9_V6_V3, 5) \
721
+PHASE(20) V(V1, 1) V(V7, 6) V(V4, 7) \
722
+PHASE(21) V(V8, 6) V(V5, 7) V(V2, 0) /* t_brr_next_addr order dependency */ \
723
+PHASE(22) V(V3a, 0) V(V9, 6) V(V6, 7) echo_22(); \
724
+PHASE(23) V(V7, 7) echo_23(); \
725
+PHASE(24) V(V8, 7) echo_24(); \
726
+PHASE(25) V(V3b, 0) V(V9, 7) echo_25(); \
727
+PHASE(26) echo_26(); \
728
+PHASE(27) misc_27(); echo_27(); \
729
+PHASE(28) misc_28(); echo_28(); \
730
+PHASE(29) misc_29(); echo_29(); \
731
+PHASE(30) misc_30(); V(V3c, 0) echo_30(); \
732
+PHASE(31) V(V4, 0) V(V1, 2)
732 733
 
733 734
 #if !SPC_DSP_CUSTOM_RUN
734 735
 void SPC_DSP::run(int clocks_remain)
... ...
@@ -748,7 +749,6 @@ void SPC_DSP::run(int clocks_remain)
748 749
 			goto loop;
749 750
 	}
750 751
 }
751
-
752 752
 #endif
753 753
 
754 754
 //// Setup
... ...
@@ -807,7 +807,7 @@ void SPC_DSP::soft_reset()
807 807
 
808 808
 void SPC_DSP::load(const uint8_t regs[register_count])
809 809
 {
810
-	std::copy(&regs[0], &regs[register_count], &this->m.regs[0]);
810
+	std::copy_n(&regs[0], static_cast<int>(register_count), &this->m.regs[0]);
811 811
 	memset(&this->m.regs[register_count], 0, offsetof(state_t, ram) - register_count);
812 812
 
813 813
 	// Internal state
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
... ...
@@ -1,9 +1,10 @@
1 1
 // snes_spc 0.9.0. http://www.slack.net/~ant/
2 2
 
3
+#include <algorithm>
4
+#include <cstring>
3 5
 #include "SPC_DSP.h"
4 6
 
5 7
 #include "blargg_endian.h"
6
-#include <string.h>
7 8
 
8 9
 /* Copyright (C) 2007 Shay Green. This module is free software; you
9 10
 can redistribute it and/or modify it under the terms of the GNU Lesser
... ...
@@ -16,73 +17,40 @@ details. You should have received a copy of the GNU Lesser General Public
16 17
 License along with this module; if not, write to the Free Software Foundation,
17 18
 Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
18 19
 
19
-#include "blargg_source.h"
20
-
21
-#ifdef BLARGG_ENABLE_OPTIMIZER
22
-	#include BLARGG_ENABLE_OPTIMIZER
23
-#endif
24
-
25 20
 #if INT_MAX < 0x7FFFFFFF
26
-	#error "Requires that int type have at least 32 bits"
21
+# error "Requires that int type have at least 32 bits"
27 22
 #endif
28 23
 
29
-// TODO: add to blargg_endian.h
30
-#define GET_LE16SA( addr )      ((BOOST::int16_t) GET_LE16( addr ))
31
-#define GET_LE16A( addr )       GET_LE16( addr )
32
-#define SET_LE16A( addr, data ) SET_LE16( addr, data )
33
-
34
-static BOOST::uint8_t const initial_regs [SPC_DSP::register_count] =
24
+static const uint8_t initial_regs[] =
35 25
 {
36
-	0x45,0x8B,0x5A,0x9A,0xE4,0x82,0x1B,0x78,0x00,0x00,0xAA,0x96,0x89,0x0E,0xE0,0x80,
37
-	0x2A,0x49,0x3D,0xBA,0x14,0xA0,0xAC,0xC5,0x00,0x00,0x51,0xBB,0x9C,0x4E,0x7B,0xFF,
38
-	0xF4,0xFD,0x57,0x32,0x37,0xD9,0x42,0x22,0x00,0x00,0x5B,0x3C,0x9F,0x1B,0x87,0x9A,
39
-	0x6F,0x27,0xAF,0x7B,0xE5,0x68,0x0A,0xD9,0x00,0x00,0x9A,0xC5,0x9C,0x4E,0x7B,0xFF,
40
-	0xEA,0x21,0x78,0x4F,0xDD,0xED,0x24,0x14,0x00,0x00,0x77,0xB1,0xD1,0x36,0xC1,0x67,
41
-	0x52,0x57,0x46,0x3D,0x59,0xF4,0x87,0xA4,0x00,0x00,0x7E,0x44,0x00,0x4E,0x7B,0xFF,
42
-	0x75,0xF5,0x06,0x97,0x10,0xC3,0x24,0xBB,0x00,0x00,0x7B,0x7A,0xE0,0x60,0x12,0x0F,
43
-	0xF7,0x74,0x1C,0xE5,0x39,0x3D,0x73,0xC1,0x00,0x00,0x7A,0xB3,0xFF,0x4E,0x7B,0xFF
26
+	0x45, 0x8B, 0x5A, 0x9A, 0xE4, 0x82, 0x1B, 0x78, 0x00, 0x00, 0xAA, 0x96, 0x89, 0x0E, 0xE0, 0x80,
27
+	0x2A, 0x49, 0x3D, 0xBA, 0x14, 0xA0, 0xAC, 0xC5, 0x00, 0x00, 0x51, 0xBB, 0x9C, 0x4E, 0x7B, 0xFF,
28
+	0xF4, 0xFD, 0x57, 0x32, 0x37, 0xD9, 0x42, 0x22, 0x00, 0x00, 0x5B, 0x3C, 0x9F, 0x1B, 0x87, 0x9A,
29
+	0x6F, 0x27, 0xAF, 0x7B, 0xE5, 0x68, 0x0A, 0xD9, 0x00, 0x00, 0x9A, 0xC5, 0x9C, 0x4E, 0x7B, 0xFF,
30
+	0xEA, 0x21, 0x78, 0x4F, 0xDD, 0xED, 0x24, 0x14, 0x00, 0x00, 0x77, 0xB1, 0xD1, 0x36, 0xC1, 0x67,
31
+	0x52, 0x57, 0x46, 0x3D, 0x59, 0xF4, 0x87, 0xA4, 0x00, 0x00, 0x7E, 0x44, 0x00, 0x4E, 0x7B, 0xFF,
32
+	0x75, 0xF5, 0x06, 0x97, 0x10, 0xC3, 0x24, 0xBB, 0x00, 0x00, 0x7B, 0x7A, 0xE0, 0x60, 0x12, 0x0F,
33
+	0xF7, 0x74, 0x1C, 0xE5, 0x39, 0x3D, 0x73, 0xC1, 0x00, 0x00, 0x7A, 0xB3, 0xFF, 0x4E, 0x7B, 0xFF
44 34
 };
45 35
 
46 36
 // if ( io < -32768 ) io = -32768;
47 37
 // if ( io >  32767 ) io =  32767;
48
-#define CLAMP16( io )\
49
-{\
50
-	if ( (int16_t) io != io )\
51
-		io = (io >> 31) ^ 0x7FFF;\
38
+template<typename T> static inline void CLAMP16(T &io)
39
+{
40
+	if (static_cast<int16_t>(io) != io)
41
+		io = (io >> 31) ^ 0x7FFF;
52 42
 }
53 43
 
54
-// Access global DSP register
55
-#define REG(n)      m.regs [r_##n]
56
-
57
-// Access voice DSP register
58
-#define VREG(r,n)   r [v_##n]
59
-
60
-#define WRITE_SAMPLES( l, r, out ) \
61
-{\
62
-	out [0] = l;\
63
-	out [1] = r;\
64
-	out += 2;\
65
-	if ( out >= m.out_end )\
66
-	{\
67
-		check( out == m.out_end );\
68
-		check( m.out_end != &m.extra [extra_size] || \
69
-			(m.extra <= m.out_begin && m.extra < &m.extra [extra_size]) );\
70
-		out       = m.extra;\
71
-		m.out_end = &m.extra [extra_size];\
72
-	}\
73
-}\
74
-
75
-void SPC_DSP::set_output( sample_t* out, int size )
44
+void SPC_DSP::set_output(sample_t *out, int size)
76 45
 {
77
-	require( (size & 1) == 0 ); // must be even
78
-	if ( !out )
46
+	assert(!(size & 1)); // must be even
47
+	if (!out)
79 48
 	{
80
-		out  = m.extra;
49
+		out = this->m.extra;
81 50
 		size = extra_size;
82 51
 	}
83
-	m.out_begin = out;
84
-	m.out       = out;
85
-	m.out_end   = out + size;
52
+	this->m.out_begin = this->m.out = out;
53
+	this->m.out_end = out + size;
86 54
 }
87 55
 
88 56
 // Volume registers and efb are signed! Easy to forget int8_t cast.
... ...
@@ -90,87 +58,85 @@ void SPC_DSP::set_output( sample_t* out, int size )
90 58
 
91 59
 // Gaussian interpolation
92 60
 
93
-static short const gauss [512] =
94
-{
95
-   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
96
-   1,   1,   1,   1,   1,   1,   1,   1,   1,   1,   1,   2,   2,   2,   2,   2,
97
-   2,   2,   3,   3,   3,   3,   3,   4,   4,   4,   4,   4,   5,   5,   5,   5,
98
-   6,   6,   6,   6,   7,   7,   7,   8,   8,   8,   9,   9,   9,  10,  10,  10,
99
-  11,  11,  11,  12,  12,  13,  13,  14,  14,  15,  15,  15,  16,  16,  17,  17,
100
-  18,  19,  19,  20,  20,  21,  21,  22,  23,  23,  24,  24,  25,  26,  27,  27,
101
-  28,  29,  29,  30,  31,  32,  32,  33,  34,  35,  36,  36,  37,  38,  39,  40,
102
-  41,  42,  43,  44,  45,  46,  47,  48,  49,  50,  51,  52,  53,  54,  55,  56,
103
-  58,  59,  60,  61,  62,  64,  65,  66,  67,  69,  70,  71,  73,  74,  76,  77,
104
-  78,  80,  81,  83,  84,  86,  87,  89,  90,  92,  94,  95,  97,  99, 100, 102,
105
- 104, 106, 107, 109, 111, 113, 115, 117, 118, 120, 122, 124, 126, 128, 130, 132,
106
- 134, 137, 139, 141, 143, 145, 147, 150, 152, 154, 156, 159, 161, 163, 166, 168,
107
- 171, 173, 175, 178, 180, 183, 186, 188, 191, 193, 196, 199, 201, 204, 207, 210,
108
- 212, 215, 218, 221, 224, 227, 230, 233, 236, 239, 242, 245, 248, 251, 254, 257,
109
- 260, 263, 267, 270, 273, 276, 280, 283, 286, 290, 293, 297, 300, 304, 307, 311,
110
- 314, 318, 321, 325, 328, 332, 336, 339, 343, 347, 351, 354, 358, 362, 366, 370,
111
- 374, 378, 381, 385, 389, 393, 397, 401, 405, 410, 414, 418, 422, 426, 430, 434,
112
- 439, 443, 447, 451, 456, 460, 464, 469, 473, 477, 482, 486, 491, 495, 499, 504,
113
- 508, 513, 517, 522, 527, 531, 536, 540, 545, 550, 554, 559, 563, 568, 573, 577,
114
- 582, 587, 592, 596, 601, 606, 611, 615, 620, 625, 630, 635, 640, 644, 649, 654,
115
- 659, 664, 669, 674, 678, 683, 688, 693, 698, 703, 708, 713, 718, 723, 728, 732,
116
- 737, 742, 747, 752, 757, 762, 767, 772, 777, 782, 787, 792, 797, 802, 806, 811,
117
- 816, 821, 826, 831, 836, 841, 846, 851, 855, 860, 865, 870, 875, 880, 884, 889,
118
- 894, 899, 904, 908, 913, 918, 923, 927, 932, 937, 941, 946, 951, 955, 960, 965,
119
- 969, 974, 978, 983, 988, 992, 997,1001,1005,1010,1014,1019,1023,1027,1032,1036,
120
-1040,1045,1049,1053,1057,1061,1066,1070,1074,1078,1082,1086,1090,1094,1098,1102,
121
-1106,1109,1113,1117,1121,1125,1128,1132,1136,1139,1143,1146,1150,1153,1157,1160,
122
-1164,1167,1170,1174,1177,1180,1183,1186,1190,1193,1196,1199,1202,1205,1207,1210,
123
-1213,1216,1219,1221,1224,1227,1229,1232,1234,1237,1239,1241,1244,1246,1248,1251,
124
-1253,1255,1257,1259,1261,1263,1265,1267,1269,1270,1272,1274,1275,1277,1279,1280,
125
-1282,1283,1284,1286,1287,1288,1290,1291,1292,1293,1294,1295,1296,1297,1297,1298,
126
-1299,1300,1300,1301,1302,1302,1303,1303,1303,1304,1304,1304,1304,1304,1305,1305,
61
+static const short gauss[] =
62
+{
63
+	   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
64
+	   1,   1,   1,   1,   1,   1,   1,   1,   1,   1,   1,   2,   2,   2,   2,   2,
65
+	   2,   2,   3,   3,   3,   3,   3,   4,   4,   4,   4,   4,   5,   5,   5,   5,
66
+	   6,   6,   6,   6,   7,   7,   7,   8,   8,   8,   9,   9,   9,  10,  10,  10,
67
+	  11,  11,  11,  12,  12,  13,  13,  14,  14,  15,  15,  15,  16,  16,  17,  17,
68
+	  18,  19,  19,  20,  20,  21,  21,  22,  23,  23,  24,  24,  25,  26,  27,  27,
69
+	  28,  29,  29,  30,  31,  32,  32,  33,  34,  35,  36,  36,  37,  38,  39,  40,
70
+	  41,  42,  43,  44,  45,  46,  47,  48,  49,  50,  51,  52,  53,  54,  55,  56,
71
+	  58,  59,  60,  61,  62,  64,  65,  66,  67,  69,  70,  71,  73,  74,  76,  77,
72
+	  78,  80,  81,  83,  84,  86,  87,  89,  90,  92,  94,  95,  97,  99, 100, 102,
73
+	 104, 106, 107, 109, 111, 113, 115, 117, 118, 120, 122, 124, 126, 128, 130, 132,
74
+	 134, 137, 139, 141, 143, 145, 147, 150, 152, 154, 156, 159, 161, 163, 166, 168,
75
+	 171, 173, 175, 178, 180, 183, 186, 188, 191, 193, 196, 199, 201, 204, 207, 210,
76
+	 212, 215, 218, 221, 224, 227, 230, 233, 236, 239, 242, 245, 248, 251, 254, 257,
77
+	 260, 263, 267, 270, 273, 276, 280, 283, 286, 290, 293, 297, 300, 304, 307, 311,
78
+	 314, 318, 321, 325, 328, 332, 336, 339, 343, 347, 351, 354, 358, 362, 366, 370,
79
+	 374, 378, 381, 385, 389, 393, 397, 401, 405, 410, 414, 418, 422, 426, 430, 434,
80
+	 439, 443, 447, 451, 456, 460, 464, 469, 473, 477, 482, 486, 491, 495, 499, 504,
81
+	 508, 513, 517, 522, 527, 531, 536, 540, 545, 550, 554, 559, 563, 568, 573, 577,
82
+	 582, 587, 592, 596, 601, 606, 611, 615, 620, 625, 630, 635, 640, 644, 649, 654,
83
+	 659, 664, 669, 674, 678, 683, 688, 693, 698, 703, 708, 713, 718, 723, 728, 732,
84
+	 737, 742, 747, 752, 757, 762, 767, 772, 777, 782, 787, 792, 797, 802, 806, 811,
85
+	 816, 821, 826, 831, 836, 841, 846, 851, 855, 860, 865, 870, 875, 880, 884, 889,
86
+	 894, 899, 904, 908, 913, 918, 923, 927, 932, 937, 941, 946, 951, 955, 960, 965,
87
+	 969, 974, 978, 983, 988, 992, 997,1001,1005,1010,1014,1019,1023,1027,1032,1036,
88
+	1040,1045,1049,1053,1057,1061,1066,1070,1074,1078,1082,1086,1090,1094,1098,1102,
89
+	1106,1109,1113,1117,1121,1125,1128,1132,1136,1139,1143,1146,1150,1153,1157,1160,
90
+	1164,1167,1170,1174,1177,1180,1183,1186,1190,1193,1196,1199,1202,1205,1207,1210,
91
+	1213,1216,1219,1221,1224,1227,1229,1232,1234,1237,1239,1241,1244,1246,1248,1251,
92
+	1253,1255,1257,1259,1261,1263,1265,1267,1269,1270,1272,1274,1275,1277,1279,1280,
93
+	1282,1283,1284,1286,1287,1288,1290,1291,1292,1293,1294,1295,1296,1297,1297,1298,
94
+	1299,1300,1300,1301,1302,1302,1303,1303,1303,1304,1304,1304,1304,1304,1305,1305,
127 95
 };
128 96
 
129
-inline int SPC_DSP::interpolate( voice_t const* v )
97
+int SPC_DSP::interpolate(const voice_t *v)
130 98
 {
131 99
 	// Make pointers into gaussian based on fractional position between samples
132
-	int offset = v->interp_pos >> 4 & 0xFF;
133
-	short const* fwd = gauss + 255 - offset;
134
-	short const* rev = gauss       + offset; // mirror left half of gaussian
135
-	
136
-	int const* in = &v->buf [(v->interp_pos >> 12) + v->buf_pos];
137
-	int out;
138
-	out  = (fwd [  0] * in [0]) >> 11;
139
-	out += (fwd [256] * in [1]) >> 11;
140
-	out += (rev [256] * in [2]) >> 11;
141
-	out = (int16_t) out;
142
-	out += (rev [  0] * in [3]) >> 11;
143
-	
144
-	CLAMP16( out );
100
+	int offset = (v->interp_pos >> 4) & 0xFF;
101
+	auto fwd = gauss + 255 - offset;
102
+	auto rev = gauss + offset; // mirror left half of gaussian
103
+
104
+	auto in = &v->buf[(v->interp_pos >> 12) + v->buf_pos];
105
+	int out = (fwd[0] * in[0]) >> 11;
106
+	out += (fwd[256] * in[1]) >> 11;
107
+	out += (rev[256] * in[2]) >> 11;
108
+	out = static_cast<int16_t>(out);
109
+	out += (rev[0] * in[3]) >> 11;
110
+
111
+	CLAMP16(out);
145 112
 	out &= ~1;
146 113
 	return out;
147 114
 }
148 115
 
149
-
150 116
 //// Counters
151 117
 
152
-int const simple_counter_range = 2048 * 5 * 3; // 30720
153
-
154
-static unsigned const counter_rates [32] =
155
-{
156
-   simple_counter_range + 1, // never fires
157
-          2048, 1536,
158
-	1280, 1024,  768,
159
-	 640,  512,  384,
160
-	 320,  256,  192,
161
-	 160,  128,   96,
162
-	  80,   64,   48,
163
-	  40,   32,   24,
164
-	  20,   16,   12,
165
-	  10,    8,    6,
166
-	   5,    4,    3,
167
-	         2,
168
-	         1
118
+static const int simple_counter_range = 2048 * 5 * 3; // 30720
119
+
120
+static const unsigned counter_rates[] =
121
+{
122
+	simple_counter_range + 1, // never fires
123
+	2048, 1536,
124
+	1280, 1024, 768,
125
+	640, 512, 384,
126
+	320, 256, 192,
127
+	160, 128, 96,
128
+	80, 64, 48,
129
+	40, 32, 24,
130
+	20, 16, 12,
131
+	10, 8, 6,
132
+	5, 4, 3,
133
+	2,
134
+	1
169 135
 };
170 136
 
171
-static unsigned const counter_offsets [32] =
137
+static const unsigned counter_offsets[] =
172 138
 {
173
-	  1, 0, 1040,
139
+	1, 0, 1040,
174 140
 	536, 0, 1040,
175 141
 	536, 0, 1040,
176 142
 	536, 0, 1040,
... ...
@@ -180,64 +146,62 @@ static unsigned const counter_offsets [32] =
180 146
 	536, 0, 1040,
181 147
 	536, 0, 1040,
182 148
 	536, 0, 1040,
183
-	     0,
184
-	     0
149
+	0,
150
+	0
185 151
 };
186 152
 
187
-inline void SPC_DSP::init_counter()
153
+void SPC_DSP::init_counter()
188 154
 {
189
-	m.counter = 0;
155
+	this->m.counter = 0;
190 156
 }
191 157
 
192
-inline void SPC_DSP::run_counters()
158
+void SPC_DSP::run_counters()
193 159
 {
194
-	if ( --m.counter < 0 )
195
-		m.counter = simple_counter_range - 1;
160
+	if (--this->m.counter < 0)
161
+		this->m.counter = simple_counter_range - 1;
196 162
 }
197 163
 
198
-inline unsigned SPC_DSP::read_counter( int rate )
164
+unsigned SPC_DSP::read_counter(int rate)
199 165
 {
200
-	return ((unsigned) m.counter + counter_offsets [rate]) % counter_rates [rate];
166
+	return (static_cast<unsigned>(this->m.counter) + counter_offsets[rate]) % counter_rates[rate];
201 167
 }
202 168
 
203
-
204 169
 //// Envelope
205 170
 
206
-inline void SPC_DSP::run_envelope( voice_t* const v )
171
+void SPC_DSP::run_envelope(voice_t *const v)
207 172
 {
208 173
 	int env = v->env;
209
-	if ( v->env_mode == env_release ) // 60%
174
+	if (v->env_mode == env_release) // 60%
210 175
 	{
211
-		if ( (env -= 0x8) < 0 )
176
+		if ((env -= 0x8) < 0)
212 177
 			env = 0;
213 178
 		v->env = env;
214 179
 	}
215 180
 	else
216 181
 	{
217 182
 		int rate;
218
-		int env_data = VREG(v->regs,adsr1);
219
-		if ( m.t_adsr0 & 0x80 ) // 99% ADSR
183
+		int env_data = v->regs[v_adsr1];
184
+		if (this->m.t_adsr0 & 0x80) // 99% ADSR
220 185
 		{
221
-			if ( v->env_mode >= env_decay ) // 99%
186
+			if (v->env_mode >= env_decay) // 99%
222 187
 			{
223
-				env--;
188
+				--env;
224 189
 				env -= env >> 8;
225 190
 				rate = env_data & 0x1F;
226
-				if ( v->env_mode == env_decay ) // 1%
227
-					rate = (m.t_adsr0 >> 3 & 0x0E) + 0x10;
191
+				if (v->env_mode == env_decay) // 1%
192
+					rate = ((this->m.t_adsr0 >> 3) & 0x0E) + 0x10;
228 193
 			}
229 194
 			else // env_attack
230 195
 			{
231
-				rate = (m.t_adsr0 & 0x0F) * 2 + 1;
196
+				rate = (this->m.t_adsr0 & 0x0F) * 2 + 1;
232 197
 				env += rate < 31 ? 0x20 : 0x400;
233 198
 			}
234 199
 		}
235 200
 		else // GAIN
236 201
 		{
237
-			int mode;
238
-			env_data = VREG(v->regs,gain);
239
-			mode = env_data >> 5;
240
-			if ( mode < 4 ) // direct
202
+			env_data = v->regs[v_gain];
203
+			int mode = env_data >> 5;
204
+			if (mode < 4) // direct
241 205
 			{
242 206
 				env = env_data * 0x10;
243 207
 				rate = 31;
... ...
@@ -245,80 +209,77 @@ inline void SPC_DSP::run_envelope( voice_t* const v )
245 209
 			else
246 210
 			{
247 211
 				rate = env_data & 0x1F;
248
-				if ( mode == 4 ) // 4: linear decrease
249
-				{
212
+				if (mode == 4) // 4: linear decrease
250 213
 					env -= 0x20;
251
-				}
252
-				else if ( mode < 6 ) // 5: exponential decrease
214
+				else if (mode < 6) // 5: exponential decrease
253 215
 				{
254
-					env--;
216
+					--env;
255 217
 					env -= env >> 8;
256 218
 				}
257 219
 				else // 6,7: linear increase
258 220
 				{
259 221
 					env += 0x20;
260
-					if ( mode > 6 && (unsigned) v->hidden_env >= 0x600 )
222
+					if (mode > 6 && static_cast<unsigned>(v->hidden_env) >= 0x600)
261 223
 						env += 0x8 - 0x20; // 7: two-slope linear increase
262 224
 				}
263 225
 			}
264 226
 		}
265
-		
227
+
266 228
 		// Sustain level
267
-		if ( (env >> 8) == (env_data >> 5) && v->env_mode == env_decay )
229
+		if ((env >> 8) == (env_data >> 5) && v->env_mode == env_decay)
268 230
 			v->env_mode = env_sustain;
269
-		
231
+
270 232
 		v->hidden_env = env;
271
-		
233
+
272 234
 		// unsigned cast because linear decrease going negative also triggers this
273
-		if ( (unsigned) env > 0x7FF )
235
+		if (static_cast<unsigned>(env) > 0x7FF)
274 236
 		{
275
-			env = (env < 0 ? 0 : 0x7FF);
276
-			if ( v->env_mode == env_attack )
237
+			env = env < 0 ? 0 : 0x7FF;
238
+			if (v->env_mode == env_attack)
277 239
 				v->env_mode = env_decay;
278 240
 		}
279 241
 		
280
-		if ( !read_counter( rate ) )
242
+		if (!this->read_counter(rate))
281 243
 			v->env = env; // nothing else is controlled by the counter
282 244
 	}
283 245
 }
284 246
 
285
-
286 247
 //// BRR Decoding
287 248
 
288
-inline void SPC_DSP::decode_brr( voice_t* v )
249
+void SPC_DSP::decode_brr(voice_t *v)
289 250
 {
290 251
 	// Arrange the four input nybbles in 0xABCD order for easy decoding
291
-	int nybbles = m.t_brr_byte * 0x100 + m.ram [(v->brr_addr + v->brr_offset + 1) & 0xFFFF];
292
-	
293
-	int const header = m.t_brr_header;
294
-	
252
+	int nybbles = this->m.t_brr_byte * 0x100 + this->m.ram[(v->brr_addr + v->brr_offset + 1) & 0xFFFF];
253
+
254
+	int header = this->m.t_brr_header;
255
+
295 256
 	// Write to next four samples in circular buffer
296
-	int* pos = &v->buf [v->buf_pos];
297
-	int* end;
298
-	if ( (v->buf_pos += 4) >= brr_buf_size )
257
+	int *pos = &v->buf[v->buf_pos];
258
+	int *end;
259
+	if ((v->buf_pos += 4) >= brr_buf_size)
299 260
 		v->buf_pos = 0;
300
-	
261
+
301 262
 	// Decode four samples
302
-	for ( end = pos + 4; pos < end; pos++, nybbles <<= 4 )
263
+	for (end = pos + 4; pos < end; ++pos, nybbles <<= 4)
303 264
 	{
304 265
 		// Extract nybble and sign-extend
305
-		int s = (int16_t) nybbles >> 12;
306
-		
266
+		int s = static_cast<int16_t>(nybbles) >> 12;
267
+
307 268
 		// Shift sample based on header
308
-		int const shift = header >> 4;
269
+		int shift = header >> 4;
309 270
 		s = (s << shift) >> 1;
310
-		if ( shift >= 0xD ) // handle invalid range
271
+		if (shift >= 0xD) // handle invalid range
311 272
 			s = (s >> 25) << 11; // same as: s = (s < 0 ? -0x800 : 0)
312
-		
273
+
313 274
 		// Apply IIR filter (8 is the most commonly used)
314
-		int const filter = header & 0x0C;
315
-		int const p1 = pos [brr_buf_size - 1];
316
-		int const p2 = pos [brr_buf_size - 2] >> 1;
317
-		if ( filter >= 8 )
275
+		int filter = header & 0x0C;
276
+		int p1 = pos[brr_buf_size - 1];
277
+		int p2 = pos[brr_buf_size - 2] >> 1;
278
+		if (filter >= 8)
318 279
 		{
319 280
 			s += p1;
320 281
 			s -= p2;
321
-			if ( filter == 8 ) // s += p1 * 0.953125 - p2 * 0.46875
282
+			if (filter == 8) // s += p1 * 0.953125 - p2 * 0.46875
322 283
 			{
323 284
 				s += p2 >> 4;
324 285
 				s += (p1 * -3) >> 6;
... ...
@@ -329,429 +290,402 @@ inline void SPC_DSP::decode_brr( voice_t* v )
329 290
 				s += (p2 * 3) >> 4;
330 291
 			}
331 292
 		}
332
-		else if ( filter ) // s += p1 * 0.46875
293
+		else if (filter) // s += p1 * 0.46875
333 294
 		{
334 295
 			s += p1 >> 1;
335
-			s += (-p1) >> 5;
296
+			s += -p1 >> 5;
336 297
 		}
337
-		
298
+
338 299
 		// Adjust and write sample
339
-		CLAMP16( s );
340
-		s = (int16_t) (s * 2);
341
-		pos [brr_buf_size] = pos [0] = s; // second copy simplifies wrap-around
300
+		CLAMP16(s);
301
+		s = static_cast<int16_t>(s * 2);
302
+		pos[brr_buf_size] = pos[0] = s; // second copy simplifies wrap-around
342 303
 	}
343 304
 }
344 305
 
345
-
346 306
 //// Misc
347 307
 
348
-#define MISC_CLOCK( n ) inline void SPC_DSP::misc_##n()
349
-
350
-MISC_CLOCK( 27 )
308
+void SPC_DSP::misc_27()
351 309
 {
352
-	m.t_pmon = REG(pmon) & 0xFE; // voice 0 doesn't support PMON
310
+	this->m.t_pmon = this->m.regs[r_pmon] & 0xFE; // voice 0 doesn't support PMON
353 311
 }
354
-MISC_CLOCK( 28 )
312
+void SPC_DSP::misc_28()
355 313
 {
356
-	m.t_non = REG(non);
357
-	m.t_eon = REG(eon);
358
-	m.t_dir = REG(dir);
314
+	this->m.t_non = this->m.regs[r_non];
315
+	this->m.t_eon = this->m.regs[r_eon];
316
+	this->m.t_dir = this->m.regs[r_dir];
359 317
 }
360
-MISC_CLOCK( 29 )
318
+void SPC_DSP::misc_29()
361 319
 {
362
-	if ( (m.every_other_sample ^= 1) != 0 )
363
-		m.new_kon &= ~m.kon; // clears KON 63 clocks after it was last read
320
+	if ((this->m.every_other_sample = !this->m.every_other_sample))
321
+		this->m.new_kon &= ~this->m.kon; // clears KON 63 clocks after it was last read
364 322
 }
365
-MISC_CLOCK( 30 )
323
+void SPC_DSP::misc_30()
366 324
 {
367
-	if ( m.every_other_sample )
325
+	if (this->m.every_other_sample)
368 326
 	{
369
-		m.kon    = m.new_kon;
370
-		m.t_koff = REG(koff) | m.mute_mask; 
327
+		this->m.kon = this->m.new_kon;
328
+		this->m.t_koff = this->m.regs[r_koff] | this->m.mute_mask; 
371 329
 	}
372
-	
373
-	run_counters();
374
-	
330
+
331
+	this->run_counters();
332
+
375 333
 	// Noise
376
-	if ( !read_counter( REG(flg) & 0x1F ) )
334
+	if (!this->read_counter(this->m.regs[r_flg] & 0x1F))
377 335
 	{
378
-		int feedback = (m.noise << 13) ^ (m.noise << 14);
379
-		m.noise = (feedback & 0x4000) ^ (m.noise >> 1);
336
+		int feedback = (this->m.noise << 13) ^ (this->m.noise << 14);
337
+		this->m.noise = (feedback & 0x4000) ^ (this->m.noise >> 1);
380 338
 	}
381 339
 }
382 340
 
383
-
384 341
 //// Voices
385 342
 
386
-#define VOICE_CLOCK( n ) void SPC_DSP::voice_##n( voice_t* const v )
387
-
388
-inline VOICE_CLOCK( V1 )
343
+void SPC_DSP::voice_V1(voice_t *const v)
389 344
 {
390
-	m.t_dir_addr = m.t_dir * 0x100 + m.t_srcn * 4;
391
-	m.t_srcn = VREG(v->regs,srcn);
345
+	this->m.t_dir_addr = this->m.t_dir * 0x100 + this->m.t_srcn * 4;
346
+	this->m.t_srcn = v->regs[v_srcn];
392 347
 }
393
-inline VOICE_CLOCK( V2 )
348
+void SPC_DSP::voice_V2(voice_t *const v)
394 349
 {
395 350
 	// Read sample pointer (ignored if not needed)
396
-	uint8_t const* entry = &m.ram [m.t_dir_addr];
397
-	if ( !v->kon_delay )
351
+	auto entry = &this->m.ram[m.t_dir_addr];
352
+	if (!v->kon_delay)
398 353
 		entry += 2;
399
-	m.t_brr_next_addr = GET_LE16A( entry );
400
-	
401
-	m.t_adsr0 = VREG(v->regs,adsr0);
402
-	
354
+	this->m.t_brr_next_addr = get_le16(entry);
355
+
356
+	this->m.t_adsr0 = v->regs[v_adsr0];
357
+
403 358
 	// Read pitch, spread over two clocks
404
-	m.t_pitch = VREG(v->regs,pitchl);
359
+	this->m.t_pitch = v->regs[v_pitchl];
405 360
 }
406
-inline VOICE_CLOCK( V3a )
361
+void SPC_DSP::voice_V3a(voice_t *const v)
407 362
 {
408
-	m.t_pitch += (VREG(v->regs,pitchh) & 0x3F) << 8;
363
+	this->m.t_pitch += (v->regs[v_pitchh] & 0x3F) << 8;
409 364
 }
410
-inline VOICE_CLOCK( V3b )
365
+void SPC_DSP::voice_V3b(voice_t *const v)
411 366
 {
412 367
 	// Read BRR header and byte
413
-	m.t_brr_byte   = m.ram [(v->brr_addr + v->brr_offset) & 0xFFFF];
414
-	m.t_brr_header = m.ram [v->brr_addr]; // brr_addr doesn't need masking
368
+	this->m.t_brr_byte = this->m.ram[(v->brr_addr + v->brr_offset) & 0xFFFF];
369
+	this->m.t_brr_header = this->m.ram[v->brr_addr]; // brr_addr doesn't need masking
415 370
 }
416
-VOICE_CLOCK( V3c )
371
+void SPC_DSP::voice_V3c(voice_t *const v)
417 372
 {
418 373
 	// Pitch modulation using previous voice's output
419
-	if ( m.t_pmon & v->vbit )
420
-		m.t_pitch += ((m.t_output >> 5) * m.t_pitch) >> 10;
421
-	
422
-	if ( v->kon_delay )
374
+	if (this->m.t_pmon & v->vbit)
375
+		this->m.t_pitch += ((this->m.t_output >> 5) * this->m.t_pitch) >> 10;
376
+
377
+	if (v->kon_delay)
423 378
 	{
424 379
 		// Get ready to start BRR decoding on next sample
425
-		if ( v->kon_delay == 5 )
380
+		if (v->kon_delay == 5)
426 381
 		{
427
-			v->brr_addr    = m.t_brr_next_addr;
428
-			v->brr_offset  = 1;
429
-			v->buf_pos     = 0;
430
-			m.t_brr_header = 0; // header is ignored on this sample
431
-			m.kon_check    = true;
432
-
433
-			if (take_spc_snapshot)
434
-			{
435
-				take_spc_snapshot = 0;
436
-				if (spc_snapshot_callback)
437
-					spc_snapshot_callback();
438
-			}
382
+			v->brr_addr = this->m.t_brr_next_addr;
383
+			v->brr_offset = 1;
384
+			v->buf_pos = 0;
385
+			this->m.t_brr_header = 0; // header is ignored on this sample
439 386
 		}
440
-		
387
+
441 388
 		// Envelope is never run during KON
442
-		v->env        = 0;
389
+		v->env = 0;
443 390
 		v->hidden_env = 0;
444
-		
391
+
445 392
 		// Disable BRR decoding until last three samples
446 393
 		v->interp_pos = 0;
447
-		if ( --v->kon_delay & 3 )
394
+		if (--v->kon_delay & 3)
448 395
 			v->interp_pos = 0x4000;
449
-		
396
+
450 397
 		// Pitch is never added during KON
451
-		m.t_pitch = 0;
398
+		this->m.t_pitch = 0;
452 399
 	}
453
-	
400
+
454 401
 	// Gaussian interpolation
455
-	{
456
-		int output = interpolate( v );
457
-		
458
-		// Noise
459
-		if ( m.t_non & v->vbit )
460
-			output = (int16_t) (m.noise * 2);
461
-		
462
-		// Apply envelope
463
-		m.t_output = (output * v->env) >> 11 & ~1;
464
-		v->t_envx_out = (uint8_t) (v->env >> 4);
465
-	}
466
-	
402
+	int output = this->interpolate(v);
403
+
404
+	// Noise
405
+	if (this->m.t_non & v->vbit)
406
+		output = static_cast<int16_t>(this->m.noise * 2);
407
+
408
+	// Apply envelope
409
+	this->m.t_output = (output * v->env) >> 11 & ~1;
410
+	v->t_envx_out = static_cast<uint8_t>(v->env >> 4);
411
+
467 412
 	// Immediate silence due to end of sample or soft reset
468
-	if ( REG(flg) & 0x80 || (m.t_brr_header & 3) == 1 )
413
+	if (this->m.regs[r_flg] & 0x80 || (this->m.t_brr_header & 3) == 1)
469 414
 	{
470 415
 		v->env_mode = env_release;
471
-		v->env      = 0;
416
+		v->env = 0;
472 417
 	}
473
-	
474
-	if ( m.every_other_sample )
418
+
419
+	if (this->m.every_other_sample)
475 420
 	{
476 421
 		// KOFF
477
-		if ( m.t_koff & v->vbit )
422
+		if (this->m.t_koff & v->vbit)
478 423
 			v->env_mode = env_release;
479
-		
424
+
480 425
 		// KON
481
-		if ( m.kon & v->vbit )
426
+		if (this->m.kon & v->vbit)
482 427
 		{
483 428
 			v->kon_delay = 5;
484 429
 			v->env_mode  = env_attack;
485 430
 		}
486 431
 	}
487
-	
432
+
488 433
 	// Run envelope for next sample
489
-	if ( !v->kon_delay )
490
-		run_envelope( v );
434
+	if (!v->kon_delay)
435
+		this->run_envelope(v);
491 436
 }
492 437
 
493
-inline void SPC_DSP::voice_output( voice_t const* v, int ch )
438
+void SPC_DSP::voice_output(const voice_t *v, int ch)
494 439
 {
495 440
 	// Apply left/right volume
496
-	int amp = (m.t_output * (int8_t) VREG(v->regs,voll + ch)) >> 7;
497
-	amp *= ((stereo_switch & (1 << (v->voice_number + ch * voice_count))) ? 1 : 0);
441
+	int amp = (this->m.t_output * static_cast<int8_t>(v->regs[v_voll + ch])) >> 7;
442
+	amp *= (this->stereo_switch & (1 << (v->voice_number + ch * voice_count))) ? 1 : 0;
498 443
 
499 444
 	// Add to output total
500
-	m.t_main_out [ch] += amp;
501
-	CLAMP16( m.t_main_out [ch] );
502
-	
445
+	this->m.t_main_out[ch] += amp;
446
+	CLAMP16(this->m.t_main_out[ch]);
447
+
503 448
 	// Optionally add to echo total
504
-	if ( m.t_eon & v->vbit )
449
+	if (this->m.t_eon & v->vbit)
505 450
 	{
506
-		m.t_echo_out [ch] += amp;
507
-		CLAMP16( m.t_echo_out [ch] );
451
+		this->m.t_echo_out[ch] += amp;
452
+		CLAMP16(this->m.t_echo_out[ch]);
508 453
 	}
509 454
 }
510
-VOICE_CLOCK( V4 )
455
+void SPC_DSP::voice_V4(voice_t *const v)
511 456
 {
512 457
 	// Decode BRR
513
-	m.t_looped = 0;
514
-	if ( v->interp_pos >= 0x4000 )
458
+	this->m.t_looped = 0;
459
+	if (v->interp_pos >= 0x4000)
515 460
 	{
516
-		decode_brr( v );
517
-		
518
-		if ( (v->brr_offset += 2) >= brr_block_size )
461
+		this->decode_brr(v);
462
+
463
+		if ((v->brr_offset += 2) >= brr_block_size)
519 464
 		{
520 465
 			// Start decoding next BRR block
521
-			assert( v->brr_offset == brr_block_size );
466
+			assert(v->brr_offset == brr_block_size);
522 467
 			v->brr_addr = (v->brr_addr + brr_block_size) & 0xFFFF;
523
-			if ( m.t_brr_header & 1 )
468
+			if (this->m.t_brr_header & 1)
524 469
 			{
525
-				v->brr_addr = m.t_brr_next_addr;
526
-				m.t_looped = v->vbit;
470
+				v->brr_addr = this->m.t_brr_next_addr;
471
+				this->m.t_looped = v->vbit;
527 472
 			}
528 473
 			v->brr_offset = 1;
529 474
 		}
530 475
 	}
531
-	
476
+
532 477
 	// Apply pitch
533 478
 	v->interp_pos = (v->interp_pos & 0x3FFF) + m.t_pitch;
534
-	
479
+
535 480
 	// Keep from getting too far ahead (when using pitch modulation)
536
-	if ( v->interp_pos > 0x7FFF )
481
+	if (v->interp_pos > 0x7FFF)
537 482
 		v->interp_pos = 0x7FFF;
538
-	
483
+
539 484
 	// Output left
540
-	voice_output( v, 0 );
485
+	this->voice_output(v, 0);
541 486
 }
542
-inline VOICE_CLOCK( V5 )
487
+void SPC_DSP::voice_V5(voice_t *const v)
543 488
 {
544 489
 	// Output right
545
-	voice_output( v, 1 );
546
-	
490
+	this->voice_output(v, 1);
491
+
547 492
 	// ENDX, OUTX, and ENVX won't update if you wrote to them 1-2 clocks earlier
548
-	int endx_buf = REG(endx) | m.t_looped;
549
-	
493
+	int endx_buf = this->m.regs[r_endx] | this->m.t_looped;
494
+
550 495
 	// Clear bit in ENDX if KON just began
551
-	if ( v->kon_delay == 5 )
496
+	if (v->kon_delay == 5)
552 497
 		endx_buf &= ~v->vbit;
553
-	m.endx_buf = (uint8_t) endx_buf;
498
+	this->m.endx_buf = static_cast<uint8_t>(endx_buf);
554 499
 }
555
-inline VOICE_CLOCK( V6 )
500
+void SPC_DSP::voice_V6(voice_t *const)
556 501
 {
557
-	(void) v; // avoid compiler warning about unused v
558
-	m.outx_buf = (uint8_t) (m.t_output >> 8);
502
+	this->m.outx_buf = static_cast<uint8_t>(this->m.t_output >> 8);
559 503
 }
560
-inline VOICE_CLOCK( V7 )
504
+void SPC_DSP::voice_V7(voice_t *const v)
561 505
 {
562 506
 	// Update ENDX
563
-	REG(endx) = m.endx_buf;
564
-	
565
-	m.envx_buf = v->t_envx_out;
507
+	this->m.regs[r_endx] = this->m.endx_buf;
508
+
509
+	this->m.envx_buf = v->t_envx_out;
566 510
 }
567
-inline VOICE_CLOCK( V8 )
511
+void SPC_DSP::voice_V8(voice_t *const v)
568 512
 {
569 513
 	// Update OUTX
570
-	VREG(v->regs,outx) = m.outx_buf;
514
+	v->regs[v_outx] = this->m.outx_buf;
571 515
 }
572
-inline VOICE_CLOCK( V9 )
516
+void SPC_DSP::voice_V9(voice_t *const v)
573 517
 {
574 518
 	// Update ENVX
575
-	VREG(v->regs,envx) = m.envx_buf;
519
+	v->regs[v_envx] = this->m.envx_buf;
576 520
 }
577 521
 
578 522
 // Most voices do all these in one clock, so make a handy composite
579
-inline VOICE_CLOCK( V3 )
523
+void SPC_DSP::voice_V3(voice_t *const v)
580 524
 {
581
-	voice_V3a( v );
582
-	voice_V3b( v );
583
-	voice_V3c( v );
525
+	this->voice_V3a(v);
526
+	this->voice_V3b(v);
527
+	this->voice_V3c(v);
584 528
 }
585 529
 
586 530
 // Common combinations of voice steps on different voices. This greatly reduces
587 531
 // code size and allows everything to be inlined in these functions.
588
-VOICE_CLOCK(V7_V4_V1) { voice_V7(v); voice_V1(v+3); voice_V4(v+1); }
589
-VOICE_CLOCK(V8_V5_V2) { voice_V8(v); voice_V5(v+1); voice_V2(v+2); }
590
-VOICE_CLOCK(V9_V6_V3) { voice_V9(v); voice_V6(v+1); voice_V3(v+2); }
591
-
532
+void SPC_DSP::voice_V7_V4_V1(voice_t *const v) { this->voice_V7(v); this->voice_V1(v + 3); this->voice_V4(v + 1); }
533
+void SPC_DSP::voice_V8_V5_V2(voice_t *const v) { this->voice_V8(v); this->voice_V5(v + 1); this->voice_V2(v + 2); }
534
+void SPC_DSP::voice_V9_V6_V3(voice_t *const v) { this->voice_V9(v); this->voice_V6(v + 1); this->voice_V3(v + 2); }
592 535
 
593 536
 //// Echo
594 537
 
595
-// Current echo buffer pointer for left/right channel
596
-#define ECHO_PTR( ch )      (&m.ram [m.t_echo_ptr + ch * 2])
597
-
598
-// Sample in echo history buffer, where 0 is the oldest
599
-#define ECHO_FIR( i )       (m.echo_hist_pos [i])
600
-
601
-// Calculate FIR point for left/right channel
602
-#define CALC_FIR( i, ch )   ((ECHO_FIR( i + 1 ) [ch] * (int8_t) REG(fir + i * 0x10)) >> 6)
603
-
604
-#define ECHO_CLOCK( n ) inline void SPC_DSP::echo_##n()
605
-
606
-inline void SPC_DSP::echo_read( int ch )
538
+void SPC_DSP::echo_read(int ch)
607 539
 {
608
-	int s = GET_LE16SA( ECHO_PTR( ch ) );
540
+	int s = static_cast<int16_t>(get_le16(this->ECHO_PTR(ch)));
609 541
 	// second copy simplifies wrap-around handling
610
-	ECHO_FIR( 0 ) [ch] = ECHO_FIR( 8 ) [ch] = s >> 1;
542
+	this->ECHO_FIR(0)[ch] = this->ECHO_FIR(8)[ch] = s >> 1;
611 543
 }
612 544
 
613
-ECHO_CLOCK( 22 )
545
+void SPC_DSP::echo_22()
614 546
 {
615 547
 	// History
616
-	if ( ++m.echo_hist_pos >= &m.echo_hist [echo_hist_size] )
617
-		m.echo_hist_pos = m.echo_hist;
618
-	
619
-	m.t_echo_ptr = (m.t_esa * 0x100 + m.echo_offset) & 0xFFFF;
620
-	echo_read( 0 );
621
-	
548
+	if (++this->m.echo_hist_pos >= &this->m.echo_hist[echo_hist_size])
549
+		this->m.echo_hist_pos = this->m.echo_hist;
550
+
551
+	this->m.t_echo_ptr = (this->m.t_esa * 0x100 + this->m.echo_offset) & 0xFFFF;
552
+	this->echo_read(0);
553
+
622 554
 	// FIR (using l and r temporaries below helps compiler optimize)
623
-	int l = CALC_FIR( 0, 0 );
624
-	int r = CALC_FIR( 0, 1 );
625
-	
626
-	m.t_echo_in [0] = l;
627
-	m.t_echo_in [1] = r;
555
+	int l = this->CALC_FIR(0, 0);
556
+	int r = this->CALC_FIR(0, 1);
557
+
558
+	this->m.t_echo_in[0] = l;
559
+	this->m.t_echo_in[1] = r;
628 560
 }
629
-ECHO_CLOCK( 23 )
561
+void SPC_DSP::echo_23()
630 562
 {
631
-	int l = CALC_FIR( 1, 0 ) + CALC_FIR( 2, 0 );
632
-	int r = CALC_FIR( 1, 1 ) + CALC_FIR( 2, 1 );
633
-	
634
-	m.t_echo_in [0] += l;
635
-	m.t_echo_in [1] += r;
636
-	
637
-	echo_read( 1 );
563
+	int l = this->CALC_FIR(1, 0) + this->CALC_FIR(2, 0);
564
+	int r = this->CALC_FIR(1, 1) + this->CALC_FIR(2, 1);
565
+
566
+	this->m.t_echo_in[0] += l;
567
+	this->m.t_echo_in[1] += r;
568
+
569
+	echo_read(1);
638 570
 }
639
-ECHO_CLOCK( 24 )
571
+void SPC_DSP::echo_24()
640 572
 {
641
-	int l = CALC_FIR( 3, 0 ) + CALC_FIR( 4, 0 ) + CALC_FIR( 5, 0 );
642
-	int r = CALC_FIR( 3, 1 ) + CALC_FIR( 4, 1 ) + CALC_FIR( 5, 1 );
643
-	
644
-	m.t_echo_in [0] += l;
645
-	m.t_echo_in [1] += r;
573
+	int l = this->CALC_FIR(3, 0) + this->CALC_FIR(4, 0) + this->CALC_FIR(5, 0);
574
+	int r = this->CALC_FIR(3, 1) + this->CALC_FIR(4, 1) + this->CALC_FIR(5, 1);
575
+
576
+	this->m.t_echo_in[0] += l;
577
+	this->m.t_echo_in[1] += r;
646 578
 }
647
-ECHO_CLOCK( 25 )
579
+void SPC_DSP::echo_25()
648 580
 {
649
-	int l = m.t_echo_in [0] + CALC_FIR( 6, 0 );
650
-	int r = m.t_echo_in [1] + CALC_FIR( 6, 1 );
651
-	
652
-	l = (int16_t) l;
653
-	r = (int16_t) r;
654
-	
655
-	l += (int16_t) CALC_FIR( 7, 0 );
656
-	r += (int16_t) CALC_FIR( 7, 1 );
657
-	
658
-	CLAMP16( l );
659
-	CLAMP16( r );
660
-	
661
-	m.t_echo_in [0] = l & ~1;
662
-	m.t_echo_in [1] = r & ~1;
581
+	int l = this->m.t_echo_in[0] + this->CALC_FIR(6, 0);
582
+	int r = this->m.t_echo_in[1] + this->CALC_FIR(6, 1);
583
+
584
+	l = static_cast<int16_t>(l);
585
+	r = static_cast<int16_t>(r);
586
+
587
+	l += static_cast<int16_t>(this->CALC_FIR(7, 0));
588
+	r += static_cast<int16_t>(this->CALC_FIR(7, 1));
589
+
590
+	CLAMP16(l);
591
+	CLAMP16(r);
592
+
593
+	this->m.t_echo_in[0] = l & ~1;
594
+	this->m.t_echo_in[1] = r & ~1;
663 595
 }
664
-inline int SPC_DSP::echo_output( int ch )
596
+int SPC_DSP::echo_output(int ch)
665 597
 {
666
-	int out = (int16_t) ((m.t_main_out [ch] * (int8_t) REG(mvoll + ch * 0x10)) >> 7) +
667
-			(int16_t) ((m.t_echo_in [ch] * (int8_t) REG(evoll + ch * 0x10)) >> 7);
668
-	CLAMP16( out );
598
+	int out = static_cast<int16_t>((this->m.t_main_out [ch] * static_cast<int8_t>(this->m.regs[r_mvoll + ch * 0x10])) >> 7) +
599
+		static_cast<int16_t>((this->m.t_echo_in [ch] * static_cast<int8_t>(this->m.regs[r_evoll + ch * 0x10])) >> 7);
600
+	CLAMP16(out);
669 601
 	return out;
670 602
 }
671
-ECHO_CLOCK( 26 )
603
+void SPC_DSP::echo_26()
672 604
 {
673 605
 	// Left output volumes
674 606
 	// (save sample for next clock so we can output both together)
675
-	m.t_main_out [0] = echo_output( 0 );
607
+	this->m.t_main_out[0] = echo_output(0);
676 608
 	
677 609
 	// Echo feedback
678
-	int l = m.t_echo_out [0] + (int16_t) ((m.t_echo_in [0] * (int8_t) REG(efb)) >> 7);
679
-	int r = m.t_echo_out [1] + (int16_t) ((m.t_echo_in [1] * (int8_t) REG(efb)) >> 7);
680
-	
681
-	CLAMP16( l );
682
-	CLAMP16( r );
683
-	
684
-	m.t_echo_out [0] = l & ~1;
685
-	m.t_echo_out [1] = r & ~1;
610
+	int l = this->m.t_echo_out[0] + static_cast<int16_t>((this->m.t_echo_in[0] * static_cast<int8_t>(this->m.regs[r_efb])) >> 7);
611
+	int r = this->m.t_echo_out[1] + static_cast<int16_t>((this->m.t_echo_in[1] * static_cast<int8_t>(this->m.regs[r_efb])) >> 7);
612
+
613
+	CLAMP16(l);
614
+	CLAMP16(r);
615
+
616
+	this->m.t_echo_out[0] = l & ~1;
617
+	this->m.t_echo_out[1] = r & ~1;
686 618
 }
687
-ECHO_CLOCK( 27 )
619
+void SPC_DSP::echo_27()
688 620
 {
689 621
 	// Output
690
-	int l = m.t_main_out [0];
691
-	int r = echo_output( 1 );
692
-	m.t_main_out [0] = 0;
693
-	m.t_main_out [1] = 0;
694
-	
622
+	int l = this->m.t_main_out[0];
623
+	int r = echo_output(1);
624
+	this->m.t_main_out[0] = this->m.t_main_out[1] = 0;
625
+
695 626
 	// TODO: global muting isn't this simple (turns DAC on and off
696 627
 	// or something, causing small ~37-sample pulse when first muted)
697
-	if ( REG(flg) & 0x40 )
628
+	if (this->m.regs[r_flg] & 0x40)
629
+		l = r = 0;
630
+
631
+	// Output sample to DAC
632
+#ifdef SPC_DSP_OUT_HOOK
633
+	SPC_DSP_OUT_HOOK(l, r);
634
+#else
635
+	sample_t *out = this->m.out;
636
+	out[0] = l;
637
+	out[1] = r;
638
+	out += 2;
639
+	if (out >= m.out_end)
698 640
 	{
699
-		l = 0;
700
-		r = 0;
641
+		out = this->m.extra;
642
+		this->m.out_end = &this->m.extra[extra_size];
701 643
 	}
702
-	
703
-	// Output sample to DAC
704
-	#ifdef SPC_DSP_OUT_HOOK
705
-		SPC_DSP_OUT_HOOK( l, r );
706
-	#else
707
-		sample_t* out = m.out;
708
-		WRITE_SAMPLES( l, r, out );
709
-		m.out = out;
710
-	#endif
644
+	this->m.out = out;
645
+#endif
711 646
 }
712
-ECHO_CLOCK( 28 )
647
+void SPC_DSP::echo_28()
713 648
 {
714
-	m.t_echo_enabled = REG(flg);
649
+	this->m.t_echo_enabled = this->m.regs[r_flg];
715 650
 }
716
-inline void SPC_DSP::echo_write( int ch )
651
+void SPC_DSP::echo_write(int ch)
717 652
 {
718
-	if ( !(m.t_echo_enabled & 0x20) )
653
+	if (!(this->m.t_echo_enabled & 0x20))
719 654
 	{
720
-		if ( m.t_echo_ptr >= 0xffc0 && rom_enabled )
721
-			SET_LE16A( &hi_ram [m.t_echo_ptr + ch * 2 - 0xffc0], m.t_echo_out [ch] );
655
+		if (this->m.t_echo_ptr >= 0xffc0 && this->rom_enabled)
656
+			set_le16(&this->hi_ram[this->m.t_echo_ptr + ch * 2 - 0xffc0], this->m.t_echo_out [ch]);
722 657
 		else
723
-			SET_LE16A( ECHO_PTR( ch ), m.t_echo_out [ch] );
658
+			set_le16(this->ECHO_PTR(ch), this->m.t_echo_out[ch]);
724 659
 	}
725 660
 
726
-	m.t_echo_out [ch] = 0;
661
+	this->m.t_echo_out[ch] = 0;
727 662
 }
728
-ECHO_CLOCK( 29 )
663
+void SPC_DSP::echo_29()
729 664
 {
730
-	m.t_esa = REG(esa);
731
-	
732
-	if ( !m.echo_offset )
733
-		m.echo_length = (REG(edl) & 0x0F) * 0x800;
734
-	
735
-	m.echo_offset += 4;
736
-	if ( m.echo_offset >= m.echo_length )
737
-		m.echo_offset = 0;
738
-	
665
+	this->m.t_esa = this->m.regs[r_esa];
666
+
667
+	if (!this->m.echo_offset)
668
+		this->m.echo_length = (this->m.regs[r_edl] & 0x0F) * 0x800;
669
+
670
+	this->m.echo_offset += 4;
671
+	if (this->m.echo_offset >= this->m.echo_length)
672
+		this->m.echo_offset = 0;
673
+
739 674
 	// Write left echo
740
-	echo_write( 0 );
741
-	
742
-	m.t_echo_enabled = REG(flg);
675
+	this->echo_write(0);
676
+
677
+	this->m.t_echo_enabled = this->m.regs[r_flg];
743 678
 }
744
-ECHO_CLOCK( 30 )
679
+void SPC_DSP::echo_30()
745 680
 {
746 681
 	// Write right echo
747
-	echo_write( 1 );
682
+	this->echo_write(1);
748 683
 }
749 684
 
750
-
751 685
 //// Timing
752 686
 
753 687
 // Execute clock for a particular voice
754
-#define V( clock, voice )   voice_##clock( &m.voices [voice] );
688
+#define V(clock, voice) voice_##clock(&this->m.voices[voice]);
755 689
 
756 690
 /* The most common sequence of clocks uses composite operations
757 691
 for efficiency. For example, the following are equivalent to the
... ...
@@ -797,272 +731,118 @@ PHASE(30) misc_30();V(V3c,0)                                         echo_30();\
797 731
 PHASE(31)  V(V4,0)       V(V1,2)\
798 732
 
799 733
 #if !SPC_DSP_CUSTOM_RUN
800
-
801
-void SPC_DSP::run( int clocks_remain )
734
+void SPC_DSP::run(int clocks_remain)
802 735
 {
803
-	require( clocks_remain > 0 );
804
-	
805
-	int const phase = m.phase;
806
-	m.phase = (phase + clocks_remain) & 31;
807
-	switch ( phase )
736
+	assert(clocks_remain > 0);
737
+
738
+	int phase = this->m.phase;
739
+	this->m.phase = (phase + clocks_remain) & 31;
740
+	switch (phase)
808 741
 	{
809
-	loop:
810
-	
811
-		#define PHASE( n ) if ( n && !--clocks_remain ) break; case n:
742
+		loop:
743
+#define PHASE(n) if (n && !--clocks_remain) break; case n:
812 744
 		GEN_DSP_TIMING
813
-		#undef PHASE
745
+#undef PHASE
814 746
 	
815
-		if ( --clocks_remain )
747
+		if (--clocks_remain)
816 748
 			goto loop;
817 749
 	}
818 750
 }
819 751
 
820 752
 #endif
821 753
 
822
-
823 754
 //// Setup
824 755
 
825
-void SPC_DSP::init( void* ram_64k )
756
+void SPC_DSP::init(uint8_t *ram_64k)
826 757
 {
827
-	m.ram = (uint8_t*) ram_64k;
828
-	mute_voices( 0 );
829
-	disable_surround( false );
830
-	set_output( 0, 0 );
831
-	reset();
832
-
833
-	stereo_switch = 0xffff;
834
-	take_spc_snapshot = 0;
835
-	spc_snapshot_callback = 0;
836
-
837
-	#ifndef NDEBUG
838
-		// be sure this sign-extends
839
-		assert( (int16_t) 0x8000 == -0x8000 );
840
-		
841
-		// be sure right shift preserves sign
842
-		assert( (-1 >> 1) == -1 );
843
-		
844
-		// check clamp macro
845
-		int i;
846
-		i = +0x8000; CLAMP16( i ); assert( i == +0x7FFF );
847
-		i = -0x8001; CLAMP16( i ); assert( i == -0x8000 );
848
-		
849
-		blargg_verify_byte_order();
850
-	#endif
851
-}
758
+	this->m.ram = ram_64k;
759
+	this->mute_voices(0);
760
+	this->disable_surround(false);
761
+	this->set_output(nullptr, 0);
762
+	this->reset();
852 763
 
853
-void SPC_DSP::soft_reset_common()
854
-{
855
-	require( m.ram ); // init() must have been called already
856
-	
857
-	m.noise              = 0x4000;
858
-	m.echo_hist_pos      = m.echo_hist;
859
-	m.every_other_sample = 1;
860
-	m.echo_offset        = 0;
861
-	m.phase              = 0;
862
-	
863
-	init_counter();
764
+	this->stereo_switch = 0xffff;
864 765
 
865
-	for (int i = 0; i < voice_count; i++)
866
-		m.voices[i].voice_number = i;
867
-}
766
+#ifndef NDEBUG
767
+	// be sure this sign-extends
768
+	assert(static_cast<int16_t>(0x8000) == -0x8000);
868 769
 
869
-void SPC_DSP::soft_reset()
870
-{
871
-	REG(flg) = 0xE0;
872
-	soft_reset_common();
873
-}
770
+	// be sure right shift preserves sign
771
+	assert((-1 >> 1) == -1);
874 772
 
875
-void SPC_DSP::load( uint8_t const regs [register_count] )
876
-{
877
-	memcpy( m.regs, regs, sizeof m.regs );
878
-	memset( &m.regs [register_count], 0, offsetof (state_t,ram) - register_count );
879
-	
880
-	// Internal state
881
-	for ( int i = voice_count; --i >= 0; )
882
-	{
883
-		voice_t* v = &m.voices [i];
884
-		v->brr_offset = 1;
885
-		v->vbit       = 1 << i;
886
-		v->regs       = &m.regs [i * 0x10];
887
-	}
888
-	m.new_kon = REG(kon);
889
-	m.t_dir   = REG(dir);
890
-	m.t_esa   = REG(esa);
891
-	
892
-	soft_reset_common();
893
-}
773
+	// check clamp macro
774
+	int i = 0x8000;
775
+	CLAMP16(i);
776
+	assert(i == 0x7FFF);
894 777
 
895
-void SPC_DSP::reset() { load( initial_regs ); }
778
+	i = -0x8001;
779
+	CLAMP16(i);
780
+	assert(i == -0x8000);
896 781
 
782
+	blargg_verify_byte_order();
783
+#endif
784
+}
897 785
 
898
-//// State save/load
786
+void SPC_DSP::soft_reset_common()
787
+{
788
+	assert(this->m.ram); // init() must have been called already
899 789
 
900
-#if !SPC_NO_COPY_STATE_FUNCS
790
+	this->m.noise = 0x4000;
791
+	this->m.echo_hist_pos = this->m.echo_hist;
792
+	this->m.every_other_sample = true;
793
+	this->m.echo_offset = 0;
794
+	this->m.phase = 0;
901 795
 
902
-void SPC_State_Copier::copy( void* state, size_t size )
903
-{
904
-	func( buf, state, size );
905
-}
796
+	this->init_counter();
906 797
 
907
-int SPC_State_Copier::copy_int( int state, int size )
908
-{
909
-	BOOST::uint8_t s [2];
910
-	SET_LE16( s, state );
911
-	func( buf, &s, size );
912
-	return GET_LE16( s );
798
+	for (int i = 0; i < voice_count; ++i)
799
+		this->m.voices[i].voice_number = i;
913 800
 }
914 801
 
915
-void SPC_State_Copier::skip( int count )
802
+void SPC_DSP::soft_reset()
916 803
 {
917
-	if ( count > 0 )
918
-	{
919
-		char temp [64];
920
-		memset( temp, 0, sizeof temp );
921
-		do
922
-		{
923
-			int n = sizeof temp;
924
-			if ( n > count )
925
-				n = count;
926
-			count -= n;
927
-			func( buf, temp, n );
928
-		}
929
-		while ( count );
930
-	}
804
+	this->m.regs[r_flg] = 0xE0;
805
+	this->soft_reset_common();
931 806
 }
932 807
 
933
-void SPC_State_Copier::extra()
808
+void SPC_DSP::load(const uint8_t regs[register_count])
934 809
 {
935
-	int n = 0;
936
-	SPC_State_Copier& copier = *this;
937
-	SPC_COPY( uint8_t, n );
938
-	skip( n );
939
-}
810
+	std::copy(&regs[0], &regs[register_count], &this->m.regs[0]);
811
+	memset(&this->m.regs[register_count], 0, offsetof(state_t, ram) - register_count);
940 812
 
941
-void SPC_DSP::copy_state( unsigned char** io, copy_func_t copy )
942
-{
943
-	SPC_State_Copier copier( io, copy );
944
-	
945
-	// DSP registers
946
-	copier.copy( m.regs, register_count );
947
-	
948 813
 	// Internal state
949
-	
950
-	// Voices
951
-	int i;
952
-	for ( i = 0; i < voice_count; i++ )
814
+	for (int i = voice_count; --i >= 0;)
953 815
 	{
954
-		voice_t* v = &m.voices [i];
955
-		
956
-		// BRR buffer
957
-		int i;
958
-		for ( i = 0; i < brr_buf_size; i++ )
959
-		{
960
-			int s = v->buf [i];
961
-			SPC_COPY(  int16_t, s );
962
-			v->buf [i] = v->buf [i + brr_buf_size] = s;
963
-		}
964
-		
965
-		SPC_COPY( uint16_t, v->interp_pos );
966
-		SPC_COPY( uint16_t, v->brr_addr );
967
-		SPC_COPY( uint16_t, v->env );
968
-		SPC_COPY(  int16_t, v->hidden_env );
969
-		SPC_COPY(  uint8_t, v->buf_pos );
970
-		SPC_COPY(  uint8_t, v->brr_offset );
971
-		SPC_COPY(  uint8_t, v->kon_delay );
972
-		{
973
-			int m = v->env_mode;
974
-			SPC_COPY(  uint8_t, m );
975
-			v->env_mode = (enum env_mode_t) m;
976
-		}
977
-		SPC_COPY(  uint8_t, v->t_envx_out );
978
-		
979
-		copier.extra();
816
+		auto &v = this->m.voices[i];
817
+		v.brr_offset = 1;
818
+		v.vbit = 1 << i;
819
+		v.regs = &this->m.regs[i * 0x10];
980 820
 	}
981
-	
982
-	// Echo history
983
-	for ( i = 0; i < echo_hist_size; i++ )
984
-	{
985
-		int j;
986
-		for ( j = 0; j < 2; j++ )
987
-		{
988
-			int s = m.echo_hist_pos [i] [j];
989
-			SPC_COPY( int16_t, s );
990
-			m.echo_hist [i] [j] = s; // write back at offset 0
991
-		}
992
-	}
993
-	m.echo_hist_pos = m.echo_hist;
994
-	memcpy( &m.echo_hist [echo_hist_size], m.echo_hist, echo_hist_size * sizeof m.echo_hist [0] );
995
-	
996
-	// Misc
997
-	SPC_COPY(  uint8_t, m.every_other_sample );
998
-	SPC_COPY(  uint8_t, m.kon );
999
-	
1000
-	SPC_COPY( uint16_t, m.noise );
1001
-	SPC_COPY( uint16_t, m.counter );
1002
-	SPC_COPY( uint16_t, m.echo_offset );
1003
-	SPC_COPY( uint16_t, m.echo_length );
1004
-	SPC_COPY(  uint8_t, m.phase );
1005
-	
1006
-	SPC_COPY(  uint8_t, m.new_kon );
1007
-	SPC_COPY(  uint8_t, m.endx_buf );
1008
-	SPC_COPY(  uint8_t, m.envx_buf );
1009
-	SPC_COPY(  uint8_t, m.outx_buf );
1010
-	
1011
-	SPC_COPY(  uint8_t, m.t_pmon );
1012
-	SPC_COPY(  uint8_t, m.t_non );
1013
-	SPC_COPY(  uint8_t, m.t_eon );
1014
-	SPC_COPY(  uint8_t, m.t_dir );
1015
-	SPC_COPY(  uint8_t, m.t_koff );
1016
-	
1017
-	SPC_COPY( uint16_t, m.t_brr_next_addr );
1018
-	SPC_COPY(  uint8_t, m.t_adsr0 );
1019
-	SPC_COPY(  uint8_t, m.t_brr_header );
1020
-	SPC_COPY(  uint8_t, m.t_brr_byte );
1021
-	SPC_COPY(  uint8_t, m.t_srcn );
1022
-	SPC_COPY(  uint8_t, m.t_esa );
1023
-	SPC_COPY(  uint8_t, m.t_echo_enabled );
1024
-	
1025
-	SPC_COPY(  int16_t, m.t_main_out [0] );
1026
-	SPC_COPY(  int16_t, m.t_main_out [1] );
1027
-	SPC_COPY(  int16_t, m.t_echo_out [0] );
1028
-	SPC_COPY(  int16_t, m.t_echo_out [1] );
1029
-	SPC_COPY(  int16_t, m.t_echo_in  [0] );
1030
-	SPC_COPY(  int16_t, m.t_echo_in  [1] );
1031
-	
1032
-	SPC_COPY( uint16_t, m.t_dir_addr );
1033
-	SPC_COPY( uint16_t, m.t_pitch );
1034
-	SPC_COPY(  int16_t, m.t_output );
1035
-	SPC_COPY( uint16_t, m.t_echo_ptr );
1036
-	SPC_COPY(  uint8_t, m.t_looped );
1037
-	
1038
-	copier.extra();
1039
-}
1040
-#endif
821
+	this->m.new_kon = this->m.regs[r_kon];
822
+	this->m.t_dir = this->m.regs[r_dir];
823
+	this->m.t_esa = this->m.regs[r_esa];
1041 824
 
1042
-
1043
-//// Snes9x Accessor
1044
-
1045
-void SPC_DSP::set_spc_snapshot_callback(void (*callback)())
1046
-{
1047
-	spc_snapshot_callback = callback;
825
+	this->soft_reset_common();
1048 826
 }
1049 827
 
1050
-void SPC_DSP::dump_spc_snapshot()
828
+void SPC_DSP::reset()
1051 829
 {
1052
-	take_spc_snapshot = 1;
830
+	this->load(initial_regs);
1053 831
 }
1054 832
 
1055
-void SPC_DSP::set_stereo_switch( int value )
833
+//// Snes9x Accessor
834
+
835
+void SPC_DSP::set_stereo_switch(int value)
1056 836
 {
1057
-	stereo_switch = value;
837
+	this->stereo_switch = value;
1058 838
 }
1059 839
 
1060
-SPC_DSP::uint8_t SPC_DSP::reg_value( int ch, int addr )
840
+uint8_t SPC_DSP::reg_value(int ch, int addr)
1061 841
 {
1062
-	return m.voices[ch].regs[addr];
842
+	return this->m.voices[ch].regs[addr];
1063 843
 }
1064 844
 
1065
-int SPC_DSP::envx_value( int ch )
845
+int SPC_DSP::envx_value(int ch)
1066 846
 {
1067
-	return m.voices[ch].env;
847
+	return this->m.voices[ch].env;
1068 848
 }
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,1068 @@
1
+// snes_spc 0.9.0. http://www.slack.net/~ant/
2
+
3
+#include "SPC_DSP.h"
4
+
5
+#include "blargg_endian.h"
6
+#include <string.h>
7
+
8
+/* Copyright (C) 2007 Shay Green. This module is free software; you
9
+can redistribute it and/or modify it under the terms of the GNU Lesser
10
+General Public License as published by the Free Software Foundation; either
11
+version 2.1 of the License, or (at your option) any later version. This
12
+module is distributed in the hope that it will be useful, but WITHOUT ANY
13
+WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
14
+FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
15
+details. You should have received a copy of the GNU Lesser General Public
16
+License along with this module; if not, write to the Free Software Foundation,
17
+Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
18
+
19
+#include "blargg_source.h"
20
+
21
+#ifdef BLARGG_ENABLE_OPTIMIZER
22
+	#include BLARGG_ENABLE_OPTIMIZER
23
+#endif
24
+
25
+#if INT_MAX < 0x7FFFFFFF
26
+	#error "Requires that int type have at least 32 bits"
27
+#endif
28
+
29
+// TODO: add to blargg_endian.h
30
+#define GET_LE16SA( addr )      ((BOOST::int16_t) GET_LE16( addr ))
31
+#define GET_LE16A( addr )       GET_LE16( addr )
32
+#define SET_LE16A( addr, data ) SET_LE16( addr, data )
33
+
34
+static BOOST::uint8_t const initial_regs [SPC_DSP::register_count] =
35
+{
36
+	0x45,0x8B,0x5A,0x9A,0xE4,0x82,0x1B,0x78,0x00,0x00,0xAA,0x96,0x89,0x0E,0xE0,0x80,
37
+	0x2A,0x49,0x3D,0xBA,0x14,0xA0,0xAC,0xC5,0x00,0x00,0x51,0xBB,0x9C,0x4E,0x7B,0xFF,
38
+	0xF4,0xFD,0x57,0x32,0x37,0xD9,0x42,0x22,0x00,0x00,0x5B,0x3C,0x9F,0x1B,0x87,0x9A,
39
+	0x6F,0x27,0xAF,0x7B,0xE5,0x68,0x0A,0xD9,0x00,0x00,0x9A,0xC5,0x9C,0x4E,0x7B,0xFF,
40
+	0xEA,0x21,0x78,0x4F,0xDD,0xED,0x24,0x14,0x00,0x00,0x77,0xB1,0xD1,0x36,0xC1,0x67,
41
+	0x52,0x57,0x46,0x3D,0x59,0xF4,0x87,0xA4,0x00,0x00,0x7E,0x44,0x00,0x4E,0x7B,0xFF,
42
+	0x75,0xF5,0x06,0x97,0x10,0xC3,0x24,0xBB,0x00,0x00,0x7B,0x7A,0xE0,0x60,0x12,0x0F,
43
+	0xF7,0x74,0x1C,0xE5,0x39,0x3D,0x73,0xC1,0x00,0x00,0x7A,0xB3,0xFF,0x4E,0x7B,0xFF
44
+};
45
+
46
+// if ( io < -32768 ) io = -32768;
47
+// if ( io >  32767 ) io =  32767;
48
+#define CLAMP16( io )\
49
+{\
50
+	if ( (int16_t) io != io )\
51
+		io = (io >> 31) ^ 0x7FFF;\
52
+}
53
+
54
+// Access global DSP register
55
+#define REG(n)      m.regs [r_##n]
56
+
57
+// Access voice DSP register
58
+#define VREG(r,n)   r [v_##n]
59
+
60
+#define WRITE_SAMPLES( l, r, out ) \
61
+{\
62
+	out [0] = l;\
63
+	out [1] = r;\
64
+	out += 2;\
65
+	if ( out >= m.out_end )\
66
+	{\
67
+		check( out == m.out_end );\
68
+		check( m.out_end != &m.extra [extra_size] || \
69
+			(m.extra <= m.out_begin && m.extra < &m.extra [extra_size]) );\
70
+		out       = m.extra;\
71
+		m.out_end = &m.extra [extra_size];\
72
+	}\
73
+}\
74
+
75
+void SPC_DSP::set_output( sample_t* out, int size )
76
+{
77
+	require( (size & 1) == 0 ); // must be even
78
+	if ( !out )
79
+	{
80
+		out  = m.extra;
81
+		size = extra_size;
82
+	}
83
+	m.out_begin = out;
84
+	m.out       = out;
85
+	m.out_end   = out + size;
86
+}
87
+
88
+// Volume registers and efb are signed! Easy to forget int8_t cast.
89
+// Prefixes are to avoid accidental use of locals with same names.
90
+
91
+// Gaussian interpolation
92
+
93
+static short const gauss [512] =
94
+{
95
+   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
96
+   1,   1,   1,   1,   1,   1,   1,   1,   1,   1,   1,   2,   2,   2,   2,   2,
97
+   2,   2,   3,   3,   3,   3,   3,   4,   4,   4,   4,   4,   5,   5,   5,   5,
98
+   6,   6,   6,   6,   7,   7,   7,   8,   8,   8,   9,   9,   9,  10,  10,  10,
99
+  11,  11,  11,  12,  12,  13,  13,  14,  14,  15,  15,  15,  16,  16,  17,  17,
100
+  18,  19,  19,  20,  20,  21,  21,  22,  23,  23,  24,  24,  25,  26,  27,  27,
101
+  28,  29,  29,  30,  31,  32,  32,  33,  34,  35,  36,  36,  37,  38,  39,  40,
102
+  41,  42,  43,  44,  45,  46,  47,  48,  49,  50,  51,  52,  53,  54,  55,  56,
103
+  58,  59,  60,  61,  62,  64,  65,  66,  67,  69,  70,  71,  73,  74,  76,  77,
104
+  78,  80,  81,  83,  84,  86,  87,  89,  90,  92,  94,  95,  97,  99, 100, 102,
105
+ 104, 106, 107, 109, 111, 113, 115, 117, 118, 120, 122, 124, 126, 128, 130, 132,
106
+ 134, 137, 139, 141, 143, 145, 147, 150, 152, 154, 156, 159, 161, 163, 166, 168,
107
+ 171, 173, 175, 178, 180, 183, 186, 188, 191, 193, 196, 199, 201, 204, 207, 210,
108
+ 212, 215, 218, 221, 224, 227, 230, 233, 236, 239, 242, 245, 248, 251, 254, 257,
109
+ 260, 263, 267, 270, 273, 276, 280, 283, 286, 290, 293, 297, 300, 304, 307, 311,
110
+ 314, 318, 321, 325, 328, 332, 336, 339, 343, 347, 351, 354, 358, 362, 366, 370,
111
+ 374, 378, 381, 385, 389, 393, 397, 401, 405, 410, 414, 418, 422, 426, 430, 434,
112
+ 439, 443, 447, 451, 456, 460, 464, 469, 473, 477, 482, 486, 491, 495, 499, 504,
113
+ 508, 513, 517, 522, 527, 531, 536, 540, 545, 550, 554, 559, 563, 568, 573, 577,
114
+ 582, 587, 592, 596, 601, 606, 611, 615, 620, 625, 630, 635, 640, 644, 649, 654,
115
+ 659, 664, 669, 674, 678, 683, 688, 693, 698, 703, 708, 713, 718, 723, 728, 732,
116
+ 737, 742, 747, 752, 757, 762, 767, 772, 777, 782, 787, 792, 797, 802, 806, 811,
117
+ 816, 821, 826, 831, 836, 841, 846, 851, 855, 860, 865, 870, 875, 880, 884, 889,
118
+ 894, 899, 904, 908, 913, 918, 923, 927, 932, 937, 941, 946, 951, 955, 960, 965,
119
+ 969, 974, 978, 983, 988, 992, 997,1001,1005,1010,1014,1019,1023,1027,1032,1036,
120
+1040,1045,1049,1053,1057,1061,1066,1070,1074,1078,1082,1086,1090,1094,1098,1102,
121
+1106,1109,1113,1117,1121,1125,1128,1132,1136,1139,1143,1146,1150,1153,1157,1160,
122
+1164,1167,1170,1174,1177,1180,1183,1186,1190,1193,1196,1199,1202,1205,1207,1210,
123
+1213,1216,1219,1221,1224,1227,1229,1232,1234,1237,1239,1241,1244,1246,1248,1251,
124
+1253,1255,1257,1259,1261,1263,1265,1267,1269,1270,1272,1274,1275,1277,1279,1280,
125
+1282,1283,1284,1286,1287,1288,1290,1291,1292,1293,1294,1295,1296,1297,1297,1298,
126
+1299,1300,1300,1301,1302,1302,1303,1303,1303,1304,1304,1304,1304,1304,1305,1305,
127
+};
128
+
129
+inline int SPC_DSP::interpolate( voice_t const* v )
130
+{
131
+	// Make pointers into gaussian based on fractional position between samples
132
+	int offset = v->interp_pos >> 4 & 0xFF;
133
+	short const* fwd = gauss + 255 - offset;
134
+	short const* rev = gauss       + offset; // mirror left half of gaussian
135
+	
136
+	int const* in = &v->buf [(v->interp_pos >> 12) + v->buf_pos];
137
+	int out;
138
+	out  = (fwd [  0] * in [0]) >> 11;
139
+	out += (fwd [256] * in [1]) >> 11;
140
+	out += (rev [256] * in [2]) >> 11;
141
+	out = (int16_t) out;
142
+	out += (rev [  0] * in [3]) >> 11;
143
+	
144
+	CLAMP16( out );
145
+	out &= ~1;
146
+	return out;
147
+}
148
+
149
+
150
+//// Counters
151
+
152
+int const simple_counter_range = 2048 * 5 * 3; // 30720
153
+
154
+static unsigned const counter_rates [32] =
155
+{
156
+   simple_counter_range + 1, // never fires
157
+          2048, 1536,
158
+	1280, 1024,  768,
159
+	 640,  512,  384,
160
+	 320,  256,  192,
161
+	 160,  128,   96,
162
+	  80,   64,   48,
163
+	  40,   32,   24,
164
+	  20,   16,   12,
165
+	  10,    8,    6,
166
+	   5,    4,    3,
167
+	         2,
168
+	         1
169
+};
170
+
171
+static unsigned const counter_offsets [32] =
172
+{
173
+	  1, 0, 1040,
174
+	536, 0, 1040,
175
+	536, 0, 1040,
176
+	536, 0, 1040,
177
+	536, 0, 1040,
178
+	536, 0, 1040,
179
+	536, 0, 1040,
180
+	536, 0, 1040,
181
+	536, 0, 1040,
182
+	536, 0, 1040,
183
+	     0,
184
+	     0
185
+};
186
+
187
+inline void SPC_DSP::init_counter()
188
+{
189
+	m.counter = 0;
190
+}
191
+
192
+inline void SPC_DSP::run_counters()
193
+{
194
+	if ( --m.counter < 0 )
195
+		m.counter = simple_counter_range - 1;
196
+}
197
+
198
+inline unsigned SPC_DSP::read_counter( int rate )
199
+{
200
+	return ((unsigned) m.counter + counter_offsets [rate]) % counter_rates [rate];
201
+}
202
+
203
+
204
+//// Envelope
205
+
206
+inline void SPC_DSP::run_envelope( voice_t* const v )
207
+{
208
+	int env = v->env;
209
+	if ( v->env_mode == env_release ) // 60%
210
+	{
211
+		if ( (env -= 0x8) < 0 )
212
+			env = 0;
213
+		v->env = env;
214
+	}
215
+	else
216
+	{
217
+		int rate;
218
+		int env_data = VREG(v->regs,adsr1);
219
+		if ( m.t_adsr0 & 0x80 ) // 99% ADSR
220
+		{
221
+			if ( v->env_mode >= env_decay ) // 99%
222
+			{
223
+				env--;
224
+				env -= env >> 8;
225
+				rate = env_data & 0x1F;
226
+				if ( v->env_mode == env_decay ) // 1%
227
+					rate = (m.t_adsr0 >> 3 & 0x0E) + 0x10;
228
+			}
229
+			else // env_attack
230
+			{
231
+				rate = (m.t_adsr0 & 0x0F) * 2 + 1;
232
+				env += rate < 31 ? 0x20 : 0x400;
233
+			}
234
+		}
235
+		else // GAIN
236
+		{
237
+			int mode;
238
+			env_data = VREG(v->regs,gain);
239
+			mode = env_data >> 5;
240
+			if ( mode < 4 ) // direct
241
+			{
242
+				env = env_data * 0x10;
243
+				rate = 31;
244
+			}
245
+			else
246
+			{
247
+				rate = env_data & 0x1F;
248
+				if ( mode == 4 ) // 4: linear decrease
249
+				{
250
+					env -= 0x20;
251
+				}
252
+				else if ( mode < 6 ) // 5: exponential decrease
253
+				{
254
+					env--;
255
+					env -= env >> 8;
256
+				}
257
+				else // 6,7: linear increase
258
+				{
259
+					env += 0x20;
260
+					if ( mode > 6 && (unsigned) v->hidden_env >= 0x600 )
261
+						env += 0x8 - 0x20; // 7: two-slope linear increase
262
+				}
263
+			}
264
+		}
265
+		
266
+		// Sustain level
267
+		if ( (env >> 8) == (env_data >> 5) && v->env_mode == env_decay )
268
+			v->env_mode = env_sustain;
269
+		
270
+		v->hidden_env = env;
271
+		
272
+		// unsigned cast because linear decrease going negative also triggers this
273
+		if ( (unsigned) env > 0x7FF )
274
+		{
275
+			env = (env < 0 ? 0 : 0x7FF);
276
+			if ( v->env_mode == env_attack )
277
+				v->env_mode = env_decay;
278
+		}
279
+		
280
+		if ( !read_counter( rate ) )
281
+			v->env = env; // nothing else is controlled by the counter
282
+	}
283
+}
284
+
285
+
286
+//// BRR Decoding
287
+
288
+inline void SPC_DSP::decode_brr( voice_t* v )
289
+{
290
+	// Arrange the four input nybbles in 0xABCD order for easy decoding
291
+	int nybbles = m.t_brr_byte * 0x100 + m.ram [(v->brr_addr + v->brr_offset + 1) & 0xFFFF];
292
+	
293
+	int const header = m.t_brr_header;
294
+	
295
+	// Write to next four samples in circular buffer
296
+	int* pos = &v->buf [v->buf_pos];
297
+	int* end;
298
+	if ( (v->buf_pos += 4) >= brr_buf_size )
299
+		v->buf_pos = 0;
300
+	
301
+	// Decode four samples
302
+	for ( end = pos + 4; pos < end; pos++, nybbles <<= 4 )
303
+	{
304
+		// Extract nybble and sign-extend
305
+		int s = (int16_t) nybbles >> 12;
306
+		
307
+		// Shift sample based on header
308
+		int const shift = header >> 4;
309
+		s = (s << shift) >> 1;
310
+		if ( shift >= 0xD ) // handle invalid range
311
+			s = (s >> 25) << 11; // same as: s = (s < 0 ? -0x800 : 0)
312
+		
313
+		// Apply IIR filter (8 is the most commonly used)
314
+		int const filter = header & 0x0C;
315
+		int const p1 = pos [brr_buf_size - 1];
316
+		int const p2 = pos [brr_buf_size - 2] >> 1;
317
+		if ( filter >= 8 )
318
+		{
319
+			s += p1;
320
+			s -= p2;
321
+			if ( filter == 8 ) // s += p1 * 0.953125 - p2 * 0.46875
322
+			{
323
+				s += p2 >> 4;
324
+				s += (p1 * -3) >> 6;
325
+			}
326
+			else // s += p1 * 0.8984375 - p2 * 0.40625
327
+			{
328
+				s += (p1 * -13) >> 7;
329
+				s += (p2 * 3) >> 4;
330
+			}
331
+		}
332
+		else if ( filter ) // s += p1 * 0.46875
333
+		{
334
+			s += p1 >> 1;
335
+			s += (-p1) >> 5;
336
+		}
337
+		
338
+		// Adjust and write sample
339
+		CLAMP16( s );
340
+		s = (int16_t) (s * 2);
341
+		pos [brr_buf_size] = pos [0] = s; // second copy simplifies wrap-around
342
+	}
343
+}
344
+
345
+
346
+//// Misc
347
+
348
+#define MISC_CLOCK( n ) inline void SPC_DSP::misc_##n()
349
+
350
+MISC_CLOCK( 27 )
351
+{
352
+	m.t_pmon = REG(pmon) & 0xFE; // voice 0 doesn't support PMON
353
+}
354
+MISC_CLOCK( 28 )
355
+{
356
+	m.t_non = REG(non);
357
+	m.t_eon = REG(eon);
358
+	m.t_dir = REG(dir);
359
+}
360
+MISC_CLOCK( 29 )
361
+{
362
+	if ( (m.every_other_sample ^= 1) != 0 )
363
+		m.new_kon &= ~m.kon; // clears KON 63 clocks after it was last read
364
+}
365
+MISC_CLOCK( 30 )
366
+{
367
+	if ( m.every_other_sample )
368
+	{
369
+		m.kon    = m.new_kon;
370
+		m.t_koff = REG(koff) | m.mute_mask; 
371
+	}
372
+	
373
+	run_counters();
374
+	
375
+	// Noise
376
+	if ( !read_counter( REG(flg) & 0x1F ) )
377
+	{
378
+		int feedback = (m.noise << 13) ^ (m.noise << 14);
379
+		m.noise = (feedback & 0x4000) ^ (m.noise >> 1);
380
+	}
381
+}
382
+
383
+
384
+//// Voices
385
+
386
+#define VOICE_CLOCK( n ) void SPC_DSP::voice_##n( voice_t* const v )
387
+
388
+inline VOICE_CLOCK( V1 )
389
+{
390
+	m.t_dir_addr = m.t_dir * 0x100 + m.t_srcn * 4;
391
+	m.t_srcn = VREG(v->regs,srcn);
392
+}
393
+inline VOICE_CLOCK( V2 )
394
+{
395
+	// Read sample pointer (ignored if not needed)
396
+	uint8_t const* entry = &m.ram [m.t_dir_addr];
397
+	if ( !v->kon_delay )
398
+		entry += 2;
399
+	m.t_brr_next_addr = GET_LE16A( entry );
400
+	
401
+	m.t_adsr0 = VREG(v->regs,adsr0);
402
+	
403
+	// Read pitch, spread over two clocks
404
+	m.t_pitch = VREG(v->regs,pitchl);
405
+}
406
+inline VOICE_CLOCK( V3a )
407
+{
408
+	m.t_pitch += (VREG(v->regs,pitchh) & 0x3F) << 8;
409
+}
410
+inline VOICE_CLOCK( V3b )
411
+{
412
+	// Read BRR header and byte
413
+	m.t_brr_byte   = m.ram [(v->brr_addr + v->brr_offset) & 0xFFFF];
414
+	m.t_brr_header = m.ram [v->brr_addr]; // brr_addr doesn't need masking
415
+}
416
+VOICE_CLOCK( V3c )
417
+{
418
+	// Pitch modulation using previous voice's output
419
+	if ( m.t_pmon & v->vbit )
420
+		m.t_pitch += ((m.t_output >> 5) * m.t_pitch) >> 10;
421
+	
422
+	if ( v->kon_delay )
423
+	{
424
+		// Get ready to start BRR decoding on next sample
425
+		if ( v->kon_delay == 5 )
426
+		{
427
+			v->brr_addr    = m.t_brr_next_addr;
428
+			v->brr_offset  = 1;
429
+			v->buf_pos     = 0;
430
+			m.t_brr_header = 0; // header is ignored on this sample
431
+			m.kon_check    = true;
432
+
433
+			if (take_spc_snapshot)
434
+			{
435
+				take_spc_snapshot = 0;
436
+				if (spc_snapshot_callback)
437
+					spc_snapshot_callback();
438
+			}
439
+		}
440
+		
441
+		// Envelope is never run during KON
442
+		v->env        = 0;
443
+		v->hidden_env = 0;
444
+		
445
+		// Disable BRR decoding until last three samples
446
+		v->interp_pos = 0;
447
+		if ( --v->kon_delay & 3 )
448
+			v->interp_pos = 0x4000;
449
+		
450
+		// Pitch is never added during KON
451
+		m.t_pitch = 0;
452
+	}
453
+	
454
+	// Gaussian interpolation
455
+	{
456
+		int output = interpolate( v );
457
+		
458
+		// Noise
459
+		if ( m.t_non & v->vbit )
460
+			output = (int16_t) (m.noise * 2);
461
+		
462
+		// Apply envelope
463
+		m.t_output = (output * v->env) >> 11 & ~1;
464
+		v->t_envx_out = (uint8_t) (v->env >> 4);
465
+	}
466
+	
467
+	// Immediate silence due to end of sample or soft reset
468
+	if ( REG(flg) & 0x80 || (m.t_brr_header & 3) == 1 )
469
+	{
470
+		v->env_mode = env_release;
471
+		v->env      = 0;
472
+	}
473
+	
474
+	if ( m.every_other_sample )
475
+	{
476
+		// KOFF
477
+		if ( m.t_koff & v->vbit )
478
+			v->env_mode = env_release;
479
+		
480
+		// KON
481
+		if ( m.kon & v->vbit )
482
+		{
483
+			v->kon_delay = 5;
484
+			v->env_mode  = env_attack;
485
+		}
486
+	}
487
+	
488
+	// Run envelope for next sample
489
+	if ( !v->kon_delay )
490
+		run_envelope( v );
491
+}
492
+
493
+inline void SPC_DSP::voice_output( voice_t const* v, int ch )
494
+{
495
+	// Apply left/right volume
496
+	int amp = (m.t_output * (int8_t) VREG(v->regs,voll + ch)) >> 7;
497
+	amp *= ((stereo_switch & (1 << (v->voice_number + ch * voice_count))) ? 1 : 0);
498
+
499
+	// Add to output total
500
+	m.t_main_out [ch] += amp;
501
+	CLAMP16( m.t_main_out [ch] );
502
+	
503
+	// Optionally add to echo total
504
+	if ( m.t_eon & v->vbit )
505
+	{
506
+		m.t_echo_out [ch] += amp;
507
+		CLAMP16( m.t_echo_out [ch] );
508
+	}
509
+}
510
+VOICE_CLOCK( V4 )
511
+{
512
+	// Decode BRR
513
+	m.t_looped = 0;
514
+	if ( v->interp_pos >= 0x4000 )
515
+	{
516
+		decode_brr( v );
517
+		
518
+		if ( (v->brr_offset += 2) >= brr_block_size )
519
+		{
520
+			// Start decoding next BRR block
521
+			assert( v->brr_offset == brr_block_size );
522
+			v->brr_addr = (v->brr_addr + brr_block_size) & 0xFFFF;
523
+			if ( m.t_brr_header & 1 )
524
+			{
525
+				v->brr_addr = m.t_brr_next_addr;
526
+				m.t_looped = v->vbit;
527
+			}
528
+			v->brr_offset = 1;
529
+		}
530
+	}
531
+	
532
+	// Apply pitch
533
+	v->interp_pos = (v->interp_pos & 0x3FFF) + m.t_pitch;
534
+	
535
+	// Keep from getting too far ahead (when using pitch modulation)
536
+	if ( v->interp_pos > 0x7FFF )
537
+		v->interp_pos = 0x7FFF;
538
+	
539
+	// Output left
540
+	voice_output( v, 0 );
541
+}
542
+inline VOICE_CLOCK( V5 )
543
+{
544
+	// Output right
545
+	voice_output( v, 1 );
546
+	
547
+	// ENDX, OUTX, and ENVX won't update if you wrote to them 1-2 clocks earlier
548
+	int endx_buf = REG(endx) | m.t_looped;
549
+	
550
+	// Clear bit in ENDX if KON just began
551
+	if ( v->kon_delay == 5 )
552
+		endx_buf &= ~v->vbit;
553
+	m.endx_buf = (uint8_t) endx_buf;
554
+}
555
+inline VOICE_CLOCK( V6 )
556
+{
557
+	(void) v; // avoid compiler warning about unused v
558
+	m.outx_buf = (uint8_t) (m.t_output >> 8);
559
+}
560
+inline VOICE_CLOCK( V7 )
561
+{
562
+	// Update ENDX
563
+	REG(endx) = m.endx_buf;
564
+	
565
+	m.envx_buf = v->t_envx_out;
566
+}
567
+inline VOICE_CLOCK( V8 )
568
+{
569
+	// Update OUTX
570
+	VREG(v->regs,outx) = m.outx_buf;
571
+}
572
+inline VOICE_CLOCK( V9 )
573
+{
574
+	// Update ENVX
575
+	VREG(v->regs,envx) = m.envx_buf;
576
+}
577
+
578
+// Most voices do all these in one clock, so make a handy composite
579
+inline VOICE_CLOCK( V3 )
580
+{
581
+	voice_V3a( v );
582
+	voice_V3b( v );
583
+	voice_V3c( v );
584
+}
585
+
586
+// Common combinations of voice steps on different voices. This greatly reduces
587
+// code size and allows everything to be inlined in these functions.
588
+VOICE_CLOCK(V7_V4_V1) { voice_V7(v); voice_V1(v+3); voice_V4(v+1); }
589
+VOICE_CLOCK(V8_V5_V2) { voice_V8(v); voice_V5(v+1); voice_V2(v+2); }
590
+VOICE_CLOCK(V9_V6_V3) { voice_V9(v); voice_V6(v+1); voice_V3(v+2); }
591
+
592
+
593
+//// Echo
594
+
595
+// Current echo buffer pointer for left/right channel
596
+#define ECHO_PTR( ch )      (&m.ram [m.t_echo_ptr + ch * 2])
597
+
598
+// Sample in echo history buffer, where 0 is the oldest
599
+#define ECHO_FIR( i )       (m.echo_hist_pos [i])
600
+
601
+// Calculate FIR point for left/right channel
602
+#define CALC_FIR( i, ch )   ((ECHO_FIR( i + 1 ) [ch] * (int8_t) REG(fir + i * 0x10)) >> 6)
603
+
604
+#define ECHO_CLOCK( n ) inline void SPC_DSP::echo_##n()
605
+
606
+inline void SPC_DSP::echo_read( int ch )
607
+{
608
+	int s = GET_LE16SA( ECHO_PTR( ch ) );
609
+	// second copy simplifies wrap-around handling
610
+	ECHO_FIR( 0 ) [ch] = ECHO_FIR( 8 ) [ch] = s >> 1;
611
+}
612
+
613
+ECHO_CLOCK( 22 )
614
+{
615
+	// History
616
+	if ( ++m.echo_hist_pos >= &m.echo_hist [echo_hist_size] )
617
+		m.echo_hist_pos = m.echo_hist;
618
+	
619
+	m.t_echo_ptr = (m.t_esa * 0x100 + m.echo_offset) & 0xFFFF;
620
+	echo_read( 0 );
621
+	
622
+	// FIR (using l and r temporaries below helps compiler optimize)
623
+	int l = CALC_FIR( 0, 0 );
624
+	int r = CALC_FIR( 0, 1 );
625
+	
626
+	m.t_echo_in [0] = l;
627
+	m.t_echo_in [1] = r;
628
+}
629
+ECHO_CLOCK( 23 )
630
+{
631
+	int l = CALC_FIR( 1, 0 ) + CALC_FIR( 2, 0 );
632
+	int r = CALC_FIR( 1, 1 ) + CALC_FIR( 2, 1 );
633
+	
634
+	m.t_echo_in [0] += l;
635
+	m.t_echo_in [1] += r;
636
+	
637
+	echo_read( 1 );
638
+}
639
+ECHO_CLOCK( 24 )
640
+{
641
+	int l = CALC_FIR( 3, 0 ) + CALC_FIR( 4, 0 ) + CALC_FIR( 5, 0 );
642
+	int r = CALC_FIR( 3, 1 ) + CALC_FIR( 4, 1 ) + CALC_FIR( 5, 1 );
643
+	
644
+	m.t_echo_in [0] += l;
645
+	m.t_echo_in [1] += r;
646
+}
647
+ECHO_CLOCK( 25 )
648
+{
649
+	int l = m.t_echo_in [0] + CALC_FIR( 6, 0 );
650
+	int r = m.t_echo_in [1] + CALC_FIR( 6, 1 );
651
+	
652
+	l = (int16_t) l;
653
+	r = (int16_t) r;
654
+	
655
+	l += (int16_t) CALC_FIR( 7, 0 );
656
+	r += (int16_t) CALC_FIR( 7, 1 );
657
+	
658
+	CLAMP16( l );
659
+	CLAMP16( r );
660
+	
661
+	m.t_echo_in [0] = l & ~1;
662
+	m.t_echo_in [1] = r & ~1;
663
+}
664
+inline int SPC_DSP::echo_output( int ch )
665
+{
666
+	int out = (int16_t) ((m.t_main_out [ch] * (int8_t) REG(mvoll + ch * 0x10)) >> 7) +
667
+			(int16_t) ((m.t_echo_in [ch] * (int8_t) REG(evoll + ch * 0x10)) >> 7);
668
+	CLAMP16( out );
669
+	return out;
670
+}
671
+ECHO_CLOCK( 26 )
672
+{
673
+	// Left output volumes
674
+	// (save sample for next clock so we can output both together)
675
+	m.t_main_out [0] = echo_output( 0 );
676
+	
677
+	// Echo feedback
678
+	int l = m.t_echo_out [0] + (int16_t) ((m.t_echo_in [0] * (int8_t) REG(efb)) >> 7);
679
+	int r = m.t_echo_out [1] + (int16_t) ((m.t_echo_in [1] * (int8_t) REG(efb)) >> 7);
680
+	
681
+	CLAMP16( l );
682
+	CLAMP16( r );
683
+	
684
+	m.t_echo_out [0] = l & ~1;
685
+	m.t_echo_out [1] = r & ~1;
686
+}
687
+ECHO_CLOCK( 27 )
688
+{
689
+	// Output
690
+	int l = m.t_main_out [0];
691
+	int r = echo_output( 1 );
692
+	m.t_main_out [0] = 0;
693
+	m.t_main_out [1] = 0;
694
+	
695
+	// TODO: global muting isn't this simple (turns DAC on and off
696
+	// or something, causing small ~37-sample pulse when first muted)
697
+	if ( REG(flg) & 0x40 )
698
+	{
699
+		l = 0;
700
+		r = 0;
701
+	}
702
+	
703
+	// Output sample to DAC
704
+	#ifdef SPC_DSP_OUT_HOOK
705
+		SPC_DSP_OUT_HOOK( l, r );
706
+	#else
707
+		sample_t* out = m.out;
708
+		WRITE_SAMPLES( l, r, out );
709
+		m.out = out;
710
+	#endif
711
+}
712
+ECHO_CLOCK( 28 )
713
+{
714
+	m.t_echo_enabled = REG(flg);
715
+}
716
+inline void SPC_DSP::echo_write( int ch )
717
+{
718
+	if ( !(m.t_echo_enabled & 0x20) )
719
+	{
720
+		if ( m.t_echo_ptr >= 0xffc0 && rom_enabled )
721
+			SET_LE16A( &hi_ram [m.t_echo_ptr + ch * 2 - 0xffc0], m.t_echo_out [ch] );
722
+		else
723
+			SET_LE16A( ECHO_PTR( ch ), m.t_echo_out [ch] );
724
+	}
725
+
726
+	m.t_echo_out [ch] = 0;
727
+}
728
+ECHO_CLOCK( 29 )
729
+{
730
+	m.t_esa = REG(esa);
731
+	
732
+	if ( !m.echo_offset )
733
+		m.echo_length = (REG(edl) & 0x0F) * 0x800;
734
+	
735
+	m.echo_offset += 4;
736
+	if ( m.echo_offset >= m.echo_length )
737
+		m.echo_offset = 0;
738
+	
739
+	// Write left echo
740
+	echo_write( 0 );
741
+	
742
+	m.t_echo_enabled = REG(flg);
743
+}
744
+ECHO_CLOCK( 30 )
745
+{
746
+	// Write right echo
747
+	echo_write( 1 );
748
+}
749
+
750
+
751
+//// Timing
752
+
753
+// Execute clock for a particular voice
754
+#define V( clock, voice )   voice_##clock( &m.voices [voice] );
755
+
756
+/* The most common sequence of clocks uses composite operations
757
+for efficiency. For example, the following are equivalent to the
758
+individual steps on the right:
759
+
760
+V(V7_V4_V1,2) -> V(V7,2) V(V4,3) V(V1,5)
761
+V(V8_V5_V2,2) -> V(V8,2) V(V5,3) V(V2,4)
762
+V(V9_V6_V3,2) -> V(V9,2) V(V6,3) V(V3,4) */
763
+
764
+// Voice      0      1      2      3      4      5      6      7
765
+#define GEN_DSP_TIMING \
766
+PHASE( 0)  V(V5,0)V(V2,1)\
767
+PHASE( 1)  V(V6,0)V(V3,1)\
768
+PHASE( 2)  V(V7_V4_V1,0)\
769
+PHASE( 3)  V(V8_V5_V2,0)\
770
+PHASE( 4)  V(V9_V6_V3,0)\
771
+PHASE( 5)         V(V7_V4_V1,1)\
772
+PHASE( 6)         V(V8_V5_V2,1)\
773
+PHASE( 7)         V(V9_V6_V3,1)\
774
+PHASE( 8)                V(V7_V4_V1,2)\
775
+PHASE( 9)                V(V8_V5_V2,2)\
776
+PHASE(10)                V(V9_V6_V3,2)\
777
+PHASE(11)                       V(V7_V4_V1,3)\
778
+PHASE(12)                       V(V8_V5_V2,3)\
779
+PHASE(13)                       V(V9_V6_V3,3)\
780
+PHASE(14)                              V(V7_V4_V1,4)\
781
+PHASE(15)                              V(V8_V5_V2,4)\
782
+PHASE(16)                              V(V9_V6_V3,4)\
783
+PHASE(17)  V(V1,0)                            V(V7,5)V(V4,6)\
784
+PHASE(18)                                     V(V8_V5_V2,5)\
785
+PHASE(19)                                     V(V9_V6_V3,5)\
786
+PHASE(20)         V(V1,1)                            V(V7,6)V(V4,7)\
787
+PHASE(21)                                            V(V8,6)V(V5,7)  V(V2,0)  /* t_brr_next_addr order dependency */\
788
+PHASE(22)  V(V3a,0)                                  V(V9,6)V(V6,7)  echo_22();\
789
+PHASE(23)                                                   V(V7,7)  echo_23();\
790
+PHASE(24)                                                   V(V8,7)  echo_24();\
791
+PHASE(25)  V(V3b,0)                                         V(V9,7)  echo_25();\
792
+PHASE(26)                                                            echo_26();\
793
+PHASE(27) misc_27();                                                 echo_27();\
794
+PHASE(28) misc_28();                                                 echo_28();\
795
+PHASE(29) misc_29();                                                 echo_29();\
796
+PHASE(30) misc_30();V(V3c,0)                                         echo_30();\
797
+PHASE(31)  V(V4,0)       V(V1,2)\
798
+
799
+#if !SPC_DSP_CUSTOM_RUN
800
+
801
+void SPC_DSP::run( int clocks_remain )
802
+{
803
+	require( clocks_remain > 0 );
804
+	
805
+	int const phase = m.phase;
806
+	m.phase = (phase + clocks_remain) & 31;
807
+	switch ( phase )
808
+	{
809
+	loop:
810
+	
811
+		#define PHASE( n ) if ( n && !--clocks_remain ) break; case n:
812
+		GEN_DSP_TIMING
813
+		#undef PHASE
814
+	
815
+		if ( --clocks_remain )
816
+			goto loop;
817
+	}
818
+}
819
+
820
+#endif
821
+
822
+
823
+//// Setup
824
+
825
+void SPC_DSP::init( void* ram_64k )
826
+{
827
+	m.ram = (uint8_t*) ram_64k;
828
+	mute_voices( 0 );
829
+	disable_surround( false );
830
+	set_output( 0, 0 );
831
+	reset();
832
+
833
+	stereo_switch = 0xffff;
834
+	take_spc_snapshot = 0;
835
+	spc_snapshot_callback = 0;
836
+
837
+	#ifndef NDEBUG
838
+		// be sure this sign-extends
839
+		assert( (int16_t) 0x8000 == -0x8000 );
840
+		
841
+		// be sure right shift preserves sign
842
+		assert( (-1 >> 1) == -1 );
843
+		
844
+		// check clamp macro
845
+		int i;
846
+		i = +0x8000; CLAMP16( i ); assert( i == +0x7FFF );
847
+		i = -0x8001; CLAMP16( i ); assert( i == -0x8000 );
848
+		
849
+		blargg_verify_byte_order();
850
+	#endif
851
+}
852
+
853
+void SPC_DSP::soft_reset_common()
854
+{
855
+	require( m.ram ); // init() must have been called already
856
+	
857
+	m.noise              = 0x4000;
858
+	m.echo_hist_pos      = m.echo_hist;
859
+	m.every_other_sample = 1;
860
+	m.echo_offset        = 0;
861
+	m.phase              = 0;
862
+	
863
+	init_counter();
864
+
865
+	for (int i = 0; i < voice_count; i++)
866
+		m.voices[i].voice_number = i;
867
+}
868
+
869
+void SPC_DSP::soft_reset()
870
+{
871
+	REG(flg) = 0xE0;
872
+	soft_reset_common();
873
+}
874
+
875
+void SPC_DSP::load( uint8_t const regs [register_count] )
876
+{
877
+	memcpy( m.regs, regs, sizeof m.regs );
878
+	memset( &m.regs [register_count], 0, offsetof (state_t,ram) - register_count );
879
+	
880
+	// Internal state
881
+	for ( int i = voice_count; --i >= 0; )
882
+	{
883
+		voice_t* v = &m.voices [i];
884
+		v->brr_offset = 1;
885
+		v->vbit       = 1 << i;
886
+		v->regs       = &m.regs [i * 0x10];
887
+	}
888
+	m.new_kon = REG(kon);
889
+	m.t_dir   = REG(dir);
890
+	m.t_esa   = REG(esa);
891
+	
892
+	soft_reset_common();
893
+}
894
+
895
+void SPC_DSP::reset() { load( initial_regs ); }
896
+
897
+
898
+//// State save/load
899
+
900
+#if !SPC_NO_COPY_STATE_FUNCS
901
+
902
+void SPC_State_Copier::copy( void* state, size_t size )
903
+{
904
+	func( buf, state, size );
905
+}
906
+
907
+int SPC_State_Copier::copy_int( int state, int size )
908
+{
909
+	BOOST::uint8_t s [2];
910
+	SET_LE16( s, state );
911
+	func( buf, &s, size );
912
+	return GET_LE16( s );
913
+}
914
+
915
+void SPC_State_Copier::skip( int count )
916
+{
917
+	if ( count > 0 )
918
+	{
919
+		char temp [64];
920
+		memset( temp, 0, sizeof temp );
921
+		do
922
+		{
923
+			int n = sizeof temp;
924
+			if ( n > count )
925
+				n = count;
926
+			count -= n;
927
+			func( buf, temp, n );
928
+		}
929
+		while ( count );
930
+	}
931
+}
932
+
933
+void SPC_State_Copier::extra()
934
+{
935
+	int n = 0;
936
+	SPC_State_Copier& copier = *this;
937
+	SPC_COPY( uint8_t, n );
938
+	skip( n );
939
+}
940
+
941
+void SPC_DSP::copy_state( unsigned char** io, copy_func_t copy )
942
+{
943
+	SPC_State_Copier copier( io, copy );
944
+	
945
+	// DSP registers
946
+	copier.copy( m.regs, register_count );
947
+	
948
+	// Internal state
949
+	
950
+	// Voices
951
+	int i;
952
+	for ( i = 0; i < voice_count; i++ )
953
+	{
954
+		voice_t* v = &m.voices [i];
955
+		
956
+		// BRR buffer
957
+		int i;
958
+		for ( i = 0; i < brr_buf_size; i++ )
959
+		{
960
+			int s = v->buf [i];
961
+			SPC_COPY(  int16_t, s );
962
+			v->buf [i] = v->buf [i + brr_buf_size] = s;
963
+		}
964
+		
965
+		SPC_COPY( uint16_t, v->interp_pos );
966
+		SPC_COPY( uint16_t, v->brr_addr );
967
+		SPC_COPY( uint16_t, v->env );
968
+		SPC_COPY(  int16_t, v->hidden_env );
969
+		SPC_COPY(  uint8_t, v->buf_pos );
970
+		SPC_COPY(  uint8_t, v->brr_offset );
971
+		SPC_COPY(  uint8_t, v->kon_delay );
972
+		{
973
+			int m = v->env_mode;
974
+			SPC_COPY(  uint8_t, m );
975
+			v->env_mode = (enum env_mode_t) m;
976
+		}
977
+		SPC_COPY(  uint8_t, v->t_envx_out );
978
+		
979
+		copier.extra();
980
+	}
981
+	
982
+	// Echo history
983
+	for ( i = 0; i < echo_hist_size; i++ )
984
+	{
985
+		int j;
986
+		for ( j = 0; j < 2; j++ )
987
+		{
988
+			int s = m.echo_hist_pos [i] [j];
989
+			SPC_COPY( int16_t, s );
990
+			m.echo_hist [i] [j] = s; // write back at offset 0
991
+		}
992
+	}
993
+	m.echo_hist_pos = m.echo_hist;
994
+	memcpy( &m.echo_hist [echo_hist_size], m.echo_hist, echo_hist_size * sizeof m.echo_hist [0] );
995
+	
996
+	// Misc
997
+	SPC_COPY(  uint8_t, m.every_other_sample );
998
+	SPC_COPY(  uint8_t, m.kon );
999
+	
1000
+	SPC_COPY( uint16_t, m.noise );
1001
+	SPC_COPY( uint16_t, m.counter );
1002
+	SPC_COPY( uint16_t, m.echo_offset );
1003
+	SPC_COPY( uint16_t, m.echo_length );
1004
+	SPC_COPY(  uint8_t, m.phase );
1005
+	
1006
+	SPC_COPY(  uint8_t, m.new_kon );
1007
+	SPC_COPY(  uint8_t, m.endx_buf );
1008
+	SPC_COPY(  uint8_t, m.envx_buf );
1009
+	SPC_COPY(  uint8_t, m.outx_buf );
1010
+	
1011
+	SPC_COPY(  uint8_t, m.t_pmon );
1012
+	SPC_COPY(  uint8_t, m.t_non );
1013
+	SPC_COPY(  uint8_t, m.t_eon );
1014
+	SPC_COPY(  uint8_t, m.t_dir );
1015
+	SPC_COPY(  uint8_t, m.t_koff );
1016
+	
1017
+	SPC_COPY( uint16_t, m.t_brr_next_addr );
1018
+	SPC_COPY(  uint8_t, m.t_adsr0 );
1019
+	SPC_COPY(  uint8_t, m.t_brr_header );
1020
+	SPC_COPY(  uint8_t, m.t_brr_byte );
1021
+	SPC_COPY(  uint8_t, m.t_srcn );
1022
+	SPC_COPY(  uint8_t, m.t_esa );
1023
+	SPC_COPY(  uint8_t, m.t_echo_enabled );
1024
+	
1025
+	SPC_COPY(  int16_t, m.t_main_out [0] );
1026
+	SPC_COPY(  int16_t, m.t_main_out [1] );
1027
+	SPC_COPY(  int16_t, m.t_echo_out [0] );
1028
+	SPC_COPY(  int16_t, m.t_echo_out [1] );
1029
+	SPC_COPY(  int16_t, m.t_echo_in  [0] );
1030
+	SPC_COPY(  int16_t, m.t_echo_in  [1] );
1031
+	
1032
+	SPC_COPY( uint16_t, m.t_dir_addr );
1033
+	SPC_COPY( uint16_t, m.t_pitch );
1034
+	SPC_COPY(  int16_t, m.t_output );
1035
+	SPC_COPY( uint16_t, m.t_echo_ptr );
1036
+	SPC_COPY(  uint8_t, m.t_looped );
1037
+	
1038
+	copier.extra();
1039
+}
1040
+#endif
1041
+
1042
+
1043
+//// Snes9x Accessor
1044
+
1045
+void SPC_DSP::set_spc_snapshot_callback(void (*callback)())
1046
+{
1047
+	spc_snapshot_callback = callback;
1048
+}
1049
+
1050
+void SPC_DSP::dump_spc_snapshot()
1051
+{
1052
+	take_spc_snapshot = 1;
1053
+}
1054
+
1055
+void SPC_DSP::set_stereo_switch( int value )
1056
+{
1057
+	stereo_switch = value;
1058
+}
1059
+
1060
+SPC_DSP::uint8_t SPC_DSP::reg_value( int ch, int addr )
1061
+{
1062
+	return m.voices[ch].regs[addr];
1063
+}
1064
+
1065
+int SPC_DSP::envx_value( int ch )
1066
+{
1067
+	return m.voices[ch].env;
1068
+}