summaryrefslogtreecommitdiffstatshomepage
path: root/src/emu/emupal.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/emu/emupal.cpp')
-rw-r--r--src/emu/emupal.cpp1000
1 files changed, 1000 insertions, 0 deletions
diff --git a/src/emu/emupal.cpp b/src/emu/emupal.cpp
new file mode 100644
index 00000000000..b1bda17bc98
--- /dev/null
+++ b/src/emu/emupal.cpp
@@ -0,0 +1,1000 @@
+// license:BSD-3-Clause
+// copyright-holders:Aaron Giles
+/***************************************************************************
+
+ emupal.c
+
+ Palette device.
+
+***************************************************************************/
+
+#include "emu.h"
+
+#define VERBOSE 0
+
+
+//**************************************************************************
+// DEVICE DEFINITIONS
+//**************************************************************************
+
+const device_type PALETTE = &device_creator<palette_device>;
+
+palette_device::palette_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
+ : device_t(mconfig, PALETTE, "palette", tag, owner, clock, "palette", __FILE__),
+ m_entries(0),
+ m_indirect_entries(0),
+ m_enable_shadows(0),
+ m_enable_hilights(0),
+ m_membits_supplied(false),
+ m_endianness_supplied(false),
+ m_raw_to_rgb(raw_to_rgb_converter()),
+ m_palette(NULL),
+ m_pens(NULL),
+ m_shadow_table(NULL),
+ m_shadow_group(0),
+ m_hilight_group(0),
+ m_init(palette_init_delegate())
+{
+}
+
+
+//**************************************************************************
+// INITIALIZATION AND CONFIGURATION
+//**************************************************************************
+
+void palette_device::static_set_init(device_t &device, palette_init_delegate init)
+{
+ downcast<palette_device &>(device).m_init = init;
+}
+
+
+void palette_device::static_set_format(device_t &device, raw_to_rgb_converter raw_to_rgb)
+{
+ downcast<palette_device &>(device).m_raw_to_rgb = raw_to_rgb;
+}
+
+
+void palette_device::static_set_membits(device_t &device, int membits)
+{
+ palette_device &palette = downcast<palette_device &>(device);
+ palette.m_membits = membits;
+ palette.m_membits_supplied = true;
+}
+
+
+void palette_device::static_set_endianness(device_t &device, endianness_t endianness)
+{
+ palette_device &palette = downcast<palette_device &>(device);
+ palette.m_endianness = endianness;
+ palette.m_endianness_supplied = true;
+}
+
+
+void palette_device::static_set_entries(device_t &device, int entries)
+{
+ downcast<palette_device &>(device).m_entries = entries;
+}
+
+
+void palette_device::static_set_indirect_entries(device_t &device, int entries)
+{
+ downcast<palette_device &>(device).m_indirect_entries = entries;
+}
+
+
+void palette_device::static_enable_shadows(device_t &device)
+{
+ downcast<palette_device &>(device).m_enable_shadows = true;
+}
+
+
+void palette_device::static_enable_hilights(device_t &device)
+{
+ downcast<palette_device &>(device).m_enable_hilights = true;
+}
+
+
+
+//**************************************************************************
+// INDIRECTION (AKA COLORTABLES)
+//**************************************************************************
+
+//-------------------------------------------------
+// set_indirect_color - set an indirect color
+//-------------------------------------------------
+
+void palette_device::set_indirect_color(int index, rgb_t rgb)
+{
+ // make sure we are in range
+ assert(index < m_indirect_entries);
+
+ // alpha doesn't matter
+ rgb.set_a(255);
+
+ // update if it has changed
+ if (m_indirect_colors[index] != rgb)
+ {
+ m_indirect_colors[index] = rgb;
+
+ // update the palette for any colortable entries that reference it
+ for (UINT32 pen = 0; pen < m_indirect_pens.size(); pen++)
+ if (m_indirect_pens[pen] == index)
+ m_palette->entry_set_color(pen, rgb);
+ }
+}
+
+
+//-------------------------------------------------
+// set_pen_indirect - set an indirect pen index
+//-------------------------------------------------
+
+void palette_device::set_pen_indirect(pen_t pen, UINT16 index)
+{
+ // make sure we are in range
+ assert(pen < m_entries && index < m_indirect_entries);
+
+ m_indirect_pens[pen] = index;
+
+ m_palette->entry_set_color(pen, m_indirect_colors[index]);
+}
+
+
+//-------------------------------------------------
+// transpen_mask - return a mask of pens that
+// whose indirect values match the given
+// transcolor
+//-------------------------------------------------
+
+UINT32 palette_device::transpen_mask(gfx_element &gfx, int color, int transcolor)
+{
+ UINT32 entry = gfx.colorbase() + (color % gfx.colors()) * gfx.granularity();
+
+ // make sure we are in range
+ assert(entry < m_indirect_pens.size());
+ assert(gfx.depth() <= 32);
+
+ // either gfx->color_depth entries or as many as we can get up until the end
+ int count = MIN(gfx.depth(), m_indirect_pens.size() - entry);
+
+ // set a bit anywhere the transcolor matches
+ UINT32 mask = 0;
+ for (int bit = 0; bit < count; bit++)
+ if (m_indirect_pens[entry++] == transcolor)
+ mask |= 1 << bit;
+
+ // return the final mask
+ return mask;
+}
+
+
+
+//**************************************************************************
+// SHADOW TABLE CONFIGURATION
+//**************************************************************************
+
+//-------------------------------------------------
+// palette_set_shadow_mode(mode)
+//
+// mode: 0 = use preset 0 (default shadow)
+// 1 = use preset 1 (default highlight)
+// 2 = use preset 2 *
+// 3 = use preset 3 *
+//
+// * Preset 2 & 3 work independently under 32bpp,
+// supporting up to four different types of
+// shadows at one time. They mirror preset 1 & 2
+// in lower depth settings to maintain
+// compatibility.
+//
+//
+// set_shadow_dRGB32(mode, dr, dg, db, noclip)
+//
+// mode: 0 to 3 (which preset to configure)
+//
+// dr: -255 to 255 ( red displacement )
+// dg: -255 to 255 ( green displacement )
+// db: -255 to 255 ( blue displacement )
+//
+// noclip: 0 = resultant RGB clipped at 0x00/0xff
+// 1 = resultant RGB wraparound 0x00/0xff
+//
+//
+// * Color shadows only work under 32bpp.
+// This function has no effect in lower color
+// depths where
+//
+// set_shadow_factor() or
+// set_highlight_factor()
+//
+// should be used instead.
+//
+// * 32-bit shadows are lossy. Even with zero RGB
+// displacements the affected area will still look
+// slightly darkened.
+//
+// Drivers should ensure all shadow pens in
+// gfx_drawmode_table[] are set to DRAWMODE_NONE
+// when RGB displacements are zero to avoid the
+// darkening effect.
+//-------------------------------------------------
+
+//-------------------------------------------------
+// set_shadow_dRGB32 - configure delta RGB values
+// for 1 of 4 shadow tables
+//-------------------------------------------------
+
+void palette_device::set_shadow_dRGB32(int mode, int dr, int dg, int db, bool noclip)
+{
+ shadow_table_data &stable = m_shadow_tables[mode];
+
+ // only applies to RGB direct modes
+ assert(m_format != BITMAP_FORMAT_IND16);
+ assert(stable.base != NULL);
+
+ // clamp the deltas (why?)
+ if (dr < -0xff) dr = -0xff; else if (dr > 0xff) dr = 0xff;
+ if (dg < -0xff) dg = -0xff; else if (dg > 0xff) dg = 0xff;
+ if (db < -0xff) db = -0xff; else if (db > 0xff) db = 0xff;
+
+ // early exit if nothing changed
+ if (dr == stable.dr && dg == stable.dg && db == stable.db && noclip == stable.noclip)
+ return;
+ stable.dr = dr;
+ stable.dg = dg;
+ stable.db = db;
+ stable.noclip = noclip;
+
+ if (VERBOSE)
+ popmessage("shadow %d recalc %d %d %d %02x", mode, dr, dg, db, noclip);
+
+ // regenerate the table
+ for (int i = 0; i < 32768; i++)
+ {
+ int r = pal5bit(i >> 10) + dr;
+ int g = pal5bit(i >> 5) + dg;
+ int b = pal5bit(i >> 0) + db;
+
+ // apply clipping
+ if (!noclip)
+ {
+ r = rgb_t::clamp(r);
+ g = rgb_t::clamp(g);
+ b = rgb_t::clamp(b);
+ }
+ rgb_t final = rgb_t(r, g, b);
+
+ // store either 16 or 32 bit
+ if (m_format == BITMAP_FORMAT_RGB32)
+ stable.base[i] = final;
+ else
+ stable.base[i] = final.as_rgb15();
+ }
+}
+
+
+
+//**************************************************************************
+// GENERIC WRITE HANDLERS
+//**************************************************************************
+
+//-------------------------------------------------
+// update_for_write - given a write of a given
+// length to a given byte offset, update all
+// potentially modified palette entries
+//-------------------------------------------------
+
+inline void palette_device::update_for_write(offs_t byte_offset, int bytes_modified, bool indirect)
+{
+ assert((m_indirect_entries != 0) == indirect);
+
+ // determine how many entries were modified
+ int bpe = m_paletteram.bytes_per_entry();
+ assert(bpe != 0);
+ int count = (bytes_modified + bpe - 1) / bpe;
+
+ // for each entry modified, fetch the palette data and set the pen color or indirect color
+ offs_t base = byte_offset / bpe;
+ for (int index = 0; index < count; index++)
+ {
+ UINT32 data = m_paletteram.read(base + index);
+ if (m_paletteram_ext.base() != NULL)
+ data |= m_paletteram_ext.read(base + index) << (8 * bpe);
+
+ if (indirect)
+ set_indirect_color(base + index, m_raw_to_rgb(data));
+ else
+ m_palette->entry_set_color(base + index, m_raw_to_rgb(data));
+ }
+}
+
+
+//-------------------------------------------------
+// write - write a byte to the base paletteram
+//-------------------------------------------------
+
+WRITE8_MEMBER(palette_device::write)
+{
+ m_paletteram.write8(offset, data);
+ update_for_write(offset, 1);
+}
+
+WRITE16_MEMBER(palette_device::write)
+{
+ m_paletteram.write16(offset, data, mem_mask);
+ update_for_write(offset * 2, 2);
+}
+
+WRITE32_MEMBER(palette_device::write)
+{
+ m_paletteram.write32(offset, data, mem_mask);
+ update_for_write(offset * 4, 4);
+}
+
+READ8_MEMBER(palette_device::read)
+{
+ return m_paletteram.read8(offset);
+}
+
+READ16_MEMBER(palette_device::read)
+{
+ return m_paletteram.read16(offset);
+}
+
+READ32_MEMBER(palette_device::read)
+{
+ return m_paletteram.read32(offset);
+}
+
+
+//-------------------------------------------------
+// write_ext - write a byte to the extended
+// paletteram
+//-------------------------------------------------
+
+WRITE8_MEMBER(palette_device::write_ext)
+{
+ m_paletteram_ext.write8(offset, data);
+ update_for_write(offset, 1);
+}
+
+
+WRITE16_MEMBER(palette_device::write_ext)
+{
+ m_paletteram_ext.write16(offset, data, mem_mask);
+ update_for_write(offset * 2, 2);
+}
+
+
+//-------------------------------------------------
+// write_indirect - write a byte to the base
+// paletteram, updating indirect colors
+//-------------------------------------------------
+
+WRITE8_MEMBER(palette_device::write_indirect)
+{
+ m_paletteram.write8(offset, data);
+ update_for_write(offset, 1, true);
+}
+
+
+//-------------------------------------------------
+// write_ext - write a byte to the extended
+// paletteram, updating indirect colors
+//-------------------------------------------------
+
+WRITE8_MEMBER(palette_device::write_indirect_ext)
+{
+ m_paletteram_ext.write8(offset, data);
+ update_for_write(offset, 1, true);
+}
+
+
+
+//**************************************************************************
+// DEVICE MANAGEMENT
+//**************************************************************************
+
+//-------------------------------------------------
+// device_start - start up the device
+//-------------------------------------------------
+
+void palette_device::device_start()
+{
+ // bind the init function
+ m_init.bind_relative_to(*owner());
+
+ // find the memory, if present
+ const memory_share *share = memshare(tag());
+ if (share != NULL)
+ {
+ // find the extended (split) memory, if present
+ std::string tag_ext = std::string(tag()).append("_ext");
+ const memory_share *share_ext = memshare(tag_ext.c_str());
+
+ // make sure we have specified a format
+ assert_always(m_raw_to_rgb.bytes_per_entry() > 0, "Palette has memory share but no format specified");
+
+ // determine bytes per entry and configure
+ int bytes_per_entry = m_raw_to_rgb.bytes_per_entry();
+ if (share_ext == NULL)
+ m_paletteram.set(*share, bytes_per_entry);
+ else
+ {
+ m_paletteram.set(*share, bytes_per_entry / 2);
+ m_paletteram_ext.set(*share_ext, bytes_per_entry / 2);
+ }
+
+ // override membits if provided
+ if (m_membits_supplied)
+ {
+ // forcing width only makes sense when narrower than the native bus width
+ assert_always(m_membits < share->bitwidth(), "Improper use of MCFG_PALETTE_MEMBITS");
+ m_paletteram.set_membits(m_membits);
+ if (share_ext != NULL)
+ m_paletteram_ext.set_membits(m_membits);
+ }
+
+ // override endianness if provided
+ if (m_endianness_supplied)
+ {
+ // forcing endianness only makes sense when the RAM is narrower than the palette format and not split
+ assert_always((share_ext == NULL && m_paletteram.membits() / 8 < bytes_per_entry), "Improper use of MCFG_PALETTE_ENDIANNESS");
+ m_paletteram.set_endianness(m_endianness);
+ }
+ }
+
+ // reset all our data
+ screen_device *device = machine().first_screen();
+ m_format = (device != NULL) ? device->format() : BITMAP_FORMAT_INVALID;
+
+ // allocate the palette
+ if (m_entries > 0)
+ {
+ allocate_palette();
+ allocate_color_tables();
+ allocate_shadow_tables();
+
+ // allocate indirection tables
+ if (m_indirect_entries > 0)
+ {
+ m_indirect_colors.resize(m_indirect_entries);
+ for (int color = 0; color < m_indirect_entries; color++)
+ {
+ // alpha = 0 ensures change is detected the first time set_indirect_color() is called
+ m_indirect_colors[color] = rgb_t(0, 0, 0, 0);
+ }
+
+ m_indirect_pens.resize(m_entries);
+ for (int pen = 0; pen < m_entries; pen++)
+ m_indirect_pens[pen] = pen % m_indirect_entries;
+ }
+ }
+
+ // call the initialization helper if present
+ if (!m_init.isnull())
+ m_init(*this);
+
+ // set up save/restore of the palette
+ m_save_pen.resize(m_palette->num_colors());
+ m_save_contrast.resize(m_palette->num_colors());
+ save_item(NAME(m_save_pen));
+ save_item(NAME(m_save_contrast));
+
+ // save indirection tables if we have them
+ if (m_indirect_entries > 0)
+ {
+ save_item(NAME(m_indirect_colors));
+ save_item(NAME(m_indirect_pens));
+ }
+}
+
+
+
+//**************************************************************************
+// INTERNAL FUNCTIONS
+//**************************************************************************
+
+//-------------------------------------------------
+// device_pre_save - prepare the save arrays
+// for saving
+//-------------------------------------------------
+
+void palette_device::device_pre_save()
+{
+ // fill the save arrays with updated pen and brightness information
+ int numcolors = m_palette->num_colors();
+ for (int index = 0; index < numcolors; index++)
+ {
+ m_save_pen[index] = pen_color(index);
+ m_save_contrast[index] = pen_contrast(index);
+ }
+}
+
+
+//-------------------------------------------------
+// device_post_load - called after restore to
+// actually update the palette
+//-------------------------------------------------
+
+void palette_device::device_post_load()
+{
+ // reset the pen and brightness for each entry
+ int numcolors = m_palette->num_colors();
+ for (int index = 0; index < numcolors; index++)
+ {
+ set_pen_color(index, m_save_pen[index]);
+ set_pen_contrast(index, m_save_contrast[index]);
+ }
+}
+
+
+//-------------------------------------------------
+// device_stop - final cleanup
+//-------------------------------------------------
+
+void palette_device::device_stop()
+{
+ // dereference the palette
+ if (m_palette != NULL)
+ m_palette->deref();
+}
+
+
+//-------------------------------------------------
+// device_validity_check - validate device
+// configuration
+//-------------------------------------------------
+
+void palette_device::device_validity_check(validity_checker &valid) const
+{
+}
+
+
+//-------------------------------------------------
+// allocate_palette - allocate and configure the
+// palette object itself
+//-------------------------------------------------
+
+void palette_device::allocate_palette()
+{
+ // determine the number of groups we need
+ int numgroups = 1;
+ if (m_enable_shadows)
+ m_shadow_group = numgroups++;
+ if (m_enable_hilights)
+ m_hilight_group = numgroups++;
+ assert_always(m_entries * numgroups <= 65536, "Palette has more than 65536 colors.");
+
+ // allocate a palette object containing all the colors and groups
+ m_palette = palette_t::alloc(m_entries, numgroups);
+
+ // configure the groups
+ if (m_shadow_group != 0)
+ set_shadow_factor(float(PALETTE_DEFAULT_SHADOW_FACTOR));
+ if (m_hilight_group != 0)
+ set_highlight_factor(float(PALETTE_DEFAULT_HIGHLIGHT_FACTOR));
+
+ // set the initial colors to a standard rainbow
+ for (int index = 0; index < m_entries; index++)
+ set_pen_color(index, rgbexpand<1,1,1>(index, 0, 1, 2));
+
+ // switch off the color mode
+ switch (m_format)
+ {
+ // 16-bit paletteized case
+ case BITMAP_FORMAT_IND16:
+ m_black_pen = m_palette->black_entry();
+ m_white_pen = m_palette->white_entry();
+ if (m_black_pen >= 65536)
+ m_black_pen = 0;
+ if (m_white_pen >= 65536)
+ m_white_pen = 65535;
+ break;
+
+ // 32-bit direct case
+ case BITMAP_FORMAT_RGB32:
+ m_black_pen = rgb_t::black;
+ m_white_pen = rgb_t::white;
+ break;
+
+ // screenless case
+ case BITMAP_FORMAT_INVALID:
+ default:
+ break;
+ }
+}
+
+
+//-------------------------------------------------
+// allocate_color_tables - allocate memory for
+// pen and color tables
+//-------------------------------------------------
+
+void palette_device::allocate_color_tables()
+{
+ int total_colors = m_palette->num_colors() * m_palette->num_groups();
+
+ // allocate memory for the pen table
+ switch (m_format)
+ {
+ case BITMAP_FORMAT_IND16:
+ // create a dummy 1:1 mapping
+ {
+ m_pen_array.resize(total_colors + 2);
+ pen_t *pentable = &m_pen_array[0];
+ m_pens = &m_pen_array[0];
+ for (int i = 0; i < total_colors + 2; i++)
+ pentable[i] = i;
+ }
+ break;
+
+ case BITMAP_FORMAT_RGB32:
+ m_pens = reinterpret_cast<const pen_t *>(m_palette->entry_list_adjusted());
+ break;
+
+ default:
+ m_pens = NULL;
+ break;
+ }
+}
+
+
+//-------------------------------------------------
+// allocate_shadow_tables - allocate memory for
+// shadow tables
+//-------------------------------------------------
+
+void palette_device::allocate_shadow_tables()
+{
+ // if we have shadows, allocate shadow tables
+ if (m_enable_shadows)
+ {
+ m_shadow_array.resize(65536);
+
+ // palettized mode gets a single 64k table in slots 0 and 2
+ if (m_format == BITMAP_FORMAT_IND16)
+ {
+ m_shadow_tables[0].base = m_shadow_tables[2].base = &m_shadow_array[0];
+ for (int i = 0; i < 65536; i++)
+ m_shadow_array[i] = (i < m_entries) ? (i + m_entries) : i;
+ }
+
+ // RGB mode gets two 32k tables in slots 0 and 2
+ else
+ {
+ m_shadow_tables[0].base = &m_shadow_array[0];
+ m_shadow_tables[2].base = &m_shadow_array[32768];
+ configure_rgb_shadows(0, float(PALETTE_DEFAULT_SHADOW_FACTOR));
+ }
+ }
+
+ // if we have hilights, allocate shadow tables
+ if (m_enable_hilights)
+ {
+ m_hilight_array.resize(65536);
+
+ // palettized mode gets a single 64k table in slots 1 and 3
+ if (m_format == BITMAP_FORMAT_IND16)
+ {
+ m_shadow_tables[1].base = m_shadow_tables[3].base = &m_hilight_array[0];
+ for (int i = 0; i < 65536; i++)
+ m_hilight_array[i] = (i < m_entries) ? (i + 2 * m_entries) : i;
+ }
+
+ // RGB mode gets two 32k tables in slots 1 and 3
+ else
+ {
+ m_shadow_tables[1].base = &m_hilight_array[0];
+ m_shadow_tables[3].base = &m_hilight_array[32768];
+ configure_rgb_shadows(1, float(PALETTE_DEFAULT_HIGHLIGHT_FACTOR));
+ }
+ }
+
+ // set the default table
+ m_shadow_table = m_shadow_tables[0].base;
+}
+
+
+//-------------------------------------------------
+// configure_rgb_shadows - configure shadows
+// for the RGB tables
+//-------------------------------------------------
+
+void palette_device::configure_rgb_shadows(int mode, float factor)
+{
+ // only applies to RGB direct modes
+ assert(m_format != BITMAP_FORMAT_IND16);
+
+ // verify the shadow table
+ assert(mode >= 0 && mode < ARRAY_LENGTH(m_shadow_tables));
+ shadow_table_data &stable = m_shadow_tables[mode];
+ assert(stable.base != NULL);
+
+ // regenerate the table
+ int ifactor = int(factor * 256.0f);
+ for (int rgb555 = 0; rgb555 < 32768; rgb555++)
+ {
+ UINT8 r = rgb_t::clamp((pal5bit(rgb555 >> 10) * ifactor) >> 8);
+ UINT8 g = rgb_t::clamp((pal5bit(rgb555 >> 5) * ifactor) >> 8);
+ UINT8 b = rgb_t::clamp((pal5bit(rgb555 >> 0) * ifactor) >> 8);
+
+ // store either 16 or 32 bit
+ rgb_t final = rgb_t(r, g, b);
+ if (m_format == BITMAP_FORMAT_RGB32)
+ stable.base[rgb555] = final;
+ else
+ stable.base[rgb555] = final.as_rgb15();
+ }
+}
+
+
+
+//**************************************************************************
+// COMMON PALETTE INITIALIZATION
+//**************************************************************************
+
+/*-------------------------------------------------
+ black - completely black palette
+-------------------------------------------------*/
+
+void palette_device::palette_init_all_black(palette_device &palette)
+{
+ int i;
+
+ for (i = 0; i < palette.entries(); i++)
+ {
+ palette.set_pen_color(i,rgb_t::black); // black
+ }
+}
+
+
+/*-------------------------------------------------
+ black_and_white - basic 2-color black & white
+-------------------------------------------------*/
+
+void palette_device::palette_init_black_and_white(palette_device &palette)
+{
+ palette.set_pen_color(0,rgb_t::black); // black
+ palette.set_pen_color(1,rgb_t::white); // white
+}
+
+
+/*-------------------------------------------------
+ white_and_black - basic 2-color white & black
+-------------------------------------------------*/
+
+void palette_device::palette_init_white_and_black(palette_device &palette)
+{
+ palette.set_pen_color(0,rgb_t::white); // white
+ palette.set_pen_color(1,rgb_t::black); // black
+}
+
+
+/*-------------------------------------------------
+ monochrome_amber - 2-color black & amber
+-------------------------------------------------*/
+
+void palette_device::palette_init_monochrome_amber(palette_device &palette)
+{
+ palette.set_pen_color(0, rgb_t::black); // black
+ palette.set_pen_color(1, rgb_t(0xf7, 0xaa, 0x00)); // amber
+}
+
+
+/*-------------------------------------------------
+ monochrome_green - 2-color black & green
+-------------------------------------------------*/
+
+void palette_device::palette_init_monochrome_green(palette_device &palette)
+{
+ palette.set_pen_color(0, rgb_t::black); // black
+ palette.set_pen_color(1, rgb_t(0x00, 0xff, 0x00)); // green
+}
+
+
+/*-------------------------------------------------
+ monochrome_green_highlight - 3-color black & green
+-------------------------------------------------*/
+
+void palette_device::palette_init_monochrome_green_highlight(palette_device &palette)
+{
+ palette.set_pen_color(0, rgb_t::black); // black
+ palette.set_pen_color(1, rgb_t(0x00, 0xc0, 0x00)); // green
+ palette.set_pen_color(2, rgb_t(0x00, 0xff, 0x00)); // green
+}
+
+
+/*-------------------------------------------------
+ monochrome_yellow - 2-color black & yellow
+-------------------------------------------------*/
+
+void palette_device::palette_init_monochrome_yellow(palette_device &palette)
+{
+ palette.set_pen_color(0, rgb_t::black); // black
+ palette.set_pen_color(1, rgb_t(0xff, 0xff, 0x00)); // yellow
+}
+
+
+/*-------------------------------------------------
+ 3bit_rgb - 8-color rgb
+-------------------------------------------------*/
+
+void palette_device::palette_init_3bit_rgb(palette_device &palette)
+{
+ for (int i = 0; i < 8; i++)
+ palette.set_pen_color(i, rgb_t(pal1bit(i >> 0), pal1bit(i >> 1), pal1bit(i >> 2)));
+}
+
+
+/*-------------------------------------------------
+ 3bit_rbg - 8-color rgb
+-------------------------------------------------*/
+
+void palette_device::palette_init_3bit_rbg(palette_device &palette)
+{
+ for (int i = 0; i < 8; i++)
+ palette.set_pen_color(i, rgb_t(pal1bit(i >> 0), pal1bit(i >> 2), pal1bit(i >> 1)));
+}
+
+
+/*-------------------------------------------------
+ 3bit_brg - 8-color rgb
+-------------------------------------------------*/
+
+void palette_device::palette_init_3bit_brg(palette_device &palette)
+{
+ for (int i = 0; i < 8; i++)
+ palette.set_pen_color(i, rgb_t(pal1bit(i >> 1), pal1bit(i >> 2), pal1bit(i >> 0)));
+}
+
+
+/*-------------------------------------------------
+ 3bit_grb - 8-color rgb
+-------------------------------------------------*/
+
+void palette_device::palette_init_3bit_grb(palette_device &palette)
+{
+ for (int i = 0; i < 8; i++)
+ palette.set_pen_color(i, rgb_t(pal1bit(i >> 1), pal1bit(i >> 0), pal1bit(i >> 2)));
+}
+
+
+/*-------------------------------------------------
+ 3bit_gbr - 8-color rgb
+-------------------------------------------------*/
+
+void palette_device::palette_init_3bit_gbr(palette_device &palette)
+{
+ for (int i = 0; i < 8; i++)
+ palette.set_pen_color(i, rgb_t(pal1bit(i >> 2), pal1bit(i >> 0), pal1bit(i >> 1)));
+}
+
+
+/*-------------------------------------------------
+ 3bit_bgr - 8-color rgb
+-------------------------------------------------*/
+
+void palette_device::palette_init_3bit_bgr(palette_device &palette)
+{
+ for (int i = 0; i < 8; i++)
+ palette.set_pen_color(i, rgb_t(pal1bit(i >> 2), pal1bit(i >> 1), pal1bit(i >> 0)));
+}
+
+
+/*-------------------------------------------------
+ RRRR_GGGG_BBBB - standard 4-4-4 palette,
+ assuming the commonly used resistor values:
+
+ bit 3 -- 220 ohm resistor -- RED/GREEN/BLUE
+ -- 470 ohm resistor -- RED/GREEN/BLUE
+ -- 1 kohm resistor -- RED/GREEN/BLUE
+ bit 0 -- 2.2kohm resistor -- RED/GREEN/BLUE
+-------------------------------------------------*/
+
+void palette_device::palette_init_RRRRGGGGBBBB_proms(palette_device &palette)
+{
+ const UINT8 *color_prom = machine().root_device().memregion("proms")->base();
+ int i;
+
+ for (i = 0; i < palette.entries(); i++)
+ {
+ int bit0,bit1,bit2,bit3,r,g,b;
+
+ // red component
+ bit0 = (color_prom[i] >> 0) & 0x01;
+ bit1 = (color_prom[i] >> 1) & 0x01;
+ bit2 = (color_prom[i] >> 2) & 0x01;
+ bit3 = (color_prom[i] >> 3) & 0x01;
+ r = 0x0e * bit0 + 0x1f * bit1 + 0x43 * bit2 + 0x8f * bit3;
+
+ // green component
+ bit0 = (color_prom[i + palette.entries()] >> 0) & 0x01;
+ bit1 = (color_prom[i + palette.entries()] >> 1) & 0x01;
+ bit2 = (color_prom[i + palette.entries()] >> 2) & 0x01;
+ bit3 = (color_prom[i + palette.entries()] >> 3) & 0x01;
+ g = 0x0e * bit0 + 0x1f * bit1 + 0x43 * bit2 + 0x8f * bit3;
+
+ // blue component
+ bit0 = (color_prom[i + 2*palette.entries()] >> 0) & 0x01;
+ bit1 = (color_prom[i + 2*palette.entries()] >> 1) & 0x01;
+ bit2 = (color_prom[i + 2*palette.entries()] >> 2) & 0x01;
+ bit3 = (color_prom[i + 2*palette.entries()] >> 3) & 0x01;
+ b = 0x0e * bit0 + 0x1f * bit1 + 0x43 * bit2 + 0x8f * bit3;
+
+ palette.set_pen_color(i,rgb_t(r,g,b));
+ }
+}
+
+
+
+/*-------------------------------------------------
+ RRRRR_GGGGG_BBBBB/BBBBB_GGGGG_RRRRR -
+ standard 5-5-5 palette for games using a
+ 15-bit color space
+-------------------------------------------------*/
+
+void palette_device::palette_init_RRRRRGGGGGBBBBB(palette_device &palette)
+{
+ int i;
+
+ for (i = 0; i < 0x8000; i++)
+ palette.set_pen_color(i, rgbexpand<5,5,5>(i, 10, 5, 0));
+}
+
+
+void palette_device::palette_init_BBBBBGGGGGRRRRR(palette_device &palette)
+{
+ int i;
+
+ for (i = 0; i < 0x8000; i++)
+ palette.set_pen_color(i, rgbexpand<5,5,5>(i, 0, 5, 10));
+}
+
+
+
+/*-------------------------------------------------
+ RRRRR_GGGGGG_BBBBB -
+ standard 5-6-5 palette for games using a
+ 16-bit color space
+-------------------------------------------------*/
+
+void palette_device::palette_init_RRRRRGGGGGGBBBBB(palette_device &palette)
+{
+ int i;
+
+ for (i = 0; i < 0x10000; i++)
+ palette.set_pen_color(i, rgbexpand<5,6,5>(i, 11, 5, 0));
+}
+
+rgb_t raw_to_rgb_converter::IRRRRRGGGGGBBBBB_decoder(UINT32 raw)
+{
+ UINT8 i = (raw >> 15) & 1;
+ UINT8 r = pal6bit(((raw >> 9) & 0x3e) | i);
+ UINT8 g = pal6bit(((raw >> 4) & 0x3e) | i);
+ UINT8 b = pal6bit(((raw << 1) & 0x3e) | i);
+ return rgb_t(r, g, b);
+}
+
+rgb_t raw_to_rgb_converter::RRRRGGGGBBBBRGBx_decoder(UINT32 raw)
+{
+ UINT8 r = pal5bit(((raw >> 11) & 0x1e) | ((raw >> 3) & 0x01));
+ UINT8 g = pal5bit(((raw >> 7) & 0x1e) | ((raw >> 2) & 0x01));
+ UINT8 b = pal5bit(((raw >> 3) & 0x1e) | ((raw >> 1) & 0x01));
+ return rgb_t(r, g, b);
+}
+
+rgb_t raw_to_rgb_converter::xRGBRRRRGGGGBBBB_bit0_decoder(UINT32 raw)
+{
+ UINT8 r = pal5bit(((raw >> 7) & 0x1e) | ((raw >> 14) & 0x01));
+ UINT8 g = pal5bit(((raw >> 3) & 0x1e) | ((raw >> 13) & 0x01));
+ UINT8 b = pal5bit(((raw << 1) & 0x1e) | ((raw >> 12) & 0x01));
+ return rgb_t(r, g, b);
+}
+
+rgb_t raw_to_rgb_converter::xRGBRRRRGGGGBBBB_bit4_decoder(UINT32 raw)
+{
+ UINT8 r = pal5bit(((raw >> 8) & 0x0f) | ((raw >> 10) & 0x10));
+ UINT8 g = pal5bit(((raw >> 4) & 0x0f) | ((raw >> 9) & 0x10));
+ UINT8 b = pal5bit(((raw >> 0) & 0x0f) | ((raw >> 8) & 0x10));
+ return rgb_t(r, g, b);
+}