summaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
author Angelo Salese <angelosa@users.noreply.github.com>2011-06-05 21:53:19 +0000
committer Angelo Salese <angelosa@users.noreply.github.com>2011-06-05 21:53:19 +0000
commit69ece3433ccd0a9a30b5c3c3da021f2467c4344f (patch)
tree26f94c4155a700d559ebdb2499eae0adbd820fb2
parent7506e9cf1348c82f1015c256e17fb7f4b529383d (diff)
Added echo emulation to the OkiM6376 sound chip [J. Wallace]
-rw-r--r--src/emu/sound/okim6376.c267
-rw-r--r--src/emu/sound/okim6376.h10
-rw-r--r--src/mame/drivers/highvdeo.c47
-rw-r--r--src/mame/drivers/mpu4.c24
4 files changed, 246 insertions, 102 deletions
diff --git a/src/emu/sound/okim6376.c b/src/emu/sound/okim6376.c
index c1ac5f5eb92..d974df20812 100644
--- a/src/emu/sound/okim6376.c
+++ b/src/emu/sound/okim6376.c
@@ -6,7 +6,10 @@
* TODO:
* add BEEP tone generator
* add 2ch handling (for echoing and continuous speech)
- *
+ * add echo
+ * Something is definitely not right with the rates and divisions here - the maximum
+ * oscillation frequency should only be 256KHz, yet this only sounds decent at 3MHz
+ * add proper NAR handling - this varies with clock rate
**********************************************************************************************/
@@ -36,10 +39,19 @@ struct _okim6376_state
{
#define OKIM6376_VOICES 2
struct ADPCMVoice voice[OKIM6376_VOICES];
- INT32 command;
+ INT32 command[OKIM6376_VOICES];
+ INT32 latch; /* Command data is held before transferring to either channel */
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 */
+ UINT8 channel;
+ UINT8 nar; /* Next Address Ready */
+ UINT8 busy;
+ UINT8 ch2; /* 2CH pin - enables Channel 2 operation */
+ UINT8 st; /* STart */
+ UINT8 st_pulses; /* Keep track of attenuation */
+ UINT8 ch2_update; /* Pulse shape */
+ UINT8 st_update;
};
/* step size index shift table */
@@ -49,13 +61,13 @@ static const int index_shift[8] = { -1, -1, -1, -1, 2, 4, 6, 8 };
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 const int volume_table[4] =
+ attenuation to apply to the sound signal. However, this only applies to the second
+ channel*/
+static const int volume_table[3] =
{
0x20, // 0 dB
0x10, // -6.0 dB
0x08, // -12.0 dB
- 0x04, // -24.0 dB
};
/* tables computed? */
@@ -279,13 +291,82 @@ static void adpcm_state_save_register(struct ADPCMVoice *voice, device_t *device
static void okim6376_state_save_register(okim6376_state *info, device_t *device)
{
int j;
-
- device->save_item(NAME(info->command));
for (j = 0; j < OKIM6376_VOICES; j++)
+ {
adpcm_state_save_register(&info->voice[j], device, j);
+ }
+ device->save_item(NAME(info->command[0]));
+ device->save_item(NAME(info->command[1]));
}
+static void oki_process(device_t *device, int channel, int command)
+{
+ okim6376_state *info = get_safe_token(device);
+
+ /* if a command is pending, process the second half */
+ if ((command != -1) && (command != 0)) //process silence separately
+ {
+ int start;
+ unsigned char *base/*, *base_end*/;
+ info->nar = 0;//processing
+ /* update the stream */
+ info->stream->update();
+
+ /* determine which voice(s) (voice is set by the state of 2CH) */
+ {
+ struct ADPCMVoice *voice = &info->voice[channel];
+
+ /* determine the start position, max address space is 16Mbit */
+ base = &info->region_base[info->command[channel] * 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
+ {
+ /* set up the voice to play this sample */
+ if (!voice->playing)
+ {
+ voice->playing = 1;
+ voice->base_offset = start;
+ voice->sample = 0;
+ voice->count = 0;
+
+ /* also reset the ADPCM parameters */
+ reset_adpcm(voice);
+ /* FIX: no attenuation for now, handle for channel 2 separately */
+ voice->volume = volume_table[0];
+ }
+ else
+ {
+ logerror("OKIM6376:'%s' requested to play sample %02x on non-stopped voice\n",device->tag(),info->command[channel]);
+ }
+ }
+ info->nar = 1;
+ }
+ }
+ /* otherwise, see if this is a silence command */
+ else
+ {
+ info->nar = 0;
+ /* update the stream, then turn it off */
+ info->stream->update();
+ if (command ==0)
+ {
+ int i;
+ for (i = 0; i < OKIM6376_VOICES; i++)
+ {
+ struct ADPCMVoice *voice = &info->voice[i];
+ voice->playing = 0;
+ }
+ info->nar = 1;
+ }
+ }
+}
/**********************************************************************************************
@@ -301,10 +382,17 @@ static DEVICE_START( okim6376 )
compute_tables();
- info->command = -1;
+ info->command[0] = -1;
+ info->command[1] = -1;
+ info->latch = 0;
info->region_base = *device->region();
info->master_clock = device->clock();
-
+ info->nar = 1;
+ info->busy = 1;
+ info->st = 1;
+ info->st_update = 0;
+ info->ch2_update = 0;
+ info->st_pulses = 0;
/* generate the name and create the stream */
info->stream = device->machine().sound().stream_alloc(*device, 0, 1, device->clock()/divisor, info, okim6376_update);
@@ -319,7 +407,13 @@ static DEVICE_START( okim6376 )
okim6376_state_save_register(info, device);
}
+void okim6376_set_frequency(device_t *device, int frequency)
+{
+ okim6376_state *info = get_safe_token(device);
+ info->master_clock = frequency;
+ info->stream->set_sample_rate(info->master_clock / 165);
+}
/**********************************************************************************************
@@ -368,101 +462,106 @@ READ8_DEVICE_HANDLER( okim6376_r )
}
+READ_LINE_DEVICE_HANDLER( okim6376_busy_r )
+{
+ okim6376_state *info = get_safe_token(device);
+ int i,result=1;
-/**********************************************************************************************
+ for (i = 0; i < OKIM6376_VOICES; i++)
+ {
+ struct ADPCMVoice *voice = &info->voice[i];
- okim6376_data_w -- write to the data port of an OKIM6376-compatible chip
+ /* set the bit low if it's playing */
+ if (voice->playing)
+ result = 0;
+ }
+ return result;
+}
-***********************************************************************************************/
+READ_LINE_DEVICE_HANDLER( okim6376_nar_r )
+{
+ okim6376_state *info = get_safe_token(device);
+ return info->nar;
+}
-WRITE8_DEVICE_HANDLER( okim6376_w )
+WRITE_LINE_DEVICE_HANDLER( okim6376_ch2_w )
{
okim6376_state *info = get_safe_token(device);
- /* if a command is pending, process the second half */
- if (info->command != -1)
+ if (info->ch2 != state)
{
- int temp = data >> 4, i, start;
- unsigned char *base/*, *base_end*/;
+ info->ch2 = state;
+ info->ch2_update = 1;
+ }
+ if((!info->ch2)&&(info->ch2_update))
+ {
+ info->channel = 1;
+ if (info->command[1] != info->latch)
+ {
+ info->command[1] = info->latch;
+ }
+ }
+ if((info->ch2)&&(info->ch2_update))
+ {
+ info->channel = 0;
+ oki_process(device, 0, info->command[1]);
+ }
+}
- /* 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 */
- info->stream->update();
+WRITE_LINE_DEVICE_HANDLER( okim6376_st_w )
+{
+ //As in STart, presumably, this triggers everything
- /* 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];
+ okim6376_state *info = get_safe_token(device);
+
+ if (info->st != state)
+ {
- /* determine the start position, 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;
+ info->st = state;
+ info->st_update = 1;
- if (start == 0)
+ if ((info->channel == 1) & !info->st)//ST acts as attenuation for Channel 2 when low, and stays at that level until the channel is reset
+ {
+ struct ADPCMVoice *voice = &info->voice[info->channel];
+ {
+
+ info->st_pulses ++;
+ if (info->st_pulses > 3)
{
- voice->playing = 0;
+ info->st_pulses = 3; //undocumented behaviour beyond 3 pulses
}
- else
- {
- /* set up the voice to play this sample */
- if (!voice->playing)
- {
- voice->playing = 1;
- voice->base_offset = start;
- voice->sample = 0;
- voice->count = 0;
- /* also reset the ADPCM parameters */
- reset_adpcm(voice);
- /* FIX: no attenuation for now */
- voice->volume = volume_table[0];
- }
- else
- {
- logerror("OKIM6376:'%s' requested to play sample %02x on non-stopped voice\n",device->tag(),info->command);
- }
- }
+ voice->volume = volume_table[info->st_pulses];
}
}
+ if (info->st && info->st_update)
+ {
+ info->command[info->channel] = info->latch;
- /* reset the command */
- info->command = -1;
+ if (info->channel ==0)
+ {
+ oki_process(device, 0, info->command[0]);
+ }
+ }
}
+}
- /* 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;
+ okim6376_data_w -- write to the data port of an OKIM6376-compatible chip
- /* update the stream, then turn it off */
- info->stream->update();
+***********************************************************************************************/
- /* 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];
+WRITE8_DEVICE_HANDLER( okim6376_w )
+{
+ // The data port is purely used to set the latch, everything else is started by an ST pulse
- voice->playing = 0;
- }
- }
- }
+ okim6376_state *info = get_safe_token(device);
+ info->latch = data & 0x7f;
+ // 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)
}
@@ -476,18 +575,18 @@ DEVICE_GET_INFO( okim6376 )
switch (state)
{
/* --- the following bits of info are returned as 64-bit signed integers --- */
- case DEVINFO_INT_TOKEN_BYTES: info->i = sizeof(okim6376_state); break;
+ case DEVINFO_INT_TOKEN_BYTES: info->i = sizeof(okim6376_state); break;
/* --- the following bits of info are returned as pointers to data or functions --- */
- case DEVINFO_FCT_START: info->start = DEVICE_START_NAME( okim6376 ); break;
- case DEVINFO_FCT_STOP: /* nothing */ break;
- case DEVINFO_FCT_RESET: info->reset = DEVICE_RESET_NAME( okim6376 ); break;
+ case DEVINFO_FCT_START: info->start = DEVICE_START_NAME( okim6376 ); break;
+ case DEVINFO_FCT_STOP: /* nothing */ break;
+ case DEVINFO_FCT_RESET: info->reset = DEVICE_RESET_NAME( okim6376 ); break;
/* --- the following bits of info are returned as NULL-terminated strings --- */
- case DEVINFO_STR_NAME: strcpy(info->s, "OKI6376"); break;
+ case DEVINFO_STR_NAME: strcpy(info->s, "OKI6376"); break;
case DEVINFO_STR_FAMILY: strcpy(info->s, "OKI ADPCM"); break;
case DEVINFO_STR_VERSION: strcpy(info->s, "1.0"); break;
- case DEVINFO_STR_SOURCE_FILE: strcpy(info->s, __FILE__); 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/okim6376.h b/src/emu/sound/okim6376.h
index 12346342396..171bcdfdf00 100644
--- a/src/emu/sound/okim6376.h
+++ b/src/emu/sound/okim6376.h
@@ -12,4 +12,14 @@ WRITE8_DEVICE_HANDLER( okim6376_w );
DECLARE_LEGACY_SOUND_DEVICE(OKIM6376, okim6376);
+WRITE_LINE_DEVICE_HANDLER( okim6376_st_w );
+WRITE_LINE_DEVICE_HANDLER( okim6376_ch2_w );
+
+READ_LINE_DEVICE_HANDLER( okim6376_busy_r );
+READ_LINE_DEVICE_HANDLER( okim6376_nar_r );
+
+DECLARE_LEGACY_SOUND_DEVICE(OKIM6376, okim6376);
+
+void okim6376_set_frequency(device_t *device, int frequency);
+
#endif /* __OKIM6376_H__ */
diff --git a/src/mame/drivers/highvdeo.c b/src/mame/drivers/highvdeo.c
index c53181aca83..7d28da446b9 100644
--- a/src/mame/drivers/highvdeo.c
+++ b/src/mame/drivers/highvdeo.c
@@ -26,7 +26,7 @@ Port layout:
0x0000 W Keyboard Lights control port
0x0002 W \ Hopper or ticket related
0x0004 W /
-0x0006 W OKI6395 ADPCM command: need to be latched
+0x0006 W OKI6395 (6376?)ADPCM command: need to be latched
0x0010 W Like 0x3c8 in VGA
0x0014 W Like 0x3c9 in VGA
@@ -235,14 +235,24 @@ static WRITE16_HANDLER( tv_vcf_bankselect_w )
}
-static WRITE16_DEVICE_HANDLER( tv_oki6395_w )
+static WRITE16_DEVICE_HANDLER( tv_oki6376_w )
{
static int okidata;
- if (ACCESSING_BITS_0_7 && okidata != data) {
+ if (ACCESSING_BITS_0_7 && okidata != data)
+ {
okidata = data;
- okim6376_w(device, 0, data);
- okim6376_w(device, 0, (1 << 4));
+ okim6376_w(device, 0, data & ~0x80);
+ okim6376_st_w (device, data & 0x80);
+ }
+}
+
+static READ16_DEVICE_HANDLER( tv_oki6376_r )
+{
+ if (ACCESSING_BITS_0_7)
+ {
+ return okim6376_busy_r(device);
}
+ return 0xff;
}
static WRITE16_HANDLER( write1_w )
@@ -278,12 +288,12 @@ ADDRESS_MAP_END
static ADDRESS_MAP_START( tv_vcf_io, AS_IO, 16 )
AM_RANGE(0x0000, 0x0001) AM_WRITE( write1_w ) // lamps
- AM_RANGE(0x0006, 0x0007) AM_DEVWRITE( "oki", tv_oki6395_w )
+ AM_RANGE(0x0006, 0x0007) AM_DEVWRITE( "oki", tv_oki6376_w )
AM_RANGE(0x0008, 0x0009) AM_READ( read1_r )
AM_RANGE(0x000a, 0x000b) AM_READ( read2_r )
AM_RANGE(0x000c, 0x000d) AM_READ( read3_r )
AM_RANGE(0x0010, 0x0015) AM_WRITE( tv_vcf_paletteram_w )
- AM_RANGE(0x0030, 0x0031) AM_WRITE( tv_vcf_bankselect_w ) AM_DEVREAD8( "oki", okim6376_r, 0x00ff )
+ AM_RANGE(0x0030, 0x0031) AM_WRITE( tv_vcf_bankselect_w ) AM_DEVREAD( "oki", tv_oki6376_r )
ADDRESS_MAP_END
@@ -298,15 +308,23 @@ static READ16_HANDLER( tv_ncf_read2_r )
return (input_port_read(space->machine(), "IN1") & 0xbf) | resetpulse;
}
-static WRITE16_DEVICE_HANDLER( tv_ncf_oki6395_w )
+static WRITE16_DEVICE_HANDLER( tv_ncf_oki6376_w )
{
static int okidata;
if (ACCESSING_BITS_0_7 && okidata != data) {
okidata = data;
- okim6376_w(device, 0, data | 0x80);
- okim6376_w(device, 0, (1 << 4));
+ okim6376_w(device, 0, data );
}
}
+
+static WRITE16_DEVICE_HANDLER( tv_ncf_oki6376_st_w )
+{
+ if (ACCESSING_BITS_0_7)
+ {
+ okim6376_st_w(device, (data & 0x80) );
+ }
+}
+
static ADDRESS_MAP_START( tv_ncf_map, AS_PROGRAM, 16 )
AM_RANGE(0x00000, 0x003ff) AM_RAM /*irq vector area*/
AM_RANGE(0x00400, 0x03fff) AM_RAM AM_SHARE("nvram")
@@ -317,7 +335,8 @@ ADDRESS_MAP_END
static ADDRESS_MAP_START( tv_ncf_io, AS_IO, 16 )
AM_RANGE(0x0000, 0x0001) AM_WRITE( write1_w ) // lamps
- AM_RANGE(0x0008, 0x0009) AM_DEVWRITE( "oki", tv_ncf_oki6395_w )
+ AM_RANGE(0x0008, 0x0009) AM_DEVWRITE( "oki", tv_ncf_oki6376_w )
+ AM_RANGE(0x000a, 0x000b) AM_DEVWRITE( "oki", tv_ncf_oki6376_st_w )
AM_RANGE(0x000c, 0x000d) AM_READ( read1_r )
AM_RANGE(0x0010, 0x0011) AM_READ( tv_ncf_read2_r )
AM_RANGE(0x0012, 0x0013) AM_READ( read3_r )
@@ -361,7 +380,7 @@ ADDRESS_MAP_END
static ADDRESS_MAP_START( tv_tcf_io, AS_IO, 16 )
AM_RANGE(0x0000, 0x0001) AM_WRITE( write1_w ) // lamps
- AM_RANGE(0x0006, 0x0007) AM_DEVWRITE( "oki", tv_oki6395_w )
+ AM_RANGE(0x0006, 0x0007) AM_DEVWRITE( "oki", tv_oki6376_w )
AM_RANGE(0x0008, 0x0009) AM_READ( read1_r )
AM_RANGE(0x000a, 0x000b) AM_READ( read2_r )
AM_RANGE(0x0030, 0x0031) AM_READ( read3_r ) AM_WRITE( tv_tcf_bankselect_w )
@@ -423,7 +442,7 @@ static ADDRESS_MAP_START( newmcard_io, AS_IO, 16 )
AM_RANGE(0x0000, 0x0001) AM_WRITE( write1_w ) // lamps
AM_RANGE(0x0002, 0x0003) AM_WRITE( write2_w ) // coin counter & coin lockout
AM_RANGE(0x0004, 0x0005) AM_WRITE( newmcard_vblank_w )
- AM_RANGE(0x0006, 0x0007) AM_DEVWRITE( "oki", tv_oki6395_w )
+ AM_RANGE(0x0006, 0x0007) AM_DEVWRITE( "oki", tv_oki6376_w )
AM_RANGE(0x0008, 0x0009) AM_READ( read1_r )
AM_RANGE(0x000a, 0x000b) AM_READ( read2_r )
AM_RANGE(0x000c, 0x000d) AM_READ( newmcard_vblank_r )
@@ -491,7 +510,7 @@ static ADDRESS_MAP_START( brasil_io, AS_IO, 16 )
AM_RANGE(0x0030, 0x0031) AM_WRITE( brasil_status_w )
AM_RANGE(0x0000, 0x0001) AM_WRITE( write1_w ) // lamps
AM_RANGE(0x0002, 0x0003) AM_WRITE( write2_w ) // coin counter & coin lockout
- AM_RANGE(0x0006, 0x0007) AM_DEVWRITE( "oki", tv_oki6395_w )
+ AM_RANGE(0x0006, 0x0007) AM_DEVWRITE( "oki", tv_oki6376_w )
AM_RANGE(0x0008, 0x0009) AM_READ( read1_r )
AM_RANGE(0x000a, 0x000b) AM_READ( read2_r )
AM_RANGE(0x000e, 0x000f) AM_READ( read3_r )
diff --git a/src/mame/drivers/mpu4.c b/src/mame/drivers/mpu4.c
index 3f4efa1ec9d..ed2956d5f19 100644
--- a/src/mame/drivers/mpu4.c
+++ b/src/mame/drivers/mpu4.c
@@ -4,6 +4,7 @@
This is the core driver, no video specific stuff should go in here.
This driver holds all the mechanical games.
+ 05-2011: Add better OKI emulation - clock rate may be wrong but samples sound good now.
04-2011: More accurate gamball code, fixed ROM banking (Project Amber), added BwB CHR simulator (Amber)
This is still a hard coded system, but significantly different to Barcrest's version.
Started adding support for the Crystal Gaming program card, and the link keys for setting parameters.
@@ -217,8 +218,9 @@ TODO: - Distinguish door switches using manual
For now, we're ignoring any extra writes to strobes, as the alternative is to assign a timer to *everything*
- Flo's move in Great Escape gives spin alarms - need a different opto setting for reverse spin reels?
- Fix BwB characteriser, need to be able to calculate stabiliser bytes. Anyone fancy reading 6809 source?
- - Fix MSM6376 - We're triggering 'contact MAMEDEV' since we need all features of the chip,
- including dynamic sample rate adjustment and BEEP.
+ - Fix MSM6376 - We need all features of the chip, including dynamic sample rate adjustment and BEEP.
+ - OKI sound chip rate - need to confirm independently (3MHz sounds good, but that could be because
+ of the old driver - BwB manual claims 64KHz to 128KHz).
***********************************************************************************************************/
#include "emu.h"
#include "machine/6821pia.h"
@@ -374,6 +376,7 @@ public:
int m_pageset;
int m_hopper;
int m_reels;
+ int m_chrdata;
const mpu4_chr_table* m_current_chr_table;
const bwb_chr_table* m_bwb_chr_table1;
//Video
@@ -1670,6 +1673,8 @@ static WRITE8_DEVICE_HANDLER( pia_gb_porta_w )
static WRITE8_DEVICE_HANDLER( pia_gb_portb_w )
{
mpu4_state *state = device->machine().driver_data<mpu4_state>();
+ device_t *msm6376 = device->machine().device("msm6376");
+
int changed = state->m_expansion_latch^data;
LOG_SS(("%s: GAMEBOARD: PIA Port A Set to %2x\n", device->machine().describe_context(),data));
@@ -1695,18 +1700,29 @@ static WRITE8_DEVICE_HANDLER( pia_gb_portb_w )
}
}
}
+ okim6376_ch2_w(msm6376,data&0x02);
+ okim6376_st_w(msm6376,data&0x01);
+
}
static READ8_DEVICE_HANDLER( pia_gb_portb_r )
{
device_t *msm6376 = device->machine().device("msm6376");
+ mpu4_state *state = device->machine().driver_data<mpu4_state>();
LOG_SS(("%s: GAMEBOARD: PIA Read of Port B\n",device->machine().describe_context()));
+ int data=0;
//
// b7, 1 = OKI ready, 0 = OKI busy
// b5, vol clock
// b4, 1 = Vol down, 0 = Vol up
//
- return okim6376_r(msm6376,0);
+ if ( okim6376_busy_r(msm6376) ) data |= 0x80;
+ else data &= ~0x80;
+
+ if ( okim6376_nar_r(msm6376) ) data |= 0x40;
+ else data &= ~0x40;
+
+ return ( data | state->m_expansion_latch );
}
static WRITE_LINE_DEVICE_HANDLER( pia_gb_ca2_w )
@@ -2883,7 +2899,7 @@ static MACHINE_CONFIG_DERIVED( mod4oki, mpu4mod2 )
MCFG_CPU_PROGRAM_MAP(mod4_oki_map)
MCFG_DEVICE_REMOVE("ay8913")
- MCFG_SOUND_ADD("msm6376", OKIM6376, 64000) //Dynamic, can also be 85430 at 10.5KHz and 128000 at 16KHz
+ MCFG_SOUND_ADD("msm6376", OKIM6376, 3000000) //Wrong, needs to be 64 KHz, can also be 85430 at 10.5KHz and 128000 at 16KHz
MCFG_SOUND_ROUTE(ALL_OUTPUTS, "mono", 1.0)
MACHINE_CONFIG_END