diff --git a/.gitattributes b/.gitattributes index e981fb8068f..6a6257301aa 100644 --- a/.gitattributes +++ b/.gitattributes @@ -1049,6 +1049,8 @@ 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/okim9810.c svneol=native#text/plain +src/emu/sound/okim9810.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/sound/okim9810.c b/src/emu/sound/okim9810.c new file mode 100644 index 00000000000..183693639ea --- /dev/null +++ b/src/emu/sound/okim9810.c @@ -0,0 +1,478 @@ +/*************************************************************************** + + okim9810.h + + OKI MSM9810 ADCPM(2) sound chip. + +***************************************************************************/ + +#include "emu.h" +#include "okim9810.h" + + +//************************************************************************** +// GLOBAL VARIABLES +//************************************************************************** + +// devices +const device_type OKIM9810 = okim9810_device_config::static_alloc_device_config; + + +// default address map +static ADDRESS_MAP_START( okim9810, 0, 8 ) + AM_RANGE(0x000000, 0xffffff) AM_ROM +ADDRESS_MAP_END + + +//************************************************************************** +// DEVICE CONFIGURATION +//************************************************************************** + +//------------------------------------------------- +// okim9810_device_config - constructor +//------------------------------------------------- + +okim9810_device_config::okim9810_device_config(const machine_config &mconfig, const char *tag, const device_config *owner, UINT32 clock) + : device_config(mconfig, static_alloc_device_config, "OKI9810", tag, owner, clock), + device_config_sound_interface(mconfig, *this), + device_config_memory_interface(mconfig, *this), + m_space_config("samples", ENDIANNESS_BIG, 8, 24, 0, NULL, *ADDRESS_MAP_NAME(okim9810)) +{ +} + + +//------------------------------------------------- +// static_alloc_device_config - allocate a new +// configuration object +//------------------------------------------------- + +device_config *okim9810_device_config::static_alloc_device_config(const machine_config &mconfig, const char *tag, const device_config *owner, UINT32 clock) +{ + return global_alloc(okim9810_device_config(mconfig, tag, owner, clock)); +} + + +//------------------------------------------------- +// alloc_device - allocate a new device object +//------------------------------------------------- + +device_t *okim9810_device_config::alloc_device(running_machine &machine) const +{ + return auto_alloc(&machine, okim9810_device(machine, *this)); +} + + +//------------------------------------------------- +// memory_space_config - return a description of +// any address spaces owned by this device +//------------------------------------------------- + +const address_space_config *okim9810_device_config::memory_space_config(int spacenum) const +{ + return (spacenum == 0) ? &m_space_config : NULL; +} + + + +//************************************************************************** +// LIVE DEVICE +//************************************************************************** + +//------------------------------------------------- +// okim9810_device - constructor +//------------------------------------------------- + +okim9810_device::okim9810_device(running_machine &_machine, const okim9810_device_config &config) + : device_t(_machine, config), + device_sound_interface(_machine, config, *this), + device_memory_interface(_machine, config, *this), + m_config(config), + m_stream(NULL), + m_TMP_register(0x00) +{ +} + + +//------------------------------------------------- +// device_start - device-specific startup +//------------------------------------------------- + +void okim9810_device::device_start() +{ + // find our direct access + m_direct = &space()->direct(); + + // create the stream + //int divisor = m_config.m_pin7 ? 132 : 165; + m_stream = m_machine.sound().stream_alloc(*this, 0, 1, clock()); + + // save state stuff + // m_TMP_register + // m_voice +} + + +//------------------------------------------------- +// device_reset - device-specific reset +//------------------------------------------------- + +void okim9810_device::device_reset() +{ + m_stream->update(); + for (int voicenum = 0; voicenum < OKIM9810_VOICES; voicenum++) + m_voice[voicenum].m_playing = false; +} + + +//------------------------------------------------- +// device_post_load - device-specific post-load +//------------------------------------------------- + +void okim9810_device::device_post_load() +{ +} + + +//------------------------------------------------- +// device_clock_changed - called if the clock +// changes +//------------------------------------------------- + +void okim9810_device::device_clock_changed() +{ +} + + +//------------------------------------------------- +// stream_generate - handle update requests for +// our sound stream +//------------------------------------------------- + +void okim9810_device::sound_stream_update(sound_stream &stream, stream_sample_t **inputs, stream_sample_t **outputs, int samples) +{ + // reset the output stream + memset(outputs[0], 0, samples * sizeof(*outputs[0])); + + // iterate over voices and accumulate sample data + for (int voicenum = 0; voicenum < OKIM9810_VOICES; voicenum++) + m_voice[voicenum].generate_adpcm(*m_direct, outputs[0], samples); +} + + +//------------------------------------------------- +// read_status - read the status register +//------------------------------------------------- + +UINT8 okim9810_device::read_status() +{ + UINT8 result = 0x00; + return result; +} + + +//------------------------------------------------- +// read - memory interface for read +//------------------------------------------------- + +READ8_MEMBER( okim9810_device::read ) +{ + return read_status(); +} + + +//------------------------------------------------- +// write - memory interface for write +//------------------------------------------------- + +// The command is written when the CMD pin is low +void okim9810_device::write_command(UINT8 data) +{ + const UINT8 cmd = (data & 0xf8) >> 3; + const UINT8 channel = (data & 0x07); + + switch(cmd) + { + case 0x00: // START + { + mame_printf_verbose("START channel mask %02x\n", m_TMP_register); + UINT8 channelMask = 0x01; + for (int i = 0; i < OKIM9810_VOICES; i++, channelMask <<= 1) + { + if (channelMask & m_TMP_register) + { + m_voice[i].m_playing = true; + mame_printf_verbose("\t\tPlaying channel %d: type %02x @ %08x for %d samples (looping=%d).\n", i, + m_voice[i].m_startFlags, + m_voice[i].m_base_offset, + m_voice[i].m_count, + m_voice[i].m_looping); + } + } + break; + } + case 0x01: // STOP + { + mame_printf_verbose("STOP channel mask %02x\n", m_TMP_register); + UINT8 channelMask = 0x01; + for (int i = 0; i < OKIM9810_VOICES; i++, channelMask <<= 1) + { + if (channelMask & m_TMP_register) + { + m_voice[i].m_playing = false; + mame_printf_verbose("\tChannel %d stopping.\n", i); + } + } + break; + } + case 0x02: // LOOP + { + mame_printf_verbose("LOOP channel mask %02x\n", m_TMP_register); + UINT8 channelMask = 0x01; + for (int i = 0; i < OKIM9810_VOICES; i++, channelMask <<= 1) + { + if (channelMask & m_TMP_register) + { + m_voice[i].m_looping = true; + mame_printf_verbose("\tChannel %d looping.\n", i); + } + else + { + m_voice[i].m_looping = false; + mame_printf_verbose("\tChannel %d done looping.\n", i); + } + } + break; + } + case 0x03: // OPT (options) + { + mame_printf_warning("OPT complex data %02x\n", m_TMP_register); + mame_printf_warning("MSM9810: UNIMPLEMENTED COMMAND!\n"); + break; + } + case 0x04: // MUON (silence) + { + mame_printf_warning("MUON channel %d length %02x\n", channel, m_TMP_register); + mame_printf_warning("MSM9810: UNIMPLEMENTED COMMAND!\n"); + break; + } + + case 0x05: // FADR (phrase address) + { + const offs_t base = m_TMP_register * 8; + + offs_t startAddr; + const UINT8 startFlags = m_direct->read_raw_byte(base + 0); + startAddr = m_direct->read_raw_byte(base + 1) << 16; + startAddr |= m_direct->read_raw_byte(base + 2) << 8; + startAddr |= m_direct->read_raw_byte(base + 3) << 0; + + offs_t endAddr; + const UINT8 endFlags = m_direct->read_raw_byte(base + 4); + endAddr = m_direct->read_raw_byte(base + 5) << 16; + endAddr |= m_direct->read_raw_byte(base + 6) << 8; + endAddr |= m_direct->read_raw_byte(base + 7) << 0; + + // Note: flags might be (& 0x30 => voice synthesis algorithm) (& 0x0f => sampling frequency) + mame_printf_verbose("FADR channel %d phrase offset %02x => ", channel, m_TMP_register); + mame_printf_verbose("\tstartFlags(%02x) startAddr(%06x) endFlags(%02x) endAddr(%06x) bytes(%d)\n", startFlags, startAddr, endFlags, endAddr, endAddr-startAddr); + m_voice[channel].m_startFlags = startFlags; + m_voice[channel].m_base_offset = startAddr; + m_voice[channel].m_endFlags = endFlags; + m_voice[channel].m_sample = 0; + // TODO: Sample count (m_count) changes based on decoding mode + m_voice[channel].m_count = 2 * ((endAddr-startAddr) + 1); // TODO: Explain the +1 + break; + } + + case 0x06: // DADR (direct address playback) + { + mame_printf_warning("DADR channel %d complex data %02x\n", channel, m_TMP_register); + mame_printf_warning("MSM9810: UNIMPLEMENTED COMMAND!\n"); + break; + } + case 0x07: // CVOL (channel volume) + { + mame_printf_verbose("CVOL channel %d volume level %02x\n", channel, m_TMP_register); + mame_printf_verbose("\tChannel %d -> volume %d.\n", channel, m_TMP_register); + + // TODO: Use the proper volume table p37 + m_voice[channel].m_volume = m_TMP_register; + break; + } + case 0x08: // PAN + { + mame_printf_warning("PAN channel %d volume level %02x\n", channel, m_TMP_register); + mame_printf_warning("MSM9810: UNIMPLEMENTED COMMAND!\n"); + break; + } + default: + { + mame_printf_warning("MSM9810: UNKNOWN COMMAND!\n"); + break; + } + } +} + +WRITE8_MEMBER( okim9810_device::write ) +{ + write_command(data); +} + + +//----------------------------------------------------------- +// writeTMP - memory interface for writing the TMP register +//----------------------------------------------------------- + +// TMP is written when the CMD pin is high +void okim9810_device::write_TMP_register(UINT8 data) +{ + m_TMP_register = data; +} + +WRITE8_MEMBER( okim9810_device::write_TMP_register ) +{ + write_TMP_register(data); +} + + +//************************************************************************** +// OKIM VOICE +//************************************************************************** + +//------------------------------------------------- +// okim_voice - constructor +//------------------------------------------------- + +okim9810_device::okim_voice::okim_voice() + : m_playing(false), + m_looping(false), + m_startFlags(0), + m_endFlags(0), + m_base_offset(0), + m_sample(0), + m_count(0), + m_volume(0) +{ +} + +//------------------------------------------------- +// generate_adpcm - generate ADPCM samples and +// add them to an output stream +//------------------------------------------------- + +void okim9810_device::okim_voice::generate_adpcm(direct_read_data &direct, stream_sample_t *buffer, int samples) +{ + // skip if not active + if (!m_playing) + return; + + // loop while we still have samples to generate + while (samples-- != 0) + { + // fetch the next sample byte + int nibble = direct.read_raw_byte(m_base_offset + m_sample / 2) >> (((m_sample & 1) << 2) ^ 4); + + // output to the buffer, scaling by the volume + // signal in range -2048..2047, volume in range 2..32 => signal * volume / 2 in range -32768..32767 + *buffer++ += m_adpcm.clock(nibble); //TODO * m_volume / 2; + + // next! + if (++m_sample >= m_count) + { + if (!m_looping) + m_playing = false; + else + m_sample = 0; + break; + } + } +} + + +//************************************************************************** +// ADPCM STATE HELPER +//************************************************************************** + +// ADPCM state and tables +bool adpcm_stateCopy::s_tables_computed = false; +const INT8 adpcm_stateCopy::s_index_shift[8] = { -1, -1, -1, -1, 2, 4, 6, 8 }; +int adpcm_stateCopy::s_diff_lookup[49*16]; + +//------------------------------------------------- +// reset - reset the ADPCM state +//------------------------------------------------- + +void adpcm_stateCopy::reset() +{ + // reset the signal/step + m_signal = -2; + m_step = 0; +} + + +//------------------------------------------------- +// device_clock_changed - called if the clock +// changes +//------------------------------------------------- + +INT16 adpcm_stateCopy::clock(UINT8 nibble) +{ + // update the signal + m_signal += s_diff_lookup[m_step * 16 + (nibble & 15)]; + + // clamp to the maximum + if (m_signal > 2047) + m_signal = 2047; + else if (m_signal < -2048) + m_signal = -2048; + + // adjust the step size and clamp + m_step += s_index_shift[nibble & 7]; + if (m_step > 48) + m_step = 48; + else if (m_step < 0) + m_step = 0; + + // return the signal + return m_signal; +} + + +//------------------------------------------------- +// compute_tables - precompute tables for faster +// sound generation +//------------------------------------------------- + +void adpcm_stateCopy::compute_tables() +{ + // skip if we already did it + if (s_tables_computed) + return; + s_tables_computed = true; + + // nibble to bit map + static const INT8 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} + }; + + // loop over all possible steps + for (int 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 (int nib = 0; nib < 16; nib++) + { + s_diff_lookup[step*16 + nib] = nbl2bit[nib][0] * + (stepval * nbl2bit[nib][1] + + stepval/2 * nbl2bit[nib][2] + + stepval/4 * nbl2bit[nib][3] + + stepval/8); + } + } +} diff --git a/src/emu/sound/okim9810.h b/src/emu/sound/okim9810.h new file mode 100644 index 00000000000..377ec63f7a8 --- /dev/null +++ b/src/emu/sound/okim9810.h @@ -0,0 +1,164 @@ +/*************************************************************************** + + okim9810.h + + OKI MSM9810 ADCPM(2) sound chip. + +***************************************************************************/ + +#pragma once + +#ifndef __OKIM9810_H__ +#define __OKIM9810_H__ + + +//************************************************************************** +// CONSTANTS +//************************************************************************** + +enum +{ + OKIM9810_SERIAL_PIN_LOW = 0, + OKIM9810_SERIAL_PIN_HIGH = 1, + // etc +}; + + + +//************************************************************************** +// INTERFACE CONFIGURATION MACROS +//************************************************************************** + +#define MCFG_OKIM9810_ADD(_tag, _clock) \ + MCFG_DEVICE_ADD(_tag, OKIM9810, _clock) + +#define MCFG_OKIM9810_REPLACE(_tag, _clock) \ + MCFG_DEVICE_REPLACE(_tag, OKIM9810, _clock) + + + +//************************************************************************** +// TYPE DEFINITIONS +//************************************************************************** + +// ======================> adpcm_stateCopy + +// Internal ADPCM state, used by external ADPCM generators with compatible specs to the OKIM 6295. +class adpcm_stateCopy +{ +public: + adpcm_stateCopy() { compute_tables(); reset(); } + + void reset(); + INT16 clock(UINT8 nibble); + + INT32 m_signal; + INT32 m_step; + +private: + static const INT8 s_index_shift[8]; + static int s_diff_lookup[49*16]; + + static void compute_tables(); + static bool s_tables_computed; +}; + + +// ======================> okim9810_device_config + +class okim9810_device_config : public device_config, + public device_config_sound_interface, + public device_config_memory_interface +{ + friend class okim9810_device; + + // construction/destruction + okim9810_device_config(const machine_config &mconfig, const char *tag, const device_config *owner, UINT32 clock); + +public: + // allocators + static device_config *static_alloc_device_config(const machine_config &mconfig, const char *tag, const device_config *owner, UINT32 clock); + virtual device_t *alloc_device(running_machine &machine) const; + +protected: + // device_config overrides + virtual const address_space_config *memory_space_config(int spacenum = 0) const; + + // internal state + const address_space_config m_space_config; +}; + + + +// ======================> okim9810_device + +class okim9810_device : public device_t, + public device_sound_interface, + public device_memory_interface +{ + friend class okim9810_device_config; + + // construction/destruction + okim9810_device(running_machine &_machine, const okim9810_device_config &config); + +public: + + UINT8 read_status(); + void write_TMP_register(UINT8 command); + void write_command(UINT8 command); + + DECLARE_READ8_MEMBER( read ); + DECLARE_WRITE8_MEMBER( write ); + DECLARE_WRITE8_MEMBER( write_TMP_register ); + +protected: + // device-level overrides + virtual void device_start(); + virtual void device_reset(); + virtual void device_post_load(); + virtual void device_clock_changed(); + + // sound interface overrides + virtual void sound_stream_update(sound_stream &stream, stream_sample_t **inputs, stream_sample_t **outputs, int samples); + + // a single voice + class okim_voice + { + public: + okim_voice(); + void generate_adpcm(direct_read_data &direct, stream_sample_t *buffer, int samples); + + adpcm_stateCopy m_adpcm; // current ADPCM state + bool m_playing; + bool m_looping; + UINT8 m_startFlags; + UINT8 m_endFlags; + offs_t m_base_offset; // pointer to the base memory location + UINT32 m_sample; // current sample number + UINT32 m_count; // total bytes to play + + INT8 m_volume; // output volume + // TODO: m_volume_left; // stereo volume + // TODO: m_volume_right; // stereo volume + }; + + + // internal state + const okim9810_device_config &m_config; + + sound_stream* m_stream; + direct_read_data* m_direct; + + UINT8 m_TMP_register; + + static const int OKIM9810_VOICES = 8; + okim_voice m_voice[OKIM9810_VOICES]; +}; + + +// device type definition +extern const device_type OKIM9810; + + + +#endif // __OKIM9810_H__ diff --git a/src/emu/sound/sound.mak b/src/emu/sound/sound.mak index c3201a7a3db..9fc73adc5cb 100644 --- a/src/emu/sound/sound.mak +++ b/src/emu/sound/sound.mak @@ -376,6 +376,10 @@ ifneq ($(filter OKIM6258,$(SOUNDS)),) SOUNDOBJS += $(SOUNDOBJ)/okim6258.o endif +ifneq ($(filter OKIM9810,$(SOUNDS)),) +SOUNDOBJS += $(SOUNDOBJ)/okim9810.o +endif + #------------------------------------------------- diff --git a/src/mame/drivers/seta2.c b/src/mame/drivers/seta2.c index e751c39d46f..20149e9eb0e 100644 --- a/src/mame/drivers/seta2.c +++ b/src/mame/drivers/seta2.c @@ -535,6 +535,7 @@ The same H8/3007 code "FC21 IOPR-0" at U49 is used for FUNCUBE 2,3,4 & 5 #include "cpu/h83002/h8.h" #include "machine/eeprom.h" #include "sound/x1_010.h" +#include "sound/okim9810.h" #include "includes/seta2.h" #include "machine/nvram.h" @@ -959,6 +960,20 @@ static READ32_HANDLER( funcube_debug_r ) return ret; } +static WRITE32_DEVICE_HANDLER( oki_write ) +{ + if (ACCESSING_BITS_0_7) + { + const UINT8 tmp = (data & 0x000000ff); + downcast(device)->write_TMP_register(tmp); + } + else if (ACCESSING_BITS_16_23) + { + const UINT8 cmd = (data & 0x00ff0000) >> 16; + downcast(device)->write_command(cmd); + } +} + static ADDRESS_MAP_START( funcube_map, ADDRESS_SPACE_PROGRAM, 32 ) AM_RANGE( 0x00000000, 0x0007ffff ) AM_ROM @@ -967,7 +982,7 @@ static ADDRESS_MAP_START( funcube_map, ADDRESS_SPACE_PROGRAM, 32 ) AM_RANGE( 0x00500000, 0x00500003 ) AM_READ( funcube_debug_r ) AM_RANGE( 0x00500004, 0x00500007 ) AM_READ( watchdog_reset32_r ) AM_WRITENOP - AM_RANGE( 0x00600000, 0x00600003 ) AM_WRITENOP // sound chip + AM_RANGE( 0x00600000, 0x00600003 ) AM_DEVWRITE("oki", oki_write) AM_RANGE( 0x00800000, 0x0083ffff ) AM_READWRITE( spriteram32_dword_r, spriteram32_dword_w ) AM_BASE_SIZE_MEMBER(seta2_state, spriteram, spriteram_size) AM_RANGE( 0x00840000, 0x0084ffff ) AM_READWRITE( paletteram32_dword_r, paletteram32_dword_w ) AM_BASE_GENERIC(paletteram) @@ -2494,9 +2509,11 @@ static MACHINE_CONFIG_START( funcube, seta2_state ) MCFG_VIDEO_EOF(seta2) /* sound hardware */ + MCFG_SPEAKER_STANDARD_STEREO("lspeaker", "rspeaker") - // MSM9810B - + MCFG_OKIM9810_ADD("oki", XTAL_14_7456MHz/10/10/10) + MCFG_SOUND_ROUTE(ALL_OUTPUTS, "lspeaker", 0.80) + MCFG_SOUND_ROUTE(ALL_OUTPUTS, "rspeaker", 0.80) MACHINE_CONFIG_END @@ -2804,8 +2821,8 @@ ROM_START( funcube2 ) ROM_LOAD32_WORD( "fc21_obj-0.u43", 0x000000, 0x400000, CRC(08cfe6d9) SHA1(d10f362dcde01f7a9855d8f76af3084b5dd1573a) ) ROM_LOAD32_WORD( "fc21_obj-1.u42", 0x000002, 0x400000, CRC(4c1fbc20) SHA1(ff83691c19ce3600b31c494eaec26d2ac79e0028) ) - ROM_REGION( 0x400000, "samples", 0 ) - ROM_LOAD( "fc21_voi0.u47", 0x00000, 0x400000, CRC(25b5fc3f) SHA1(18b16a14e9ee62f3fea382e9d3fdcd43bdb165f5) ) + ROM_REGION( 0x1000000, "oki", 0 ) + ROM_LOAD( "fc21_voi0.u47", 0x000000, 0x400000, CRC(25b5fc3f) SHA1(18b16a14e9ee62f3fea382e9d3fdcd43bdb165f5) ) ROM_END ROM_START( funcube4 ) @@ -2822,8 +2839,8 @@ ROM_START( funcube4 ) ROM_LOAD32_WORD( "fc41_obj-0.u43", 0x000000, 0x400000, CRC(9ff029d5) SHA1(e057f4929aa745ecaf9d4ff7e39974c82e440146) ) ROM_LOAD32_WORD( "fc41_obj-1.u42", 0x000002, 0x400000, CRC(5ab7b087) SHA1(c600158b2358cdf947357170044dda2deacd4f37) ) - ROM_REGION( 0x400000, "samples", 0 ) - ROM_LOAD( "fc41_snd0.u47", 0x00000, 0x400000, CRC(48337257) SHA1(d1755024b824100070b489f48f6ae921765329e8) ) + ROM_REGION( 0x1000000, "oki", 0 ) + ROM_LOAD( "fc41_snd0.u47", 0x000000, 0x400000, CRC(48337257) SHA1(d1755024b824100070b489f48f6ae921765329e8) ) ROM_END static DRIVER_INIT( funcube2 ) @@ -2841,8 +2858,15 @@ static DRIVER_INIT( funcube2 ) main_cpu[0xa8c/4] = 0x4e7141f9; // Sub CPU - sub_cpu[0x4d4/2] = 0x5470; // rte -> rts + + // Audio + // The first half of the rom appears to be a dupe of the second half with 0xffs destructively interleaved + UINT8* oki = (UINT8*) machine->region("oki")->base(); + for (int i = 0; i < 0x200000; i++) + { + oki[i] = oki[i+0x200000]; + } } // Note: same as funcube2 @@ -2861,8 +2885,15 @@ static DRIVER_INIT( funcube4 ) main_cpu[0xa8c/4] = 0x4e7141f9; // Sub CPU - sub_cpu[0x4d4/2] = 0x5470; // rte -> rts + + // Audio + // The first half of the rom appears to be a dupe of the second half with 0xffs destructively interleaved + UINT8* oki = (UINT8*) machine->region("oki")->base(); + for (int i = 0; i < 0x200000; i++) + { + oki[i] = oki[i+0x200000]; + } } GAME( 1994, gundamex, 0, gundamex, gundamex, 0, ROT0, "Banpresto", "Mobile Suit Gundam EX Revue", 0 ) diff --git a/src/mame/mame.mak b/src/mame/mame.mak index fd77bcbc10b..1af5778e898 100644 --- a/src/mame/mame.mak +++ b/src/mame/mame.mak @@ -177,6 +177,7 @@ SOUNDS += MSM5232 SOUNDS += OKIM6258 SOUNDS += OKIM6295 SOUNDS += OKIM6376 +SOUNDS += OKIM9810 SOUNDS += UPD7759 SOUNDS += HC55516 SOUNDS += K005289