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