diff options
Diffstat (limited to 'trunk/src/emu/sound/st0016.c')
-rw-r--r-- | trunk/src/emu/sound/st0016.c | 176 |
1 files changed, 176 insertions, 0 deletions
diff --git a/trunk/src/emu/sound/st0016.c b/trunk/src/emu/sound/st0016.c new file mode 100644 index 00000000000..e67e235f9d5 --- /dev/null +++ b/trunk/src/emu/sound/st0016.c @@ -0,0 +1,176 @@ +/************************************ + Seta custom ST-0016 chip + sound emulation by R. Belmont, Tomasz Slanina, and David Haywood +************************************/ + +#include "emu.h" +#include "st0016.h" + +#define VERBOSE (0) +#define LOG(x) do { if (VERBOSE) logerror x; } while (0) + +typedef struct _st0016_state st0016_state; +struct _st0016_state +{ + sound_stream * stream; + UINT8 **sound_ram; + int vpos[8], frac[8], lponce[8]; + UINT8 regs[0x100]; +}; + +INLINE st0016_state *get_safe_token(device_t *device) +{ + assert(device != NULL); + assert(device->type() == ST0016); + return (st0016_state *)downcast<legacy_device_base *>(device)->token(); +} + + +READ8_DEVICE_HANDLER( st0016_snd_r ) +{ + st0016_state *info = get_safe_token(device); + return info->regs[offset]; +} + +WRITE8_DEVICE_HANDLER( st0016_snd_w ) +{ + st0016_state *info = get_safe_token(device); + int voice = offset/32; + int reg = offset & 0x1f; + int oldreg = info->regs[offset]; + int vbase = offset & ~0x1f; + + info->regs[offset] = data; + + if ((voice < 8) && (data != oldreg)) + { + if ((reg == 0x16) && (data != 0)) + { + info->vpos[voice] = info->frac[voice] = info->lponce[voice] = 0; + + LOG(("Key on V%02d: st %06x-%06x lp %06x-%06x frq %x flg %x\n", voice, + info->regs[vbase+2]<<16 | info->regs[vbase+1]<<8 | info->regs[vbase+2], + info->regs[vbase+0xe]<<16 | info->regs[vbase+0xd]<<8 | info->regs[vbase+0xc], + info->regs[vbase+6]<<16 | info->regs[vbase+5]<<8 | info->regs[vbase+4], + info->regs[vbase+0xa]<<16 | info->regs[vbase+0x9]<<8 | info->regs[vbase+0x8], + info->regs[vbase+0x11]<<8 | info->regs[vbase+0x10], + info->regs[vbase+0x16])); + } + } +} + +static STREAM_UPDATE( st0016_update ) +{ + st0016_state *info = (st0016_state *)param; + UINT8 *sound_ram = *info->sound_ram; + int v, i, snum; + unsigned char *slot; + INT32 mix[48000*2]; + INT32 *mixp; + INT16 sample; + int sptr, eptr, freq, lsptr, leptr; + + memset(mix, 0, sizeof(mix[0])*samples*2); + + for (v = 0; v < 8; v++) + { + slot = (unsigned char *)&info->regs[v * 32]; + + if (slot[0x16] & 0x06) + { + mixp = &mix[0]; + + sptr = slot[0x02]<<16 | slot[0x01]<<8 | slot[0x00]; + eptr = slot[0x0e]<<16 | slot[0x0d]<<8 | slot[0x0c]; + freq = slot[0x11]<<8 | slot[0x10]; + lsptr = slot[0x06]<<16 | slot[0x05]<<8 | slot[0x04]; + leptr = slot[0x0a]<<16 | slot[0x09]<<8 | slot[0x08]; + + for (snum = 0; snum < samples; snum++) + { + sample = sound_ram[(sptr + info->vpos[v])&0x1fffff]<<8; + + *mixp++ += (sample * (char)slot[0x14]) >> 8; + *mixp++ += (sample * (char)slot[0x15]) >> 8; + + 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) + { + if (slot[0x16] & 0x01) // loop? + { + info->vpos[v] = (lsptr - sptr); + info->lponce[v] = 1; + } + else + { + slot[0x16] = 0; + info->vpos[v] = 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( st0016 ) +{ + const st0016_interface *intf = (const st0016_interface *)device->static_config(); + st0016_state *info = get_safe_token(device); + + info->sound_ram = intf->p_soundram; + + info->stream = device->machine().sound().stream_alloc(*device, 0, 2, 44100, info, st0016_update); +} + + + +/************************************************************************** + * Generic get_info + **************************************************************************/ + +DEVICE_GET_INFO( st0016 ) +{ + switch (state) + { + /* --- the following bits of info are returned as 64-bit signed integers --- */ + case DEVINFO_INT_TOKEN_BYTES: info->i = sizeof(st0016_state); break; + + /* --- the following bits of info are returned as pointers to data or functions --- */ + case DEVINFO_FCT_START: info->start = DEVICE_START_NAME( st0016 ); 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, "ST0016"); 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(ST0016, st0016); |