diff options
| -rw-r--r-- | .gitattributes | 2 | ||||
| -rw-r--r-- | src/emu/sndintrf.c | 1 | ||||
| -rw-r--r-- | src/emu/sndintrf.h | 1 | ||||
| -rw-r--r-- | src/emu/sound/okim6258.c | 494 | ||||
| -rw-r--r-- | src/emu/sound/okim6258.h | 41 | ||||
| -rw-r--r-- | src/emu/sound/sound.mak | 5 | ||||
| -rw-r--r-- | src/mame/mame.mak | 3 |
7 files changed, 546 insertions, 1 deletions
diff --git a/.gitattributes b/.gitattributes index 6be2931761b..79553880e34 100644 --- a/.gitattributes +++ b/.gitattributes @@ -834,6 +834,8 @@ src/emu/sound/nes_apu.h svneol=native#text/plain src/emu/sound/nes_defs.h svneol=native#text/plain src/emu/sound/nile.c svneol=native#text/plain src/emu/sound/nile.h svneol=native#text/plain +src/emu/sound/okim6258.c svneol=native#text/plain +src/emu/sound/okim6258.h svneol=native#text/plain src/emu/sound/okim6295.c svneol=native#text/plain src/emu/sound/okim6295.h svneol=native#text/plain src/emu/sound/pokey.c svneol=native#text/plain diff --git a/src/emu/sndintrf.c b/src/emu/sndintrf.c index c6671698f46..c7dccc2e52d 100644 --- a/src/emu/sndintrf.c +++ b/src/emu/sndintrf.c @@ -121,6 +121,7 @@ SND_GET_INFO( tms5220 ); SND_GET_INFO( vlm5030 ); SND_GET_INFO( adpcm ); SND_GET_INFO( okim6295 ); +SND_GET_INFO( okim6258 ); SND_GET_INFO( msm5205 ); SND_GET_INFO( msm5232 ); SND_GET_INFO( upd7759 ); diff --git a/src/emu/sndintrf.h b/src/emu/sndintrf.h index 73dc9629cd2..7db71a1385e 100644 --- a/src/emu/sndintrf.h +++ b/src/emu/sndintrf.h @@ -84,6 +84,7 @@ enum _sound_type SOUND_TMS5220, SOUND_VLM5030, SOUND_OKIM6295, + SOUND_OKIM6258, SOUND_MSM5205, SOUND_MSM5232, SOUND_UPD7759, diff --git a/src/emu/sound/okim6258.c b/src/emu/sound/okim6258.c new file mode 100644 index 00000000000..d00cea5a1de --- /dev/null +++ b/src/emu/sound/okim6258.c @@ -0,0 +1,494 @@ +/********************************************************************************************** + * + * OKI MSM6258 ADPCM + * + * TODO: + * 3-bit ADPCM support + * Recording? + * + **********************************************************************************************/ + + +#include <math.h> + +#include "sndintrf.h" +#include "deprecat.h" +#include "streams.h" +#include "okim6258.h" + +#define COMMAND_STOP (1 << 0) +#define COMMAND_PLAY (1 << 1) +#define COMMAND_RECORD (1 << 2) + +#define STATUS_PLAYING (1 << 1) +#define STATUS_RECORDING (1 << 2) + +static const int dividers[4] = { 1024, 768, 512, 512 }; + +struct okim6258 +{ + UINT8 status; + + UINT32 master_clock; /* master clock frequency */ + UINT32 divider; /* master clock divider */ + UINT8 adpcm_type; /* 3/4 bit ADPCM select */ + UINT8 data_in; /* ADPCM data-in register */ + UINT8 nibble_shift; /* nibble select */ + sound_stream *stream; /* which stream are we playing on? */ + + UINT8 output_bits; + + INT32 signal; + INT32 step; +}; + +/* step size index shift table */ +static const int index_shift[8] = { -1, -1, -1, -1, 2, 4, 6, 8 }; + +/* lookup table for the precomputed difference */ +static int diff_lookup[49*16]; + +/* tables computed? */ +static int tables_computed = 0; + +/********************************************************************************************** + + compute_tables -- compute the difference tables + +***********************************************************************************************/ + +static void compute_tables(void) +{ + /* nibble to bit map */ + static const int nbl2bit[16][4] = + { + { 1, 0, 0, 0}, { 1, 0, 0, 1}, { 1, 0, 1, 0}, { 1, 0, 1, 1}, + { 1, 1, 0, 0}, { 1, 1, 0, 1}, { 1, 1, 1, 0}, { 1, 1, 1, 1}, + {-1, 0, 0, 0}, {-1, 0, 0, 1}, {-1, 0, 1, 0}, {-1, 0, 1, 1}, + {-1, 1, 0, 0}, {-1, 1, 0, 1}, {-1, 1, 1, 0}, {-1, 1, 1, 1} + }; + + int step, nib; + + /* loop over all possible steps */ + for (step = 0; step <= 48; step++) + { + /* compute the step value */ + int stepval = floor(16.0 * pow(11.0 / 10.0, (double)step)); + + /* loop over all nibbles and compute the difference */ + for (nib = 0; nib < 16; nib++) + { + diff_lookup[step*16 + nib] = nbl2bit[nib][0] * + (stepval * nbl2bit[nib][1] + + stepval/2 * nbl2bit[nib][2] + + stepval/4 * nbl2bit[nib][3] + + stepval/8); + } + } + + tables_computed = 1; +} + + +static INT16 clock_adpcm(struct okim6258 *chip, UINT8 nibble) +{ + INT32 max = (1 << (chip->output_bits - 1)) - 1; + INT32 min = -(1 << (chip->output_bits - 1)); + + chip->signal += diff_lookup[chip->step * 16 + (nibble & 15)]; + + /* clamp to the maximum */ + if (chip->signal > max) + chip->signal = max; + else if (chip->signal < min) + chip->signal = min; + + /* adjust the step size and clamp */ + chip->step += index_shift[nibble & 7]; + if (chip->step > 48) + chip->step = 48; + else if (chip->step < 0) + chip->step = 0; + + /* return the signal scaled up to 32767 */ + return chip->signal << 4; +} + +/********************************************************************************************** + + okim6258_update -- update the sound chip so that it is in sync with CPU execution + +***********************************************************************************************/ + +static void okim6258_update(void *param, stream_sample_t **inputs, stream_sample_t **outputs, int samples) +{ + struct okim6258 *chip = param; + stream_sample_t *buffer = outputs[0]; + + memset(outputs[0], 0, samples * sizeof(*outputs[0])); + + if (chip->status & STATUS_PLAYING) + { + int nibble_shift = chip->nibble_shift; + + while (samples) + { + /* Compute the new amplitude and update the current step */ + int nibble = (chip->data_in >> nibble_shift) & 0xf; + + /* Output to the buffer */ + INT16 sample = clock_adpcm(chip, nibble); + + nibble_shift ^= 4; + + *buffer++ = sample; + samples--; + } + + /* Update the parameters */ + chip->nibble_shift = nibble_shift; + } + else + { + /* Fill with 0 */ + while (samples--) + *buffer++ = 0; + } +} + + + +/********************************************************************************************** + + state save support for MAME + +***********************************************************************************************/ + +static void okim6258_state_save_register(struct okim6258 *info, const char *tag) +{ + state_save_register_item("OKIM6258", tag, 0, info->status); + state_save_register_item("OKIM6258", tag, 0, info->master_clock); + state_save_register_item("OKIM6258", tag, 0, info->divider); + state_save_register_item("OKIM6258", tag, 0, info->data_in); + state_save_register_item("OKIM6258", tag, 0, info->nibble_shift); + state_save_register_item("OKIM6258", tag, 0, info->signal); + state_save_register_item("OKIM6258", tag, 0, info->step); +} + + +/********************************************************************************************** + + OKIM6258_start -- start emulation of an OKIM6258-compatible chip + +***********************************************************************************************/ + +static SND_START( okim6258 ) +{ + const okim6258_interface *intf = config; + struct okim6258 *info; + + info = auto_malloc(sizeof(*info)); + memset(info, 0, sizeof(*info)); + + compute_tables(); + + info->master_clock = clock; + info->adpcm_type = intf->adpcm_type; + + /* D/A precision is 10-bits but 12-bit data can be output serially to an external DAC */ + info->output_bits = intf->output_12bits ? 12 : 10; + info->divider = dividers[intf->divider]; + + info->stream = stream_create(0, 1, clock/info->divider, info, okim6258_update); + + info->signal = -2; + info->step = 0; + + okim6258_state_save_register(info, tag); + + return info; +} + + +/********************************************************************************************** + + OKIM6258_stop -- stop emulation of an OKIM6258-compatible chip + +***********************************************************************************************/ + +static SND_RESET( okim6258 ) +{ + struct okim6258 *info = token; + + stream_update(info->stream); + + info->signal = -2; + info->step = 0; + info->status = 0; +} + + +/********************************************************************************************** + + okim6258_set_divider -- set the master clock divider + +***********************************************************************************************/ + +void okim6258_set_divider(int which, int val) +{ + struct okim6258 *info = sndti_token(SOUND_OKIM6258, which); + int divider = dividers[val]; + + info->divider = dividers[val]; + stream_set_sample_rate(info->stream, info->master_clock / divider); +} + + +/********************************************************************************************** + + okim6258_set_clock -- set the master clock + +***********************************************************************************************/ + +void okim6258_set_clock(int which, int val) +{ + struct okim6258 *info = sndti_token(SOUND_OKIM6258, which); + + info->master_clock = val; + stream_set_sample_rate(info->stream, info->master_clock / info->divider); +} + + +/********************************************************************************************** + + okim6258_get_vclk -- get the VCLK/sampling frequency + +***********************************************************************************************/ + +int okim6258_get_vclk(int which) +{ + struct okim6258 *info = sndti_token(SOUND_OKIM6258, which); + + return (info->master_clock / info->divider); +} + + +/********************************************************************************************** + + okim6258_status_r -- read the status port of an OKIM6258-compatible chip + +***********************************************************************************************/ + +static int okim6258_status_r(int num) +{ + struct okim6258 *info = sndti_token(SOUND_OKIM6258, num); + + stream_update(info->stream); + + return (info->status & STATUS_PLAYING) ? 0x00 : 0x80; +} + + +/********************************************************************************************** + + okim6258_data_w -- write to the control port of an OKIM6258-compatible chip + +***********************************************************************************************/ +static void okim6258_data_w(int num, int data) +{ + struct okim6258 *info = sndti_token(SOUND_OKIM6258, num); + + /* update the stream */ + stream_update(info->stream); + + info->data_in = data; + info->nibble_shift = 0; +} + + +/********************************************************************************************** + + okim6258_ctrl_w -- write to the control port of an OKIM6258-compatible chip + +***********************************************************************************************/ + +static void okim6258_ctrl_w(int num, int data) +{ + struct okim6258 *info = sndti_token(SOUND_OKIM6258, num); + + stream_update(info->stream); + + if (data & COMMAND_STOP) + { + info->status &= ~(STATUS_PLAYING | STATUS_RECORDING); + return; + } + + if (data & COMMAND_PLAY) + { + if (!(info->status & STATUS_PLAYING)) + { + info->status |= STATUS_PLAYING; + + /* Also reset the ADPCM parameters */ + info->signal = -2; + info->step = 0; + info->nibble_shift = 0; + } + } + else + { + info->status &= ~STATUS_PLAYING; + } + + if (data & COMMAND_RECORD) + { + logerror("M6258: Record enabled\n"); + info->status |= STATUS_RECORDING; + } + else + { + info->status &= ~STATUS_RECORDING; + } +} + + +/********************************************************************************************** + + okim6258_status_0_r -- generic status read functions + +***********************************************************************************************/ + +READ8_HANDLER( okim6258_status_0_r ) +{ + return okim6258_status_r(0); +} + +READ16_HANDLER( okim6258_status_0_lsb_r ) +{ + return okim6258_status_r(0); +} + +READ16_HANDLER( okim6258_status_0_msb_r ) +{ + return okim6258_status_r(0) << 8; +} + +READ8_HANDLER( okim6258_data_0_r ) +{ + // TODO + return 0; +} + +READ16_HANDLER( okim6258_data_0_lsb_r ) +{ + // TODO + return 0; +} + +READ16_HANDLER( okim6258_data_0_msb_r ) +{ + // TODO + return 0; +} + +/********************************************************************************************** + + okim6258_data_0_w -- generic data write functions + okim6258_data_1_w + +***********************************************************************************************/ + +WRITE8_HANDLER( okim6258_data_0_w ) +{ + okim6258_data_w(0, data); +} + +WRITE8_HANDLER( okim6258_data_1_w ) +{ + okim6258_data_w(1, data); +} + +WRITE8_HANDLER( okim6258_data_2_w ) +{ + okim6258_data_w(2, data); +} + +WRITE16_HANDLER( okim6258_data_0_lsb_w ) +{ + if (ACCESSING_BITS_0_7) + okim6258_data_w(0, data & 0xff); +} + +WRITE16_HANDLER( okim6258_data_1_lsb_w ) +{ + if (ACCESSING_BITS_0_7) + okim6258_data_w(1, data & 0xff); +} + +WRITE16_HANDLER( okim6258_data_2_lsb_w ) +{ + if (ACCESSING_BITS_0_7) + okim6258_data_w(2, data & 0xff); +} + +WRITE16_HANDLER( okim6258_data_0_msb_w ) +{ + if (ACCESSING_BITS_8_15) + okim6258_data_w(0, data >> 8); +} + +WRITE16_HANDLER( okim6258_data_1_msb_w ) +{ + if (ACCESSING_BITS_8_15) + okim6258_data_w(1, data >> 8); +} + +WRITE16_HANDLER( okim6258_data_2_msb_w ) +{ + if (ACCESSING_BITS_8_15) + okim6258_data_w(2, data >> 8); +} + +WRITE16_HANDLER( okim6258_ctrl_0_lsb_w ) +{ + if (ACCESSING_BITS_0_7) + okim6258_ctrl_w(0, data & 0xff); +} + + +/************************************************************************** + * Generic get_info + **************************************************************************/ + +static SND_SET_INFO( okim6258 ) +{ + switch (state) + { + /* no parameters to set */ + } +} + + +SND_GET_INFO( okim6258 ) +{ + switch (state) + { + /* --- the following bits of info are returned as 64-bit signed integers --- */ + + /* --- the following bits of info are returned as pointers to data or functions --- */ + case SNDINFO_PTR_SET_INFO: info->set_info = SND_SET_INFO_NAME(okim6258); break; + case SNDINFO_PTR_START: info->start = SND_START_NAME(okim6258); break; + case SNDINFO_PTR_STOP: /* nothing */ break; + case SNDINFO_PTR_RESET: info->reset = SND_RESET_NAME(okim6258); break; + + /* --- the following bits of info are returned as NULL-terminated strings --- */ + case SNDINFO_STR_NAME: info->s = "OKI6258"; break; + case SNDINFO_STR_CORE_FAMILY: info->s = "OKI ADPCM"; break; + case SNDINFO_STR_CORE_VERSION: info->s = "1.0"; break; + case SNDINFO_STR_CORE_FILE: info->s = __FILE__; break; + case SNDINFO_STR_CORE_CREDITS: info->s = "Copyright Nicola Salmoria and the MAME Team"; break; + } +} + diff --git a/src/emu/sound/okim6258.h b/src/emu/sound/okim6258.h new file mode 100644 index 00000000000..c930ee14702 --- /dev/null +++ b/src/emu/sound/okim6258.h @@ -0,0 +1,41 @@ +#pragma once + +#ifndef __OKIM6258_H__ +#define __OKIM6258_H__ + +/* an interface for the OKIM6258 and similar chips */ + +struct _okim6258_interface +{ + int divider; + int adpcm_type; + int output_12bits; +}; + +typedef struct _okim6258_interface okim6258_interface; + +#define FOSC_DIV_BY_1024 0 +#define FOSC_DIV_BY_768 1 +#define FOSC_DIV_BY_512 2 + +#define TYPE_3BITS 0 +#define TYPE_4BITS 1 + +#define OUTPUT_10BITS 0 +#define OUTPUT_12BITS 1 + +void okim6258_set_divider(int which, int val); +void okim6258_set_clock(int which, int val); + +READ8_HANDLER( okim6258_status_0_r ); +READ16_HANDLER( okim6258_status_0_lsb_r ); +READ16_HANDLER( okim6258_status_0_msb_r ); +WRITE8_HANDLER( okim6258_data_0_w ); +READ8_HANDLER( okim6258_data_0_r ); +WRITE8_HANDLER( okim6258_ctrl_0_w ); +WRITE16_HANDLER( okim6258_data_0_lsb_w ); +WRITE16_HANDLER( okim6258_ctrl_0_lsb_w ); +READ16_HANDLER( okim6258_data_0_lsb_r ); +READ16_HANDLER( okim6258_data_0_msb_r ); + +#endif /* __OKIM6258_H__ */ diff --git a/src/emu/sound/sound.mak b/src/emu/sound/sound.mak index d6ec478e444..d285b5a58f5 100644 --- a/src/emu/sound/sound.mak +++ b/src/emu/sound/sound.mak @@ -366,6 +366,7 @@ endif SOUNDDEFS += -DHAS_MSM5205=$(if $(filter MSM5205,$(SOUNDS)),1,0) SOUNDDEFS += -DHAS_MSM5232=$(if $(filter MSM5232,$(SOUNDS)),1,0) SOUNDDEFS += -DHAS_OKIM6295=$(if $(filter OKIM6295,$(SOUNDS)),1,0) +SOUNDDEFS += -DHAS_OKIM6258=$(if $(filter OKIM6258,$(SOUNDS)),1,0) ifneq ($(filter MSM5205,$(SOUNDS)),) SOUNDOBJS += $(SOUNDOBJ)/msm5205.o @@ -379,6 +380,10 @@ ifneq ($(filter OKIM6295,$(SOUNDS)),) SOUNDOBJS += $(SOUNDOBJ)/okim6295.o endif +ifneq ($(filter OKIM6258,$(SOUNDS)),) +SOUNDOBJS += $(SOUNDOBJ)/okim6258.o +endif + #------------------------------------------------- diff --git a/src/mame/mame.mak b/src/mame/mame.mak index cb13ddb651c..865b17ff1b8 100644 --- a/src/mame/mame.mak +++ b/src/mame/mame.mak @@ -299,6 +299,7 @@ SOUNDS += VLM5030 SOUNDS += ADPCM SOUNDS += MSM5205 SOUNDS += MSM5232 +SOUNDS += OKIM6258 SOUNDS += OKIM6295 SOUNDS += UPD7759 SOUNDS += HC55516 @@ -336,7 +337,7 @@ SOUNDS += VRENDER0 SOUNDS += ES8712 SOUNDS += CDP1869 SOUNDS += S14001A -#SOUNDS += WAVE +SOUNDS += WAVE #SOUNDS += SID6581 #SOUNDS += SID8580 SOUNDS += SP0256 |
