1 // license:LGPL-2.1+
2 // copyright-holders:R. Belmont, Brad Martin
3 /***************************************************************************
4 
5   s_dsp.cpp
6 
7   File to handle the S-DSP emulation used in Nintendo Super NES.
8 
9   By R. Belmont, adapted from OpenSPC 0.3.99 by Brad Martin with permission.
10   Thanks to Brad and also to Charles Bilyu? of SNeESe.
11 
12   OpenSPC's license terms (the LGPL) follow:
13 
14  ---------------------------------------------------------------------------
15 
16   Copyright Brad Martin.
17 
18   OpenSPC is free software; you can redistribute it and/or modify
19   it under the terms of the GNU Lesser General Public License as published by
20   the Free Software Foundation; either version 2 of the License, or
21   (at your option) any later version.
22 
23   OpenSPC is distributed in the hope that it will be useful,
24   but WITHOUT ANY WARRANTY; without even the implied warranty of
25   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
26   GNU Lesser General Public License for more details.
27 
28 ***************************************************************************/
29 
30 #include "emu.h"
31 #include "s_dsp.h"
32 
33 /***************************************************************************
34  CONSTANTS AND MACROS
35 ***************************************************************************/
36 
37 static const int gauss[]=
38 {
39 	0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000,
40 	0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000,
41 	0x001, 0x001, 0x001, 0x001, 0x001, 0x001, 0x001, 0x001,
42 	0x001, 0x001, 0x001, 0x002, 0x002, 0x002, 0x002, 0x002,
43 	0x002, 0x002, 0x003, 0x003, 0x003, 0x003, 0x003, 0x004,
44 	0x004, 0x004, 0x004, 0x004, 0x005, 0x005, 0x005, 0x005,
45 	0x006, 0x006, 0x006, 0x006, 0x007, 0x007, 0x007, 0x008,
46 	0x008, 0x008, 0x009, 0x009, 0x009, 0x00A, 0x00A, 0x00A,
47 	0x00B, 0x00B, 0x00B, 0x00C, 0x00C, 0x00D, 0x00D, 0x00E,
48 	0x00E, 0x00F, 0x00F, 0x00F, 0x010, 0x010, 0x011, 0x011,
49 	0x012, 0x013, 0x013, 0x014, 0x014, 0x015, 0x015, 0x016,
50 	0x017, 0x017, 0x018, 0x018, 0x019, 0x01A, 0x01B, 0x01B,
51 	0x01C, 0x01D, 0x01D, 0x01E, 0x01F, 0x020, 0x020, 0x021,
52 	0x022, 0x023, 0x024, 0x024, 0x025, 0x026, 0x027, 0x028,
53 	0x029, 0x02A, 0x02B, 0x02C, 0x02D, 0x02E, 0x02F, 0x030,
54 	0x031, 0x032, 0x033, 0x034, 0x035, 0x036, 0x037, 0x038,
55 	0x03A, 0x03B, 0x03C, 0x03D, 0x03E, 0x040, 0x041, 0x042,
56 	0x043, 0x045, 0x046, 0x047, 0x049, 0x04A, 0x04C, 0x04D,
57 	0x04E, 0x050, 0x051, 0x053, 0x054, 0x056, 0x057, 0x059,
58 	0x05A, 0x05C, 0x05E, 0x05F, 0x061, 0x063, 0x064, 0x066,
59 	0x068, 0x06A, 0x06B, 0x06D, 0x06F, 0x071, 0x073, 0x075,
60 	0x076, 0x078, 0x07A, 0x07C, 0x07E, 0x080, 0x082, 0x084,
61 	0x086, 0x089, 0x08B, 0x08D, 0x08F, 0x091, 0x093, 0x096,
62 	0x098, 0x09A, 0x09C, 0x09F, 0x0A1, 0x0A3, 0x0A6, 0x0A8,
63 	0x0AB, 0x0AD, 0x0AF, 0x0B2, 0x0B4, 0x0B7, 0x0BA, 0x0BC,
64 	0x0BF, 0x0C1, 0x0C4, 0x0C7, 0x0C9, 0x0CC, 0x0CF, 0x0D2,
65 	0x0D4, 0x0D7, 0x0DA, 0x0DD, 0x0E0, 0x0E3, 0x0E6, 0x0E9,
66 	0x0EC, 0x0EF, 0x0F2, 0x0F5, 0x0F8, 0x0FB, 0x0FE, 0x101,
67 	0x104, 0x107, 0x10B, 0x10E, 0x111, 0x114, 0x118, 0x11B,
68 	0x11E, 0x122, 0x125, 0x129, 0x12C, 0x130, 0x133, 0x137,
69 	0x13A, 0x13E, 0x141, 0x145, 0x148, 0x14C, 0x150, 0x153,
70 	0x157, 0x15B, 0x15F, 0x162, 0x166, 0x16A, 0x16E, 0x172,
71 	0x176, 0x17A, 0x17D, 0x181, 0x185, 0x189, 0x18D, 0x191,
72 	0x195, 0x19A, 0x19E, 0x1A2, 0x1A6, 0x1AA, 0x1AE, 0x1B2,
73 	0x1B7, 0x1BB, 0x1BF, 0x1C3, 0x1C8, 0x1CC, 0x1D0, 0x1D5,
74 	0x1D9, 0x1DD, 0x1E2, 0x1E6, 0x1EB, 0x1EF, 0x1F3, 0x1F8,
75 	0x1FC, 0x201, 0x205, 0x20A, 0x20F, 0x213, 0x218, 0x21C,
76 	0x221, 0x226, 0x22A, 0x22F, 0x233, 0x238, 0x23D, 0x241,
77 	0x246, 0x24B, 0x250, 0x254, 0x259, 0x25E, 0x263, 0x267,
78 	0x26C, 0x271, 0x276, 0x27B, 0x280, 0x284, 0x289, 0x28E,
79 	0x293, 0x298, 0x29D, 0x2A2, 0x2A6, 0x2AB, 0x2B0, 0x2B5,
80 	0x2BA, 0x2BF, 0x2C4, 0x2C9, 0x2CE, 0x2D3, 0x2D8, 0x2DC,
81 	0x2E1, 0x2E6, 0x2EB, 0x2F0, 0x2F5, 0x2FA, 0x2FF, 0x304,
82 	0x309, 0x30E, 0x313, 0x318, 0x31D, 0x322, 0x326, 0x32B,
83 	0x330, 0x335, 0x33A, 0x33F, 0x344, 0x349, 0x34E, 0x353,
84 	0x357, 0x35C, 0x361, 0x366, 0x36B, 0x370, 0x374, 0x379,
85 	0x37E, 0x383, 0x388, 0x38C, 0x391, 0x396, 0x39B, 0x39F,
86 	0x3A4, 0x3A9, 0x3AD, 0x3B2, 0x3B7, 0x3BB, 0x3C0, 0x3C5,
87 	0x3C9, 0x3CE, 0x3D2, 0x3D7, 0x3DC, 0x3E0, 0x3E5, 0x3E9,
88 	0x3ED, 0x3F2, 0x3F6, 0x3FB, 0x3FF, 0x403, 0x408, 0x40C,
89 	0x410, 0x415, 0x419, 0x41D, 0x421, 0x425, 0x42A, 0x42E,
90 	0x432, 0x436, 0x43A, 0x43E, 0x442, 0x446, 0x44A, 0x44E,
91 	0x452, 0x455, 0x459, 0x45D, 0x461, 0x465, 0x468, 0x46C,
92 	0x470, 0x473, 0x477, 0x47A, 0x47E, 0x481, 0x485, 0x488,
93 	0x48C, 0x48F, 0x492, 0x496, 0x499, 0x49C, 0x49F, 0x4A2,
94 	0x4A6, 0x4A9, 0x4AC, 0x4AF, 0x4B2, 0x4B5, 0x4B7, 0x4BA,
95 	0x4BD, 0x4C0, 0x4C3, 0x4C5, 0x4C8, 0x4CB, 0x4CD, 0x4D0,
96 	0x4D2, 0x4D5, 0x4D7, 0x4D9, 0x4DC, 0x4DE, 0x4E0, 0x4E3,
97 	0x4E5, 0x4E7, 0x4E9, 0x4EB, 0x4ED, 0x4EF, 0x4F1, 0x4F3,
98 	0x4F5, 0x4F6, 0x4F8, 0x4FA, 0x4FB, 0x4FD, 0x4FF, 0x500,
99 	0x502, 0x503, 0x504, 0x506, 0x507, 0x508, 0x50A, 0x50B,
100 	0x50C, 0x50D, 0x50E, 0x50F, 0x510, 0x511, 0x511, 0x512,
101 	0x513, 0x514, 0x514, 0x515, 0x516, 0x516, 0x517, 0x517,
102 	0x517, 0x518, 0x518, 0x518, 0x518, 0x518, 0x519, 0x519,
103 	0x519, 0x519, 0x519, 0x519, 0x519, 0x519, 0x519, 0x519
104 };
105 
106 #undef DEBUG
107 #undef DBG_KEY
108 #undef DBG_ENV
109 #undef DBG_PMOD
110 #undef DBG_BRR
111 #undef DBG_ECHO
112 #undef DBG_INTRP
113 
114 #undef NO_PMOD
115 #undef NO_ECHO
116 
117 /* Ptrs to Gaussian table */
118 static const int *const G1 = &gauss[256];
119 static const int *const G2 = &gauss[512];
120 static const int *const G3 = &gauss[255];
121 static const int *const G4 = &gauss[0];
122 
123 static const int        mask = 0xFF;
124 
125 /* This table is for envelope timing.  It represents the number of counts
126    that should be subtracted from the counter each sample period (32kHz).
127    The counter starts at 30720 (0x7800). */
128 static const int CNT_INIT = 0x7800;
129 static const int ENVCNT[0x20]
130 	= {
131 	0x0000, 0x000F, 0x0014, 0x0018, 0x001E, 0x0028, 0x0030, 0x003C,
132 	0x0050, 0x0060, 0x0078, 0x00A0, 0x00C0, 0x00F0, 0x0140, 0x0180,
133 	0x01E0, 0x0280, 0x0300, 0x03C0, 0x0500, 0x0600, 0x0780, 0x0A00,
134 	0x0C00, 0x0F00, 0x1400, 0x1800, 0x1E00, 0x2800, 0x3C00, 0x7800
135 	};
136 
137 
138 ALLOW_SAVE_TYPE(s_dsp_device::env_state_t32);
139 
140 
141 DEFINE_DEVICE_TYPE(S_DSP, s_dsp_device, "s_dsp", "Nintendo/Sony S-DSP")
142 
143 
s_dsp_device(const machine_config & mconfig,const char * tag,device_t * owner,u32 clock)144 s_dsp_device::s_dsp_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
145 	: device_t(mconfig, S_DSP, tag, owner, clock)
146 	, device_sound_interface(mconfig, *this)
147 	, device_memory_interface(mconfig, *this)
148 	, m_data_config("data", ENDIANNESS_LITTLE, 8, 16)
149 {
150 }
151 
152 
153 //-------------------------------------------------
154 //  device_start - device-specific startup
155 //-------------------------------------------------
156 
device_start()157 void s_dsp_device::device_start()
158 {
159 	// Find our direct access
160 	space().cache(m_cache);
161 	space().specific(m_data);
162 
163 	m_channel = stream_alloc(0, 2, clock() / 64);
164 
165 	state_register();
166 }
167 
168 //-------------------------------------------------
169 //  device_reset - device-specific reset
170 //-------------------------------------------------
171 
device_reset()172 void s_dsp_device::device_reset()
173 {
174 	dsp_reset();
175 }
176 
177 //-------------------------------------------------
178 //  device_clock_changed - called if the clock
179 //  changes
180 //-------------------------------------------------
181 
device_clock_changed()182 void s_dsp_device::device_clock_changed()
183 {
184 	m_channel->set_sample_rate(clock() / 64);
185 }
186 
187 //-------------------------------------------------
188 //  memory_space_config - return a description of
189 //  any address spaces owned by this device
190 //-------------------------------------------------
191 
memory_space_config() const192 device_memory_interface::space_config_vector s_dsp_device::memory_space_config() const
193 {
194 	return space_config_vector{ std::make_pair(0, &m_data_config) };
195 }
196 
197 
198 /*****************************************************************************
199     IMPLEMENTATION
200 *****************************************************************************/
201 
202 
203 /*-------------------------------------------------
204  dsp_reset
205 
206  Reset emulated DSP
207 -------------------------------------------------*/
208 
dsp_reset()209 void s_dsp_device::dsp_reset()
210 {
211 #ifdef MAME_DEBUG
212 	logerror("dsp_reset\n");
213 #endif
214 
215 	for (int i = 0; i < 8; i++)
216 	{
217 #ifndef NO_ECHO
218 		m_fir_lbuf[i] = 0;
219 		m_fir_rbuf[i] = 0;
220 #endif
221 		m_voice_state[i].on_cnt = 0;
222 	}
223 
224 #ifndef NO_ECHO
225 	m_fir_ptr   = 0;
226 	m_echo_ptr = 0;
227 #endif
228 
229 	m_keys      = 0;
230 	m_keyed_on  = 0;
231 	m_noise_cnt = 0;
232 	m_noise_lev = 0x4000;
233 	m_dsp_regs[0x6c] |= 0xe0;
234 	m_dsp_regs[0x4c] = 0;
235 	m_dsp_regs[0x5c] = 0;
236 }
237 
238 
239 /*-------------------------------------------------
240  dsp_update
241 
242  Mix one sample of audio. sound_ptr is a pointer
243  to mix audio into
244 -------------------------------------------------*/
245 
dsp_update(s16 * sound_ptr)246 void s_dsp_device::dsp_update( s16 *sound_ptr )
247 {
248 	int V;
249 
250 	int envx;
251 	int m;
252 	int v;
253 	int vl;
254 	voice_state_type * vp;
255 	int vr;
256 
257 	const u16 sd = m_dsp_regs[0x5d];
258 
259 	/* Check for reset */
260 	if (m_dsp_regs[0x6c] & 0x80)
261 		dsp_reset();
262 
263 	/* Here we check for keys on/off.  Docs say that successive writes to KON/KOF
264 	must be separated by at least 2 Ts periods or risk being neglected.
265 	Therefore DSP only looks at these during an update, and not at the time of
266 	the write.  Only need to do this once however, since the regs haven't
267 	changed over the whole period we need to catch up with. */
268 #ifdef DBG_KEY
269 	m_dsp_regs[0x4c] &= mask;
270 #endif
271 
272 	/* Keying on a voice resets that bit in ENDX */
273 	m_dsp_regs[0x7c] &= ~m_dsp_regs[0x4c];
274 
275 	/* Question: what is the expected behavior when pitch modulation is enabled on
276 	voice 0?  Jurassic Park 2 does this.  For now, using outx of zero for first
277 	voice. */
278 	s32 outx = 0;       /* Smpl height (must be signed) */
279 
280 	/* Same table for noise and envelope */
281 	m_noise_cnt -= ENVCNT[m_dsp_regs[0x6c] & 0x1f];
282 	if (m_noise_cnt <= 0)
283 	{
284 		m_noise_cnt = CNT_INIT;
285 		m_noise_lev = (((m_noise_lev << 13) ^ (m_noise_lev << 14)) & 0x4000) | (m_noise_lev >> 1);
286 	}
287 
288 	int outl  = 0;
289 	int outr  = 0;
290 
291 #ifndef NO_ECHO
292 	int echol = 0;
293 	int echor = 0;
294 #endif
295 
296 	for (v = 0, m = 1, V = 0; v < 8; v++, V += 16, m <<= 1)
297 	{
298 		vp = &m_voice_state[v];
299 
300 		if (vp->on_cnt && (--vp->on_cnt == 0))
301 		{
302 			/* Voice was keyed on */
303 			m_keys       |= m;
304 			m_keyed_on   |= m;
305 #ifdef DBG_KEY
306 			vl          = m_dsp_regs[(v << 4) + 4];
307 #endif
308 			vp->samp_id = (vptr(sd, V) << 16) | lptr(sd, V);
309 			vp->mem_ptr = vptr(sd, V);
310 
311 #ifdef DBG_KEY
312 			logerror("Keying on voice %d, samp=0x%04X (0x%02X)\n", v, vp->mem_ptr, vl);
313 #endif
314 
315 			vp->header_cnt = 0;
316 			vp->half       = 0;
317 			vp->envx       = 0;
318 			vp->end        = 0;
319 			vp->sampptr    = 0;
320 			vp->mixfrac    = 3 * 4096;
321 
322 			/* NOTE: Real SNES does *not* appear to initialize the envelope
323 			counter to anything in particular.  The first cycle always seems to
324 			come at a random time sooner than expected; as yet, I have been
325 			unable to find any pattern.  I doubt it will matter though, so
326 			we'll go ahead and do the full time for now. */
327 			vp->envcnt   = CNT_INIT;
328 			vp->envstate = env_state_t32::ATTACK;
329 		}
330 
331 		if (m_dsp_regs[0x4c] & m & ~m_dsp_regs[0x5c])
332 		{
333 			/* Voice doesn't come on if key off is set */
334 			m_dsp_regs[0x4c] &= ~m;
335 			vp->on_cnt       = 8;
336 
337 #ifdef DBG_KEY
338 			logerror("Key on set for voice %d\n", v);
339 #endif
340 		}
341 
342 		if (m_keys & m_dsp_regs[0x5c] & m)
343 		{
344 			/* Voice was keyed off */
345 			vp->envstate = env_state_t32::RELEASE;
346 			vp->on_cnt   = 0;
347 
348 #ifdef DBG_KEY
349 			logerror("Keying off voice %d\n", v);
350 #endif
351 		}
352 
353 		if (!(m_keys & m & mask) || ((envx = advance_envelope(v)) < 0))
354 		{
355 			m_dsp_regs[V + 8] = 0;
356 			m_dsp_regs[V + 9] = 0;
357 			outx             = 0;
358 			continue;
359 		}
360 
361 		vp->pitch = pitch(V);
362 
363 #ifndef NO_PMOD
364 		/* Pitch mod uses OUTX from last voice for this one.  Luckily we haven't
365 		modified OUTX since it was used for last voice. */
366 		if (m_dsp_regs[0x2d] & m)
367 		{
368 #ifdef DBG_PMOD
369 			logerror("Pitch Modulating voice %d, outx=%ld, old pitch=%d, ", v, outx, vp->pitch);
370 #endif
371 			vp->pitch = (vp->pitch * (outx + 32768)) >> 15;
372 			}
373 #endif
374 
375 #ifdef DBG_PMOD
376 			logerror("pitch=%d\n", vp->pitch);
377 #endif
378 
379 			for ( ; vp->mixfrac >= 0; vp->mixfrac -= 4096)
380 			{
381 				/* This part performs the BRR decode 'on-the-fly'.  This is more
382 				correct than the old way, which could be fooled if the data and/or
383 				the loop point changed while the sample was playing, or if the BRR
384 				decode didn't produce the same result every loop because of the
385 				filters.  The event interface still has no chance of keeping up
386 				with those kinds of tricks, though. */
387 				if (!vp->header_cnt)
388 				{
389 					if (vp->end & 1)
390 					{
391 						/* Docs say ENDX bit is set when decode of block with source
392 						end flag set is done.  Does this apply to looping samples?
393 						Some info I've seen suggests yes. */
394 						m_dsp_regs[0x7c] |= m;
395 						if (vp->end & 2)
396 						{
397 							vp->mem_ptr = lptr(sd, V);
398 
399 #ifdef DBG_BRR
400 							logerror("BRR looping to 0x%04X\n", vp->mem_ptr);
401 #endif
402 						}
403 						else
404 						{
405 #ifdef DBG_KEY
406 							logerror("BRR decode end, voice %d\n", v);
407 #endif
408 
409 							m_keys &= ~m;
410 							m_dsp_regs[V + 8] = 0;
411 							vp->envx         = 0;
412 							while (vp->mixfrac >= 0)
413 							{
414 								vp->sampbuf[vp->sampptr] = 0;
415 								outx         = 0;
416 								vp->sampptr  = (vp->sampptr + 1) & 3;
417 								vp->mixfrac -= 4096;
418 							}
419 							break;
420 						}
421 					}
422 
423 					vp->header_cnt = 8;
424 					vl = (u8)read_byte(vp->mem_ptr++);
425 					vp->range  = vl >> 4;
426 					vp->end    = vl & 3;
427 					vp->filter = (vl & 12) >> 2;
428 
429 #ifdef DBG_BRR
430 					logerror("V%d: header read, range=%d, end=%d, filter=%d\n", v, vp->range, vp->end, vp->filter);
431 #endif
432 				}
433 
434 				if (vp->half == 0)
435 				{
436 					vp->half = 1;
437 					outx     = ((s8)read_byte(vp->mem_ptr)) >> 4;
438 				}
439 				else
440 				{
441 					vp->half = 0;
442 					/* Funkiness to get 4-bit signed to carry through */
443 					outx   = (s8)(read_byte(vp->mem_ptr++) << 4);
444 					outx >>= 4;
445 					vp->header_cnt--;
446 				}
447 
448 #ifdef DBG_BRR
449 				logerror("V%d: nybble=%X, ptr=%04X, smp1=%d, smp2=%d\n", v, outx & 0x0f, vp->mem_ptr, vp->smp1, vp->smp2);
450 #endif
451 
452 				/* For invalid ranges (D,E,F): if the nybble is negative, the result
453 				is F000.  If positive, 0000.  Nothing else like previous range,
454 				etc. seems to have any effect.  If range is valid, do the shift
455 				normally.  Note these are both shifted right once to do the filters
456 				properly, but the output will be shifted back again at the end. */
457 				if (vp->range <= 0xc)
458 				{
459 					outx = (outx << vp->range) >> 1;
460 				}
461 				else
462 				{
463 					outx &= ~0x7ff;
464 
465 #ifdef DBG_BRR
466 					logerror("V%d: invalid range! (%X)\n", v, vp->range);
467 #endif
468 				}
469 
470 #ifdef DBG_BRR
471 				logerror("V%d: shifted delta=%04X\n", v, (u16)outx);
472 #endif
473 
474 				switch (vp->filter)
475 				{
476 				case 0:
477 					break;
478 
479 				case 1:
480 					outx += (vp->smp1 >> 1) + ((-vp->smp1) >> 5);
481 					break;
482 
483 				case 2:
484 					outx += vp->smp1 + ((-(vp->smp1 + (vp->smp1 >> 1))) >> 5) - (vp->smp2 >> 1) + (vp->smp2 >> 5);
485 					break;
486 
487 				case 3:
488 					outx += vp->smp1 + ((-(vp->smp1 + (vp->smp1 << 2) + (vp->smp1 << 3))) >> 7)
489 							- (vp->smp2 >> 1) + ((vp->smp2 + (vp->smp2 >> 1)) >> 4);
490 					break;
491 				}
492 
493 				if (outx < (s16)0x8000)
494 				{
495 					outx = (s16)0x8000;
496 				}
497 				else if (outx > (s16)0x7fff)
498 				{
499 					outx = (s16)0x7fff;
500 				}
501 
502 #ifdef DBG_BRR
503 				logerror("V%d: filter + delta=%04X\n", v, (u16)outx);
504 #endif
505 
506 				vp->smp2 = (s16)vp->smp1;
507 				vp->smp1 = (s16)(outx << 1);
508 				vp->sampbuf[vp->sampptr] = vp->smp1;
509 
510 #ifdef DBG_BRR
511 				logerror("V%d: final output: %04X\n", v, vp->sampbuf[vp->sampptr]);
512 #endif
513 
514 				vp->sampptr = (vp->sampptr + 1) & 3;
515 			}
516 
517 			if (m_dsp_regs[0x3d] & m)
518 			{
519 #ifdef DBG_PMOD
520 				logerror("Noise enabled, voice %d\n", v);
521 #endif
522 				outx = (s16)(m_noise_lev << 1);
523 			}
524 			else
525 			{
526 			/* Perform 4-Point Gaussian interpolation.  Take an approximation of a
527 			Gaussian bell-curve, and move it through the sample data at a rate
528 			determined by the pitch.  The sample output at any given time is
529 			the sum of the products of each input sample point with the value
530 			of the bell-curve corresponding to that point. */
531 			vl  = vp->mixfrac >> 4;
532 			vr  = ((G4[-vl-1] * vp->sampbuf[vp->sampptr]) >> 11 ) & ~1;
533 			vr += ((G3[-vl] * vp->sampbuf[(vp->sampptr + 1) & 3]) >> 11) & ~1;
534 			vr += ((G2[vl] * vp->sampbuf[(vp->sampptr + 2) & 3]) >> 11 ) & ~1;
535 
536 			/* This is to do the wrapping properly.  Based on my tests with the
537 			SNES, it appears clipping is done only if it is the fourth addition
538 			that would cause a wrap.  If it has already wrapped before the
539 			fourth addition, it is not clipped. */
540 			vr  = (s16)vr;
541 			vr += ((G1[vl] * vp->sampbuf[(vp->sampptr + 3) & 3]) >> 11) & ~1;
542 
543 			if (vr > 32767)
544 				vr = 32767;
545 			else if (vr < -32768)
546 				vr = -32768;
547 
548 			outx = (s16)vr;
549 
550 #ifdef DBG_INTRP
551 			logerror("V%d: mixfrac=%d: [%d]*%d + [%d]*%d + [%d]*%d + [%d]*%d = %d\n", v, vl,
552 				G1[vl],
553 				vp->sampbuf[(vp->sampptr + 3) & 3],
554 				G2[vl],
555 				vp->sampbuf[(vp->sampptr + 2) & 3],
556 				G3[-vl],
557 				vp->sampbuf[(vp->sampptr + 1) & 3],
558 				G4[-vl-1],
559 				vp->sampbuf[vp->sampptr],
560 				outx);
561 #endif
562 		}
563 
564 		/* Advance the sample position for next update. */
565 		vp->mixfrac += vp->pitch;
566 
567 		outx = ((outx * envx) >> 11) & ~1;
568 		m_dsp_regs[V + 9] = outx >> 8;
569 
570 		vl = (((int)(s8)m_dsp_regs[V    ]) * outx) >> 7;
571 		vr = (((int)(s8)m_dsp_regs[V + 1]) * outx) >> 7;
572 		outl += vl;
573 		outr += vr;
574 
575 		if (m_dsp_regs[0x4d] & m)
576 		{
577 #ifndef NO_ECHO
578 			echol += vl;
579 			echor += vr;
580 #endif
581 		}
582 	}
583 
584 	outl = (outl * (s8)m_dsp_regs[0x0c]) >> 7;
585 	outr = (outr * (s8)m_dsp_regs[0x1c]) >> 7;
586 
587 #ifndef NO_ECHO
588 	/* Perform echo.  First, read mem at current location, and put those samples
589 	into the FIR filter queue. */
590 #ifdef DBG_ECHO
591 	logerror("Echo delay=%dms, feedback=%d%%\n", m_dsp_regs[0x7d] * 16,
592 		((s8)m_dsp_regs[0x0d] * 100) / 0x7f);
593 #endif
594 
595 	int echo_base = ((m_dsp_regs[0x6d] << 8) + m_echo_ptr) & 0xffff;
596 	m_fir_lbuf[m_fir_ptr] = (s16)read_word(echo_base);
597 	m_fir_rbuf[m_fir_ptr] = (s16)read_word(echo_base + sizeof(s16));
598 
599 	/* Now, evaluate the FIR filter, and add the results into the final output. */
600 	vl = m_fir_lbuf[m_fir_ptr] * (s8)m_dsp_regs[0x7f];
601 	vr = m_fir_rbuf[m_fir_ptr] * (s8)m_dsp_regs[0x7f];
602 	m_fir_ptr = (m_fir_ptr + 1) & 7;
603 	vl += m_fir_lbuf[m_fir_ptr] * (s8)m_dsp_regs[0x6f];
604 	vr += m_fir_rbuf[m_fir_ptr] * (s8)m_dsp_regs[0x6f];
605 	m_fir_ptr = (m_fir_ptr + 1) & 7;
606 	vl += m_fir_lbuf[m_fir_ptr] * (s8)m_dsp_regs[0x5f];
607 	vr += m_fir_rbuf[m_fir_ptr] * (s8)m_dsp_regs[0x5f];
608 	m_fir_ptr = (m_fir_ptr + 1) & 7;
609 	vl += m_fir_lbuf[m_fir_ptr] * (s8)m_dsp_regs[0x4f];
610 	vr += m_fir_rbuf[m_fir_ptr] * (s8)m_dsp_regs[0x4f];
611 	m_fir_ptr = (m_fir_ptr + 1) & 7;
612 	vl += m_fir_lbuf[m_fir_ptr] * (s8)m_dsp_regs[0x3f];
613 	vr += m_fir_rbuf[m_fir_ptr] * (s8)m_dsp_regs[0x3f];
614 	m_fir_ptr = (m_fir_ptr + 1) & 7;
615 	vl += m_fir_lbuf[m_fir_ptr] * (s8)m_dsp_regs[0x2f];
616 	vr += m_fir_rbuf[m_fir_ptr] * (s8)m_dsp_regs[0x2f];
617 	m_fir_ptr = (m_fir_ptr + 1) & 7;
618 	vl += m_fir_lbuf[m_fir_ptr] * (s8)m_dsp_regs[0x1f];
619 	vr += m_fir_rbuf[m_fir_ptr] * (s8)m_dsp_regs[0x1f];
620 	m_fir_ptr = (m_fir_ptr + 1) & 7;
621 	vl += m_fir_lbuf[m_fir_ptr] * (s8)m_dsp_regs[0x0f];
622 	vr += m_fir_rbuf[m_fir_ptr] * (s8)m_dsp_regs[0x0f];
623 
624 #ifdef DBG_ECHO
625 	logerror("FIR Coefficients: %02X %02X %02X %02X %02X %02X %02X %02X\n",
626 		m_dsp_regs[0x0f],
627 		m_dsp_regs[0x1f],
628 		m_dsp_regs[0x2f],
629 		m_dsp_regs[0x3f],
630 		m_dsp_regs[0x4f],
631 		m_dsp_regs[0x5f],
632 		m_dsp_regs[0x6f],
633 		m_dsp_regs[0x7f]);
634 #endif
635 
636 	/* FIR_ptr is left in the position of the oldest sample, the one that will be replaced next update. */
637 	outl += vl * (s8)m_dsp_regs[0x2c] >> 14;
638 	outr += vr * (s8)m_dsp_regs[0x3c] >> 14;
639 
640 	if (!(m_dsp_regs[0x6c] & 0x20))
641 	{
642 		/* Add the echo feedback back into the original result, and save that into memory for use later. */
643 		echol += vl * (s8)m_dsp_regs[0x0d] >> 14;
644 
645 		if (echol > 32767)
646 			echol = 32767;
647 		else if (echol < -32768)
648 			echol = -32768;
649 
650 		echor += vr * (s8)m_dsp_regs[0x0D ] >> 14;
651 
652 		if (echor > 32767)
653 			echor = 32767;
654 		else if (echor < -32768)
655 			echor = -32768;
656 
657 #ifdef DBG_ECHO
658 		logerror("Echo: Writing %04X,%04X at location %04X\n", (u16)echol, (u16)echor, echo_base);
659 #endif
660 
661 		write_word(echo_base, (u16)echol);
662 		write_word(echo_base + sizeof(s16), (u16)echor);
663 	}
664 
665 	m_echo_ptr += 2 * sizeof(s16);
666 
667 	if (m_echo_ptr >= ((m_dsp_regs[0x7d] & 0x0f) << 11))
668 	{
669 		m_echo_ptr = 0;
670 	}
671 #endif                              /* !defined( NO_ECHO ) */
672 
673 	if (sound_ptr != nullptr)
674 	{
675 		if (m_dsp_regs[0x6c] & 0x40)
676 		{
677 			/* MUTE */
678 #ifdef MAME_DEBUG
679 			logerror("MUTED!\n");
680 #endif
681 
682 			*sound_ptr = 0;
683 			sound_ptr++;
684 			*sound_ptr = 0;
685 			sound_ptr++;
686 		}
687 		else
688 		{
689 			if (outl > 32767)
690 					*sound_ptr = 32767;
691 			else if (outl < -32768)
692 				*sound_ptr = -32768;
693 			else
694 				*sound_ptr = outl;
695 
696 			sound_ptr++;
697 
698 			if (outr > 32767)
699 					*sound_ptr = 32767;
700 			else if (outr < -32768)
701 				*sound_ptr = -32768;
702 			else
703 				*sound_ptr = outr;
704 
705 			sound_ptr++;
706 		}
707 	}
708 }
709 
710 
711 /*-------------------------------------------------
712  advance_envelope
713 
714  Run envelope step & return ENVX. v is the voice
715  to process envelope for.
716 -------------------------------------------------*/
717 
advance_envelope(int v)718 int s_dsp_device::advance_envelope( int v )
719 {
720 	int t;
721 
722 	int envx = m_voice_state[v].envx;
723 
724 	if (m_voice_state[v].envstate == env_state_t32::RELEASE)
725 	{
726 		/* Docs: "When in the state of "key off". the "click" sound is prevented
727 		by the addition of the fixed value 1/256"  WTF???  Alright, I'm going
728 		to choose to interpret that this way:  When a note is keyed off, start
729 		the RELEASE state, which subtracts 1/256th each sample period (32kHz).
730 		Note there's no need for a count because it always happens every
731 		update. */
732 		envx -= 0x8;                    /* 0x8 / 0x800 = 1/256th        */
733 		if (envx <= 0)
734 		{
735 			envx = 0;
736 			m_keys &= ~(1 << v);
737 			return -1;
738 		}
739 
740 		m_voice_state[v].envx = envx;
741 		m_dsp_regs[(v << 4) + 8] = envx >> 8;
742 
743 #ifdef DBG_ENV
744 		logerror("ENV voice %d: envx=%03X, state=RELEASE\n", v, envx);
745 #endif
746 
747 		return envx;
748 	}
749 
750 	int cnt = m_voice_state[v].envcnt;
751 	int adsr1 = m_dsp_regs[(v << 4) + 5];
752 
753 	if (adsr1 & 0x80)
754 	{
755 		switch (m_voice_state[v].envstate)
756 		{
757 		case env_state_t32::ATTACK:
758 			/* Docs are very confusing.  "AR is multiplied by the fixed value
759 			1/64..."  I believe it means to add 1/64th to ENVX once every
760 			time ATTACK is updated, and that's what I'm going to implement. */
761 			t = adsr1 & 0x0f;
762 
763 				if (t == 0x0f)
764 			{
765 #ifdef DBG_ENV
766 				logerror("ENV voice %d: instant attack\n", v);
767 #endif
768 
769 				envx += 0x400;
770 			}
771 			else
772 			{
773 				cnt -= ENVCNT[(t << 1) + 1];
774 
775 				if (cnt > 0)
776 					break;
777 
778 				envx += 0x20;       /* 0x020 / 0x800 = 1/64         */
779 				cnt   = CNT_INIT;
780 			}
781 
782 			if (envx > 0x7ff)
783 			{
784 				envx = 0x7ff;
785 				m_voice_state[v].envstate = env_state_t32::DECAY;
786 			}
787 
788 #ifdef DBG_ENV
789 			logerror("ENV voice %d: envx=%03X, state=ATTACK\n", v, envx);
790 #endif
791 
792 			m_voice_state[v].envx = envx;
793 			break;
794 
795 		case env_state_t32::DECAY:
796 			/* Docs: "DR... [is multiplied] by the fixed value 1-1/256."
797 			Well, at least that makes some sense.  Multiplying ENVX by
798 			255/256 every time DECAY is updated. */
799 			cnt -= ENVCNT[((adsr1 >> 3) & 0x0e) + 0x10];
800 
801 			if (cnt <= 0)
802 			{
803 				cnt   = CNT_INIT;
804 				envx -= ((envx - 1) >> 8) + 1;
805 				m_voice_state[v].envx = envx;
806 			}
807 
808 			if (envx <= 0x100 * (SL(v) + 1))
809 				m_voice_state[v].envstate = env_state_t32::SUSTAIN;
810 
811 #ifdef DBG_ENV
812 			logerror("ENV voice %d: envx=%03X, state=DECAY\n", v, envx);
813 #endif
814 
815 			break;
816 
817 		case env_state_t32::SUSTAIN:
818 			/* Docs: "SR [is multiplied] by the fixed value 1-1/256."
819 			Multiplying ENVX by 255/256 every time SUSTAIN is updated. */
820 #ifdef DBG_ENV
821 			if (ENVCNT[SR(v)] == 0)
822 				logerror("ENV voice %d: envx=%03X, state=SUSTAIN, zero rate\n", v, envx);
823 #endif
824 
825 			cnt -= ENVCNT[SR(v)];
826 			if (cnt > 0)
827 				break;
828 
829 			cnt   = CNT_INIT;
830 			envx -= ((envx - 1) >> 8) + 1;
831 
832 #ifdef DBG_ENV
833 			logerror("ENV voice %d: envx=%03X, state=SUSTAIN\n", v, envx);
834 #endif
835 
836 			m_voice_state[v].envx = envx;
837 
838 			/* Note: no way out of this state except by explicit KEY OFF (or switch to GAIN). */
839 			break;
840 
841 		case env_state_t32::RELEASE:   /* Handled earlier to prevent GAIN mode from stopping KEY OFF events */
842 			break;
843 		}
844 	}
845 	else
846 	{
847 		/* GAIN mode is set
848 		Note: if the game switches between ADSR and GAIN modes partway
849 		through, should the count be reset, or should it continue from
850 		where it was?  Does the DSP actually watch for that bit to
851 		change, or does it just go along with whatever it sees when it
852 		performs the update?  I'm going to assume the latter and not
853 		update the count, unless I see a game that obviously wants the
854 		other behavior.  The effect would be pretty subtle, in any case.
855 		*/
856 		t = m_dsp_regs[(v << 4) + 7];
857 
858 		if (t < 0x80)
859 		{
860 			envx = t << 4;
861 			m_voice_state[v].envx = envx;
862 
863 #ifdef DBG_ENV
864 			logerror("ENV voice %d: envx=%03X, state=DIRECT\n", v, envx);
865 #endif
866 		}
867 		else
868 		{
869 			switch (t >> 5)
870 			{
871 			case 4:
872 				/* Docs: "Decrease (linear): Subtraction of the fixed value 1/64." */
873 				cnt -= ENVCNT[t & 0x1f];
874 
875 				if (cnt > 0)
876 					break;
877 
878 				cnt   = CNT_INIT;
879 				envx -= 0x020;      /* 0x020 / 0x800 = 1/64th       */
880 
881 				if (envx < 0)
882 					envx = 0;
883 
884 #ifdef DBG_ENV
885 				logerror("ENV voice %d: envx=%03X, state=DECREASE\n", v, envx);
886 #endif
887 
888 				m_voice_state[v].envx = envx;
889 				break;
890 
891 			case 5:
892 				/* Docs: "Drecrease <sic> (exponential): Multiplication by the fixed value 1-1/256." */
893 				cnt -= ENVCNT[t & 0x1f];
894 
895 				if (cnt > 0)
896 					break;
897 
898 				cnt = CNT_INIT;
899 				envx -= ((envx - 1) >> 8) + 1;
900 
901 #ifdef DBG_ENV
902 				logerror("ENV voice %d: envx=%03X, state=EXP\n", v, envx);
903 #endif
904 
905 				m_voice_state[v].envx = envx;
906 				break;
907 
908 			case 6:
909 				/* Docs: "Increase (linear): Addition of the fixed value 1/64." */
910 				cnt -= ENVCNT[t & 0x1f];
911 
912 				if (cnt > 0)
913 					break;
914 
915 				cnt = CNT_INIT;
916 				envx += 0x020;      /* 0x020 / 0x800 = 1/64th   */
917 				if (envx > 0x7ff)
918 					envx = 0x7ff;
919 
920 #ifdef DBG_ENV
921 				logerror("ENV voice %d: envx=%03X, state=INCREASE\n", v, envx);
922 #endif
923 
924 				m_voice_state[v].envx = envx;
925 				break;
926 
927 			case 7:
928 				/* Docs: "Increase (bent line): Addition of the constant
929 				     1/64 up to .75 of the constaint <sic> 1/256 from .75 to 1." */
930 				cnt -= ENVCNT[t & 0x1f];
931 
932 				if (cnt > 0)
933 					break;
934 
935 				cnt = CNT_INIT;
936 
937 				if (envx < 0x600)  /* 0x600 / 0x800 = .75          */
938 					envx += 0x020;  /* 0x020 / 0x800 = 1/64         */
939 				else
940 					envx += 0x008;  /* 0x008 / 0x800 = 1/256        */
941 
942 				if (envx > 0x7ff)
943 					envx=0x7ff;
944 
945 #ifdef DBG_ENV
946 				logerror("ENV voice %d: envx=%03X, state=INCREASE\n", v, envx);
947 #endif
948 
949 				m_voice_state[v].envx = envx;
950 				break;
951 			}
952 		}
953 	}
954 
955 	m_voice_state[v].envcnt = cnt;
956 	m_dsp_regs[(v << 4) + 8] = envx >> 4;
957 
958 	return envx;
959 }
960 
961 /*-------------------------------------------------
962     set_volume - sets S-DSP volume level
963     for both speakers, used for fade in/out effects
964 -------------------------------------------------*/
965 
set_volume(int volume)966 void s_dsp_device::set_volume(int volume)
967 {
968 	set_output_gain(0, volume / 100.0);
969 	set_output_gain(1, volume / 100.0);
970 }
971 
972 
973 /***************************
974          I/O for DSP
975  ***************************/
976 
dsp_io_r(offs_t offset)977 u8 s_dsp_device::dsp_io_r(offs_t offset)
978 {
979 	m_channel->update();
980 
981 #ifdef NO_ENVX
982 	if (!machine().side_effects_disabled())
983 		if (8 == (m_dsp_addr & 0x0f))
984 			m_dsp_regs[m_dsp_addr] = 0;
985 #endif
986 
987 	/* All reads simply return the contents of the addressed register. */
988 	if (offset & 1)
989 		return m_dsp_regs[m_dsp_addr & 0x7f];
990 
991 	return m_dsp_addr;
992 }
993 
dsp_io_w(offs_t offset,u8 data)994 void s_dsp_device::dsp_io_w(offs_t offset, u8 data)
995 {
996 	m_channel->update();
997 
998 	if (offset & 1)
999 	{
1000 		if (!(m_dsp_addr & 0x80))
1001 		{
1002 			offset = m_dsp_addr & 0x7f;
1003 			if (offset == 0x7c)
1004 			{
1005 				/* Writes to register 0x7c (ENDX) clear ALL bits no matter which value is written */
1006 				m_dsp_regs[offset & 0x7f] = 0;
1007 			}
1008 			else
1009 			{
1010 				/* All other writes store the value in the addressed register as expected. */
1011 				m_dsp_regs[offset & 0x7f] = data;
1012 			}
1013 		}
1014 	}
1015 	else
1016 		m_dsp_addr = data;
1017 }
1018 
1019 /*****************************************************************************
1020     DEVICE INTERFACE
1021 *****************************************************************************/
1022 
state_register()1023 void s_dsp_device::state_register()
1024 {
1025 	save_item(NAME(m_dsp_addr));
1026 	save_item(NAME(m_dsp_regs));
1027 
1028 	save_item(NAME(m_keyed_on));
1029 	save_item(NAME(m_keys));
1030 
1031 	save_item(NAME(m_noise_cnt));
1032 	save_item(NAME(m_noise_lev));
1033 
1034 #ifndef NO_ECHO
1035 	save_item(NAME(m_fir_lbuf));
1036 	save_item(NAME(m_fir_rbuf));
1037 	save_item(NAME(m_fir_ptr));
1038 	save_item(NAME(m_echo_ptr));
1039 #endif
1040 
1041 	for (int v = 0; v < 8; v++)
1042 	{
1043 		save_item(NAME(m_voice_state[v].mem_ptr), v);
1044 		save_item(NAME(m_voice_state[v].end), v);
1045 		save_item(NAME(m_voice_state[v].envcnt), v);
1046 		save_item(NAME(m_voice_state[v].envstate), v);
1047 		save_item(NAME(m_voice_state[v].envx), v);
1048 		save_item(NAME(m_voice_state[v].filter), v);
1049 		save_item(NAME(m_voice_state[v].half), v);
1050 		save_item(NAME(m_voice_state[v].header_cnt), v);
1051 		save_item(NAME(m_voice_state[v].mixfrac), v);
1052 		save_item(NAME(m_voice_state[v].on_cnt), v);
1053 		save_item(NAME(m_voice_state[v].pitch), v);
1054 		save_item(NAME(m_voice_state[v].range), v);
1055 		save_item(NAME(m_voice_state[v].samp_id), v);
1056 		save_item(NAME(m_voice_state[v].sampptr), v);
1057 		save_item(NAME(m_voice_state[v].smp1), v);
1058 		save_item(NAME(m_voice_state[v].smp2), v);
1059 		save_item(NAME(m_voice_state[v].sampbuf), v);
1060 	}
1061 }
1062 
1063 //-------------------------------------------------
1064 //  sound_stream_update - handle a stream update
1065 //-------------------------------------------------
1066 
sound_stream_update(sound_stream & stream,std::vector<read_stream_view> const & inputs,std::vector<write_stream_view> & outputs)1067 void s_dsp_device::sound_stream_update(sound_stream &stream, std::vector<read_stream_view> const &inputs, std::vector<write_stream_view> &outputs)
1068 {
1069 	s16 mix[2];
1070 
1071 	for (int i = 0; i < outputs[0].samples(); i++)
1072 	{
1073 		mix[0] = mix[1] = 0;
1074 		dsp_update(mix);
1075 
1076 		/* Update the buffers */
1077 		outputs[0].put_int(i, (s32)mix[0], 32768);
1078 		outputs[1].put_int(i, (s32)mix[1], 32768);
1079 	}
1080 }
1081