From 49e9851b24f4e606e1bf55b20beeed21caafb719 Mon Sep 17 00:00:00 2001 From: "R. Belmont" Date: Sun, 7 Feb 2010 04:59:42 +0000 Subject: [PATCH] Add and hook up ZOOM ZSG-2 skeleton [Olivier Galibert] Doesn't do much at the moment, but the increase in documentation value is significant (we're documenting the sample compression format, for one thing). --- .gitattributes | 2 + src/emu/sound/sound.mak | 9 ++ src/emu/sound/zsg2.c | 251 ++++++++++++++++++++++++++++++++++++++ src/emu/sound/zsg2.h | 22 ++++ src/mame/audio/taito_zm.c | 18 ++- src/mame/mame.mak | 2 +- 6 files changed, 300 insertions(+), 4 deletions(-) create mode 100644 src/emu/sound/zsg2.c create mode 100644 src/emu/sound/zsg2.h diff --git a/.gitattributes b/.gitattributes index ba4e89dc818..5bd06e41a29 100644 --- a/.gitattributes +++ b/.gitattributes @@ -999,6 +999,8 @@ src/emu/sound/ymf278b.c svneol=native#text/plain src/emu/sound/ymf278b.h svneol=native#text/plain src/emu/sound/ymz280b.c svneol=native#text/plain src/emu/sound/ymz280b.h svneol=native#text/plain +src/emu/sound/zsg2.c svneol=native#text/plain +src/emu/sound/zsg2.h svneol=native#text/plain src/emu/state.c svneol=native#text/plain src/emu/state.h svneol=native#text/plain src/emu/streams.c svneol=native#text/plain diff --git a/src/emu/sound/sound.mak b/src/emu/sound/sound.mak index f779a9feb03..5128659471f 100644 --- a/src/emu/sound/sound.mak +++ b/src/emu/sound/sound.mak @@ -648,3 +648,12 @@ endif ifneq ($(filter YMZ280B,$(SOUNDS)),) SOUNDOBJS += $(SOUNDOBJ)/ymz280b.o endif + +#------------------------------------------------- +# ZOOM ZSG-2 +#------------------------------------------------- + +ifneq ($(filter ZSG2,$(SOUNDS)),) +SOUNDOBJS += $(SOUNDOBJ)/zsg2.o +endif + diff --git a/src/emu/sound/zsg2.c b/src/emu/sound/zsg2.c new file mode 100644 index 00000000000..932403f1745 --- /dev/null +++ b/src/emu/sound/zsg2.c @@ -0,0 +1,251 @@ +/* + ZOOM ZSG-2 custom wavetable synthesizer + + Written by Olivier Galibert + MAME conversion by R. Belmont + + Copyright Nicola Salmoria and the MAME Team. + Visit http://mamedev.org for licensing and usage restrictions. + + --------------------------------------------------------- + + Additional notes on the sample format, reverse-engineered + by Olivier Galibert and David Haywood: + + The zoom sample rom is decomposed in 0x40000 bytes pages. Each page + starts by a header and is followed by compressed samples. + + The header is a vector of 16 bytes structures composed of 4 32bits + little-endian values representing: + - sample start position in bytes, always a multiple of 4 + - sample end position in bytes, minus 4, always... + - loop position in bytes, always.... + - flags, probably + + The samples are compressed with a 2:1 ratio. Each bloc of 4-bytes + becomes 4 16-bits samples. Reading the 4 bytes as a *little-endian* + 32bits values, the structure is: + + 1444 4444 1333 3333 1222 2222 ssss1111 + + 's' is a 4-bit scale value. '1', '2', '3', '4' are signed 7-bits + values corresponding to the 4 samples. To compute the final 16bits + value just shift left by (9-s). Yes, that simple. + +*/ + +#include "emu.h" +#include "streams.h" +#include "zsg2.h" + +typedef struct _zchan zchan; +struct _zchan +{ + UINT16 v[16]; +}; + +typedef struct _zsg2_state zsg2_state; +struct _zsg2_state +{ + zchan zc[48]; + UINT16 act[3]; + UINT16 alow, ahigh; + UINT8 *bank_samples; + + int sample_rate; + sound_stream *stream; +}; + +INLINE zsg2_state *get_safe_token(running_device *device) +{ + assert(device != NULL); + assert(device->token != NULL); + assert(device->type == SOUND); + assert(sound_get_type(device) == SOUND_ZSG2); + return (zsg2_state *)device->token; +} + +static STREAM_UPDATE( update_stereo ) +{ +// zsg2_state *info = (zsg2_state *)param; + stream_sample_t *dest1 = outputs[0]; + stream_sample_t *dest2 = outputs[1]; + + memset(dest1, 0, sizeof(stream_sample_t) * samples); + memset(dest2, 0, sizeof(stream_sample_t) * samples); +} + +static void chan_w(zsg2_state *info, int chan, int reg, UINT16 data) +{ + info->zc[chan].v[reg] = data; + // log_event("ZOOMCHAN", "chan %02x reg %x = %04x", chan, reg, data); +} + +static UINT16 chan_r(zsg2_state *info, int chan, int reg) +{ + // log_event("ZOOMCHAN", "chan %02x read reg %x: %04x", chan, reg, zc[chan].v[reg]); + return info->zc[chan].v[reg]; +} + +static void check_channel(zsg2_state *info, int chan) +{ + // log_event("ZOOM", "chan %02x e=%04x f=%04x", chan, zc[chan].v[14], zc[chan].v[15]); +} + +static void keyon(zsg2_state *info, int chan) +{ +#if 0 + log_event("ZOOM", "keyon %02x %04x %04x %04x %04x %04x %04x %04x %04x %04x %04x %04x %04x %04x %04x %04x %04x", + chan, + info->zc[chan].v[0x0], info->zc[chan].v[0x1], info->zc[chan].v[0x2], info->zc[chan].v[0x3], + info->zc[chan].v[0x4], info->zc[chan].v[0x5], info->zc[chan].v[0x6], info->zc[chan].v[0x7], + info->zc[chan].v[0x8], info->zc[chan].v[0x9], info->zc[chan].v[0xa], info->zc[chan].v[0xb], + info->zc[chan].v[0xc], info->zc[chan].v[0xd], info->zc[chan].v[0xe], info->zc[chan].v[0xf]); +#endif +} + +static void control_w(zsg2_state *info, int reg, UINT16 data) +{ + switch(reg) + { + case 0x00: case 0x02: case 0x04: + { + int base = (reg & 6) << 3; + int i; + for(i=0; i<16; i++) + if(data & (1<alow = data; + break; + + case 0x3a: + info->ahigh = data; + break; + + default: + // log_event("ZOOMCTRL", "%02x = %04x", reg, data); + break; + } +} + +static UINT16 control_r(zsg2_state *info, int reg) +{ + switch(reg) + { + case 0x28: + return 0xff00; + + case 0x3c: case 0x3e: + { + UINT32 adr = (info->ahigh << 16) | info->alow; + UINT32 val = *(unsigned int *)(info->bank_samples+adr); +// log_event("ZOOMCTRL", "rom read.%c %06x = %08x", reg == 0x3e ? 'h' : 'l', adr, val); + return (reg == 0x3e) ? (val >> 16) : val; + } + } + +// log_event("ZOOMCTRL", "read %02x", reg); + + return 0xffff; +} + +WRITE16_DEVICE_HANDLER( zsg2_w ) +{ + zsg2_state *info = get_safe_token(device); + int adr = offset * 2; + + assert(mem_mask == 0xffff); // we only support full 16-bit accesses + + stream_update(info->stream); + + if (adr < 0x600) + { + int chan = adr >> 5; + int reg = (adr >> 1) & 15; + + chan_w(info, chan, reg, data); + } + else + { + control_w(info, adr - 0x600, data); + } +} + +READ16_DEVICE_HANDLER( zsg2_r ) +{ + zsg2_state *info = get_safe_token(device); + int adr = offset * 2; + + assert(mem_mask == 0xffff); // we only support full 16-bit accesses + + if (adr < 0x600) + { + int chan = adr >> 5; + int reg = (adr >> 1) & 15; + return chan_r(info, chan, reg); + } + else + { + return control_r(info, adr - 0x600); + } + + return 0; +} + +static DEVICE_START( zsg2 ) +{ + const zsg2_interface *intf = (const zsg2_interface *)device->baseconfig().static_config; + zsg2_state *info = get_safe_token(device); + + info->sample_rate = device->clock; + + memset(&info->zc, 0, sizeof(info->zc)); + memset(&info->act, 0, sizeof(info->act)); + + info->stream = stream_create(device, 0, 2, info->sample_rate, info, update_stereo); + + info->bank_samples = memory_region(device->machine, intf->samplergn); +} + +/************************************************************************** + * Generic get_info + **************************************************************************/ + +DEVICE_GET_INFO( zsg2 ) +{ + switch (state) + { + /* --- the following bits of info are returned as 64-bit signed integers --- */ + case DEVINFO_INT_TOKEN_BYTES: info->i = sizeof(zsg2_state); break; + + /* --- the following bits of info are returned as pointers to data or functions --- */ + case DEVINFO_FCT_START: info->start = DEVICE_START_NAME( zsg2 ); 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, "ZSG-2"); break; + case DEVINFO_STR_FAMILY: strcpy(info->s, "Zoom 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; + } +} + diff --git a/src/emu/sound/zsg2.h b/src/emu/sound/zsg2.h new file mode 100644 index 00000000000..4947c8c143c --- /dev/null +++ b/src/emu/sound/zsg2.h @@ -0,0 +1,22 @@ +/* + ZOOM ZSG-2 custom wavetable synthesizer +*/ + +#pragma once + +#ifndef __ZSG2_H__ +#define __ZSG2_H__ + +READ16_DEVICE_HANDLER( zsg2_r ); +WRITE16_DEVICE_HANDLER( zsg2_w ); + +typedef struct _zsg2_interface zsg2_interface; +struct _zsg2_interface +{ + const char *samplergn; +}; + +DEVICE_GET_INFO( zsg2 ); +#define SOUND_ZSG2 DEVICE_GET_INFO_NAME( zsg2 ) + +#endif /* __ZSG2_H__ */ diff --git a/src/mame/audio/taito_zm.c b/src/mame/audio/taito_zm.c index 5ce66faf7ae..749b4e2209c 100644 --- a/src/mame/audio/taito_zm.c +++ b/src/mame/audio/taito_zm.c @@ -1,7 +1,7 @@ /*************************************************************************** - Taito Zoom ZSG-1 sound board - Includes: MN10200 CPU, ZOOM ZSG-1 audio chip, TMS57002 DASP + Taito Zoom ZSG-2 sound board + Includes: MN10200 CPU, ZOOM ZSG-2 audio chip, TMS57002 DASP By Olivier Galibert. Copyright Nicola Salmoria and the MAME Team. @@ -13,11 +13,12 @@ #include "cpu/mn10200/mn10200.h" #include "cpu/tms57002/tms57002.h" #include "audio/taito_zm.h" +#include "sound/zsg2.h" static ADDRESS_MAP_START(taitozoom_map, ADDRESS_SPACE_PROGRAM, 16) AM_RANGE(0x080000, 0x0fffff) AM_ROM AM_REGION("mn10200", 0) AM_RANGE(0x400000, 0x40ffff) AM_RAM - AM_RANGE(0x800000, 0x800fff) AM_RAM // Zoom ZSG-1 + AM_RANGE(0x800000, 0x800fff) AM_DEVREADWRITE("zsg2", zsg2_r, zsg2_w) AM_RANGE(0xe00000, 0xe000ff) AM_RAM // main CPU comms? AM_RANGE(0xc00000, 0xc00001) AM_RAM // TMS57002 comms ADDRESS_MAP_END @@ -44,8 +45,19 @@ static ADDRESS_MAP_START(taitozoom_io_map, ADDRESS_SPACE_IO, 8) AM_RANGE(MN10200_PORT1, MN10200_PORT1) AM_READWRITE(tms_ctrl_r, tms_ctrl_w) ADDRESS_MAP_END +static const zsg2_interface zsg2_taito_config = +{ + "zsg2" /* sample region */ +}; + MACHINE_DRIVER_START( taito_zoom_sound ) MDRV_CPU_ADD("mn10200", MN10200, 25000000/2) MDRV_CPU_PROGRAM_MAP(taitozoom_map) MDRV_CPU_IO_MAP(taitozoom_io_map) + + // we assume the parent machine has created lspeaker/rspeaker + MDRV_SOUND_ADD("zsg2", ZSG2, 25000000/2) + MDRV_SOUND_CONFIG(zsg2_taito_config) + MDRV_SOUND_ROUTE(0, "lspeaker", 1.0) + MDRV_SOUND_ROUTE(1, "rspeaker", 1.0) MACHINE_DRIVER_END diff --git a/src/mame/mame.mak b/src/mame/mame.mak index d3dced3f7ff..69855e35c1c 100644 --- a/src/mame/mame.mak +++ b/src/mame/mame.mak @@ -220,7 +220,7 @@ SOUNDS += SP0256 SOUNDS += DIGITALKER SOUNDS += CDP1863 SOUNDS += CDP1864 - +SOUNDS += ZSG2 #------------------------------------------------- # this is the list of driver libraries that