diff --git a/.gitattributes b/.gitattributes index 4dc04206dad..198cd9c9e10 100644 --- a/.gitattributes +++ b/.gitattributes @@ -832,6 +832,8 @@ 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/okim6376.c svneol=native#text/plain +src/emu/sound/okim6376.h svneol=native#text/plain src/emu/sound/pokey.c svneol=native#text/plain src/emu/sound/pokey.h svneol=native#text/plain src/emu/sound/pokey.txt svneol=native#text/plain diff --git a/src/emu/sndintrf.c b/src/emu/sndintrf.c index 0bad67a56b6..d0c906b434b 100644 --- a/src/emu/sndintrf.c +++ b/src/emu/sndintrf.c @@ -108,6 +108,7 @@ SND_GET_INFO( tms5200 ); SND_GET_INFO( tms5220 ); SND_GET_INFO( vlm5030 ); SND_GET_INFO( adpcm ); +SND_GET_INFO( okim6376 ); SND_GET_INFO( okim6295 ); SND_GET_INFO( okim6258 ); SND_GET_INFO( msm5205 ); @@ -317,6 +318,9 @@ static const struct #if (HAS_VLM5030) { SOUND_VLM5030, SND_GET_INFO_NAME( vlm5030 ) }, #endif +#if (HAS_OKIM6376) + { SOUND_OKIM6376, SND_GET_INFO_NAME( okim6376 ) }, +#endif #if (HAS_OKIM6295) { SOUND_OKIM6295, SND_GET_INFO_NAME( okim6295 ) }, #endif diff --git a/src/emu/sndintrf.h b/src/emu/sndintrf.h index 6cd4f5f90bb..3fcd63c01b8 100644 --- a/src/emu/sndintrf.h +++ b/src/emu/sndintrf.h @@ -83,6 +83,7 @@ enum _sound_type SOUND_TMS5200, SOUND_TMS5220, SOUND_VLM5030, + SOUND_OKIM6376, SOUND_OKIM6295, SOUND_OKIM6258, SOUND_MSM5205, diff --git a/src/emu/sound/okim6376.c b/src/emu/sound/okim6376.c new file mode 100644 index 00000000000..251bbd926e0 --- /dev/null +++ b/src/emu/sound/okim6376.c @@ -0,0 +1,611 @@ +/********************************************************************************************** + * + * OKI MSM6376 ADPCM + * by Mirko Buffoni + * + * TODO: + * add BEEP tone generator + * add 2ch handling (for echoing and continuous speech) + * + **********************************************************************************************/ + + +#include + +#include "sndintrf.h" +#include "streams.h" +#include "okim6376.h" + +#define MAX_SAMPLE_CHUNK 10000 +#define MAX_WORDS 111 + + +/* struct describing a single playing ADPCM voice */ +struct ADPCMVoice +{ + UINT8 playing; /* 1 if we are actively playing */ + + UINT32 base_offset; /* pointer to the base memory location */ + UINT32 sample; /* current sample number */ + UINT32 count; /* total samples to play */ + + UINT32 volume; /* output volume */ + INT32 signal; + INT32 step; +}; + +struct okim6376 +{ + #define OKIM6376_VOICES 2 + struct ADPCMVoice voice[OKIM6376_VOICES]; + INT32 command; + UINT8 *region_base; /* pointer to the base of the region */ + sound_stream *stream; /* which stream are we playing on? */ + UINT32 master_clock; /* master clock frequency */ +}; + +/* 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]; + +/* volume lookup table. Upon configuration, the number of ST pulses determine how much + attenuation to apply to the sound signal. */ +static int volume_table[4] = +{ + 0x10, // 0 dB + 0x08, // -6.0 dB + 0x04, // -12.0 dB + 0x02, // -24.0 dB +}; + +/* 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; +} + + + +/********************************************************************************************** + + reset_adpcm -- reset the ADPCM stream + +***********************************************************************************************/ + +static void reset_adpcm(struct ADPCMVoice *voice) +{ + /* make sure we have our tables */ + if (!tables_computed) + compute_tables(); + + /* reset the signal/step */ + voice->signal = -2; + voice->step = 0; +} + + + +/********************************************************************************************** + + clock_adpcm -- clock the next ADPCM byte + +***********************************************************************************************/ + +static INT16 clock_adpcm(struct ADPCMVoice *voice, UINT8 nibble) +{ + voice->signal += diff_lookup[voice->step * 16 + (nibble & 15)]; + + /* clamp to the maximum 12bit */ + if (voice->signal > 4095) + voice->signal = 4095; + else if (voice->signal < -4096) + voice->signal = -4096; + + /* adjust the step size and clamp */ + voice->step += index_shift[nibble & 7]; + if (voice->step > 48) + voice->step = 48; + else if (voice->step < 0) + voice->step = 0; + + /* return the signal */ + return voice->signal; +} + + + +/********************************************************************************************** + + generate_adpcm -- general ADPCM decoding routine + +***********************************************************************************************/ + +static void generate_adpcm(struct okim6376 *chip, struct ADPCMVoice *voice, INT16 *buffer, int samples) +{ + /* if this voice is active */ + if (voice->playing) + { + UINT8 *base = chip->region_base + voice->base_offset; + int sample = voice->sample; + int count = voice->count; + + /* loop while we still have samples to generate */ + while (samples) + { + /* compute the new amplitude and update the current step */ + int nibble = base[sample / 2] >> (((sample & 1) << 2) ^ 4); + + /* output to the buffer, scaling by the volume */ + /* signal in range -4096..4095, volume in range 2..16 => signal * volume / 2 in range -32768..32767 */ + *buffer++ = clock_adpcm(voice, nibble) * voice->volume / 2; + samples--; + + /* next! */ + if (++sample >= count) + { + voice->playing = 0; + break; + } + } + + /* update the parameters */ + voice->sample = sample; + } + + /* fill the rest with silence */ + while (samples--) + *buffer++ = 0; +} + + + +/********************************************************************************************** + + okim6376_update -- update the sound chip so that it is in sync with CPU execution + +***********************************************************************************************/ + +static STREAM_UPDATE( okim6376_update ) +{ + struct okim6376 *chip = param; + int i; + + memset(outputs[0], 0, samples * sizeof(*outputs[0])); + + for (i = 0; i < OKIM6376_VOICES; i++) + { + struct ADPCMVoice *voice = &chip->voice[i]; + stream_sample_t *buffer = outputs[0]; + INT16 sample_data[MAX_SAMPLE_CHUNK]; + int remaining = samples; + + /* loop while we have samples remaining */ + while (remaining) + { + int samples = (remaining > MAX_SAMPLE_CHUNK) ? MAX_SAMPLE_CHUNK : remaining; + int samp; + + generate_adpcm(chip, voice, sample_data, samples); + for (samp = 0; samp < samples; samp++) + *buffer++ += sample_data[samp]; + + remaining -= samples; + } + } +} + + + +/********************************************************************************************** + + state save support for MAME + +***********************************************************************************************/ + +static void adpcm_state_save_register(struct ADPCMVoice *voice, const device_config *device, int index) +{ + state_save_register_device_item(device, index, voice->playing); + state_save_register_device_item(device, index, voice->sample); + state_save_register_device_item(device, index, voice->count); + state_save_register_device_item(device, index, voice->signal); + state_save_register_device_item(device, index, voice->step); + state_save_register_device_item(device, index, voice->volume); + state_save_register_device_item(device, index, voice->base_offset); +} + +static void okim6376_state_save_register(struct okim6376 *info, const device_config *device) +{ + int j; + + state_save_register_device_item(device, 0, info->command); + for (j = 0; j < OKIM6376_VOICES; j++) + adpcm_state_save_register(&info->voice[j], device, j); +} + + + +/********************************************************************************************** + + SND_START( okim6376 ) -- start emulation of an OKIM6376-compatible chip + +***********************************************************************************************/ + +static SND_START( okim6376 ) +{ + struct okim6376 *info; + int voice; + int divisor = 165; + + info = auto_malloc(sizeof(*info)); + memset(info, 0, sizeof(*info)); + + compute_tables(); + + info->command = -1; + info->region_base = device->region; + info->master_clock = clock; + + /* generate the name and create the stream */ + info->stream = stream_create(device, 0, 1, clock/divisor, info, okim6376_update); + + /* initialize the voices */ + for (voice = 0; voice < OKIM6376_VOICES; voice++) + { + /* initialize the rest of the structure */ + info->voice[voice].volume = 0; + reset_adpcm(&info->voice[voice]); + } + + okim6376_state_save_register(info, device); + + /* success */ + return info; +} + + + +/********************************************************************************************** + + SND_RESET( okim6376 ) -- stop emulation of an OKIM6376-compatible chip + +***********************************************************************************************/ + +static SND_RESET( okim6376 ) +{ + struct okim6376 *info = device->token; + int i; + + stream_update(info->stream); + for (i = 0; i < OKIM6376_VOICES; i++) + info->voice[i].playing = 0; +} + + + + +/********************************************************************************************** + + okim6376_status_r -- read the status port of an OKIM6376-compatible chip + +***********************************************************************************************/ + +static int okim6376_status_r(int num) +{ + struct okim6376 *info = sndti_token(SOUND_OKIM6376, num); + int i, result; + + result = 0xff; + + /* set the bit to 1 if something is playing on a given channel */ + stream_update(info->stream); + for (i = 0; i < OKIM6376_VOICES; i++) + { + struct ADPCMVoice *voice = &info->voice[i]; + + /* set the bit if it's playing */ + if (!voice->playing) + result ^= 1 << i; + } + + return result; +} + + + +/********************************************************************************************** + + okim6376_data_w -- write to the data port of an OKIM6376-compatible chip + +***********************************************************************************************/ + +static void okim6376_data_w(int num, int data) +{ + struct okim6376 *info = sndti_token(SOUND_OKIM6376, num); + + /* if a command is pending, process the second half */ + if (info->command != -1) + { + int temp = data >> 4, i, start, stop; + unsigned char *base, *base_end; + + + /* FIX: Check if it's possible to start multiple voices at the same time */ + if (temp != 0 && temp != 1 && temp != 2) + popmessage("OKI6376 start %x contact MAMEDEV", temp); + + /* update the stream */ + stream_update(info->stream); + + /* determine which voice(s) (voice is set by a 1 bit in the upper 4 bits of the second byte) */ + for (i = 0; i < OKIM6376_VOICES; i++, temp >>= 1) + { + if (temp & 1) + { + struct ADPCMVoice *voice = &info->voice[i]; + + /* determine the start/stop positions, max address space is 16Mbit */ + base = &info->region_base[info->command * 4]; + base_end = &info->region_base[(MAX_WORDS+1) * 4]; + start = ((base[0] << 16) + (base[1] << 8) + base[2]) & 0x1fffff; + if (start == 0) { + voice->playing = 0; + } else { + /* FIX: for now handle stop reading the next sample start */ + do { + stop = ((base[4] << 16) + (base[5] << 8) + base[6]) & 0x1fffff; + if (stop == 0) base += 4; + } while (stop == 0 && base < base_end); + + /* set up the voice to play this sample */ + if (start < stop) + { + if (!voice->playing) + { + voice->playing = 1; + voice->base_offset = start; + voice->sample = 0; + voice->count = 2 * (stop - start + 1); + + /* also reset the ADPCM parameters */ + reset_adpcm(voice); + /* FIX: no attenuation for now */ + voice->volume = volume_table[0]; + } + else + { + logerror("OKIM6376:%d requested to play sample %02x on non-stopped voice\n",num,info->command); + } + } + /* invalid samples go here */ + else + { + logerror("OKIM6376:%d requested to play invalid sample %02x\n",num,info->command); + voice->playing = 0; + } + } + } + } + + /* reset the command */ + info->command = -1; + } + + /* if this is the start of a command, remember the sample number for next time */ + else if (data & 0x80) + { + // FIX: maximum adpcm words are 111, there are other 8 commands to generate BEEP tone (0x70 to 0x77), + // and others for internal testing, that manual explicitly says not to use (0x78 to 0x7f) + info->command = data & 0x7f; + } + + /* otherwise, see if this is a silence command */ + else + { + int temp = data >> 3, i; + + /* update the stream, then turn it off */ + stream_update(info->stream); + + /* determine which voice(s) (voice is set by a 1 bit in bits 3-6 of the command */ + for (i = 0; i < OKIM6376_VOICES; i++, temp >>= 1) + { + if (temp & 1) + { + struct ADPCMVoice *voice = &info->voice[i]; + + voice->playing = 0; + } + } + } +} + + + +/********************************************************************************************** + + okim6376_status_0_r -- generic status read functions + okim6376_status_1_r + +***********************************************************************************************/ + +READ8_HANDLER( okim6376_status_0_r ) +{ + return okim6376_status_r(0); +} + +READ8_HANDLER( okim6376_status_1_r ) +{ + return okim6376_status_r(1); +} + +READ8_HANDLER( okim6376_status_2_r ) +{ + return okim6376_status_r(2); +} + +READ16_HANDLER( okim6376_status_0_lsb_r ) +{ + return okim6376_status_r(0); +} + +READ16_HANDLER( okim6376_status_1_lsb_r ) +{ + return okim6376_status_r(1); +} + +READ16_HANDLER( okim6376_status_2_lsb_r ) +{ + return okim6376_status_r(2); +} + +READ16_HANDLER( okim6376_status_0_msb_r ) +{ + return okim6376_status_r(0) << 8; +} + +READ16_HANDLER( okim6376_status_1_msb_r ) +{ + return okim6376_status_r(1) << 8; +} + +READ16_HANDLER( okim6376_status_2_msb_r ) +{ + return okim6376_status_r(2) << 8; +} + + + +/********************************************************************************************** + + okim6376_data_0_w -- generic data write functions + okim6376_data_1_w + +***********************************************************************************************/ + +WRITE8_HANDLER( okim6376_data_0_w ) +{ + okim6376_data_w(0, data); +} + +WRITE8_HANDLER( okim6376_data_1_w ) +{ + okim6376_data_w(1, data); +} + +WRITE8_HANDLER( okim6376_data_2_w ) +{ + okim6376_data_w(2, data); +} + +WRITE16_HANDLER( okim6376_data_0_lsb_w ) +{ + if (ACCESSING_BITS_0_7) + okim6376_data_w(0, data & 0xff); +} + +WRITE16_HANDLER( okim6376_data_1_lsb_w ) +{ + if (ACCESSING_BITS_0_7) + okim6376_data_w(1, data & 0xff); +} + +WRITE16_HANDLER( okim6376_data_2_lsb_w ) +{ + if (ACCESSING_BITS_0_7) + okim6376_data_w(2, data & 0xff); +} + +WRITE16_HANDLER( okim6376_data_0_msb_w ) +{ + if (ACCESSING_BITS_8_15) + okim6376_data_w(0, data >> 8); +} + +WRITE16_HANDLER( okim6376_data_1_msb_w ) +{ + if (ACCESSING_BITS_8_15) + okim6376_data_w(1, data >> 8); +} + +WRITE16_HANDLER( okim6376_data_2_msb_w ) +{ + if (ACCESSING_BITS_8_15) + okim6376_data_w(2, data >> 8); +} + + + +/************************************************************************** + * Generic get_info + **************************************************************************/ + +static SND_SET_INFO( okim6376 ) +{ + switch (state) + { + /* no parameters to set */ + } +} + + +SND_GET_INFO( okim6376 ) +{ + 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( okim6376 ); break; + case SNDINFO_PTR_START: info->start = SND_START_NAME( okim6376 ); break; + case SNDINFO_PTR_STOP: /* nothing */ break; + case SNDINFO_PTR_RESET: info->reset = SND_RESET_NAME( okim6376 ); break; + + /* --- the following bits of info are returned as NULL-terminated strings --- */ + case SNDINFO_STR_NAME: strcpy(info->s, "OKI6376"); break; + case SNDINFO_STR_CORE_FAMILY: strcpy(info->s, "OKI ADPCM"); break; + case SNDINFO_STR_CORE_VERSION: strcpy(info->s, "1.0"); break; + case SNDINFO_STR_CORE_FILE: strcpy(info->s, __FILE__); break; + case SNDINFO_STR_CORE_CREDITS: strcpy(info->s, "Copyright Nicola Salmoria and the MAME Team"); break; + } +} + diff --git a/src/emu/sound/okim6376.h b/src/emu/sound/okim6376.h new file mode 100644 index 00000000000..6fe7221d831 --- /dev/null +++ b/src/emu/sound/okim6376.h @@ -0,0 +1,29 @@ +#pragma once + +#ifndef __OKIM6376_H__ +#define __OKIM6376_H__ + +/* an interface for the OKIM6376 and similar chips */ + +READ8_HANDLER( okim6376_status_0_r ); +READ8_HANDLER( okim6376_status_1_r ); +READ8_HANDLER( okim6376_status_2_r ); +READ16_HANDLER( okim6376_status_0_lsb_r ); +READ16_HANDLER( okim6376_status_1_lsb_r ); +READ16_HANDLER( okim6376_status_2_lsb_r ); +READ16_HANDLER( okim6376_status_0_msb_r ); +READ16_HANDLER( okim6376_status_1_msb_r ); +READ16_HANDLER( okim6376_status_2_msb_r ); +WRITE8_HANDLER( okim6376_data_0_w ); +WRITE8_HANDLER( okim6376_data_1_w ); +WRITE8_HANDLER( okim6376_data_2_w ); +WRITE16_HANDLER( okim6376_data_0_lsb_w ); +WRITE16_HANDLER( okim6376_data_1_lsb_w ); +WRITE16_HANDLER( okim6376_data_2_lsb_w ); +WRITE16_HANDLER( okim6376_data_0_msb_w ); +WRITE16_HANDLER( okim6376_data_1_msb_w ); +WRITE16_HANDLER( okim6376_data_2_msb_w ); + +SND_GET_INFO( okim6376 ); + +#endif /* __OKIM6376_H__ */ diff --git a/src/emu/sound/sound.mak b/src/emu/sound/sound.mak index d285b5a58f5..f61156cbac6 100644 --- a/src/emu/sound/sound.mak +++ b/src/emu/sound/sound.mak @@ -365,6 +365,7 @@ endif SOUNDDEFS += -DHAS_MSM5205=$(if $(filter MSM5205,$(SOUNDS)),1,0) SOUNDDEFS += -DHAS_MSM5232=$(if $(filter MSM5232,$(SOUNDS)),1,0) +SOUNDDEFS += -DHAS_OKIM6376=$(if $(filter OKIM6376,$(SOUNDS)),1,0) SOUNDDEFS += -DHAS_OKIM6295=$(if $(filter OKIM6295,$(SOUNDS)),1,0) SOUNDDEFS += -DHAS_OKIM6258=$(if $(filter OKIM6258,$(SOUNDS)),1,0) @@ -376,6 +377,10 @@ ifneq ($(filter MSM5232,$(SOUNDS)),) SOUNDOBJS += $(SOUNDOBJ)/msm5232.o endif +ifneq ($(filter OKIM6376,$(SOUNDS)),) +SOUNDOBJS += $(SOUNDOBJ)/okim6376.o +endif + ifneq ($(filter OKIM6295,$(SOUNDS)),) SOUNDOBJS += $(SOUNDOBJ)/okim6295.o endif diff --git a/src/mame/drivers/brasil.c b/src/mame/drivers/brasil.c index 0b4f3201b8d..562d2703272 100644 --- a/src/mame/drivers/brasil.c +++ b/src/mame/drivers/brasil.c @@ -24,6 +24,7 @@ TODO: #include "driver.h" #include "cpu/nec/nec.h" #include "cpu/i86/i86.h" +#include "sound/okim6376.h" #include "fashion.lh" static UINT16 *blit_ram; @@ -275,7 +276,11 @@ static WRITE16_HANDLER( fashion_write2_w ) static WRITE16_HANDLER( write3_w ) { - t3 = data; + if (t3 != data) { + t3 = data; + okim6376_data_0_lsb_w(space, 0, t3, mem_mask); + okim6376_data_0_lsb_w(space, 0, (1 << 4), mem_mask); + } // popmessage("%04x %04x",t1,t3); } @@ -588,7 +593,13 @@ static MACHINE_DRIVER_START( brasil ) MDRV_VIDEO_START(brasil) MDRV_VIDEO_UPDATE(brasil) + /* sound hardware */ + MDRV_SPEAKER_STANDARD_MONO("mono") + //OkiM6376 + MDRV_SOUND_ADD("samples", OKIM6376, XTAL_12MHz/2/2) + MDRV_SOUND_ROUTE(ALL_OUTPUTS, "mono", 1.0) + MACHINE_DRIVER_END @@ -610,7 +621,13 @@ static MACHINE_DRIVER_START( vidpokr2 ) MDRV_VIDEO_START(brasil) MDRV_VIDEO_UPDATE(vidpokr2) + /* sound hardware */ + MDRV_SPEAKER_STANDARD_MONO("mono") + //OkiM6376 + MDRV_SOUND_ADD("samples", OKIM6376, XTAL_12MHz/2/2) + MDRV_SOUND_ROUTE(ALL_OUTPUTS, "mono", 1.0) + MACHINE_DRIVER_END /* @@ -709,6 +726,6 @@ static DRIVER_INIT( fashion ) memory_install_write16_handler(cpu_get_address_space(machine->cpu[0], ADDRESS_SPACE_IO), 0x0002, 0x0003, 0, 0, fashion_write2_w ); } -GAMEL( 19??, newmcard, 0, vidpokr2, brasil, 0, ROT0, "New High Video?", "New Magic Card", GAME_NO_SOUND, layout_fashion ) -GAMEL( 2000, brasil, 0, brasil, brasil, 0, ROT0, "New High Video?", "Bra$il (Version 3)", GAME_IMPERFECT_GRAPHICS | GAME_NO_SOUND, layout_fashion ) -GAMEL( 2000, fashion, brasil, brasil, fashion, fashion, ROT0, "New High Video?", "Fashion (Version 2.14)", GAME_IMPERFECT_GRAPHICS | GAME_NO_SOUND, layout_fashion ) +GAMEL( 19??, newmcard, 0, vidpokr2, brasil, 0, ROT0, "New High Video?", "New Magic Card", 0, layout_fashion ) +GAMEL( 2000, brasil, 0, brasil, brasil, 0, ROT0, "New High Video?", "Bra$il (Version 3)", GAME_IMPERFECT_GRAPHICS, layout_fashion ) +GAMEL( 2000, fashion, brasil, brasil, fashion, fashion, ROT0, "New High Video?", "Fashion (Version 2.14)", GAME_IMPERFECT_GRAPHICS, layout_fashion ) diff --git a/src/mame/mame.mak b/src/mame/mame.mak index 37e9b21e4e1..ac2b71f5ac8 100644 --- a/src/mame/mame.mak +++ b/src/mame/mame.mak @@ -274,6 +274,7 @@ SOUNDS += MSM5205 SOUNDS += MSM5232 SOUNDS += OKIM6258 SOUNDS += OKIM6295 +SOUNDS += OKIM6376 SOUNDS += UPD7759 SOUNDS += HC55516 SOUNDS += K005289