summaryrefslogtreecommitdiffstatshomepage
path: root/trunk/src/emu/sound/nile.c
diff options
context:
space:
mode:
Diffstat (limited to 'trunk/src/emu/sound/nile.c')
-rw-r--r--trunk/src/emu/sound/nile.c261
1 files changed, 261 insertions, 0 deletions
diff --git a/trunk/src/emu/sound/nile.c b/trunk/src/emu/sound/nile.c
new file mode 100644
index 00000000000..3ef19009fdb
--- /dev/null
+++ b/trunk/src/emu/sound/nile.c
@@ -0,0 +1,261 @@
+/************************************
+ Seta custom Nile ST-0026 chip
+ sound emulation by Tomasz Slanina
+ based on ST-0016 emulation
+
+8 voices, 16 words of config data for each:
+
+ 00
+ 01 - sptr ?? (always 0)
+ 02 - sptr LO
+ 03 - sptr HI
+ 04
+ 05 - flags? 00000000 0000?L0? - bit 0 loops, other bits appear to be not used by the chip
+ 06 - freq
+ 07 - lsptr LO
+ 08
+ 09 - lsptr HI
+ 0a - leptr LO
+ 0b - leptr HI
+ 0c - eptr LO
+ 0d - eptr HI
+ 0e - vol R
+ 0f - vol L
+
+************************************/
+
+#include "emu.h"
+#include "nile.h"
+
+#define NILE_VOICES 8
+
+enum
+{
+ NILE_REG_UNK0=0,
+ NILE_REG_SPTR_TOP,
+ NILE_REG_SPTR_LO,
+ NILE_REG_SPTR_HI,
+ NILE_REG_UNK_4,
+ NILE_REG_FLAGS,
+ NILE_REG_FREQ,
+ NILE_REG_LSPTR_LO,
+ MILE_REG_UNK_8,
+ NILE_REG_LSPTR_HI,
+ NILE_REG_LEPTR_LO,
+ NILE_REG_LEPTR_HI,
+ NILE_REG_EPTR_LO,
+ NILE_REG_EPTR_HI,
+ NILE_REG_VOL_R,
+ NILE_REG_VOL_L
+};
+
+
+
+typedef struct _nile_state nile_state;
+struct _nile_state
+{
+ sound_stream * stream;
+ UINT8 *sound_ram;
+ UINT16 sound_regs[0x80];
+ int vpos[NILE_VOICES], frac[NILE_VOICES], lponce[NILE_VOICES];
+ UINT16 ctrl;
+};
+
+INLINE nile_state *get_safe_token(device_t *device)
+{
+ assert(device != NULL);
+ assert(device->type() == NILE);
+ return (nile_state *)downcast<legacy_device_base *>(device)->token();
+}
+
+
+WRITE16_DEVICE_HANDLER( nile_sndctrl_w )
+{
+ nile_state *info = get_safe_token(device);
+ UINT16 ctrl=info->ctrl;
+
+ info->stream->update();
+
+ COMBINE_DATA(&info->ctrl);
+
+// printf("CTRL: %04x -> %04x (PC=%x)\n", ctrl, info->ctrl, cpu_get_pc(&space->device()));
+
+ ctrl^=info->ctrl;
+}
+
+READ16_DEVICE_HANDLER( nile_sndctrl_r )
+{
+ nile_state *info = get_safe_token(device);
+
+ info->stream->update();
+
+ return info->ctrl;
+}
+
+READ16_DEVICE_HANDLER( nile_snd_r )
+{
+ nile_state *info = get_safe_token(device);
+ int reg=offset&0xf;
+
+ info->stream->update();
+
+ if(reg==2 || reg==3)
+ {
+ int slot=offset/16;
+ int sptr = ((info->sound_regs[slot*16+3]<<16)|info->sound_regs[slot*16+2])+info->vpos[slot];
+
+ if(reg==2)
+ {
+ return sptr&0xffff;
+ }
+ else
+ {
+ return sptr>>16;
+ }
+ }
+ return info->sound_regs[offset];
+}
+
+WRITE16_DEVICE_HANDLER( nile_snd_w )
+{
+ nile_state *info = get_safe_token(device);
+ int v, r;
+
+ info->stream->update();
+
+ COMBINE_DATA(&info->sound_regs[offset]);
+
+ v = offset / 16;
+ r = offset % 16;
+
+ if ((r == 2) || (r == 3))
+ {
+ info->vpos[v] = info->frac[v] = info->lponce[v] = 0;
+ }
+
+ //printf("v%02d: %04x to reg %02d (PC=%x)\n", v, info->sound_regs[offset], r, cpu_get_pc(&space->device()));
+}
+
+static STREAM_UPDATE( nile_update )
+{
+ nile_state *info = (nile_state *)param;
+ UINT8 *sound_ram = info->sound_ram;
+ int v, i, snum;
+ UINT16 *slot;
+ INT32 mix[48000*2];
+ INT32 *mixp;
+ INT16 sample;
+ int sptr, eptr, freq, lsptr, leptr;
+
+ lsptr=leptr=0;
+
+ memset(mix, 0, sizeof(mix[0])*samples*2);
+
+ for (v = 0; v < NILE_VOICES; v++)
+ {
+ slot = &info->sound_regs[v * 16];
+
+ if (info->ctrl&(1<<v))
+ {
+ mixp = &mix[0];
+
+ sptr = slot[NILE_REG_SPTR_HI]<<16 | slot[NILE_REG_SPTR_LO];
+ eptr = slot[NILE_REG_EPTR_HI]<<16 | slot[NILE_REG_EPTR_LO];
+
+ freq=slot[NILE_REG_FREQ]*14;
+ lsptr = slot[NILE_REG_LSPTR_HI]<<16 | slot[NILE_REG_LSPTR_LO];
+ leptr = slot[NILE_REG_LEPTR_HI]<<16 | slot[NILE_REG_LEPTR_LO];
+
+ for (snum = 0; snum < samples; snum++)
+ {
+ sample = sound_ram[sptr + info->vpos[v]]<<8;
+
+ *mixp++ += (sample * (INT32)slot[NILE_REG_VOL_R]) >> 16;
+ *mixp++ += (sample * (INT32)slot[NILE_REG_VOL_L]) >> 16;
+
+ info->frac[v] += freq;
+ info->vpos[v] += info->frac[v]>>16;
+ info->frac[v] &= 0xffff;
+
+ // stop if we're at the end
+ if (info->lponce[v])
+ {
+ // we've looped once, check loop end rather than sample end
+ if ((info->vpos[v] + sptr) >= leptr)
+ {
+ info->vpos[v] = (lsptr - sptr);
+ }
+ }
+ else
+ {
+ // not looped yet, check sample end
+ if ((info->vpos[v] + sptr) >= eptr)
+ {
+ // code at 11d8c:
+ // if bit 2 (0x4) is set, check if loop start = loop end.
+ // if they are equal, clear bit 0 and don't set the loop start/end
+ // registers in the NiLe. if they aren't, set bit 0 and set
+ // the loop start/end registers in the NiLe.
+ if ((slot[NILE_REG_FLAGS] & 0x5) == 0x5)
+ {
+ info->vpos[v] = (lsptr - sptr);
+ info->lponce[v] = 1;
+ }
+ else
+ {
+ info->ctrl &= ~(1<<v);
+ info->vpos[v] = (eptr - sptr);
+ info->frac[v] = 0;
+ }
+
+ }
+ }
+ }
+ }
+ }
+ mixp = &mix[0];
+ for (i = 0; i < samples; i++)
+ {
+ outputs[0][i] = (*mixp++)>>4;
+ outputs[1][i] = (*mixp++)>>4;
+ }
+}
+
+static DEVICE_START( nile )
+{
+ nile_state *info = get_safe_token(device);
+
+ info->sound_ram = *device->region();
+
+ info->stream = device->machine().sound().stream_alloc(*device, 0, 2, 44100, info, nile_update);
+}
+
+
+
+/**************************************************************************
+ * Generic get_info
+ **************************************************************************/
+
+DEVICE_GET_INFO( nile )
+{
+ switch (state)
+ {
+ /* --- the following bits of info are returned as 64-bit signed integers --- */
+ case DEVINFO_INT_TOKEN_BYTES: info->i = sizeof(nile_state); break;
+
+ /* --- the following bits of info are returned as pointers to data or functions --- */
+ case DEVINFO_FCT_START: info->start = DEVICE_START_NAME( nile ); break;
+ case DEVINFO_FCT_STOP: /* Nothing */ break;
+ case DEVINFO_FCT_RESET: /* Nothing */ break;
+
+ /* --- the following bits of info are returned as NULL-terminated strings --- */
+ case DEVINFO_STR_NAME: strcpy(info->s, "NiLe"); break;
+ case DEVINFO_STR_FAMILY: strcpy(info->s, "Seta custom"); break;
+ case DEVINFO_STR_VERSION: strcpy(info->s, "1.0"); break;
+ case DEVINFO_STR_SOURCE_FILE: strcpy(info->s, __FILE__); break;
+ case DEVINFO_STR_CREDITS: strcpy(info->s, "Copyright Nicola Salmoria and the MAME Team"); break;
+ }
+}
+
+
+DEFINE_LEGACY_SOUND_DEVICE(NILE, nile);