diff options
Diffstat (limited to 'src/emu/emupal.c')
-rw-r--r-- | src/emu/emupal.c | 1118 |
1 files changed, 588 insertions, 530 deletions
diff --git a/src/emu/emupal.c b/src/emu/emupal.c index b9a514a260b..5f79b903140 100644 --- a/src/emu/emupal.c +++ b/src/emu/emupal.c @@ -1,751 +1,809 @@ -/****************************************************************************** +/*************************************************************************** emupal.c - Emulator palette handling functions. - - Copyright Nicola Salmoria and the MAME Team. - Visit http://mamedev.org for licensing and usage restrictions. + Palette device. + +**************************************************************************** + + 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" #define VERBOSE 0 -/*************************************************************************** - CONSTANTS -***************************************************************************/ +//************************************************************************** +// DEVICE DEFINITIONS +//************************************************************************** -#define PEN_BRIGHTNESS_BITS 8 -#define MAX_PEN_BRIGHTNESS (4 << PEN_BRIGHTNESS_BITS) -#define MAX_SHADOW_PRESETS 4 +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_palette(NULL) +{ +} -/*************************************************************************** - TYPE DEFINITIONS -***************************************************************************/ +//************************************************************************** +// INITIALIZATION AND CONFIGURATION +//************************************************************************** -/* information about a shadow table */ -struct shadow_table_data +void palette_device::static_set_init(device_t &device, palette_init_delegate init) { - UINT32 * base; /* pointer to the base of the table */ - INT16 dr; /* delta red value */ - INT16 dg; /* delta green value */ - INT16 db; /* delta blue value */ - UINT8 noclip; /* clip? */ -}; + downcast<palette_device &>(device).m_init = init; +} -struct palette_private +void palette_device::static_set_format(device_t &device, raw_to_rgb_converter raw_to_rgb) { - bitmap_format format; /* format assumed for palette data */ - - UINT32 shadow_group; /* index of the shadow group, or 0 if none */ - UINT32 hilight_group; /* index of the hilight group, or 0 if none */ - - pen_t black_pen; /* precomputed black pen value */ - pen_t white_pen; /* precomputed white pen value */ - - shadow_table_data shadow_table[MAX_SHADOW_PRESETS]; /* array of shadow table data */ - - pen_t * save_pen; /* pens for save/restore */ - float * save_bright; /* brightness for save/restore */ -}; + downcast<palette_device &>(device).m_raw_to_rgb = raw_to_rgb; +} -class colortable_t +void palette_device::static_set_entries(device_t &device, int entries) { -public: - colortable_t(running_machine &machine) - : m_machine(machine) { } - - running_machine &machine() const { return m_machine; } - - UINT32 entries; /* number of entries */ - UINT32 palentries; /* number of palette entries */ - UINT16 * raw; /* raw data about each entry */ - rgb_t * palette; /* palette entries */ - -private: - running_machine & m_machine; /* associated machine */ -}; - - - -/*************************************************************************** - FUNCTION PROTOTYPES -***************************************************************************/ - -static void palette_presave(running_machine &machine); -static void palette_postload(running_machine &machine); -static void palette_exit(running_machine &machine); -static void allocate_palette(running_machine &machine, palette_private *palette); -static void allocate_color_tables(running_machine &machine, palette_private *palette); -static void allocate_shadow_tables(running_machine &machine, palette_private *palette); -static void configure_rgb_shadows(running_machine &machine, int mode, float factor); - - - -/*************************************************************************** - INITIALIZATION AND CONFIGURATION -***************************************************************************/ + downcast<palette_device &>(device).m_entries = entries; +} -/*------------------------------------------------- - palette_init - palette initialization that - takes place before the display is created --------------------------------------------------*/ -void palette_init(running_machine &machine) +void palette_device::static_enable_shadows(device_t &device) { - palette_private *palette = auto_alloc_clear(machine, palette_private); - screen_device *device = machine.first_screen(); - - /* get the format from the first screen, or use BITMAP_FORMAT_INVALID, if screenless */ - bitmap_format format = (device != NULL) ? device->format() : BITMAP_FORMAT_INVALID; - - /* request cleanup */ - machine.palette_data = palette; - machine.add_notifier(MACHINE_NOTIFY_EXIT, machine_notify_delegate(FUNC(palette_exit), &machine)); - - /* reset all our data */ - palette->format = format; - - /* determine the color mode */ - switch (format) - { - case BITMAP_FORMAT_IND16: - case BITMAP_FORMAT_RGB32: - /* indexed and RGB modes are fine for everything */ - break; - - case BITMAP_FORMAT_INVALID: - /* invalid format means no palette - or at least it should */ - /* Do not assert for now, palette manager should be added */ - /* in order to make possible adding of palette items per */ - /* device otherwise we need to set total colors per driver */ - //assert(machine.total_colors() == 0); - return; + downcast<palette_device &>(device).m_enable_shadows = true; +} - default: - fatalerror("Unsupported screen bitmap format!\n"); - break; - } - /* allocate all the data structures */ - if (machine.total_colors() > 0) - { - int numcolors; - - allocate_palette(machine, palette); - allocate_color_tables(machine, palette); - allocate_shadow_tables(machine, palette); - - /* set up save/restore of the palette */ - numcolors = machine.palette->num_colors(); - palette->save_pen = auto_alloc_array(machine, pen_t, numcolors); - palette->save_bright = auto_alloc_array(machine, float, numcolors); - machine.save().save_pointer(NAME(palette->save_pen), numcolors); - machine.save().save_pointer(NAME(palette->save_bright), numcolors); - machine.save().register_presave(save_prepost_delegate(FUNC(palette_presave), &machine)); - machine.save().register_postload(save_prepost_delegate(FUNC(palette_postload), &machine)); - } +void palette_device::static_enable_hilights(device_t &device) +{ + downcast<palette_device &>(device).m_enable_hilights = true; } -/*************************************************************************** - SHADOW/HIGHLIGHT CONFIGURATION -***************************************************************************/ +//************************************************************************** +// INDIRECTION (AKA COLORTABLES) +//************************************************************************** -/*------------------------------------------------- - palette_set_shadow_factor - set the global - shadow brightness factor --------------------------------------------------*/ +//------------------------------------------------- +// set_indirect_color - set an indirect color +//------------------------------------------------- -void palette_set_shadow_factor(running_machine &machine, double factor) +void palette_device::set_indirect_color(int index, rgb_t rgb) { - palette_private *palette = machine.palette_data; - - assert(palette->shadow_group != 0); - machine.palette->group_set_contrast(palette->shadow_group, factor); + // ensure the array is expanded enough to handle the index, then set it + m_indirect_colors.resize(index + 1); + m_indirect_colors[index] = rgb; } -/*------------------------------------------------- - palette_set_highlight_factor - set the global - highlight brightness factor --------------------------------------------------*/ +//------------------------------------------------- +// set_pen_indirect - set an indirect pen index +//------------------------------------------------- -void palette_set_highlight_factor(running_machine &machine, double factor) +void palette_device::set_pen_indirect(pen_t pen, UINT16 index) { - palette_private *palette = machine.palette_data; - - assert(palette->hilight_group != 0); - machine.palette->group_set_contrast(palette->hilight_group, factor); + // ensure the array is expanded enough to handle the index, then set it + m_indirect_entry.resize(index + 1); + m_indirect_entry[index] = index; } +//------------------------------------------------- +// transpen_mask - return a mask of pens that +// whose indirect values match the given +// transcolor +//------------------------------------------------- -/*************************************************************************** - 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. - - - palette_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 ) +UINT32 palette_device::transpen_mask(gfx_element &gfx, int color, int transcolor) +{ + UINT32 entry = gfx.colorbase() + (color % gfx.colors()) * gfx.granularity(); - noclip: 0 = resultant RGB clipped at 0x00/0xff - 1 = resultant RGB wraparound 0x00/0xff + // make sure we are in range + assert(entry < m_indirect_entry.count()); + 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_entry.count() - entry); - * Color shadows only work under 32bpp. - This function has no effect in lower color - depths where + // set a bit anywhere the transcolor matches + UINT32 mask = 0; + for (int bit = 0; bit < count; bit++) + if (m_indirect_entry[entry++] == transcolor) + mask |= 1 << bit; - palette_set_shadow_factor() or - palette_set_highlight_factor() + // return the final mask + return mask; +} - should be used instead. - * 32-bit shadows are lossy. Even with zero RGB - displacements the affected area will still look - slightly darkened. +//------------------------------------------------- +// configure_tilemap_groups - configure groups +// within a tilemap to match the indirect masks +//------------------------------------------------- - 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. --------------------------------------------------*/ +void palette_device::configure_tilemap_groups(tilemap_t &tmap, gfx_element &gfx, int transcolor) +{ + int color; -/*------------------------------------------------- - palette_set_shadow_mode - select 1 of 4 - different live shadow tables --------------------------------------------------*/ + assert(gfx.colors() <= TILEMAP_NUM_GROUPS); -void palette_set_shadow_mode(running_machine &machine, int mode) -{ - palette_private *palette = machine.palette_data; - assert(mode >= 0 && mode < MAX_SHADOW_PRESETS); - machine.shadow_table = palette->shadow_table[mode].base; + // iterate over all colors in the tilemap + for (color = 0; color < gfx.colors(); color++) + tmap.set_transmask(color, transpen_mask(gfx, color, transcolor), 0); } -/*------------------------------------------------- - palette_set_shadow_dRGB32 - configure delta - RGB values for 1 of 4 shadow tables --------------------------------------------------*/ -void palette_set_shadow_dRGB32(running_machine &machine, int mode, int dr, int dg, int db, int noclip) +//************************************************************************** +// 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) { - palette_private *palette = machine.palette_data; - shadow_table_data *stable = &palette->shadow_table[mode]; - int i; + shadow_table_data &stable = m_shadow_tables[mode]; - /* only applies to RGB direct modes */ - assert(palette->format != BITMAP_FORMAT_IND16); - assert(stable->base != NULL); + // only applies to RGB direct modes + assert(m_format != BITMAP_FORMAT_IND16); + assert(stable.base != NULL); - /* clamp the deltas (why?) */ + // 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) + // 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; + 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 (i = 0; i < 32768; i++) + // 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 */ + // 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); + rgb_t final = rgb_t(r, g, b); - /* store either 16 or 32 bit */ - if (palette->format == BITMAP_FORMAT_RGB32) - stable->base[i] = final; + // store either 16 or 32 bit + if (m_format == BITMAP_FORMAT_RGB32) + stable.base[i] = final; else - stable->base[i] = final.as_rgb15(); + stable.base[i] = final.as_rgb15(); } } -/*************************************************************************** - COLORTABLE MANAGEMENT -***************************************************************************/ +//************************************************************************** +// GENERIC WRITE HANDLERS +//************************************************************************** -/*------------------------------------------------- - colortable_alloc - allocate a new colortable - with the given number of entries --------------------------------------------------*/ +//------------------------------------------------- +// update_for_write - given a write of a given +// length to a given byte offset, update all +// potentially modified palette entries +//------------------------------------------------- -colortable_t *colortable_alloc(running_machine &machine, UINT32 palettesize) +inline void palette_device::update_for_write(offs_t byte_offset, int bytes_modified) +{ + // 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 + 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()) + data |= m_paletteram_ext.read(base + index) << (8 * bpe); + set_pen_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) { - colortable_t *ctable; - UINT32 index; + m_paletteram.write16(offset, data, mem_mask); + update_for_write(offset * 2, 2); +} - assert(palettesize > 0); +WRITE32_MEMBER(palette_device::write) +{ + m_paletteram.write32(offset, data, mem_mask); + update_for_write(offset * 4, 4); +} - /* allocate the colortable */ - ctable = auto_alloc_clear(machine, colortable_t(machine)); - /* fill in the basics */ - ctable->entries = machine.total_colors(); - ctable->palentries = palettesize; +//------------------------------------------------- +// write_ext - write a byte to the extended +// paletteram +//------------------------------------------------- - /* allocate the raw colortable */ - ctable->raw = auto_alloc_array(machine, UINT16, ctable->entries); - for (index = 0; index < ctable->entries; index++) - ctable->raw[index] = index % ctable->palentries; - machine.save().save_pointer(NAME(ctable->raw), ctable->entries); +WRITE8_MEMBER(palette_device::write_ext) +{ + m_paletteram_ext.write8(offset, data); + update_for_write(offset, 1); +} - /* allocate the palette */ - ctable->palette = auto_alloc_array(machine, rgb_t, ctable->palentries); - for (index = 0; index < ctable->palentries; index++) - ctable->palette[index] = rgb_t(0x80,0xff,0xff,0xff); - machine.save().save_pointer(NAME(ctable->palette), ctable->palentries); - return ctable; +WRITE16_MEMBER(palette_device::write_ext) +{ + m_paletteram_ext.write16(offset, data, mem_mask); + update_for_write(offset * 2, 2); } -/*------------------------------------------------- - colortable_entry_set_value - set the value - of a colortable entry --------------------------------------------------*/ -void colortable_entry_set_value(colortable_t *ctable, UINT32 entry, UINT16 value) +//************************************************************************** +// DEVICE MANAGEMENT +//************************************************************************** + +//------------------------------------------------- +// device_start - start up the device +//------------------------------------------------- + +void palette_device::device_start() { - /* ensure values are within range */ - assert(ctable != NULL); - assert(entry < ctable->entries); - assert(value < ctable->palentries); + // bind the init function + m_init.bind_relative_to(*owner()); - /* update if it has changed */ - if (ctable->raw[entry] != value) + // find the memory, if present + const memory_share *share = memshare(tag()); + if (share != NULL) { - ctable->raw[entry] = value; - palette_set_color(ctable->machine(), entry, ctable->palette[value]); - } -} + // find the extended (split) memory, if present + astring tag_ext(tag(), "_ext"); + const memory_share *share_ext = memshare(tag_ext.cstr()); + + // make sure we have specified a format + assert(m_raw_to_rgb.bytes_per_entry() > 0); + + // determine bytes per entry + 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); + } + // look for an extension entry + if (share_ext != NULL) + m_paletteram_ext.set(*share_ext, m_raw_to_rgb.bytes_per_entry()); + } + + // reset all our data + screen_device *device = machine().first_screen(); + m_format = (device != NULL) ? device->format() : BITMAP_FORMAT_INVALID; + if (m_entries > 0) + { + allocate_palette(); + allocate_color_tables(); + allocate_shadow_tables(); + } -/*------------------------------------------------- - colortable_entry_get_value - return the value - of a colortable entry --------------------------------------------------*/ + // call the initialization helper if present (this will expand the indirection tables to full size) + if (!m_init.isnull()) + m_init(*this); -UINT16 colortable_entry_get_value(colortable_t *ctable, UINT32 entry) -{ - assert(ctable != NULL); - assert(entry < ctable->entries); - return ctable->raw[entry]; + // set up save/restore of the palette + int numcolors = m_palette->num_colors(); + m_save_pen.resize(numcolors); + m_save_contrast.resize(numcolors); + save_item(NAME(m_save_pen)); + save_item(NAME(m_save_contrast)); } -/*------------------------------------------------- - colortable_palette_set_color - change the - color of a colortable palette entry --------------------------------------------------*/ -void colortable_palette_set_color(colortable_t *ctable, UINT32 entry, rgb_t color) -{ - /* ensure values are within range */ - assert(ctable != NULL); - assert(entry < ctable->palentries); +//************************************************************************** +// INTERNAL FUNCTIONS +//************************************************************************** - /* alpha doesn't matter */ - color.set_a(0xff); +//------------------------------------------------- +// device_pre_save - prepare the save arrays +// for saving +//------------------------------------------------- - /* update if it has changed */ - if (ctable->palette[entry] != color) +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++) { - UINT32 index; + m_save_pen[index] = pen_color(index); + m_save_contrast[index] = pen_contrast(index); + } +} - ctable->palette[entry] = color; - /* update the palette for any colortable entries that reference it */ - for (index = 0; index < ctable->entries; index++) - if (ctable->raw[index] == entry) - palette_set_color(ctable->machine(), index, color); +//------------------------------------------------- +// 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]); } } -/*------------------------------------------------- - colortable_entry_get_value - return the color - of a colortable palette entry --------------------------------------------------*/ +//------------------------------------------------- +// device_stop - final cleanup +//------------------------------------------------- -rgb_t colortable_palette_get_color(colortable_t *ctable, UINT32 entry) +void palette_device::device_stop() { - assert(ctable != NULL); - assert(entry < ctable->palentries); - return ctable->palette[entry]; + // dereference the palette + if (m_palette != NULL) + m_palette->deref(); } -/*------------------------------------------------- - colortable_get_transpen_mask - return a 32-bit - transparency mask for a given gfx element and - color --------------------------------------------------*/ +//------------------------------------------------- +// device_validity_check - validate device +// configuration +//------------------------------------------------- -UINT32 colortable_get_transpen_mask(colortable_t *ctable, gfx_element *gfx, int color, int transcolor) +void palette_device::device_validity_check(validity_checker &valid) const { - UINT32 entry = gfx->colorbase() + (color % gfx->colors()) * gfx->granularity(); - UINT32 mask = 0; - UINT32 count, bit; +} - /* make sure we are in range */ - assert(ctable != NULL); - assert(entry < ctable->entries); - assert(gfx->depth() <= 32); - /* either gfx->color_depth entries or as many as we can get up until the end */ - count = MIN(gfx->depth(), ctable->entries - entry); +//------------------------------------------------- +// allocate_palette - allocate and configure the +// palette object itself +//------------------------------------------------- - /* set a bit anywhere the transcolor matches */ - for (bit = 0; bit < count; bit++) - if (ctable->raw[entry++] == transcolor) - mask |= 1 << bit; +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, "Error: 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, rgb_t(pal1bit(index >> 0), pal1bit(index >> 1), pal1bit(index >> 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 = 65536; + break; - /* return the final mask */ - return mask; + // 32-bit direct case + case BITMAP_FORMAT_RGB32: + m_black_pen = rgb_t(0x00,0x00,0x00); + m_white_pen = rgb_t(0xff,0xff,0xff); + break; + + // screenless case + case BITMAP_FORMAT_INVALID: + default: + break; + } } -/*------------------------------------------------- - colortable_configure_tilemap_groups - - configure groups in a tilemap to represent - transparency based on colortable entries - (each group maps to a gfx color) --------------------------------------------------*/ +//------------------------------------------------- +// allocate_color_tables - allocate memory for +// pen and color tables +//------------------------------------------------- -void colortable_configure_tilemap_groups(colortable_t *ctable, tilemap_t *tmap, gfx_element *gfx, int transcolor) +void palette_device::allocate_color_tables() { - int color; + 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; - assert(ctable != NULL); - assert(gfx != NULL); - assert(tmap != NULL); - assert(gfx->colors() <= TILEMAP_NUM_GROUPS); + case BITMAP_FORMAT_RGB32: + m_pens = reinterpret_cast<const pen_t *>(m_palette->entry_list_adjusted()); + break; - /* iterate over all colors in the tilemap */ - for (color = 0; color < gfx->colors(); color++) - tmap->set_transmask(color, colortable_get_transpen_mask(ctable, gfx, color, transcolor), 0); + default: + m_pens = NULL; + break; + } } -/*------------------------------------------------- - colortable_palette_get_size - - return the number of entries in a colortable --------------------------------------------------*/ +//------------------------------------------------- +// allocate_shadow_tables - allocate memory for +// shadow tables +//------------------------------------------------- -UINT32 colortable_palette_get_size(colortable_t *ctable) +void palette_device::allocate_shadow_tables() { - assert(ctable != NULL); - return ctable->palentries; -} + // 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)); + } + } -/*************************************************************************** - UTILITIES -***************************************************************************/ + // if we have hilights, allocate shadow tables + if (m_enable_hilights) + { + m_hilight_array.resize(65536); -/*------------------------------------------------- - get_black_pen - return the pen for a fixed - black color --------------------------------------------------*/ + // 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; + } -pen_t get_black_pen(running_machine &machine) -{ - palette_private *palette = machine.palette_data; - return palette->black_pen; + // 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; } -/*------------------------------------------------- - get_white_pen - return the pen for a fixed - white color --------------------------------------------------*/ +//------------------------------------------------- +// configure_rgb_shadows - configure shadows +// for the RGB tables +//------------------------------------------------- -pen_t get_white_pen(running_machine &machine) +void palette_device::configure_rgb_shadows(int mode, float factor) { - palette_private *palette = machine.palette_data; - return palette->white_pen; + // 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(); + } } -/*************************************************************************** - INTERNAL FUNCTIONS -***************************************************************************/ +//************************************************************************** +// COMMON PALETTE INITIALIZATION +//************************************************************************** /*------------------------------------------------- - palette_presave - prepare the save arrays - for saving + black - completely black palette -------------------------------------------------*/ -static void palette_presave(running_machine &machine) +void palette_device::palette_init_all_black(palette_device &palette) { - int numcolors = machine.palette->num_colors(); - palette_private *palette = machine.palette_data; - int index; + int i; - /* fill the save arrays with updated pen and brightness information */ - for (index = 0; index < numcolors; index++) + for (i = 0; i < palette.entries(); i++) { - palette->save_pen[index] = machine.palette->entry_color(index); - palette->save_bright[index] = machine.palette->entry_contrast(index); + palette.set_pen_color(i,rgb_t::black); // black } } /*------------------------------------------------- - palette_postload - called after restore to - actually update the palette + black_and_white - basic 2-color black & white -------------------------------------------------*/ -static void palette_postload(running_machine &machine) +void palette_device::palette_init_black_and_white(palette_device &palette) { - int numcolors = machine.palette->num_colors(); - palette_private *palette = machine.palette_data; - int index; - - /* reset the pen and brightness for each entry */ - for (index = 0; index < numcolors; index++) - { - machine.palette->entry_set_color(index, palette->save_pen[index]); - machine.palette->entry_set_contrast(index, palette->save_bright[index]); - } + palette.set_pen_color(0,rgb_t::black); // black + palette.set_pen_color(1,rgb_t::white); // white } /*------------------------------------------------- - palette_exit - free any allocated memory + white_and_black - basic 2-color white & black -------------------------------------------------*/ -static void palette_exit(running_machine &machine) +void palette_device::palette_init_white_and_black(palette_device &palette) { - /* dereference the palette */ - if (machine.palette != NULL) - machine.palette->deref(); + palette.set_pen_color(0,rgb_t::white); // white + palette.set_pen_color(1,rgb_t::black); // black } /*------------------------------------------------- - allocate_palette - allocate and configure the - palette object itself + monochrome_amber - 2-color black & amber -------------------------------------------------*/ -static void allocate_palette(running_machine &machine, palette_private *palette) +void palette_device::palette_init_monochrome_amber(palette_device &palette) { - int numgroups, index; - - /* determine the number of groups we need */ - numgroups = 1; - if (machine.config().m_video_attributes & VIDEO_HAS_SHADOWS) - palette->shadow_group = numgroups++; - if (machine.config().m_video_attributes & VIDEO_HAS_HIGHLIGHTS) - palette->hilight_group = numgroups++; - assert_always(machine.total_colors() * numgroups <= 65536, "Error: palette has more than 65536 colors."); - - /* allocate a palette object containing all the colors and groups */ - machine.palette = palette_t::alloc(machine.total_colors(), numgroups); - - /* configure the groups */ - if (palette->shadow_group != 0) - machine.palette->group_set_contrast(palette->shadow_group, (float)PALETTE_DEFAULT_SHADOW_FACTOR); - if (palette->hilight_group != 0) - machine.palette->group_set_contrast(palette->hilight_group, (float)PALETTE_DEFAULT_HIGHLIGHT_FACTOR); - - /* set the initial colors to a standard rainbow */ - for (index = 0; index < machine.total_colors(); index++) - machine.palette->entry_set_color(index, rgb_t(pal1bit(index >> 0), pal1bit(index >> 1), pal1bit(index >> 2))); + palette.set_pen_color(0, rgb_t::black); // black + palette.set_pen_color(1, 0xf7, 0xaa, 0x00); // amber +} - /* switch off the color mode */ - switch (palette->format) - { - /* 16-bit paletteized case */ - case BITMAP_FORMAT_IND16: - palette->black_pen = machine.palette->black_entry(); - palette->white_pen = machine.palette->white_entry(); - if (palette->black_pen >= 65536) - palette->black_pen = 0; - if (palette->white_pen >= 65536) - palette->white_pen = 65536; - break; - /* 32-bit direct case */ - case BITMAP_FORMAT_RGB32: - palette->black_pen = rgb_t(0x00,0x00,0x00); - palette->white_pen = rgb_t(0xff,0xff,0xff); - break; +/*------------------------------------------------- + monochrome_green - 2-color black & green +-------------------------------------------------*/ - /* screenless case */ - case BITMAP_FORMAT_INVALID: - default: - break; - } +void palette_device::palette_init_monochrome_green(palette_device &palette) +{ + palette.set_pen_color(0, rgb_t::black); // black + palette.set_pen_color(1, 0x00, 0xff, 0x00); // green } /*------------------------------------------------- - allocate_color_tables - allocate memory for - pen and color tables + 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 -------------------------------------------------*/ -static void allocate_color_tables(running_machine &machine, palette_private *palette) +void palette_device::palette_init_RRRRGGGGBBBB_proms(palette_device &palette) { - int total_colors = machine.palette->num_colors() * machine.palette->num_groups(); - pen_t *pentable; + const UINT8 *color_prom = machine().root_device().memregion("proms")->base(); int i; - /* allocate memory for the pen table */ - switch (palette->format) + for (i = 0; i < palette.entries(); i++) { - case BITMAP_FORMAT_IND16: - /* create a dummy 1:1 mapping */ - machine.pens = pentable = auto_alloc_array(machine, pen_t, total_colors + 2); - for (i = 0; i < total_colors + 2; i++) - pentable[i] = i; - break; - - case BITMAP_FORMAT_RGB32: - machine.pens = reinterpret_cast<const pen_t *>(machine.palette->entry_list_adjusted()); - break; - - default: - machine.pens = NULL; - break; + 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)); } } + /*------------------------------------------------- - allocate_shadow_tables - allocate memory for - shadow tables + RRRRR_GGGGG_BBBBB/BBBBB_GGGGG_RRRRR - + standard 5-5-5 palette for games using a + 15-bit color space -------------------------------------------------*/ -static void allocate_shadow_tables(running_machine &machine, palette_private *palette) +void palette_device::palette_init_RRRRRGGGGGBBBBB(palette_device &palette) { - /* if we have shadows, allocate shadow tables */ - if (machine.config().m_video_attributes & VIDEO_HAS_SHADOWS) - { - pen_t *table = auto_alloc_array(machine, pen_t, 65536); - int i; - - /* palettized mode gets a single 64k table in slots 0 and 2 */ - if (palette->format == BITMAP_FORMAT_IND16) - { - palette->shadow_table[0].base = palette->shadow_table[2].base = table; - for (i = 0; i < 65536; i++) - table[i] = (i < machine.total_colors()) ? (i + machine.total_colors()) : i; - } - - /* RGB mode gets two 32k tables in slots 0 and 2 */ - else - { - palette->shadow_table[0].base = table; - palette->shadow_table[2].base = table + 32768; - configure_rgb_shadows(machine, 0, (float)PALETTE_DEFAULT_SHADOW_FACTOR); - } - } + int i; - /* if we have hilights, allocate shadow tables */ - if (machine.config().m_video_attributes & VIDEO_HAS_HIGHLIGHTS) - { - pen_t *table = auto_alloc_array(machine, pen_t, 65536); - int i; + for (i = 0; i < 0x8000; i++) + palette.set_pen_color(i, rgb_t(pal5bit(i >> 10), pal5bit(i >> 5), pal5bit(i >> 0))); +} - /* palettized mode gets a single 64k table in slots 1 and 3 */ - if (palette->format == BITMAP_FORMAT_IND16) - { - palette->shadow_table[1].base = palette->shadow_table[3].base = table; - for (i = 0; i < 65536; i++) - table[i] = (i < machine.total_colors()) ? (i + 2 * machine.total_colors()) : i; - } - /* RGB mode gets two 32k tables in slots 1 and 3 */ - else - { - palette->shadow_table[1].base = table; - palette->shadow_table[3].base = table + 32768; - configure_rgb_shadows(machine, 1, (float)PALETTE_DEFAULT_HIGHLIGHT_FACTOR); - } - } +void palette_device::palette_init_BBBBBGGGGGRRRRR(palette_device &palette) +{ + int i; - /* set the default table */ - machine.shadow_table = palette->shadow_table[0].base; + for (i = 0; i < 0x8000; i++) + palette.set_pen_color(i, rgb_t(pal5bit(i >> 0), pal5bit(i >> 5), pal5bit(i >> 10))); } + /*------------------------------------------------- - configure_rgb_shadows - configure shadows - for the RGB tables + RRRRR_GGGGGG_BBBBB - + standard 5-6-5 palette for games using a + 16-bit color space -------------------------------------------------*/ -static void configure_rgb_shadows(running_machine &machine, int mode, float factor) +void palette_device::palette_init_RRRRRGGGGGGBBBBB(palette_device &palette) { - palette_private *palette = machine.palette_data; - shadow_table_data *stable = &palette->shadow_table[mode]; - int ifactor = (int)(factor * 256.0f); int i; - /* only applies to RGB direct modes */ - assert(palette->format != BITMAP_FORMAT_IND16); - assert(stable->base != NULL); + for (i = 0; i < 0x10000; i++) + palette.set_pen_color(i, rgb_t(pal5bit(i >> 11), pal6bit(i >> 5), pal5bit(i >> 0))); +} - /* regenerate the table */ - for (i = 0; i < 32768; i++) - { - rgb_t final = pal555(i, 10, 5, 0).scale8(ifactor); - /* store either 16 or 32 bit */ - if (palette->format == BITMAP_FORMAT_RGB32) - stable->base[i] = final; - else - stable->base[i] = final.as_rgb15(); - } +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_decoder(UINT32 raw) +{ + UINT8 r = pal5bit(((raw >> 8) & 0x1e) | ((raw >> 12) & 0x01)); + UINT8 g = pal5bit(((raw >> 4) & 0x1e) | ((raw >> 13) & 0x01)); + UINT8 b = pal5bit(((raw >> 0) & 0x1e) | ((raw >> 14) & 0x01)); + return rgb_t(r, g, b); } |