1 // Game_Music_Emu https://bitbucket.org/mpyne/game-music-emu/
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
30 // TODO: add to blargg_endian.h
31 #define GET_LE16SA( addr ) ((int16_t) GET_LE16( addr ))
32 #define GET_LE16A( addr ) GET_LE16( addr )
33 #define SET_LE16A( addr, data ) SET_LE16( addr, data )
34
35 static uint8_t const initial_regs [Spc_Dsp::register_count] =
36 {
37 0x45,0x8B,0x5A,0x9A,0xE4,0x82,0x1B,0x78,0x00,0x00,0xAA,0x96,0x89,0x0E,0xE0,0x80,
38 0x2A,0x49,0x3D,0xBA,0x14,0xA0,0xAC,0xC5,0x00,0x00,0x51,0xBB,0x9C,0x4E,0x7B,0xFF,
39 0xF4,0xFD,0x57,0x32,0x37,0xD9,0x42,0x22,0x00,0x00,0x5B,0x3C,0x9F,0x1B,0x87,0x9A,
40 0x6F,0x27,0xAF,0x7B,0xE5,0x68,0x0A,0xD9,0x00,0x00,0x9A,0xC5,0x9C,0x4E,0x7B,0xFF,
41 0xEA,0x21,0x78,0x4F,0xDD,0xED,0x24,0x14,0x00,0x00,0x77,0xB1,0xD1,0x36,0xC1,0x67,
42 0x52,0x57,0x46,0x3D,0x59,0xF4,0x87,0xA4,0x00,0x00,0x7E,0x44,0x9C,0x4E,0x7B,0xFF,
43 0x75,0xF5,0x06,0x97,0x10,0xC3,0x24,0xBB,0x00,0x00,0x7B,0x7A,0xE0,0x60,0x12,0x0F,
44 0xF7,0x74,0x1C,0xE5,0x39,0x3D,0x73,0xC1,0x00,0x00,0x7A,0xB3,0xFF,0x4E,0x7B,0xFF
45 };
46
47 // if ( io < -32768 ) io = -32768;
48 // if ( io > 32767 ) io = 32767;
49 #define CLAMP16( io )\
50 {\
51 if ( (int16_t) io != io )\
52 io = (io >> 31) ^ 0x7FFF;\
53 }
54
55 // Access global DSP register
56 #define REG(n) m.regs [r_##n]
57
58 // Access voice DSP register
59 #define VREG(r,n) r [v_##n]
60
61 #define WRITE_SAMPLES( l, r, out ) \
62 {\
63 out [0] = l;\
64 out [1] = r;\
65 out += 2;\
66 if ( out >= m.out_end )\
67 {\
68 check( out == m.out_end );\
69 check( m.out_end != &m.extra [extra_size] || \
70 (m.extra <= m.out_begin && m.extra < &m.extra [extra_size]) );\
71 out = m.extra;\
72 m.out_end = &m.extra [extra_size];\
73 }\
74 }\
75
set_output(sample_t * out,int size)76 void Spc_Dsp::set_output( sample_t* out, int size )
77 {
78 require( (size & 1) == 0 ); // must be even
79 if ( !out )
80 {
81 out = m.extra;
82 size = extra_size;
83 }
84 m.out_begin = out;
85 m.out = out;
86 m.out_end = out + size;
87 }
88
89 // Volume registers and efb are signed! Easy to forget int8_t cast.
90 // Prefixes are to avoid accidental use of locals with same names.
91
92 // Interleved gauss table (to improve cache coherency)
93 // interleved_gauss [i] = gauss [(i & 1) * 256 + 255 - (i >> 1 & 0xFF)]
94 static short const interleved_gauss [512] =
95 {
96 370,1305, 366,1305, 362,1304, 358,1304, 354,1304, 351,1304, 347,1304, 343,1303,
97 339,1303, 336,1303, 332,1302, 328,1302, 325,1301, 321,1300, 318,1300, 314,1299,
98 311,1298, 307,1297, 304,1297, 300,1296, 297,1295, 293,1294, 290,1293, 286,1292,
99 283,1291, 280,1290, 276,1288, 273,1287, 270,1286, 267,1284, 263,1283, 260,1282,
100 257,1280, 254,1279, 251,1277, 248,1275, 245,1274, 242,1272, 239,1270, 236,1269,
101 233,1267, 230,1265, 227,1263, 224,1261, 221,1259, 218,1257, 215,1255, 212,1253,
102 210,1251, 207,1248, 204,1246, 201,1244, 199,1241, 196,1239, 193,1237, 191,1234,
103 188,1232, 186,1229, 183,1227, 180,1224, 178,1221, 175,1219, 173,1216, 171,1213,
104 168,1210, 166,1207, 163,1205, 161,1202, 159,1199, 156,1196, 154,1193, 152,1190,
105 150,1186, 147,1183, 145,1180, 143,1177, 141,1174, 139,1170, 137,1167, 134,1164,
106 132,1160, 130,1157, 128,1153, 126,1150, 124,1146, 122,1143, 120,1139, 118,1136,
107 117,1132, 115,1128, 113,1125, 111,1121, 109,1117, 107,1113, 106,1109, 104,1106,
108 102,1102, 100,1098, 99,1094, 97,1090, 95,1086, 94,1082, 92,1078, 90,1074,
109 89,1070, 87,1066, 86,1061, 84,1057, 83,1053, 81,1049, 80,1045, 78,1040,
110 77,1036, 76,1032, 74,1027, 73,1023, 71,1019, 70,1014, 69,1010, 67,1005,
111 66,1001, 65, 997, 64, 992, 62, 988, 61, 983, 60, 978, 59, 974, 58, 969,
112 56, 965, 55, 960, 54, 955, 53, 951, 52, 946, 51, 941, 50, 937, 49, 932,
113 48, 927, 47, 923, 46, 918, 45, 913, 44, 908, 43, 904, 42, 899, 41, 894,
114 40, 889, 39, 884, 38, 880, 37, 875, 36, 870, 36, 865, 35, 860, 34, 855,
115 33, 851, 32, 846, 32, 841, 31, 836, 30, 831, 29, 826, 29, 821, 28, 816,
116 27, 811, 27, 806, 26, 802, 25, 797, 24, 792, 24, 787, 23, 782, 23, 777,
117 22, 772, 21, 767, 21, 762, 20, 757, 20, 752, 19, 747, 19, 742, 18, 737,
118 17, 732, 17, 728, 16, 723, 16, 718, 15, 713, 15, 708, 15, 703, 14, 698,
119 14, 693, 13, 688, 13, 683, 12, 678, 12, 674, 11, 669, 11, 664, 11, 659,
120 10, 654, 10, 649, 10, 644, 9, 640, 9, 635, 9, 630, 8, 625, 8, 620,
121 8, 615, 7, 611, 7, 606, 7, 601, 6, 596, 6, 592, 6, 587, 6, 582,
122 5, 577, 5, 573, 5, 568, 5, 563, 4, 559, 4, 554, 4, 550, 4, 545,
123 4, 540, 3, 536, 3, 531, 3, 527, 3, 522, 3, 517, 2, 513, 2, 508,
124 2, 504, 2, 499, 2, 495, 2, 491, 2, 486, 1, 482, 1, 477, 1, 473,
125 1, 469, 1, 464, 1, 460, 1, 456, 1, 451, 1, 447, 1, 443, 1, 439,
126 0, 434, 0, 430, 0, 426, 0, 422, 0, 418, 0, 414, 0, 410, 0, 405,
127 0, 401, 0, 397, 0, 393, 0, 389, 0, 385, 0, 381, 0, 378, 0, 374,
128 };
129
130
131 //// Counters
132
133 #define RATE( rate, div )\
134 (rate >= div ? rate / div * 8 - 1 : rate - 1)
135
136 static unsigned const counter_mask [32] =
137 {
138 RATE( 2,2), RATE(2048,4), RATE(1536,3),
139 RATE(1280,5), RATE(1024,4), RATE( 768,3),
140 RATE( 640,5), RATE( 512,4), RATE( 384,3),
141 RATE( 320,5), RATE( 256,4), RATE( 192,3),
142 RATE( 160,5), RATE( 128,4), RATE( 96,3),
143 RATE( 80,5), RATE( 64,4), RATE( 48,3),
144 RATE( 40,5), RATE( 32,4), RATE( 24,3),
145 RATE( 20,5), RATE( 16,4), RATE( 12,3),
146 RATE( 10,5), RATE( 8,4), RATE( 6,3),
147 RATE( 5,5), RATE( 4,4), RATE( 3,3),
148 RATE( 2,4),
149 RATE( 1,4)
150 };
151 #undef RATE
152
init_counter()153 inline void Spc_Dsp::init_counter()
154 {
155 // counters start out with this synchronization
156 m.counters [0] = 1;
157 m.counters [1] = 0;
158 m.counters [2] = -0x20u;
159 m.counters [3] = 0x0B;
160
161 int n = 2;
162 for ( int i = 1; i < 32; i++ )
163 {
164 m.counter_select [i] = &m.counters [n];
165 if ( !--n )
166 n = 3;
167 }
168 m.counter_select [ 0] = &m.counters [0];
169 m.counter_select [30] = &m.counters [2];
170 }
171
run_counter(int i)172 inline void Spc_Dsp::run_counter( int i )
173 {
174 int n = m.counters [i];
175 if ( !(n-- & 7) )
176 n -= 6 - i;
177 m.counters [i] = n;
178 }
179
180 #define READ_COUNTER( rate )\
181 (*m.counter_select [rate] & counter_mask [rate])
182
183
184 //// Emulation
185
run(int clock_count)186 void Spc_Dsp::run( int clock_count )
187 {
188 int new_phase = m.phase + clock_count;
189 int count = new_phase >> 5;
190 m.phase = new_phase & 31;
191 if ( !count )
192 return;
193
194 uint8_t* const ram = m.ram;
195 uint8_t const* const dir = &ram [REG(dir) * 0x100];
196 int const slow_gaussian = (REG(pmon) >> 1) | REG(non);
197 int const noise_rate = REG(flg) & 0x1F;
198
199 // Global volume
200 int mvoll = (int8_t) REG(mvoll);
201 int mvolr = (int8_t) REG(mvolr);
202 if ( mvoll * mvolr < m.surround_threshold )
203 mvoll = -mvoll; // eliminate surround
204
205 do
206 {
207 // KON/KOFF reading
208 if ( (m.every_other_sample ^= 1) != 0 )
209 {
210 m.new_kon &= ~m.kon;
211 m.kon = m.new_kon;
212 m.t_koff = REG(koff);
213 }
214
215 run_counter( 1 );
216 run_counter( 2 );
217 run_counter( 3 );
218
219 // Noise
220 if ( !READ_COUNTER( noise_rate ) )
221 {
222 int feedback = (m.noise << 13) ^ (m.noise << 14);
223 m.noise = (feedback & 0x4000) ^ (m.noise >> 1);
224 }
225
226 // Voices
227 int pmon_input = 0;
228 int main_out_l = 0;
229 int main_out_r = 0;
230 int echo_out_l = 0;
231 int echo_out_r = 0;
232 voice_t* v = m.voices;
233 uint8_t* v_regs = m.regs;
234 int vbit = 1;
235 do
236 {
237 #define SAMPLE_PTR(i) GET_LE16A( &dir [VREG(v_regs,srcn) * 4 + i * 2] )
238
239 int brr_header = ram [v->brr_addr];
240 int kon_delay = v->kon_delay;
241
242 // Pitch
243 int pitch = GET_LE16A( &VREG(v_regs,pitchl) ) & 0x3FFF;
244 if ( REG(pmon) & vbit )
245 pitch += ((pmon_input >> 5) * pitch) >> 10;
246
247 // KON phases
248 if ( --kon_delay >= 0 )
249 {
250 v->kon_delay = kon_delay;
251
252 // Get ready to start BRR decoding on next sample
253 if ( kon_delay == 4 )
254 {
255 v->brr_addr = SAMPLE_PTR( 0 );
256 v->brr_offset = 1;
257 v->buf_pos = v->buf;
258 brr_header = 0; // header is ignored on this sample
259 }
260
261 // Envelope is never run during KON
262 v->env = 0;
263 v->hidden_env = 0;
264
265 // Disable BRR decoding until last three samples
266 v->interp_pos = (kon_delay & 3 ? 0x4000 : 0);
267
268 // Pitch is never added during KON
269 pitch = 0;
270 }
271
272 int env = v->env;
273
274 // Gaussian interpolation
275 {
276 int output = 0;
277 VREG(v_regs,envx) = (uint8_t) (env >> 4);
278 if ( env )
279 {
280 // Make pointers into gaussian based on fractional position between samples
281 int offset = (unsigned) v->interp_pos >> 3 & 0x1FE;
282 short const* fwd = interleved_gauss + offset;
283 short const* rev = interleved_gauss + 510 - offset; // mirror left half of gaussian
284
285 int const* in = &v->buf_pos [(unsigned) v->interp_pos >> 12];
286
287 if ( !(slow_gaussian & vbit) ) // 99%
288 {
289 // Faster approximation when exact sample value isn't necessary for pitch mod
290 output = (fwd [0] * in [0] +
291 fwd [1] * in [1] +
292 rev [1] * in [2] +
293 rev [0] * in [3]) >> 11;
294 output = (output * env) >> 11;
295 }
296 else
297 {
298 output = (int16_t) (m.noise * 2);
299 if ( !(REG(non) & vbit) )
300 {
301 output = (fwd [0] * in [0]) >> 11;
302 output += (fwd [1] * in [1]) >> 11;
303 output += (rev [1] * in [2]) >> 11;
304 output = (int16_t) output;
305 output += (rev [0] * in [3]) >> 11;
306
307 CLAMP16( output );
308 output &= ~1;
309 }
310 output = (output * env) >> 11 & ~1;
311 }
312
313 // Output
314 int l = output * v->volume [0];
315 int r = output * v->volume [1];
316
317 main_out_l += l;
318 main_out_r += r;
319
320 if ( REG(eon) & vbit )
321 {
322 echo_out_l += l;
323 echo_out_r += r;
324 }
325 }
326
327 pmon_input = output;
328 VREG(v_regs,outx) = (uint8_t) (output >> 8);
329 }
330
331 // Soft reset or end of sample
332 if ( REG(flg) & 0x80 || (brr_header & 3) == 1 )
333 {
334 v->env_mode = env_release;
335 env = 0;
336 }
337
338 if ( m.every_other_sample )
339 {
340 // KOFF
341 if ( m.t_koff & vbit )
342 v->env_mode = env_release;
343
344 // KON
345 if ( m.kon & vbit )
346 {
347 v->kon_delay = 5;
348 v->env_mode = env_attack;
349 REG(endx) &= ~vbit;
350 }
351 }
352
353 // Envelope
354 if ( !v->kon_delay )
355 {
356 if ( v->env_mode == env_release ) // 97%
357 {
358 env -= 0x8;
359 v->env = env;
360 if ( env <= 0 )
361 {
362 v->env = 0;
363 goto skip_brr; // no BRR decoding for you!
364 }
365 }
366 else // 3%
367 {
368 int rate;
369 int const adsr0 = VREG(v_regs,adsr0);
370 int env_data = VREG(v_regs,adsr1);
371 if ( adsr0 >= 0x80 ) // 97% ADSR
372 {
373 if ( v->env_mode > env_decay ) // 89%
374 {
375 env--;
376 env -= env >> 8;
377 rate = env_data & 0x1F;
378
379 // optimized handling
380 v->hidden_env = env;
381 if ( READ_COUNTER( rate ) )
382 goto exit_env;
383 v->env = env;
384 goto exit_env;
385 }
386 else if ( v->env_mode == env_decay )
387 {
388 env--;
389 env -= env >> 8;
390 rate = (adsr0 >> 3 & 0x0E) + 0x10;
391 }
392 else // env_attack
393 {
394 rate = (adsr0 & 0x0F) * 2 + 1;
395 env += rate < 31 ? 0x20 : 0x400;
396 }
397 }
398 else // GAIN
399 {
400 int mode;
401 env_data = VREG(v_regs,gain);
402 mode = env_data >> 5;
403 if ( mode < 4 ) // direct
404 {
405 env = env_data * 0x10;
406 rate = 31;
407 }
408 else
409 {
410 rate = env_data & 0x1F;
411 if ( mode == 4 ) // 4: linear decrease
412 {
413 env -= 0x20;
414 }
415 else if ( mode < 6 ) // 5: exponential decrease
416 {
417 env--;
418 env -= env >> 8;
419 }
420 else // 6,7: linear increase
421 {
422 env += 0x20;
423 if ( mode > 6 && (unsigned) v->hidden_env >= 0x600 )
424 env += 0x8 - 0x20; // 7: two-slope linear increase
425 }
426 }
427 }
428
429 // Sustain level
430 if ( (env >> 8) == (env_data >> 5) && v->env_mode == env_decay )
431 v->env_mode = env_sustain;
432
433 v->hidden_env = env;
434
435 // unsigned cast because linear decrease going negative also triggers this
436 if ( (unsigned) env > 0x7FF )
437 {
438 env = (env < 0 ? 0 : 0x7FF);
439 if ( v->env_mode == env_attack )
440 v->env_mode = env_decay;
441 }
442
443 if ( !READ_COUNTER( rate ) )
444 v->env = env; // nothing else is controlled by the counter
445 }
446 }
447 exit_env:
448
449 {
450 // Apply pitch
451 int old_pos = v->interp_pos;
452 int interp_pos = (old_pos & 0x3FFF) + pitch;
453 if ( interp_pos > 0x7FFF )
454 interp_pos = 0x7FFF;
455 v->interp_pos = interp_pos;
456
457 // BRR decode if necessary
458 if ( old_pos >= 0x4000 )
459 {
460 // Arrange the four input nybbles in 0xABCD order for easy decoding
461 int nybbles = ram [(v->brr_addr + v->brr_offset) & 0xFFFF] * 0x100 +
462 ram [(v->brr_addr + v->brr_offset + 1) & 0xFFFF];
463
464 // Advance read position
465 int const brr_block_size = 9;
466 int brr_offset = v->brr_offset;
467 if ( (brr_offset += 2) >= brr_block_size )
468 {
469 // Next BRR block
470 int brr_addr = (v->brr_addr + brr_block_size) & 0xFFFF;
471 assert( brr_offset == brr_block_size );
472 if ( brr_header & 1 )
473 {
474 brr_addr = SAMPLE_PTR( 1 );
475 if ( !v->kon_delay )
476 REG(endx) |= vbit;
477 }
478 v->brr_addr = brr_addr;
479 brr_offset = 1;
480 }
481 v->brr_offset = brr_offset;
482
483 // Decode
484
485 // 0: >>1 1: <<0 2: <<1 ... 12: <<11 13-15: >>4 <<11
486 static unsigned char const shifts [16 * 2] = {
487 13,12,12,12,12,12,12,12,12,12,12, 12, 12, 16, 16, 16,
488 0, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 11, 11, 11
489 };
490 int const scale = brr_header >> 4;
491 int const right_shift = shifts [scale];
492 int const left_shift = shifts [scale + 16];
493
494 // Write to next four samples in circular buffer
495 int* pos = v->buf_pos;
496 int* end;
497
498 // Decode four samples
499 for ( end = pos + 4; pos < end; pos++, nybbles <<= 4 )
500 {
501 // Extract upper nybble and scale appropriately. Every cast is
502 // necessary to maintain correctness and avoid undef behavior
503 int s = int16_t(uint16_t((int16_t) nybbles >> right_shift) << left_shift);
504
505 // Apply IIR filter (8 is the most commonly used)
506 int const filter = brr_header & 0x0C;
507 int const p1 = pos [brr_buf_size - 1];
508 int const p2 = pos [brr_buf_size - 2] >> 1;
509 if ( filter >= 8 )
510 {
511 s += p1;
512 s -= p2;
513 if ( filter == 8 ) // s += p1 * 0.953125 - p2 * 0.46875
514 {
515 s += p2 >> 4;
516 s += (p1 * -3) >> 6;
517 }
518 else // s += p1 * 0.8984375 - p2 * 0.40625
519 {
520 s += (p1 * -13) >> 7;
521 s += (p2 * 3) >> 4;
522 }
523 }
524 else if ( filter ) // s += p1 * 0.46875
525 {
526 s += p1 >> 1;
527 s += (-p1) >> 5;
528 }
529
530 // Adjust and write sample
531 CLAMP16( s );
532 s = (int16_t) (s * 2);
533 pos [brr_buf_size] = pos [0] = s; // second copy simplifies wrap-around
534 }
535
536 if ( pos >= &v->buf [brr_buf_size] )
537 pos = v->buf;
538 v->buf_pos = pos;
539 }
540 }
541 skip_brr:
542 // Next voice
543 vbit <<= 1;
544 v_regs += 0x10;
545 v++;
546 }
547 while ( vbit < 0x100 );
548
549 // Echo position
550 int echo_offset = m.echo_offset;
551 uint8_t* const echo_ptr = &ram [(REG(esa) * 0x100 + echo_offset) & 0xFFFF];
552 if ( !echo_offset )
553 m.echo_length = (REG(edl) & 0x0F) * 0x800;
554 echo_offset += 4;
555 if ( echo_offset >= m.echo_length )
556 echo_offset = 0;
557 m.echo_offset = echo_offset;
558
559 // FIR
560 int echo_in_l = GET_LE16SA( echo_ptr + 0 );
561 int echo_in_r = GET_LE16SA( echo_ptr + 2 );
562
563 int (*echo_hist_pos) [2] = m.echo_hist_pos;
564 if ( ++echo_hist_pos >= &m.echo_hist [echo_hist_size] )
565 echo_hist_pos = m.echo_hist;
566 m.echo_hist_pos = echo_hist_pos;
567
568 echo_hist_pos [0] [0] = echo_hist_pos [8] [0] = echo_in_l;
569 echo_hist_pos [0] [1] = echo_hist_pos [8] [1] = echo_in_r;
570
571 #define CALC_FIR_( i, in ) ((in) * (int8_t) REG(fir + i * 0x10))
572 echo_in_l = CALC_FIR_( 7, echo_in_l );
573 echo_in_r = CALC_FIR_( 7, echo_in_r );
574
575 #define CALC_FIR( i, ch ) CALC_FIR_( i, echo_hist_pos [i + 1] [ch] )
576 #define DO_FIR( i )\
577 echo_in_l += CALC_FIR( i, 0 );\
578 echo_in_r += CALC_FIR( i, 1 );
579 DO_FIR( 0 );
580 DO_FIR( 1 );
581 DO_FIR( 2 );
582 #if defined (__MWERKS__) && __MWERKS__ < 0x3200
583 __eieio(); // keeps compiler from stupidly "caching" things in memory
584 #endif
585 DO_FIR( 3 );
586 DO_FIR( 4 );
587 DO_FIR( 5 );
588 DO_FIR( 6 );
589
590 // Echo out
591 if ( !(REG(flg) & 0x20) )
592 {
593 int l = (echo_out_l >> 7) + ((echo_in_l * (int8_t) REG(efb)) >> 14);
594 int r = (echo_out_r >> 7) + ((echo_in_r * (int8_t) REG(efb)) >> 14);
595
596 // just to help pass more validation tests
597 #if SPC_MORE_ACCURACY
598 l &= ~1;
599 r &= ~1;
600 #endif
601
602 CLAMP16( l );
603 CLAMP16( r );
604
605 SET_LE16A( echo_ptr + 0, l );
606 SET_LE16A( echo_ptr + 2, r );
607 }
608
609 // Sound out
610 int l = (main_out_l * mvoll + echo_in_l * (int8_t) REG(evoll)) >> 14;
611 int r = (main_out_r * mvolr + echo_in_r * (int8_t) REG(evolr)) >> 14;
612
613 CLAMP16( l );
614 CLAMP16( r );
615
616 if ( (REG(flg) & 0x40) )
617 {
618 l = 0;
619 r = 0;
620 }
621
622 sample_t* out = m.out;
623 WRITE_SAMPLES( l, r, out );
624 m.out = out;
625 }
626 while ( --count );
627 }
628
629
630 //// Setup
631
mute_voices(int mask)632 void Spc_Dsp::mute_voices( int mask )
633 {
634 m.mute_mask = mask;
635 for ( int i = 0; i < voice_count; i++ )
636 {
637 m.voices [i].enabled = (mask >> i & 1) - 1;
638 update_voice_vol( i * 0x10 );
639 }
640 }
641
init(void * ram_64k)642 void Spc_Dsp::init( void* ram_64k )
643 {
644 m.ram = (uint8_t*) ram_64k;
645 mute_voices( 0 );
646 disable_surround( false );
647 set_output( 0, 0 );
648 reset();
649
650 #ifndef NDEBUG
651 // be sure this sign-extends
652 assert( (int16_t) 0x8000 == -0x8000 );
653
654 // be sure right shift preserves sign
655 assert( (-1 >> 1) == -1 );
656
657 // check clamp macro
658 int i;
659 i = +0x8000; CLAMP16( i ); assert( i == +0x7FFF );
660 i = -0x8001; CLAMP16( i ); assert( i == -0x8000 );
661
662 blargg_verify_byte_order();
663 #endif
664 }
665
soft_reset_common()666 void Spc_Dsp::soft_reset_common()
667 {
668 require( m.ram ); // init() must have been called already
669
670 m.noise = 0x4000;
671 m.echo_hist_pos = m.echo_hist;
672 m.every_other_sample = 1;
673 m.echo_offset = 0;
674 m.phase = 0;
675
676 init_counter();
677 }
678
soft_reset()679 void Spc_Dsp::soft_reset()
680 {
681 REG(flg) = 0xE0;
682 soft_reset_common();
683 }
684
load(uint8_t const regs[register_count])685 void Spc_Dsp::load( uint8_t const regs [register_count] )
686 {
687 memcpy( m.regs, regs, sizeof m.regs );
688 memset( &m.regs [register_count], 0, offsetof (state_t,ram) - register_count );
689
690 // Internal state
691 int i;
692 for ( i = voice_count; --i >= 0; )
693 {
694 voice_t& v = m.voices [i];
695 v.brr_offset = 1;
696 v.buf_pos = v.buf;
697 }
698 m.new_kon = REG(kon);
699
700 mute_voices( m.mute_mask );
701 soft_reset_common();
702 }
703
reset()704 void Spc_Dsp::reset() { load( initial_regs ); }
705