diff snes_spc/SPC_DSP.cpp @ 0:e38dacceb958

initial import
author Robert McIntyre <rlm@mit.edu>
date Fri, 21 Oct 2011 05:53:11 -0700
parents
children
line wrap: on
line diff
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/snes_spc/SPC_DSP.cpp	Fri Oct 21 05:53:11 2011 -0700
     1.3 @@ -0,0 +1,1018 @@
     1.4 +// snes_spc 0.9.0. http://www.slack.net/~ant/
     1.5 +
     1.6 +#include "SPC_DSP.h"
     1.7 +
     1.8 +#include "blargg_endian.h"
     1.9 +#include <string.h>
    1.10 +
    1.11 +/* Copyright (C) 2007 Shay Green. This module is free software; you
    1.12 +can redistribute it and/or modify it under the terms of the GNU Lesser
    1.13 +General Public License as published by the Free Software Foundation; either
    1.14 +version 2.1 of the License, or (at your option) any later version. This
    1.15 +module is distributed in the hope that it will be useful, but WITHOUT ANY
    1.16 +WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
    1.17 +FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
    1.18 +details. You should have received a copy of the GNU Lesser General Public
    1.19 +License along with this module; if not, write to the Free Software Foundation,
    1.20 +Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
    1.21 +
    1.22 +#include "blargg_source.h"
    1.23 +
    1.24 +#ifdef BLARGG_ENABLE_OPTIMIZER
    1.25 +	#include BLARGG_ENABLE_OPTIMIZER
    1.26 +#endif
    1.27 +
    1.28 +#if INT_MAX < 0x7FFFFFFF
    1.29 +	#error "Requires that int type have at least 32 bits"
    1.30 +#endif
    1.31 +
    1.32 +// TODO: add to blargg_endian.h
    1.33 +#define GET_LE16SA( addr )      ((BOOST::int16_t) GET_LE16( addr ))
    1.34 +#define GET_LE16A( addr )       GET_LE16( addr )
    1.35 +#define SET_LE16A( addr, data ) SET_LE16( addr, data )
    1.36 +
    1.37 +static BOOST::uint8_t const initial_regs [SPC_DSP::register_count] =
    1.38 +{
    1.39 +	0x45,0x8B,0x5A,0x9A,0xE4,0x82,0x1B,0x78,0x00,0x00,0xAA,0x96,0x89,0x0E,0xE0,0x80,
    1.40 +	0x2A,0x49,0x3D,0xBA,0x14,0xA0,0xAC,0xC5,0x00,0x00,0x51,0xBB,0x9C,0x4E,0x7B,0xFF,
    1.41 +	0xF4,0xFD,0x57,0x32,0x37,0xD9,0x42,0x22,0x00,0x00,0x5B,0x3C,0x9F,0x1B,0x87,0x9A,
    1.42 +	0x6F,0x27,0xAF,0x7B,0xE5,0x68,0x0A,0xD9,0x00,0x00,0x9A,0xC5,0x9C,0x4E,0x7B,0xFF,
    1.43 +	0xEA,0x21,0x78,0x4F,0xDD,0xED,0x24,0x14,0x00,0x00,0x77,0xB1,0xD1,0x36,0xC1,0x67,
    1.44 +	0x52,0x57,0x46,0x3D,0x59,0xF4,0x87,0xA4,0x00,0x00,0x7E,0x44,0x9C,0x4E,0x7B,0xFF,
    1.45 +	0x75,0xF5,0x06,0x97,0x10,0xC3,0x24,0xBB,0x00,0x00,0x7B,0x7A,0xE0,0x60,0x12,0x0F,
    1.46 +	0xF7,0x74,0x1C,0xE5,0x39,0x3D,0x73,0xC1,0x00,0x00,0x7A,0xB3,0xFF,0x4E,0x7B,0xFF
    1.47 +};
    1.48 +
    1.49 +// if ( io < -32768 ) io = -32768;
    1.50 +// if ( io >  32767 ) io =  32767;
    1.51 +#define CLAMP16( io )\
    1.52 +{\
    1.53 +	if ( (int16_t) io != io )\
    1.54 +		io = (io >> 31) ^ 0x7FFF;\
    1.55 +}
    1.56 +
    1.57 +// Access global DSP register
    1.58 +#define REG(n)      m.regs [r_##n]
    1.59 +
    1.60 +// Access voice DSP register
    1.61 +#define VREG(r,n)   r [v_##n]
    1.62 +
    1.63 +#define WRITE_SAMPLES( l, r, out ) \
    1.64 +{\
    1.65 +	out [0] = l;\
    1.66 +	out [1] = r;\
    1.67 +	out += 2;\
    1.68 +	if ( out >= m.out_end )\
    1.69 +	{\
    1.70 +		check( out == m.out_end );\
    1.71 +		check( m.out_end != &m.extra [extra_size] || \
    1.72 +			(m.extra <= m.out_begin && m.extra < &m.extra [extra_size]) );\
    1.73 +		out       = m.extra;\
    1.74 +		m.out_end = &m.extra [extra_size];\
    1.75 +	}\
    1.76 +}\
    1.77 +
    1.78 +void SPC_DSP::set_output( sample_t* out, int size )
    1.79 +{
    1.80 +	require( (size & 1) == 0 ); // must be even
    1.81 +	if ( !out )
    1.82 +	{
    1.83 +		out  = m.extra;
    1.84 +		size = extra_size;
    1.85 +	}
    1.86 +	m.out_begin = out;
    1.87 +	m.out       = out;
    1.88 +	m.out_end   = out + size;
    1.89 +}
    1.90 +
    1.91 +// Volume registers and efb are signed! Easy to forget int8_t cast.
    1.92 +// Prefixes are to avoid accidental use of locals with same names.
    1.93 +
    1.94 +// Gaussian interpolation
    1.95 +
    1.96 +static short const gauss [512] =
    1.97 +{
    1.98 +   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
    1.99 +   1,   1,   1,   1,   1,   1,   1,   1,   1,   1,   1,   2,   2,   2,   2,   2,
   1.100 +   2,   2,   3,   3,   3,   3,   3,   4,   4,   4,   4,   4,   5,   5,   5,   5,
   1.101 +   6,   6,   6,   6,   7,   7,   7,   8,   8,   8,   9,   9,   9,  10,  10,  10,
   1.102 +  11,  11,  11,  12,  12,  13,  13,  14,  14,  15,  15,  15,  16,  16,  17,  17,
   1.103 +  18,  19,  19,  20,  20,  21,  21,  22,  23,  23,  24,  24,  25,  26,  27,  27,
   1.104 +  28,  29,  29,  30,  31,  32,  32,  33,  34,  35,  36,  36,  37,  38,  39,  40,
   1.105 +  41,  42,  43,  44,  45,  46,  47,  48,  49,  50,  51,  52,  53,  54,  55,  56,
   1.106 +  58,  59,  60,  61,  62,  64,  65,  66,  67,  69,  70,  71,  73,  74,  76,  77,
   1.107 +  78,  80,  81,  83,  84,  86,  87,  89,  90,  92,  94,  95,  97,  99, 100, 102,
   1.108 + 104, 106, 107, 109, 111, 113, 115, 117, 118, 120, 122, 124, 126, 128, 130, 132,
   1.109 + 134, 137, 139, 141, 143, 145, 147, 150, 152, 154, 156, 159, 161, 163, 166, 168,
   1.110 + 171, 173, 175, 178, 180, 183, 186, 188, 191, 193, 196, 199, 201, 204, 207, 210,
   1.111 + 212, 215, 218, 221, 224, 227, 230, 233, 236, 239, 242, 245, 248, 251, 254, 257,
   1.112 + 260, 263, 267, 270, 273, 276, 280, 283, 286, 290, 293, 297, 300, 304, 307, 311,
   1.113 + 314, 318, 321, 325, 328, 332, 336, 339, 343, 347, 351, 354, 358, 362, 366, 370,
   1.114 + 374, 378, 381, 385, 389, 393, 397, 401, 405, 410, 414, 418, 422, 426, 430, 434,
   1.115 + 439, 443, 447, 451, 456, 460, 464, 469, 473, 477, 482, 486, 491, 495, 499, 504,
   1.116 + 508, 513, 517, 522, 527, 531, 536, 540, 545, 550, 554, 559, 563, 568, 573, 577,
   1.117 + 582, 587, 592, 596, 601, 606, 611, 615, 620, 625, 630, 635, 640, 644, 649, 654,
   1.118 + 659, 664, 669, 674, 678, 683, 688, 693, 698, 703, 708, 713, 718, 723, 728, 732,
   1.119 + 737, 742, 747, 752, 757, 762, 767, 772, 777, 782, 787, 792, 797, 802, 806, 811,
   1.120 + 816, 821, 826, 831, 836, 841, 846, 851, 855, 860, 865, 870, 875, 880, 884, 889,
   1.121 + 894, 899, 904, 908, 913, 918, 923, 927, 932, 937, 941, 946, 951, 955, 960, 965,
   1.122 + 969, 974, 978, 983, 988, 992, 997,1001,1005,1010,1014,1019,1023,1027,1032,1036,
   1.123 +1040,1045,1049,1053,1057,1061,1066,1070,1074,1078,1082,1086,1090,1094,1098,1102,
   1.124 +1106,1109,1113,1117,1121,1125,1128,1132,1136,1139,1143,1146,1150,1153,1157,1160,
   1.125 +1164,1167,1170,1174,1177,1180,1183,1186,1190,1193,1196,1199,1202,1205,1207,1210,
   1.126 +1213,1216,1219,1221,1224,1227,1229,1232,1234,1237,1239,1241,1244,1246,1248,1251,
   1.127 +1253,1255,1257,1259,1261,1263,1265,1267,1269,1270,1272,1274,1275,1277,1279,1280,
   1.128 +1282,1283,1284,1286,1287,1288,1290,1291,1292,1293,1294,1295,1296,1297,1297,1298,
   1.129 +1299,1300,1300,1301,1302,1302,1303,1303,1303,1304,1304,1304,1304,1304,1305,1305,
   1.130 +};
   1.131 +
   1.132 +inline int SPC_DSP::interpolate( voice_t const* v )
   1.133 +{
   1.134 +	// Make pointers into gaussian based on fractional position between samples
   1.135 +	int offset = v->interp_pos >> 4 & 0xFF;
   1.136 +	short const* fwd = gauss + 255 - offset;
   1.137 +	short const* rev = gauss       + offset; // mirror left half of gaussian
   1.138 +	
   1.139 +	int const* in = &v->buf [(v->interp_pos >> 12) + v->buf_pos];
   1.140 +	int out;
   1.141 +	out  = (fwd [  0] * in [0]) >> 11;
   1.142 +	out += (fwd [256] * in [1]) >> 11;
   1.143 +	out += (rev [256] * in [2]) >> 11;
   1.144 +	out = (int16_t) out;
   1.145 +	out += (rev [  0] * in [3]) >> 11;
   1.146 +	
   1.147 +	CLAMP16( out );
   1.148 +	out &= ~1;
   1.149 +	return out;
   1.150 +}
   1.151 +
   1.152 +
   1.153 +//// Counters
   1.154 +
   1.155 +int const simple_counter_range = 2048 * 5 * 3; // 30720
   1.156 +
   1.157 +static unsigned const counter_rates [32] =
   1.158 +{
   1.159 +   simple_counter_range + 1, // never fires
   1.160 +          2048, 1536,
   1.161 +	1280, 1024,  768,
   1.162 +	 640,  512,  384,
   1.163 +	 320,  256,  192,
   1.164 +	 160,  128,   96,
   1.165 +	  80,   64,   48,
   1.166 +	  40,   32,   24,
   1.167 +	  20,   16,   12,
   1.168 +	  10,    8,    6,
   1.169 +	   5,    4,    3,
   1.170 +	         2,
   1.171 +	         1
   1.172 +};
   1.173 +
   1.174 +static unsigned const counter_offsets [32] =
   1.175 +{
   1.176 +	  1, 0, 1040,
   1.177 +	536, 0, 1040,
   1.178 +	536, 0, 1040,
   1.179 +	536, 0, 1040,
   1.180 +	536, 0, 1040,
   1.181 +	536, 0, 1040,
   1.182 +	536, 0, 1040,
   1.183 +	536, 0, 1040,
   1.184 +	536, 0, 1040,
   1.185 +	536, 0, 1040,
   1.186 +	     0,
   1.187 +	     0
   1.188 +};
   1.189 +
   1.190 +inline void SPC_DSP::init_counter()
   1.191 +{
   1.192 +	m.counter = 0;
   1.193 +}
   1.194 +
   1.195 +inline void SPC_DSP::run_counters()
   1.196 +{
   1.197 +	if ( --m.counter < 0 )
   1.198 +		m.counter = simple_counter_range - 1;
   1.199 +}
   1.200 +
   1.201 +inline unsigned SPC_DSP::read_counter( int rate )
   1.202 +{
   1.203 +	return ((unsigned) m.counter + counter_offsets [rate]) % counter_rates [rate];
   1.204 +}
   1.205 +
   1.206 +
   1.207 +//// Envelope
   1.208 +
   1.209 +inline void SPC_DSP::run_envelope( voice_t* const v )
   1.210 +{
   1.211 +	int env = v->env;
   1.212 +	if ( v->env_mode == env_release ) // 60%
   1.213 +	{
   1.214 +		if ( (env -= 0x8) < 0 )
   1.215 +			env = 0;
   1.216 +		v->env = env;
   1.217 +	}
   1.218 +	else
   1.219 +	{
   1.220 +		int rate;
   1.221 +		int env_data = VREG(v->regs,adsr1);
   1.222 +		if ( m.t_adsr0 & 0x80 ) // 99% ADSR
   1.223 +		{
   1.224 +			if ( v->env_mode >= env_decay ) // 99%
   1.225 +			{
   1.226 +				env--;
   1.227 +				env -= env >> 8;
   1.228 +				rate = env_data & 0x1F;
   1.229 +				if ( v->env_mode == env_decay ) // 1%
   1.230 +					rate = (m.t_adsr0 >> 3 & 0x0E) + 0x10;
   1.231 +			}
   1.232 +			else // env_attack
   1.233 +			{
   1.234 +				rate = (m.t_adsr0 & 0x0F) * 2 + 1;
   1.235 +				env += rate < 31 ? 0x20 : 0x400;
   1.236 +			}
   1.237 +		}
   1.238 +		else // GAIN
   1.239 +		{
   1.240 +			int mode;
   1.241 +			env_data = VREG(v->regs,gain);
   1.242 +			mode = env_data >> 5;
   1.243 +			if ( mode < 4 ) // direct
   1.244 +			{
   1.245 +				env = env_data * 0x10;
   1.246 +				rate = 31;
   1.247 +			}
   1.248 +			else
   1.249 +			{
   1.250 +				rate = env_data & 0x1F;
   1.251 +				if ( mode == 4 ) // 4: linear decrease
   1.252 +				{
   1.253 +					env -= 0x20;
   1.254 +				}
   1.255 +				else if ( mode < 6 ) // 5: exponential decrease
   1.256 +				{
   1.257 +					env--;
   1.258 +					env -= env >> 8;
   1.259 +				}
   1.260 +				else // 6,7: linear increase
   1.261 +				{
   1.262 +					env += 0x20;
   1.263 +					if ( mode > 6 && (unsigned) v->hidden_env >= 0x600 )
   1.264 +						env += 0x8 - 0x20; // 7: two-slope linear increase
   1.265 +				}
   1.266 +			}
   1.267 +		}
   1.268 +		
   1.269 +		// Sustain level
   1.270 +		if ( (env >> 8) == (env_data >> 5) && v->env_mode == env_decay )
   1.271 +			v->env_mode = env_sustain;
   1.272 +		
   1.273 +		v->hidden_env = env;
   1.274 +		
   1.275 +		// unsigned cast because linear decrease going negative also triggers this
   1.276 +		if ( (unsigned) env > 0x7FF )
   1.277 +		{
   1.278 +			env = (env < 0 ? 0 : 0x7FF);
   1.279 +			if ( v->env_mode == env_attack )
   1.280 +				v->env_mode = env_decay;
   1.281 +		}
   1.282 +		
   1.283 +		if ( !read_counter( rate ) )
   1.284 +			v->env = env; // nothing else is controlled by the counter
   1.285 +	}
   1.286 +}
   1.287 +
   1.288 +
   1.289 +//// BRR Decoding
   1.290 +
   1.291 +inline void SPC_DSP::decode_brr( voice_t* v )
   1.292 +{
   1.293 +	// Arrange the four input nybbles in 0xABCD order for easy decoding
   1.294 +	int nybbles = m.t_brr_byte * 0x100 + m.ram [(v->brr_addr + v->brr_offset + 1) & 0xFFFF];
   1.295 +	
   1.296 +	int const header = m.t_brr_header;
   1.297 +	
   1.298 +	// Write to next four samples in circular buffer
   1.299 +	int* pos = &v->buf [v->buf_pos];
   1.300 +	int* end;
   1.301 +	if ( (v->buf_pos += 4) >= brr_buf_size )
   1.302 +		v->buf_pos = 0;
   1.303 +	
   1.304 +	// Decode four samples
   1.305 +	for ( end = pos + 4; pos < end; pos++, nybbles <<= 4 )
   1.306 +	{
   1.307 +		// Extract nybble and sign-extend
   1.308 +		int s = (int16_t) nybbles >> 12;
   1.309 +		
   1.310 +		// Shift sample based on header
   1.311 +		int const shift = header >> 4;
   1.312 +		s = (s << shift) >> 1;
   1.313 +		if ( shift >= 0xD ) // handle invalid range
   1.314 +			s = (s >> 25) << 11; // same as: s = (s < 0 ? -0x800 : 0)
   1.315 +		
   1.316 +		// Apply IIR filter (8 is the most commonly used)
   1.317 +		int const filter = header & 0x0C;
   1.318 +		int const p1 = pos [brr_buf_size - 1];
   1.319 +		int const p2 = pos [brr_buf_size - 2] >> 1;
   1.320 +		if ( filter >= 8 )
   1.321 +		{
   1.322 +			s += p1;
   1.323 +			s -= p2;
   1.324 +			if ( filter == 8 ) // s += p1 * 0.953125 - p2 * 0.46875
   1.325 +			{
   1.326 +				s += p2 >> 4;
   1.327 +				s += (p1 * -3) >> 6;
   1.328 +			}
   1.329 +			else // s += p1 * 0.8984375 - p2 * 0.40625
   1.330 +			{
   1.331 +				s += (p1 * -13) >> 7;
   1.332 +				s += (p2 * 3) >> 4;
   1.333 +			}
   1.334 +		}
   1.335 +		else if ( filter ) // s += p1 * 0.46875
   1.336 +		{
   1.337 +			s += p1 >> 1;
   1.338 +			s += (-p1) >> 5;
   1.339 +		}
   1.340 +		
   1.341 +		// Adjust and write sample
   1.342 +		CLAMP16( s );
   1.343 +		s = (int16_t) (s * 2);
   1.344 +		pos [brr_buf_size] = pos [0] = s; // second copy simplifies wrap-around
   1.345 +	}
   1.346 +}
   1.347 +
   1.348 +
   1.349 +//// Misc
   1.350 +
   1.351 +#define MISC_CLOCK( n ) inline void SPC_DSP::misc_##n()
   1.352 +
   1.353 +MISC_CLOCK( 27 )
   1.354 +{
   1.355 +	m.t_pmon = REG(pmon) & 0xFE; // voice 0 doesn't support PMON
   1.356 +}
   1.357 +MISC_CLOCK( 28 )
   1.358 +{
   1.359 +	m.t_non = REG(non);
   1.360 +	m.t_eon = REG(eon);
   1.361 +	m.t_dir = REG(dir);
   1.362 +}
   1.363 +MISC_CLOCK( 29 )
   1.364 +{
   1.365 +	if ( (m.every_other_sample ^= 1) != 0 )
   1.366 +		m.new_kon &= ~m.kon; // clears KON 63 clocks after it was last read
   1.367 +}
   1.368 +MISC_CLOCK( 30 )
   1.369 +{
   1.370 +	if ( m.every_other_sample )
   1.371 +	{
   1.372 +		m.kon    = m.new_kon;
   1.373 +		m.t_koff = REG(koff) | m.mute_mask; 
   1.374 +	}
   1.375 +	
   1.376 +	run_counters();
   1.377 +	
   1.378 +	// Noise
   1.379 +	if ( !read_counter( REG(flg) & 0x1F ) )
   1.380 +	{
   1.381 +		int feedback = (m.noise << 13) ^ (m.noise << 14);
   1.382 +		m.noise = (feedback & 0x4000) ^ (m.noise >> 1);
   1.383 +	}
   1.384 +}
   1.385 +
   1.386 +
   1.387 +//// Voices
   1.388 +
   1.389 +#define VOICE_CLOCK( n ) void SPC_DSP::voice_##n( voice_t* const v )
   1.390 +
   1.391 +inline VOICE_CLOCK( V1 )
   1.392 +{
   1.393 +	m.t_dir_addr = m.t_dir * 0x100 + m.t_srcn * 4;
   1.394 +	m.t_srcn = VREG(v->regs,srcn);
   1.395 +}
   1.396 +inline VOICE_CLOCK( V2 )
   1.397 +{
   1.398 +	// Read sample pointer (ignored if not needed)
   1.399 +	uint8_t const* entry = &m.ram [m.t_dir_addr];
   1.400 +	if ( !v->kon_delay )
   1.401 +		entry += 2;
   1.402 +	m.t_brr_next_addr = GET_LE16A( entry );
   1.403 +	
   1.404 +	m.t_adsr0 = VREG(v->regs,adsr0);
   1.405 +	
   1.406 +	// Read pitch, spread over two clocks
   1.407 +	m.t_pitch = VREG(v->regs,pitchl);
   1.408 +}
   1.409 +inline VOICE_CLOCK( V3a )
   1.410 +{
   1.411 +	m.t_pitch += (VREG(v->regs,pitchh) & 0x3F) << 8;
   1.412 +}
   1.413 +inline VOICE_CLOCK( V3b )
   1.414 +{
   1.415 +	// Read BRR header and byte
   1.416 +	m.t_brr_byte   = m.ram [(v->brr_addr + v->brr_offset) & 0xFFFF];
   1.417 +	m.t_brr_header = m.ram [v->brr_addr]; // brr_addr doesn't need masking
   1.418 +}
   1.419 +VOICE_CLOCK( V3c )
   1.420 +{
   1.421 +	// Pitch modulation using previous voice's output
   1.422 +	if ( m.t_pmon & v->vbit )
   1.423 +		m.t_pitch += ((m.t_output >> 5) * m.t_pitch) >> 10;
   1.424 +	
   1.425 +	if ( v->kon_delay )
   1.426 +	{
   1.427 +		// Get ready to start BRR decoding on next sample
   1.428 +		if ( v->kon_delay == 5 )
   1.429 +		{
   1.430 +			v->brr_addr    = m.t_brr_next_addr;
   1.431 +			v->brr_offset  = 1;
   1.432 +			v->buf_pos     = 0;
   1.433 +			m.t_brr_header = 0; // header is ignored on this sample
   1.434 +			m.kon_check    = true;
   1.435 +		}
   1.436 +		
   1.437 +		// Envelope is never run during KON
   1.438 +		v->env        = 0;
   1.439 +		v->hidden_env = 0;
   1.440 +		
   1.441 +		// Disable BRR decoding until last three samples
   1.442 +		v->interp_pos = 0;
   1.443 +		if ( --v->kon_delay & 3 )
   1.444 +			v->interp_pos = 0x4000;
   1.445 +		
   1.446 +		// Pitch is never added during KON
   1.447 +		m.t_pitch = 0;
   1.448 +	}
   1.449 +	
   1.450 +	// Gaussian interpolation
   1.451 +	{
   1.452 +		int output = interpolate( v );
   1.453 +		
   1.454 +		// Noise
   1.455 +		if ( m.t_non & v->vbit )
   1.456 +			output = (int16_t) (m.noise * 2);
   1.457 +		
   1.458 +		// Apply envelope
   1.459 +		m.t_output = (output * v->env) >> 11 & ~1;
   1.460 +		v->t_envx_out = (uint8_t) (v->env >> 4);
   1.461 +	}
   1.462 +	
   1.463 +	// Immediate silence due to end of sample or soft reset
   1.464 +	if ( REG(flg) & 0x80 || (m.t_brr_header & 3) == 1 )
   1.465 +	{
   1.466 +		v->env_mode = env_release;
   1.467 +		v->env      = 0;
   1.468 +	}
   1.469 +	
   1.470 +	if ( m.every_other_sample )
   1.471 +	{
   1.472 +		// KOFF
   1.473 +		if ( m.t_koff & v->vbit )
   1.474 +			v->env_mode = env_release;
   1.475 +		
   1.476 +		// KON
   1.477 +		if ( m.kon & v->vbit )
   1.478 +		{
   1.479 +			v->kon_delay = 5;
   1.480 +			v->env_mode  = env_attack;
   1.481 +		}
   1.482 +	}
   1.483 +	
   1.484 +	// Run envelope for next sample
   1.485 +	if ( !v->kon_delay )
   1.486 +		run_envelope( v );
   1.487 +}
   1.488 +inline void SPC_DSP::voice_output( voice_t const* v, int ch )
   1.489 +{
   1.490 +	// Apply left/right volume
   1.491 +	int amp = (m.t_output * (int8_t) VREG(v->regs,voll + ch)) >> 7;
   1.492 +	
   1.493 +	// Add to output total
   1.494 +	m.t_main_out [ch] += amp;
   1.495 +	CLAMP16( m.t_main_out [ch] );
   1.496 +	
   1.497 +	// Optionally add to echo total
   1.498 +	if ( m.t_eon & v->vbit )
   1.499 +	{
   1.500 +		m.t_echo_out [ch] += amp;
   1.501 +		CLAMP16( m.t_echo_out [ch] );
   1.502 +	}
   1.503 +}
   1.504 +VOICE_CLOCK( V4 )
   1.505 +{
   1.506 +	// Decode BRR
   1.507 +	m.t_looped = 0;
   1.508 +	if ( v->interp_pos >= 0x4000 )
   1.509 +	{
   1.510 +		decode_brr( v );
   1.511 +		
   1.512 +		if ( (v->brr_offset += 2) >= brr_block_size )
   1.513 +		{
   1.514 +			// Start decoding next BRR block
   1.515 +			assert( v->brr_offset == brr_block_size );
   1.516 +			v->brr_addr = (v->brr_addr + brr_block_size) & 0xFFFF;
   1.517 +			if ( m.t_brr_header & 1 )
   1.518 +			{
   1.519 +				v->brr_addr = m.t_brr_next_addr;
   1.520 +				m.t_looped = v->vbit;
   1.521 +			}
   1.522 +			v->brr_offset = 1;
   1.523 +		}
   1.524 +	}
   1.525 +	
   1.526 +	// Apply pitch
   1.527 +	v->interp_pos = (v->interp_pos & 0x3FFF) + m.t_pitch;
   1.528 +	
   1.529 +	// Keep from getting too far ahead (when using pitch modulation)
   1.530 +	if ( v->interp_pos > 0x7FFF )
   1.531 +		v->interp_pos = 0x7FFF;
   1.532 +	
   1.533 +	// Output left
   1.534 +	voice_output( v, 0 );
   1.535 +}
   1.536 +inline VOICE_CLOCK( V5 )
   1.537 +{
   1.538 +	// Output right
   1.539 +	voice_output( v, 1 );
   1.540 +	
   1.541 +	// ENDX, OUTX, and ENVX won't update if you wrote to them 1-2 clocks earlier
   1.542 +	int endx_buf = REG(endx) | m.t_looped;
   1.543 +	
   1.544 +	// Clear bit in ENDX if KON just began
   1.545 +	if ( v->kon_delay == 5 )
   1.546 +		endx_buf &= ~v->vbit;
   1.547 +	m.endx_buf = (uint8_t) endx_buf;
   1.548 +}
   1.549 +inline VOICE_CLOCK( V6 )
   1.550 +{
   1.551 +	(void) v; // avoid compiler warning about unused v
   1.552 +	m.outx_buf = (uint8_t) (m.t_output >> 8);
   1.553 +}
   1.554 +inline VOICE_CLOCK( V7 )
   1.555 +{
   1.556 +	// Update ENDX
   1.557 +	REG(endx) = m.endx_buf;
   1.558 +	
   1.559 +	m.envx_buf = v->t_envx_out;
   1.560 +}
   1.561 +inline VOICE_CLOCK( V8 )
   1.562 +{
   1.563 +	// Update OUTX
   1.564 +	VREG(v->regs,outx) = m.outx_buf;
   1.565 +}
   1.566 +inline VOICE_CLOCK( V9 )
   1.567 +{
   1.568 +	// Update ENVX
   1.569 +	VREG(v->regs,envx) = m.envx_buf;
   1.570 +}
   1.571 +
   1.572 +// Most voices do all these in one clock, so make a handy composite
   1.573 +inline VOICE_CLOCK( V3 )
   1.574 +{
   1.575 +	voice_V3a( v );
   1.576 +	voice_V3b( v );
   1.577 +	voice_V3c( v );
   1.578 +}
   1.579 +
   1.580 +// Common combinations of voice steps on different voices. This greatly reduces
   1.581 +// code size and allows everything to be inlined in these functions.
   1.582 +VOICE_CLOCK(V7_V4_V1) { voice_V7(v); voice_V1(v+3); voice_V4(v+1); }
   1.583 +VOICE_CLOCK(V8_V5_V2) { voice_V8(v); voice_V5(v+1); voice_V2(v+2); }
   1.584 +VOICE_CLOCK(V9_V6_V3) { voice_V9(v); voice_V6(v+1); voice_V3(v+2); }
   1.585 +
   1.586 +
   1.587 +//// Echo
   1.588 +
   1.589 +// Current echo buffer pointer for left/right channel
   1.590 +#define ECHO_PTR( ch )      (&m.ram [m.t_echo_ptr + ch * 2])
   1.591 +
   1.592 +// Sample in echo history buffer, where 0 is the oldest
   1.593 +#define ECHO_FIR( i )       (m.echo_hist_pos [i])
   1.594 +
   1.595 +// Calculate FIR point for left/right channel
   1.596 +#define CALC_FIR( i, ch )   ((ECHO_FIR( i + 1 ) [ch] * (int8_t) REG(fir + i * 0x10)) >> 6)
   1.597 +
   1.598 +#define ECHO_CLOCK( n ) inline void SPC_DSP::echo_##n()
   1.599 +
   1.600 +inline void SPC_DSP::echo_read( int ch )
   1.601 +{
   1.602 +	int s = GET_LE16SA( ECHO_PTR( ch ) );
   1.603 +	// second copy simplifies wrap-around handling
   1.604 +	ECHO_FIR( 0 ) [ch] = ECHO_FIR( 8 ) [ch] = s >> 1;
   1.605 +}
   1.606 +
   1.607 +ECHO_CLOCK( 22 )
   1.608 +{
   1.609 +	// History
   1.610 +	if ( ++m.echo_hist_pos >= &m.echo_hist [echo_hist_size] )
   1.611 +		m.echo_hist_pos = m.echo_hist;
   1.612 +	
   1.613 +	m.t_echo_ptr = (m.t_esa * 0x100 + m.echo_offset) & 0xFFFF;
   1.614 +	echo_read( 0 );
   1.615 +	
   1.616 +	// FIR (using l and r temporaries below helps compiler optimize)
   1.617 +	int l = CALC_FIR( 0, 0 );
   1.618 +	int r = CALC_FIR( 0, 1 );
   1.619 +	
   1.620 +	m.t_echo_in [0] = l;
   1.621 +	m.t_echo_in [1] = r;
   1.622 +}
   1.623 +ECHO_CLOCK( 23 )
   1.624 +{
   1.625 +	int l = CALC_FIR( 1, 0 ) + CALC_FIR( 2, 0 );
   1.626 +	int r = CALC_FIR( 1, 1 ) + CALC_FIR( 2, 1 );
   1.627 +	
   1.628 +	m.t_echo_in [0] += l;
   1.629 +	m.t_echo_in [1] += r;
   1.630 +	
   1.631 +	echo_read( 1 );
   1.632 +}
   1.633 +ECHO_CLOCK( 24 )
   1.634 +{
   1.635 +	int l = CALC_FIR( 3, 0 ) + CALC_FIR( 4, 0 ) + CALC_FIR( 5, 0 );
   1.636 +	int r = CALC_FIR( 3, 1 ) + CALC_FIR( 4, 1 ) + CALC_FIR( 5, 1 );
   1.637 +	
   1.638 +	m.t_echo_in [0] += l;
   1.639 +	m.t_echo_in [1] += r;
   1.640 +}
   1.641 +ECHO_CLOCK( 25 )
   1.642 +{
   1.643 +	int l = m.t_echo_in [0] + CALC_FIR( 6, 0 );
   1.644 +	int r = m.t_echo_in [1] + CALC_FIR( 6, 1 );
   1.645 +	
   1.646 +	l = (int16_t) l;
   1.647 +	r = (int16_t) r;
   1.648 +	
   1.649 +	l += (int16_t) CALC_FIR( 7, 0 );
   1.650 +	r += (int16_t) CALC_FIR( 7, 1 );
   1.651 +	
   1.652 +	CLAMP16( l );
   1.653 +	CLAMP16( r );
   1.654 +	
   1.655 +	m.t_echo_in [0] = l & ~1;
   1.656 +	m.t_echo_in [1] = r & ~1;
   1.657 +}
   1.658 +inline int SPC_DSP::echo_output( int ch )
   1.659 +{
   1.660 +	int out = (int16_t) ((m.t_main_out [ch] * (int8_t) REG(mvoll + ch * 0x10)) >> 7) +
   1.661 +			(int16_t) ((m.t_echo_in [ch] * (int8_t) REG(evoll + ch * 0x10)) >> 7);
   1.662 +	CLAMP16( out );
   1.663 +	return out;
   1.664 +}
   1.665 +ECHO_CLOCK( 26 )
   1.666 +{
   1.667 +	// Left output volumes
   1.668 +	// (save sample for next clock so we can output both together)
   1.669 +	m.t_main_out [0] = echo_output( 0 );
   1.670 +	
   1.671 +	// Echo feedback
   1.672 +	int l = m.t_echo_out [0] + (int16_t) ((m.t_echo_in [0] * (int8_t) REG(efb)) >> 7);
   1.673 +	int r = m.t_echo_out [1] + (int16_t) ((m.t_echo_in [1] * (int8_t) REG(efb)) >> 7);
   1.674 +	
   1.675 +	CLAMP16( l );
   1.676 +	CLAMP16( r );
   1.677 +	
   1.678 +	m.t_echo_out [0] = l & ~1;
   1.679 +	m.t_echo_out [1] = r & ~1;
   1.680 +}
   1.681 +ECHO_CLOCK( 27 )
   1.682 +{
   1.683 +	// Output
   1.684 +	int l = m.t_main_out [0];
   1.685 +	int r = echo_output( 1 );
   1.686 +	m.t_main_out [0] = 0;
   1.687 +	m.t_main_out [1] = 0;
   1.688 +	
   1.689 +	// TODO: global muting isn't this simple (turns DAC on and off
   1.690 +	// or something, causing small ~37-sample pulse when first muted)
   1.691 +	if ( REG(flg) & 0x40 )
   1.692 +	{
   1.693 +		l = 0;
   1.694 +		r = 0;
   1.695 +	}
   1.696 +	
   1.697 +	// Output sample to DAC
   1.698 +	#ifdef SPC_DSP_OUT_HOOK
   1.699 +		SPC_DSP_OUT_HOOK( l, r );
   1.700 +	#else
   1.701 +		sample_t* out = m.out;
   1.702 +		WRITE_SAMPLES( l, r, out );
   1.703 +		m.out = out;
   1.704 +	#endif
   1.705 +}
   1.706 +ECHO_CLOCK( 28 )
   1.707 +{
   1.708 +	m.t_echo_enabled = REG(flg);
   1.709 +}
   1.710 +inline void SPC_DSP::echo_write( int ch )
   1.711 +{
   1.712 +	if ( !(m.t_echo_enabled & 0x20) )
   1.713 +		SET_LE16A( ECHO_PTR( ch ), m.t_echo_out [ch] );
   1.714 +	m.t_echo_out [ch] = 0;
   1.715 +}
   1.716 +ECHO_CLOCK( 29 )
   1.717 +{
   1.718 +	m.t_esa = REG(esa);
   1.719 +	
   1.720 +	if ( !m.echo_offset )
   1.721 +		m.echo_length = (REG(edl) & 0x0F) * 0x800;
   1.722 +	
   1.723 +	m.echo_offset += 4;
   1.724 +	if ( m.echo_offset >= m.echo_length )
   1.725 +		m.echo_offset = 0;
   1.726 +	
   1.727 +	// Write left echo
   1.728 +	echo_write( 0 );
   1.729 +	
   1.730 +	m.t_echo_enabled = REG(flg);
   1.731 +}
   1.732 +ECHO_CLOCK( 30 )
   1.733 +{
   1.734 +	// Write right echo
   1.735 +	echo_write( 1 );
   1.736 +}
   1.737 +
   1.738 +
   1.739 +//// Timing
   1.740 +
   1.741 +// Execute clock for a particular voice
   1.742 +#define V( clock, voice )   voice_##clock( &m.voices [voice] );
   1.743 +
   1.744 +/* The most common sequence of clocks uses composite operations
   1.745 +for efficiency. For example, the following are equivalent to the
   1.746 +individual steps on the right:
   1.747 +
   1.748 +V(V7_V4_V1,2) -> V(V7,2) V(V4,3) V(V1,5)
   1.749 +V(V8_V5_V2,2) -> V(V8,2) V(V5,3) V(V2,4)
   1.750 +V(V9_V6_V3,2) -> V(V9,2) V(V6,3) V(V3,4) */
   1.751 +
   1.752 +// Voice      0      1      2      3      4      5      6      7
   1.753 +#define GEN_DSP_TIMING \
   1.754 +PHASE( 0)  V(V5,0)V(V2,1)\
   1.755 +PHASE( 1)  V(V6,0)V(V3,1)\
   1.756 +PHASE( 2)  V(V7_V4_V1,0)\
   1.757 +PHASE( 3)  V(V8_V5_V2,0)\
   1.758 +PHASE( 4)  V(V9_V6_V3,0)\
   1.759 +PHASE( 5)         V(V7_V4_V1,1)\
   1.760 +PHASE( 6)         V(V8_V5_V2,1)\
   1.761 +PHASE( 7)         V(V9_V6_V3,1)\
   1.762 +PHASE( 8)                V(V7_V4_V1,2)\
   1.763 +PHASE( 9)                V(V8_V5_V2,2)\
   1.764 +PHASE(10)                V(V9_V6_V3,2)\
   1.765 +PHASE(11)                       V(V7_V4_V1,3)\
   1.766 +PHASE(12)                       V(V8_V5_V2,3)\
   1.767 +PHASE(13)                       V(V9_V6_V3,3)\
   1.768 +PHASE(14)                              V(V7_V4_V1,4)\
   1.769 +PHASE(15)                              V(V8_V5_V2,4)\
   1.770 +PHASE(16)                              V(V9_V6_V3,4)\
   1.771 +PHASE(17)  V(V1,0)                            V(V7,5)V(V4,6)\
   1.772 +PHASE(18)                                     V(V8_V5_V2,5)\
   1.773 +PHASE(19)                                     V(V9_V6_V3,5)\
   1.774 +PHASE(20)         V(V1,1)                            V(V7,6)V(V4,7)\
   1.775 +PHASE(21)                                            V(V8,6)V(V5,7)  V(V2,0)  /* t_brr_next_addr order dependency */\
   1.776 +PHASE(22)  V(V3a,0)                                  V(V9,6)V(V6,7)  echo_22();\
   1.777 +PHASE(23)                                                   V(V7,7)  echo_23();\
   1.778 +PHASE(24)                                                   V(V8,7)  echo_24();\
   1.779 +PHASE(25)  V(V3b,0)                                         V(V9,7)  echo_25();\
   1.780 +PHASE(26)                                                            echo_26();\
   1.781 +PHASE(27) misc_27();                                                 echo_27();\
   1.782 +PHASE(28) misc_28();                                                 echo_28();\
   1.783 +PHASE(29) misc_29();                                                 echo_29();\
   1.784 +PHASE(30) misc_30();V(V3c,0)                                         echo_30();\
   1.785 +PHASE(31)  V(V4,0)       V(V1,2)\
   1.786 +
   1.787 +#if !SPC_DSP_CUSTOM_RUN
   1.788 +
   1.789 +void SPC_DSP::run( int clocks_remain )
   1.790 +{
   1.791 +	require( clocks_remain > 0 );
   1.792 +	
   1.793 +	int const phase = m.phase;
   1.794 +	m.phase = (phase + clocks_remain) & 31;
   1.795 +	switch ( phase )
   1.796 +	{
   1.797 +	loop:
   1.798 +	
   1.799 +		#define PHASE( n ) if ( n && !--clocks_remain ) break; case n:
   1.800 +		GEN_DSP_TIMING
   1.801 +		#undef PHASE
   1.802 +	
   1.803 +		if ( --clocks_remain )
   1.804 +			goto loop;
   1.805 +	}
   1.806 +}
   1.807 +
   1.808 +#endif
   1.809 +
   1.810 +
   1.811 +//// Setup
   1.812 +
   1.813 +void SPC_DSP::init( void* ram_64k )
   1.814 +{
   1.815 +	m.ram = (uint8_t*) ram_64k;
   1.816 +	mute_voices( 0 );
   1.817 +	disable_surround( false );
   1.818 +	set_output( 0, 0 );
   1.819 +	reset();
   1.820 +	
   1.821 +	#ifndef NDEBUG
   1.822 +		// be sure this sign-extends
   1.823 +		assert( (int16_t) 0x8000 == -0x8000 );
   1.824 +		
   1.825 +		// be sure right shift preserves sign
   1.826 +		assert( (-1 >> 1) == -1 );
   1.827 +		
   1.828 +		// check clamp macro
   1.829 +		int i;
   1.830 +		i = +0x8000; CLAMP16( i ); assert( i == +0x7FFF );
   1.831 +		i = -0x8001; CLAMP16( i ); assert( i == -0x8000 );
   1.832 +		
   1.833 +		blargg_verify_byte_order();
   1.834 +	#endif
   1.835 +}
   1.836 +
   1.837 +void SPC_DSP::soft_reset_common()
   1.838 +{
   1.839 +	require( m.ram ); // init() must have been called already
   1.840 +	
   1.841 +	m.noise              = 0x4000;
   1.842 +	m.echo_hist_pos      = m.echo_hist;
   1.843 +	m.every_other_sample = 1;
   1.844 +	m.echo_offset        = 0;
   1.845 +	m.phase              = 0;
   1.846 +	
   1.847 +	init_counter();
   1.848 +}
   1.849 +
   1.850 +void SPC_DSP::soft_reset()
   1.851 +{
   1.852 +	REG(flg) = 0xE0;
   1.853 +	soft_reset_common();
   1.854 +}
   1.855 +
   1.856 +void SPC_DSP::load( uint8_t const regs [register_count] )
   1.857 +{
   1.858 +	memcpy( m.regs, regs, sizeof m.regs );
   1.859 +	memset( &m.regs [register_count], 0, offsetof (state_t,ram) - register_count );
   1.860 +	
   1.861 +	// Internal state
   1.862 +	for ( int i = voice_count; --i >= 0; )
   1.863 +	{
   1.864 +		voice_t* v = &m.voices [i];
   1.865 +		v->brr_offset = 1;
   1.866 +		v->vbit       = 1 << i;
   1.867 +		v->regs       = &m.regs [i * 0x10];
   1.868 +	}
   1.869 +	m.new_kon = REG(kon);
   1.870 +	m.t_dir   = REG(dir);
   1.871 +	m.t_esa   = REG(esa);
   1.872 +	
   1.873 +	soft_reset_common();
   1.874 +}
   1.875 +
   1.876 +void SPC_DSP::reset() { load( initial_regs ); }
   1.877 +
   1.878 +
   1.879 +//// State save/load
   1.880 +
   1.881 +#if !SPC_NO_COPY_STATE_FUNCS
   1.882 +
   1.883 +void SPC_State_Copier::copy( void* state, size_t size )
   1.884 +{
   1.885 +	func( buf, state, size );
   1.886 +}
   1.887 +
   1.888 +int SPC_State_Copier::copy_int( int state, int size )
   1.889 +{
   1.890 +	BOOST::uint8_t s [2];
   1.891 +	SET_LE16( s, state );
   1.892 +	func( buf, &s, size );
   1.893 +	return GET_LE16( s );
   1.894 +}
   1.895 +
   1.896 +void SPC_State_Copier::skip( int count )
   1.897 +{
   1.898 +	if ( count > 0 )
   1.899 +	{
   1.900 +		char temp [64];
   1.901 +		memset( temp, 0, sizeof temp );
   1.902 +		do
   1.903 +		{
   1.904 +			int n = sizeof temp;
   1.905 +			if ( n > count )
   1.906 +				n = count;
   1.907 +			count -= n;
   1.908 +			func( buf, temp, n );
   1.909 +		}
   1.910 +		while ( count );
   1.911 +	}
   1.912 +}
   1.913 +
   1.914 +void SPC_State_Copier::extra()
   1.915 +{
   1.916 +	int n = 0;
   1.917 +	SPC_State_Copier& copier = *this;
   1.918 +	SPC_COPY( uint8_t, n );
   1.919 +	skip( n );
   1.920 +}
   1.921 +
   1.922 +void SPC_DSP::copy_state( unsigned char** io, copy_func_t copy )
   1.923 +{
   1.924 +	SPC_State_Copier copier( io, copy );
   1.925 +	
   1.926 +	// DSP registers
   1.927 +	copier.copy( m.regs, register_count );
   1.928 +	
   1.929 +	// Internal state
   1.930 +	
   1.931 +	// Voices
   1.932 +	int i;
   1.933 +	for ( i = 0; i < voice_count; i++ )
   1.934 +	{
   1.935 +		voice_t* v = &m.voices [i];
   1.936 +		
   1.937 +		// BRR buffer
   1.938 +		int i;
   1.939 +		for ( i = 0; i < brr_buf_size; i++ )
   1.940 +		{
   1.941 +			int s = v->buf [i];
   1.942 +			SPC_COPY(  int16_t, s );
   1.943 +			v->buf [i] = v->buf [i + brr_buf_size] = s;
   1.944 +		}
   1.945 +		
   1.946 +		SPC_COPY( uint16_t, v->interp_pos );
   1.947 +		SPC_COPY( uint16_t, v->brr_addr );
   1.948 +		SPC_COPY( uint16_t, v->env );
   1.949 +		SPC_COPY(  int16_t, v->hidden_env );
   1.950 +		SPC_COPY(  uint8_t, v->buf_pos );
   1.951 +		SPC_COPY(  uint8_t, v->brr_offset );
   1.952 +		SPC_COPY(  uint8_t, v->kon_delay );
   1.953 +		{
   1.954 +			int m = v->env_mode;
   1.955 +			SPC_COPY(  uint8_t, m );
   1.956 +			v->env_mode = (enum env_mode_t) m;
   1.957 +		}
   1.958 +		SPC_COPY(  uint8_t, v->t_envx_out );
   1.959 +		
   1.960 +		copier.extra();
   1.961 +	}
   1.962 +	
   1.963 +	// Echo history
   1.964 +	for ( i = 0; i < echo_hist_size; i++ )
   1.965 +	{
   1.966 +		int j;
   1.967 +		for ( j = 0; j < 2; j++ )
   1.968 +		{
   1.969 +			int s = m.echo_hist_pos [i] [j];
   1.970 +			SPC_COPY( int16_t, s );
   1.971 +			m.echo_hist [i] [j] = s; // write back at offset 0
   1.972 +		}
   1.973 +	}
   1.974 +	m.echo_hist_pos = m.echo_hist;
   1.975 +	memcpy( &m.echo_hist [echo_hist_size], m.echo_hist, echo_hist_size * sizeof m.echo_hist [0] );
   1.976 +	
   1.977 +	// Misc
   1.978 +	SPC_COPY(  uint8_t, m.every_other_sample );
   1.979 +	SPC_COPY(  uint8_t, m.kon );
   1.980 +	
   1.981 +	SPC_COPY( uint16_t, m.noise );
   1.982 +	SPC_COPY( uint16_t, m.counter );
   1.983 +	SPC_COPY( uint16_t, m.echo_offset );
   1.984 +	SPC_COPY( uint16_t, m.echo_length );
   1.985 +	SPC_COPY(  uint8_t, m.phase );
   1.986 +	
   1.987 +	SPC_COPY(  uint8_t, m.new_kon );
   1.988 +	SPC_COPY(  uint8_t, m.endx_buf );
   1.989 +	SPC_COPY(  uint8_t, m.envx_buf );
   1.990 +	SPC_COPY(  uint8_t, m.outx_buf );
   1.991 +	
   1.992 +	SPC_COPY(  uint8_t, m.t_pmon );
   1.993 +	SPC_COPY(  uint8_t, m.t_non );
   1.994 +	SPC_COPY(  uint8_t, m.t_eon );
   1.995 +	SPC_COPY(  uint8_t, m.t_dir );
   1.996 +	SPC_COPY(  uint8_t, m.t_koff );
   1.997 +	
   1.998 +	SPC_COPY( uint16_t, m.t_brr_next_addr );
   1.999 +	SPC_COPY(  uint8_t, m.t_adsr0 );
  1.1000 +	SPC_COPY(  uint8_t, m.t_brr_header );
  1.1001 +	SPC_COPY(  uint8_t, m.t_brr_byte );
  1.1002 +	SPC_COPY(  uint8_t, m.t_srcn );
  1.1003 +	SPC_COPY(  uint8_t, m.t_esa );
  1.1004 +	SPC_COPY(  uint8_t, m.t_echo_enabled );
  1.1005 +	
  1.1006 +	SPC_COPY(  int16_t, m.t_main_out [0] );
  1.1007 +	SPC_COPY(  int16_t, m.t_main_out [1] );
  1.1008 +	SPC_COPY(  int16_t, m.t_echo_out [0] );
  1.1009 +	SPC_COPY(  int16_t, m.t_echo_out [1] );
  1.1010 +	SPC_COPY(  int16_t, m.t_echo_in  [0] );
  1.1011 +	SPC_COPY(  int16_t, m.t_echo_in  [1] );
  1.1012 +	
  1.1013 +	SPC_COPY( uint16_t, m.t_dir_addr );
  1.1014 +	SPC_COPY( uint16_t, m.t_pitch );
  1.1015 +	SPC_COPY(  int16_t, m.t_output );
  1.1016 +	SPC_COPY( uint16_t, m.t_echo_ptr );
  1.1017 +	SPC_COPY(  uint8_t, m.t_looped );
  1.1018 +	
  1.1019 +	copier.extra();
  1.1020 +}
  1.1021 +#endif