mirror of
https://github.com/holub/mame
synced 2025-06-03 11:26:56 +03:00
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).
This commit is contained in:
parent
1f76758746
commit
49e9851b24
2
.gitattributes
vendored
2
.gitattributes
vendored
@ -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/ymf278b.h svneol=native#text/plain
|
||||||
src/emu/sound/ymz280b.c 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/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.c svneol=native#text/plain
|
||||||
src/emu/state.h svneol=native#text/plain
|
src/emu/state.h svneol=native#text/plain
|
||||||
src/emu/streams.c svneol=native#text/plain
|
src/emu/streams.c svneol=native#text/plain
|
||||||
|
@ -648,3 +648,12 @@ endif
|
|||||||
ifneq ($(filter YMZ280B,$(SOUNDS)),)
|
ifneq ($(filter YMZ280B,$(SOUNDS)),)
|
||||||
SOUNDOBJS += $(SOUNDOBJ)/ymz280b.o
|
SOUNDOBJS += $(SOUNDOBJ)/ymz280b.o
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
#-------------------------------------------------
|
||||||
|
# ZOOM ZSG-2
|
||||||
|
#-------------------------------------------------
|
||||||
|
|
||||||
|
ifneq ($(filter ZSG2,$(SOUNDS)),)
|
||||||
|
SOUNDOBJS += $(SOUNDOBJ)/zsg2.o
|
||||||
|
endif
|
||||||
|
|
||||||
|
251
src/emu/sound/zsg2.c
Normal file
251
src/emu/sound/zsg2.c
Normal file
@ -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<<i))
|
||||||
|
keyon(info, base+i);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case 0x08: case 0x0a: case 0x0c:
|
||||||
|
{
|
||||||
|
int base = (reg & 6) << 3;
|
||||||
|
int i;
|
||||||
|
for(i=0; i<16; i++)
|
||||||
|
if(data & (1<<i))
|
||||||
|
check_channel(info, base+i);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case 0x30:
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 0x38:
|
||||||
|
info->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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
22
src/emu/sound/zsg2.h
Normal file
22
src/emu/sound/zsg2.h
Normal file
@ -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__ */
|
@ -1,7 +1,7 @@
|
|||||||
/***************************************************************************
|
/***************************************************************************
|
||||||
|
|
||||||
Taito Zoom ZSG-1 sound board
|
Taito Zoom ZSG-2 sound board
|
||||||
Includes: MN10200 CPU, ZOOM ZSG-1 audio chip, TMS57002 DASP
|
Includes: MN10200 CPU, ZOOM ZSG-2 audio chip, TMS57002 DASP
|
||||||
By Olivier Galibert.
|
By Olivier Galibert.
|
||||||
|
|
||||||
Copyright Nicola Salmoria and the MAME Team.
|
Copyright Nicola Salmoria and the MAME Team.
|
||||||
@ -13,11 +13,12 @@
|
|||||||
#include "cpu/mn10200/mn10200.h"
|
#include "cpu/mn10200/mn10200.h"
|
||||||
#include "cpu/tms57002/tms57002.h"
|
#include "cpu/tms57002/tms57002.h"
|
||||||
#include "audio/taito_zm.h"
|
#include "audio/taito_zm.h"
|
||||||
|
#include "sound/zsg2.h"
|
||||||
|
|
||||||
static ADDRESS_MAP_START(taitozoom_map, ADDRESS_SPACE_PROGRAM, 16)
|
static ADDRESS_MAP_START(taitozoom_map, ADDRESS_SPACE_PROGRAM, 16)
|
||||||
AM_RANGE(0x080000, 0x0fffff) AM_ROM AM_REGION("mn10200", 0)
|
AM_RANGE(0x080000, 0x0fffff) AM_ROM AM_REGION("mn10200", 0)
|
||||||
AM_RANGE(0x400000, 0x40ffff) AM_RAM
|
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(0xe00000, 0xe000ff) AM_RAM // main CPU comms?
|
||||||
AM_RANGE(0xc00000, 0xc00001) AM_RAM // TMS57002 comms
|
AM_RANGE(0xc00000, 0xc00001) AM_RAM // TMS57002 comms
|
||||||
ADDRESS_MAP_END
|
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)
|
AM_RANGE(MN10200_PORT1, MN10200_PORT1) AM_READWRITE(tms_ctrl_r, tms_ctrl_w)
|
||||||
ADDRESS_MAP_END
|
ADDRESS_MAP_END
|
||||||
|
|
||||||
|
static const zsg2_interface zsg2_taito_config =
|
||||||
|
{
|
||||||
|
"zsg2" /* sample region */
|
||||||
|
};
|
||||||
|
|
||||||
MACHINE_DRIVER_START( taito_zoom_sound )
|
MACHINE_DRIVER_START( taito_zoom_sound )
|
||||||
MDRV_CPU_ADD("mn10200", MN10200, 25000000/2)
|
MDRV_CPU_ADD("mn10200", MN10200, 25000000/2)
|
||||||
MDRV_CPU_PROGRAM_MAP(taitozoom_map)
|
MDRV_CPU_PROGRAM_MAP(taitozoom_map)
|
||||||
MDRV_CPU_IO_MAP(taitozoom_io_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
|
MACHINE_DRIVER_END
|
||||||
|
@ -220,7 +220,7 @@ SOUNDS += SP0256
|
|||||||
SOUNDS += DIGITALKER
|
SOUNDS += DIGITALKER
|
||||||
SOUNDS += CDP1863
|
SOUNDS += CDP1863
|
||||||
SOUNDS += CDP1864
|
SOUNDS += CDP1864
|
||||||
|
SOUNDS += ZSG2
|
||||||
|
|
||||||
#-------------------------------------------------
|
#-------------------------------------------------
|
||||||
# this is the list of driver libraries that
|
# this is the list of driver libraries that
|
||||||
|
Loading…
Reference in New Issue
Block a user