mirror of
https://github.com/holub/mame
synced 2025-04-25 09:50:04 +03:00
Added echo emulation to the OkiM6376 sound chip [J. Wallace]
This commit is contained in:
parent
7506e9cf13
commit
69ece3433c
@ -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,6 +462,91 @@ 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];
|
||||
|
||||
/* 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;
|
||||
}
|
||||
|
||||
WRITE_LINE_DEVICE_HANDLER( okim6376_ch2_w )
|
||||
{
|
||||
okim6376_state *info = get_safe_token(device);
|
||||
|
||||
if (info->ch2 != state)
|
||||
{
|
||||
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]);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
WRITE_LINE_DEVICE_HANDLER( okim6376_st_w )
|
||||
{
|
||||
//As in STart, presumably, this triggers everything
|
||||
|
||||
okim6376_state *info = get_safe_token(device);
|
||||
|
||||
if (info->st != state)
|
||||
{
|
||||
|
||||
info->st = state;
|
||||
info->st_update = 1;
|
||||
|
||||
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)
|
||||
{
|
||||
info->st_pulses = 3; //undocumented behaviour beyond 3 pulses
|
||||
}
|
||||
|
||||
voice->volume = volume_table[info->st_pulses];
|
||||
}
|
||||
}
|
||||
if (info->st && info->st_update)
|
||||
{
|
||||
info->command[info->channel] = info->latch;
|
||||
|
||||
if (info->channel ==0)
|
||||
{
|
||||
oki_process(device, 0, info->command[0]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**********************************************************************************************
|
||||
|
||||
@ -377,92 +556,12 @@ READ8_DEVICE_HANDLER( okim6376_r )
|
||||
|
||||
WRITE8_DEVICE_HANDLER( okim6376_w )
|
||||
{
|
||||
// The data port is purely used to set the latch, everything else is started by an ST pulse
|
||||
|
||||
okim6376_state *info = get_safe_token(device);
|
||||
|
||||
/* if a command is pending, process the second half */
|
||||
if (info->command != -1)
|
||||
{
|
||||
int temp = data >> 4, i, start;
|
||||
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 */
|
||||
info->stream->update();
|
||||
|
||||
/* 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 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;
|
||||
|
||||
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 */
|
||||
voice->volume = volume_table[0];
|
||||
}
|
||||
else
|
||||
{
|
||||
logerror("OKIM6376:'%s' requested to play sample %02x on non-stopped voice\n",device->tag(),info->command);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* 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 */
|
||||
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];
|
||||
|
||||
voice->playing = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
@ -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__ */
|
||||
|
@ -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,16 +235,26 @@ 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 )
|
||||
|
@ -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
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user