summaryrefslogtreecommitdiffstatshomepage
path: root/trunk/src/emu/driver.c
diff options
context:
space:
mode:
Diffstat (limited to 'trunk/src/emu/driver.c')
-rw-r--r--trunk/src/emu/driver.c737
1 files changed, 737 insertions, 0 deletions
diff --git a/trunk/src/emu/driver.c b/trunk/src/emu/driver.c
new file mode 100644
index 00000000000..ff06e632066
--- /dev/null
+++ b/trunk/src/emu/driver.c
@@ -0,0 +1,737 @@
+/***************************************************************************
+
+ driver.c
+
+ Core driver device base class.
+
+****************************************************************************
+
+ Copyright Aaron Giles
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are
+ met:
+
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the
+ distribution.
+ * Neither the name 'MAME' nor the names of its contributors may be
+ used to endorse or promote products derived from this software
+ without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY AARON GILES ''AS IS'' AND ANY EXPRESS OR
+ IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ DISCLAIMED. IN NO EVENT SHALL AARON GILES BE LIABLE FOR ANY DIRECT,
+ INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+ IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+***************************************************************************/
+
+#include "emu.h"
+#include "drivenum.h"
+
+
+//**************************************************************************
+// DRIVER DEVICE
+//**************************************************************************
+
+//-------------------------------------------------
+// driver_device - constructor
+//-------------------------------------------------
+
+driver_device::driver_device(const machine_config &mconfig, device_type type, const char *tag)
+ : device_t(mconfig, type, "Driver Device", tag, NULL, 0),
+ m_generic_paletteram_8(*this, "paletteram"),
+ m_generic_paletteram2_8(*this, "paletteram2"),
+ m_generic_paletteram_16(*this, "paletteram"),
+ m_generic_paletteram2_16(*this, "paletteram2"),
+ m_generic_paletteram_32(*this, "paletteram"),
+ m_generic_paletteram2_32(*this, "paletteram2"),
+ m_system(NULL),
+ m_latch_clear_value(0),
+ m_flip_screen_x(0),
+ m_flip_screen_y(0)
+{
+ memset(m_legacy_callbacks, 0, sizeof(m_legacy_callbacks));
+ memset(m_latched_value, 0, sizeof(m_latched_value));
+ memset(m_latch_read, 0, sizeof(m_latch_read));
+}
+
+
+//-------------------------------------------------
+// driver_device - destructor
+//-------------------------------------------------
+
+driver_device::~driver_device()
+{
+}
+
+
+//-------------------------------------------------
+// static_set_game - set the game in the device
+// configuration
+//-------------------------------------------------
+
+void driver_device::static_set_game(device_t &device, const game_driver &game)
+{
+ driver_device &driver = downcast<driver_device &>(device);
+
+ // set the system
+ driver.m_system = &game;
+
+ // set the short name to the game's name
+ driver.m_shortname = game.name;
+
+ // set the full name to the game's description
+ driver.m_name = game.description;
+
+ // and set the search path to include all parents
+ driver.m_searchpath = game.name;
+ for (int parent = driver_list::clone(game); parent != -1; parent = driver_list::clone(parent))
+ driver.m_searchpath.cat(";").cat(driver_list::driver(parent).name);
+}
+
+
+//-------------------------------------------------
+// static_set_callback - set the a callback in
+// the device configuration
+//-------------------------------------------------
+
+void driver_device::static_set_callback(device_t &device, callback_type type, legacy_callback_func callback)
+{
+ downcast<driver_device &>(device).m_legacy_callbacks[type] = callback;
+}
+
+void driver_device::static_set_callback(device_t &device, callback_type type, driver_callback_delegate callback)
+{
+ downcast<driver_device &>(device).m_callbacks[type] = callback;
+}
+
+
+//-------------------------------------------------
+// driver_start - default implementation which
+// does nothing
+//-------------------------------------------------
+
+void driver_device::driver_start()
+{
+}
+
+
+//-------------------------------------------------
+// machine_start - default implementation which
+// calls to the legacy machine_start function
+//-------------------------------------------------
+
+void driver_device::machine_start()
+{
+}
+
+
+//-------------------------------------------------
+// sound_start - default implementation which
+// calls to the legacy sound_start function
+//-------------------------------------------------
+
+void driver_device::sound_start()
+{
+}
+
+
+//-------------------------------------------------
+// palette_init - default implementation which
+// does nothing
+//-------------------------------------------------
+
+void driver_device::palette_init()
+{
+}
+
+
+//-------------------------------------------------
+// video_start - default implementation which
+// calls to the legacy video_start function
+//-------------------------------------------------
+
+void driver_device::video_start()
+{
+}
+
+
+//-------------------------------------------------
+// driver_reset - default implementation which
+// does nothing
+//-------------------------------------------------
+
+void driver_device::driver_reset()
+{
+}
+
+
+//-------------------------------------------------
+// machine_reset - default implementation which
+// calls to the legacy machine_reset function
+//-------------------------------------------------
+
+void driver_device::machine_reset()
+{
+}
+
+
+//-------------------------------------------------
+// sound_reset - default implementation which
+// calls to the legacy sound_reset function
+//-------------------------------------------------
+
+void driver_device::sound_reset()
+{
+}
+
+
+//-------------------------------------------------
+// video_reset - default implementation which
+// calls to the legacy video_reset function
+//-------------------------------------------------
+
+void driver_device::video_reset()
+{
+}
+
+
+//-------------------------------------------------
+// device_rom_region - return a pointer to the
+// game's ROMs
+//-------------------------------------------------
+
+const rom_entry *driver_device::device_rom_region() const
+{
+ return m_system->rom;
+}
+
+
+//-------------------------------------------------
+// device_input_ports - return a pointer to the
+// game's input ports
+//-------------------------------------------------
+
+ioport_constructor driver_device::device_input_ports() const
+{
+ return m_system->ipt;
+}
+
+
+//-------------------------------------------------
+// device_start - device override which calls
+// the various helpers
+//-------------------------------------------------
+
+void driver_device::device_start()
+{
+ // bind our legacy callbacks
+ for (int index = 0; index < ARRAY_LENGTH(m_legacy_callbacks); index++)
+ if (m_legacy_callbacks[index] != NULL)
+ m_callbacks[index] = driver_callback_delegate(m_legacy_callbacks[index], "legacy_callback", &machine());
+
+ // reschedule ourselves to be last
+ device_iterator iter(*this);
+ for (device_t *test = iter.first(); test != NULL; test = iter.next())
+ if (test != this && !test->started())
+ throw device_missing_dependencies();
+
+ // call the game-specific init
+ if (m_system->driver_init != NULL)
+ (*m_system->driver_init)(machine());
+
+ // finish image devices init process
+ image_postdevice_init(machine());
+
+ // call palette_init if present
+ if (!m_callbacks[CB_PALETTE_INIT].isnull())
+ m_callbacks[CB_PALETTE_INIT]();
+ else
+ palette_init();
+
+ // start the various pieces
+ driver_start();
+
+ if (!m_callbacks[CB_MACHINE_START].isnull())
+ m_callbacks[CB_MACHINE_START]();
+ else
+ machine_start();
+
+ if (!m_callbacks[CB_SOUND_START].isnull())
+ m_callbacks[CB_SOUND_START]();
+ else
+ sound_start();
+
+ if (!m_callbacks[CB_VIDEO_START].isnull())
+ m_callbacks[CB_VIDEO_START]();
+ else
+ video_start();
+
+ // save generic states
+ save_item(NAME(m_flip_screen_x));
+ save_item(NAME(m_flip_screen_y));
+}
+
+
+//-------------------------------------------------
+// device_reset_after_children - device override
+// which calls the various helpers; must happen
+// after all child devices are reset
+//-------------------------------------------------
+
+void driver_device::device_reset_after_children()
+{
+ // reset each piece
+ driver_reset();
+
+ if (!m_callbacks[CB_MACHINE_RESET].isnull())
+ m_callbacks[CB_MACHINE_RESET]();
+ else
+ machine_reset();
+
+ if (!m_callbacks[CB_SOUND_RESET].isnull())
+ m_callbacks[CB_SOUND_RESET]();
+ else
+ sound_reset();
+
+ if (!m_callbacks[CB_VIDEO_RESET].isnull())
+ m_callbacks[CB_VIDEO_RESET]();
+ else
+ video_reset();
+}
+
+
+
+//**************************************************************************
+// INTERRUPT ENABLE AND VECTOR HELPERS
+//**************************************************************************
+
+//-------------------------------------------------
+// irq_pulse_clear - clear a "pulsed" IRQ line
+//-------------------------------------------------
+
+void driver_device::irq_pulse_clear(void *ptr, INT32 param)
+{
+ device_execute_interface *exec = reinterpret_cast<device_execute_interface *>(ptr);
+ int irqline = param;
+ exec->set_input_line(irqline, CLEAR_LINE);
+}
+
+
+//-------------------------------------------------
+// generic_pulse_irq_line - "pulse" an IRQ line by
+// asserting it and then clearing it x cycle(s)
+// later
+//-------------------------------------------------
+
+void driver_device::generic_pulse_irq_line(device_execute_interface &exec, int irqline, int cycles)
+{
+ assert(irqline != INPUT_LINE_NMI && irqline != INPUT_LINE_RESET && cycles > 0);
+ exec.set_input_line(irqline, ASSERT_LINE);
+
+ attotime target_time = exec.local_time() + exec.cycles_to_attotime(cycles * exec.min_cycles());
+ machine().scheduler().timer_set(target_time - machine().time(), timer_expired_delegate(FUNC(driver_device::irq_pulse_clear), this), irqline, (void *)&exec);
+}
+
+
+//-------------------------------------------------
+// generic_pulse_irq_line_and_vector - "pulse" an
+// IRQ line by asserting it and then clearing it
+// x cycle(s) later, specifying a vector
+//-------------------------------------------------
+
+void driver_device::generic_pulse_irq_line_and_vector(device_execute_interface &exec, int irqline, int vector, int cycles)
+{
+ assert(irqline != INPUT_LINE_NMI && irqline != INPUT_LINE_RESET && cycles > 0);
+ exec.set_input_line_and_vector(irqline, ASSERT_LINE, vector);
+
+ attotime target_time = exec.local_time() + exec.cycles_to_attotime(cycles * exec.min_cycles());
+ machine().scheduler().timer_set(target_time - machine().time(), timer_expired_delegate(FUNC(driver_device::irq_pulse_clear), this), irqline, (void *)&exec);
+}
+
+
+
+//**************************************************************************
+// INTERRUPT GENERATION CALLBACK HELPERS
+//**************************************************************************
+
+//-------------------------------------------------
+// NMI callbacks
+//-------------------------------------------------
+
+INTERRUPT_GEN_MEMBER( driver_device::nmi_line_pulse ) { device.execute().set_input_line(INPUT_LINE_NMI, PULSE_LINE); }
+INTERRUPT_GEN_MEMBER( driver_device::nmi_line_assert ) { device.execute().set_input_line(INPUT_LINE_NMI, ASSERT_LINE); }
+
+
+//-------------------------------------------------
+// IRQn callbacks
+//-------------------------------------------------
+
+INTERRUPT_GEN_MEMBER( driver_device::irq0_line_hold ) { device.execute().set_input_line(0, HOLD_LINE); }
+INTERRUPT_GEN_MEMBER( driver_device::irq0_line_pulse ) { generic_pulse_irq_line(device.execute(), 0, 1); }
+INTERRUPT_GEN_MEMBER( driver_device::irq0_line_assert ) { device.execute().set_input_line(0, ASSERT_LINE); }
+
+INTERRUPT_GEN_MEMBER( driver_device::irq1_line_hold ) { device.execute().set_input_line(1, HOLD_LINE); }
+INTERRUPT_GEN_MEMBER( driver_device::irq1_line_pulse ) { generic_pulse_irq_line(device.execute(), 1, 1); }
+INTERRUPT_GEN_MEMBER( driver_device::irq1_line_assert ) { device.execute().set_input_line(1, ASSERT_LINE); }
+
+INTERRUPT_GEN_MEMBER( driver_device::irq2_line_hold ) { device.execute().set_input_line(2, HOLD_LINE); }
+INTERRUPT_GEN_MEMBER( driver_device::irq2_line_pulse ) { generic_pulse_irq_line(device.execute(), 2, 1); }
+INTERRUPT_GEN_MEMBER( driver_device::irq2_line_assert ) { device.execute().set_input_line(2, ASSERT_LINE); }
+
+INTERRUPT_GEN_MEMBER( driver_device::irq3_line_hold ) { device.execute().set_input_line(3, HOLD_LINE); }
+INTERRUPT_GEN_MEMBER( driver_device::irq3_line_pulse ) { generic_pulse_irq_line(device.execute(), 3, 1); }
+INTERRUPT_GEN_MEMBER( driver_device::irq3_line_assert ) { device.execute().set_input_line(3, ASSERT_LINE); }
+
+INTERRUPT_GEN_MEMBER( driver_device::irq4_line_hold ) { device.execute().set_input_line(4, HOLD_LINE); }
+INTERRUPT_GEN_MEMBER( driver_device::irq4_line_pulse ) { generic_pulse_irq_line(device.execute(), 4, 1); }
+INTERRUPT_GEN_MEMBER( driver_device::irq4_line_assert ) { device.execute().set_input_line(4, ASSERT_LINE); }
+
+INTERRUPT_GEN_MEMBER( driver_device::irq5_line_hold ) { device.execute().set_input_line(5, HOLD_LINE); }
+INTERRUPT_GEN_MEMBER( driver_device::irq5_line_pulse ) { generic_pulse_irq_line(device.execute(), 5, 1); }
+INTERRUPT_GEN_MEMBER( driver_device::irq5_line_assert ) { device.execute().set_input_line(5, ASSERT_LINE); }
+
+INTERRUPT_GEN_MEMBER( driver_device::irq6_line_hold ) { device.execute().set_input_line(6, HOLD_LINE); }
+INTERRUPT_GEN_MEMBER( driver_device::irq6_line_pulse ) { generic_pulse_irq_line(device.execute(), 6, 1); }
+INTERRUPT_GEN_MEMBER( driver_device::irq6_line_assert ) { device.execute().set_input_line(6, ASSERT_LINE); }
+
+INTERRUPT_GEN_MEMBER( driver_device::irq7_line_hold ) { device.execute().set_input_line(7, HOLD_LINE); }
+INTERRUPT_GEN_MEMBER( driver_device::irq7_line_pulse ) { generic_pulse_irq_line(device.execute(), 7, 1); }
+INTERRUPT_GEN_MEMBER( driver_device::irq7_line_assert ) { device.execute().set_input_line(7, ASSERT_LINE); }
+
+
+
+//**************************************************************************
+// WATCHDOG READ/WRITE HELPERS
+//**************************************************************************
+
+//-------------------------------------------------
+// 8-bit reset read/write handlers
+//-------------------------------------------------
+
+WRITE8_MEMBER( driver_device::watchdog_reset_w ) { machine().watchdog_reset(); }
+READ8_MEMBER( driver_device::watchdog_reset_r ) { machine().watchdog_reset(); return space.unmap(); }
+
+
+//-------------------------------------------------
+// 16-bit reset read/write handlers
+//-------------------------------------------------
+
+WRITE16_MEMBER( driver_device::watchdog_reset16_w ) { machine().watchdog_reset(); }
+READ16_MEMBER( driver_device::watchdog_reset16_r ) { machine().watchdog_reset(); return space.unmap(); }
+
+
+//-------------------------------------------------
+// 32-bit reset read/write handlers
+//-------------------------------------------------
+
+WRITE32_MEMBER( driver_device::watchdog_reset32_w ) { machine().watchdog_reset(); }
+READ32_MEMBER( driver_device::watchdog_reset32_r ) { machine().watchdog_reset(); return space.unmap(); }
+
+
+
+//**************************************************************************
+// GENERIC SOUND COMMAND LATCHING
+//**************************************************************************
+
+//-------------------------------------------------
+// soundlatch_sync_callback - time-delayed
+// callback to set a latch value
+//-------------------------------------------------
+
+void driver_device::soundlatch_sync_callback(void *ptr, INT32 param)
+{
+ UINT16 value = param >> 8;
+ int which = param & 0xff;
+
+ // if the latch hasn't been read and the value is changed, log a warning
+ if (!m_latch_read[which] && m_latched_value[which] != value)
+ logerror("Warning: sound latch %d written before being read. Previous: %02x, new: %02x\n", which, m_latched_value[which], value);
+
+ // store the new value and mark it not read
+ m_latched_value[which] = value;
+ m_latch_read[which] = 0;
+}
+
+
+//-------------------------------------------------
+// soundlatch_byte_w - global write handlers for
+// writing to sound latches
+//-------------------------------------------------
+
+WRITE8_MEMBER( driver_device::soundlatch_byte_w ) { machine().scheduler().synchronize(timer_expired_delegate(FUNC(driver_device::soundlatch_sync_callback), this), 0 | (data << 8)); }
+WRITE16_MEMBER( driver_device::soundlatch_word_w ) { machine().scheduler().synchronize(timer_expired_delegate(FUNC(driver_device::soundlatch_sync_callback), this), 0 | (data << 8)); }
+WRITE8_MEMBER( driver_device::soundlatch2_byte_w ) { machine().scheduler().synchronize(timer_expired_delegate(FUNC(driver_device::soundlatch_sync_callback), this), 1 | (data << 8)); }
+WRITE16_MEMBER( driver_device::soundlatch2_word_w ) { machine().scheduler().synchronize(timer_expired_delegate(FUNC(driver_device::soundlatch_sync_callback), this), 1 | (data << 8)); }
+WRITE8_MEMBER( driver_device::soundlatch3_byte_w ) { machine().scheduler().synchronize(timer_expired_delegate(FUNC(driver_device::soundlatch_sync_callback), this), 2 | (data << 8)); }
+WRITE16_MEMBER( driver_device::soundlatch3_word_w ) { machine().scheduler().synchronize(timer_expired_delegate(FUNC(driver_device::soundlatch_sync_callback), this), 2 | (data << 8)); }
+WRITE8_MEMBER( driver_device::soundlatch4_byte_w ) { machine().scheduler().synchronize(timer_expired_delegate(FUNC(driver_device::soundlatch_sync_callback), this), 3 | (data << 8)); }
+WRITE16_MEMBER( driver_device::soundlatch4_word_w ) { machine().scheduler().synchronize(timer_expired_delegate(FUNC(driver_device::soundlatch_sync_callback), this), 3 | (data << 8)); }
+
+
+//-------------------------------------------------
+// soundlatch_byte_r - global read handlers for
+// reading from sound latches
+//-------------------------------------------------
+
+READ8_MEMBER( driver_device::soundlatch_byte_r ) { return m_latched_value[0]; }
+READ16_MEMBER( driver_device::soundlatch_word_r ) { return m_latched_value[0]; }
+READ8_MEMBER( driver_device::soundlatch2_byte_r ) { return m_latched_value[1]; }
+READ16_MEMBER( driver_device::soundlatch2_word_r ) { return m_latched_value[1]; }
+READ8_MEMBER( driver_device::soundlatch3_byte_r ) { return m_latched_value[2]; }
+READ16_MEMBER( driver_device::soundlatch3_word_r ) { return m_latched_value[2]; }
+READ8_MEMBER( driver_device::soundlatch4_byte_r ) { return m_latched_value[3]; }
+READ16_MEMBER( driver_device::soundlatch4_word_r ) { return m_latched_value[3]; }
+
+
+//-------------------------------------------------
+// soundlatch_clear_byte_w - global write handlers
+// for clearing sound latches
+//-------------------------------------------------
+
+WRITE8_MEMBER( driver_device::soundlatch_clear_byte_w ) { m_latched_value[0] = m_latch_clear_value; }
+WRITE8_MEMBER( driver_device::soundlatch2_clear_byte_w ) { m_latched_value[1] = m_latch_clear_value; }
+WRITE8_MEMBER( driver_device::soundlatch3_clear_byte_w ) { m_latched_value[2] = m_latch_clear_value; }
+WRITE8_MEMBER( driver_device::soundlatch4_clear_byte_w ) { m_latched_value[3] = m_latch_clear_value; }
+
+
+
+//**************************************************************************
+// GENERIC FLIP SCREEN HANDLING
+//**************************************************************************
+
+//-------------------------------------------------
+// updateflip - handle global flipping
+//-------------------------------------------------
+
+void driver_device::updateflip()
+{
+ // push the flip state to all tilemaps
+ machine().tilemap().set_flip_all((TILEMAP_FLIPX & m_flip_screen_x) | (TILEMAP_FLIPY & m_flip_screen_y));
+
+ // flip the visible area within the screen width/height
+ int width = machine().primary_screen->width();
+ int height = machine().primary_screen->height();
+ rectangle visarea = machine().primary_screen->visible_area();
+ if (m_flip_screen_x)
+ {
+ int temp = width - visarea.min_x - 1;
+ visarea.min_x = width - visarea.max_x - 1;
+ visarea.max_x = temp;
+ }
+ if (m_flip_screen_y)
+ {
+ int temp = height - visarea.min_y - 1;
+ visarea.min_y = height - visarea.max_y - 1;
+ visarea.max_y = temp;
+ }
+
+ // reconfigure the screen with the new visible area
+ attoseconds_t period = machine().primary_screen->frame_period().attoseconds;
+ machine().primary_screen->configure(width, height, visarea, period);
+}
+
+
+//-------------------------------------------------
+// flip_screen_set - set global flip
+//-------------------------------------------------
+
+void driver_device::flip_screen_set(UINT32 on)
+{
+ // normalize to all 1
+ if (on)
+ on = ~0;
+
+ // if something's changed, handle it
+ if (m_flip_screen_x != on || m_flip_screen_y != on)
+ {
+ if (!on)
+ updateflip(); // flip visarea back
+ m_flip_screen_x = m_flip_screen_y = on;
+ updateflip();
+ }
+}
+
+
+//-------------------------------------------------
+// flip_screen_set_no_update - set global flip
+// do not call update_flip.
+//-------------------------------------------------
+
+void driver_device::flip_screen_set_no_update(UINT32 on)
+{
+ // flip_screen_y is not updated on purpose
+ // this function is for drivers which
+ // where writing to flip_screen_x to
+ // bypass update_flip
+ if (on)
+ on = ~0;
+ m_flip_screen_x = on;
+}
+
+
+//-------------------------------------------------
+// flip_screen_x_set - set global horizontal flip
+//-------------------------------------------------
+
+void driver_device::flip_screen_x_set(UINT32 on)
+{
+ // normalize to all 1
+ if (on)
+ on = ~0;
+
+ // if something's changed, handle it
+ if (m_flip_screen_x != on)
+ {
+ m_flip_screen_x = on;
+ updateflip();
+ }
+}
+
+
+//-------------------------------------------------
+// flip_screen_y_set - set global vertical flip
+//-------------------------------------------------
+
+void driver_device::flip_screen_y_set(UINT32 on)
+{
+ // normalize to all 1
+ if (on)
+ on = ~0;
+
+ // if something's changed, handle it
+ if (m_flip_screen_y != on)
+ {
+ m_flip_screen_y = on;
+ updateflip();
+ }
+}
+
+
+
+//**************************************************************************
+// 8-BIT PALETTE WRITE HANDLERS
+//**************************************************************************
+
+// 3-3-2 RGB palette write handlers
+WRITE8_MEMBER( driver_device::paletteram_BBGGGRRR_byte_w ) { palette_8bit_byte_w<3,3,2, 0,3,6>(space, offset, data, mem_mask); }
+WRITE8_MEMBER( driver_device::paletteram_RRRGGGBB_byte_w ) { palette_8bit_byte_w<3,3,2, 5,2,0>(space, offset, data, mem_mask); }
+WRITE8_MEMBER( driver_device::paletteram_BBGGRRII_byte_w )
+{
+ m_generic_paletteram_8[offset] = data;
+ int i = (data >> 0) & 3;
+ palette_set_color_rgb(machine(), offset, pal4bit(((data >> 0) & 0x0c) | i),
+ pal4bit(((data >> 2) & 0x0c) | i),
+ pal4bit(((data >> 4) & 0x0c) | i));
+}
+
+
+
+//**************************************************************************
+// 16-BIT PALETTE WRITE HANDLERS
+//**************************************************************************
+
+// 4-4-4 RGB palette write handlers
+WRITE8_MEMBER( driver_device::paletteram_xxxxBBBBGGGGRRRR_byte_le_w ) { palette_16bit_byte_le_w<4,4,4, 0,4,8>(space, offset, data, mem_mask); }
+WRITE8_MEMBER( driver_device::paletteram_xxxxBBBBGGGGRRRR_byte_be_w ) { palette_16bit_byte_be_w<4,4,4, 0,4,8>(space, offset, data, mem_mask); }
+WRITE8_MEMBER( driver_device::paletteram_xxxxBBBBGGGGRRRR_byte_split_lo_w ) { palette_16bit_byte_split_lo_w<4,4,4, 0,4,8>(space, offset, data, mem_mask); }
+WRITE8_MEMBER( driver_device::paletteram_xxxxBBBBGGGGRRRR_byte_split_hi_w ) { palette_16bit_byte_split_hi_w<4,4,4, 0,4,8>(space, offset, data, mem_mask); }
+WRITE16_MEMBER( driver_device::paletteram_xxxxBBBBGGGGRRRR_word_w ) { palette_16bit_word_w<4,4,4, 0,4,8>(space, offset, data, mem_mask); }
+
+WRITE8_MEMBER( driver_device::paletteram_xxxxBBBBRRRRGGGG_byte_le_w ) { palette_16bit_byte_le_w<4,4,4, 4,0,8>(space, offset, data, mem_mask); }
+WRITE8_MEMBER( driver_device::paletteram_xxxxBBBBRRRRGGGG_byte_be_w ) { palette_16bit_byte_be_w<4,4,4, 4,0,8>(space, offset, data, mem_mask); }
+WRITE8_MEMBER( driver_device::paletteram_xxxxBBBBRRRRGGGG_byte_split_lo_w ) { palette_16bit_byte_split_lo_w<4,4,4, 4,0,8>(space, offset, data, mem_mask); }
+WRITE8_MEMBER( driver_device::paletteram_xxxxBBBBRRRRGGGG_byte_split_hi_w ) { palette_16bit_byte_split_hi_w<4,4,4, 4,0,8>(space, offset, data, mem_mask); }
+WRITE16_MEMBER( driver_device::paletteram_xxxxBBBBRRRRGGGG_word_w ) { palette_16bit_word_w<4,4,4, 4,0,8>(space, offset, data, mem_mask); }
+
+WRITE8_MEMBER( driver_device::paletteram_xxxxRRRRBBBBGGGG_byte_split_lo_w ) { palette_16bit_byte_split_lo_w<4,4,4, 8,0,4>(space, offset, data, mem_mask); }
+WRITE8_MEMBER( driver_device::paletteram_xxxxRRRRBBBBGGGG_byte_split_hi_w ) { palette_16bit_byte_split_hi_w<4,4,4, 8,0,4>(space, offset, data, mem_mask); }
+
+WRITE8_MEMBER( driver_device::paletteram_xxxxRRRRGGGGBBBB_byte_le_w ) { palette_16bit_byte_le_w<4,4,4, 8,4,0>(space, offset, data, mem_mask); }
+WRITE8_MEMBER( driver_device::paletteram_xxxxRRRRGGGGBBBB_byte_be_w ) { palette_16bit_byte_be_w<4,4,4, 8,4,0>(space, offset, data, mem_mask); }
+WRITE8_MEMBER( driver_device::paletteram_xxxxRRRRGGGGBBBB_byte_split_lo_w ) { palette_16bit_byte_split_lo_w<4,4,4, 8,4,0>(space, offset, data, mem_mask); }
+WRITE8_MEMBER( driver_device::paletteram_xxxxRRRRGGGGBBBB_byte_split_hi_w ) { palette_16bit_byte_split_hi_w<4,4,4, 8,4,0>(space, offset, data, mem_mask); }
+WRITE16_MEMBER( driver_device::paletteram_xxxxRRRRGGGGBBBB_word_w ) { palette_16bit_word_w<4,4,4, 8,4,0>(space, offset, data, mem_mask); }
+
+WRITE8_MEMBER( driver_device::paletteram_RRRRGGGGBBBBxxxx_byte_be_w ) { palette_16bit_byte_be_w<4,4,4, 12,8,4>(space, offset, data, mem_mask); }
+WRITE8_MEMBER( driver_device::paletteram_RRRRGGGGBBBBxxxx_byte_split_lo_w ) { palette_16bit_byte_split_lo_w<4,4,4, 12,8,4>(space, offset, data, mem_mask); }
+WRITE8_MEMBER( driver_device::paletteram_RRRRGGGGBBBBxxxx_byte_split_hi_w ) { palette_16bit_byte_split_hi_w<4,4,4, 12,8,4>(space, offset, data, mem_mask); }
+WRITE16_MEMBER( driver_device::paletteram_RRRRGGGGBBBBxxxx_word_w ) { palette_16bit_word_w<4,4,4, 12,8,4>(space, offset, data, mem_mask); }
+
+// 4-4-4-4 IRGB palette write handlers
+template<int _IShift, int _RShift, int _GShift, int _BShift>
+inline void set_color_irgb(running_machine &machine, pen_t color, UINT16 data)
+{
+ static const UINT8 ztable[16] = { 0x0, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x10, 0x11 };
+ UINT8 i = ztable[(data >> _IShift) & 15];
+ UINT8 r = ((data >> _RShift) & 15) * i;
+ UINT8 g = ((data >> _GShift) & 15) * i;
+ UINT8 b = ((data >> _BShift) & 15) * i;
+ palette_set_color_rgb(machine, color, r, g, b);
+}
+
+WRITE16_MEMBER( driver_device::paletteram_IIIIRRRRGGGGBBBB_word_w )
+{
+ COMBINE_DATA(&m_generic_paletteram_16[offset]);
+ set_color_irgb<12,8,4,0>(machine(), offset, m_generic_paletteram_16[offset]);
+}
+
+WRITE16_MEMBER( driver_device::paletteram_RRRRGGGGBBBBIIII_word_w )
+{
+ COMBINE_DATA(&m_generic_paletteram_16[offset]);
+ set_color_irgb<0,12,8,4>(machine(), offset, m_generic_paletteram_16[offset]);
+}
+
+// 5-5-5 RGB palette write handlers
+WRITE8_MEMBER( driver_device::paletteram_xBBBBBGGGGGRRRRR_byte_le_w ) { palette_16bit_byte_le_w<5,5,5, 0,5,10>(space, offset, data, mem_mask); }
+WRITE8_MEMBER( driver_device::paletteram_xBBBBBGGGGGRRRRR_byte_be_w ) { palette_16bit_byte_be_w<5,5,5, 0,5,10>(space, offset, data, mem_mask); }
+WRITE8_MEMBER( driver_device::paletteram_xBBBBBGGGGGRRRRR_byte_split_lo_w ) { palette_16bit_byte_split_lo_w<5,5,5, 0,5,10>(space, offset, data, mem_mask); }
+WRITE8_MEMBER( driver_device::paletteram_xBBBBBGGGGGRRRRR_byte_split_hi_w ) { palette_16bit_byte_split_hi_w<5,5,5, 0,5,10>(space, offset, data, mem_mask); }
+WRITE16_MEMBER( driver_device::paletteram_xBBBBBGGGGGRRRRR_word_w ) { palette_16bit_word_w<5,5,5, 0,5,10>(space, offset, data, mem_mask); }
+
+WRITE8_MEMBER( driver_device::paletteram_xBBBBBRRRRRGGGGG_byte_split_lo_w ) { palette_16bit_byte_split_lo_w<5,5,5, 5,0,10>(space, offset, data, mem_mask); }
+WRITE8_MEMBER( driver_device::paletteram_xBBBBBRRRRRGGGGG_byte_split_hi_w ) { palette_16bit_byte_split_hi_w<5,5,5, 5,0,10>(space, offset, data, mem_mask); }
+
+WRITE8_MEMBER( driver_device::paletteram_xRRRRRGGGGGBBBBB_byte_le_w ) { palette_16bit_byte_le_w<5,5,5, 10,5,0>(space, offset, data, mem_mask); }
+WRITE8_MEMBER( driver_device::paletteram_xRRRRRGGGGGBBBBB_byte_be_w ) { palette_16bit_byte_be_w<5,5,5, 10,5,0>(space, offset, data, mem_mask); }
+WRITE8_MEMBER( driver_device::paletteram_xRRRRRGGGGGBBBBB_byte_split_lo_w ) { palette_16bit_byte_split_lo_w<5,5,5, 10,5,0>(space, offset, data, mem_mask); }
+WRITE8_MEMBER( driver_device::paletteram_xRRRRRGGGGGBBBBB_byte_split_hi_w ) { palette_16bit_byte_split_hi_w<5,5,5, 10,5,0>(space, offset, data, mem_mask); }
+WRITE16_MEMBER( driver_device::paletteram_xRRRRRGGGGGBBBBB_word_w ) { palette_16bit_word_w<5,5,5, 10,5,0>(space, offset, data, mem_mask); }
+WRITE32_MEMBER( driver_device::paletteram_xRRRRRGGGGGBBBBB_dword_be_w ) { palette_16bit_dword_be_w<5,5,5, 10,5,0>(space, offset, data, mem_mask); }
+WRITE32_MEMBER( driver_device::paletteram_xRRRRRGGGGGBBBBB_dword_le_w ) { palette_16bit_dword_le_w<5,5,5, 10,5,0>(space, offset, data, mem_mask); }
+
+WRITE8_MEMBER( driver_device::paletteram_xGGGGGRRRRRBBBBB_byte_le_w ) { palette_16bit_byte_le_w<5,5,5, 5,10,0>(space, offset, data, mem_mask); }
+
+WRITE16_MEMBER( driver_device::paletteram_xGGGGGRRRRRBBBBB_word_w ) { palette_16bit_word_w<5,5,5, 5,10,0>(space, offset, data, mem_mask); }
+WRITE16_MEMBER( driver_device::paletteram_xGGGGGBBBBBRRRRR_word_w ) { palette_16bit_word_w<5,5,5, 0,10,5>(space, offset, data, mem_mask); }
+WRITE16_MEMBER( driver_device::paletteram_RRRRRGGGGGBBBBBx_word_w ) { palette_16bit_word_w<5,5,5, 11,6,1>(space, offset, data, mem_mask); }
+WRITE16_MEMBER( driver_device::paletteram_GGGGGRRRRRBBBBBx_word_w ) { palette_16bit_word_w<5,5,5, 6,11,1>(space, offset, data, mem_mask); }
+WRITE16_MEMBER( driver_device::paletteram_RRRRGGGGBBBBRGBx_word_w )
+{
+ COMBINE_DATA(&m_generic_paletteram_16[offset]);
+ data = m_generic_paletteram_16[offset];
+ palette_set_color_rgb(machine(), offset, pal5bit(((data >> 11) & 0x1e) | ((data >> 3) & 0x01)),
+ pal5bit(((data >> 7) & 0x1e) | ((data >> 2) & 0x01)),
+ pal5bit(((data >> 3) & 0x1e) | ((data >> 1) & 0x01)));
+}
+
+
+//**************************************************************************
+// 32-BIT PALETTE WRITE HANDLERS
+//**************************************************************************
+
+// 8-8-8 RGB palette write handlers
+WRITE16_MEMBER( driver_device::paletteram_xrgb_word_be_w ) { palette_32bit_word_be_w<8,8,8, 16,8,0>(space, offset, data, mem_mask); }
+WRITE16_MEMBER( driver_device::paletteram_xbgr_word_be_w ) { palette_32bit_word_be_w<8,8,8, 0,8,16>(space, offset, data, mem_mask); }