New device interface for palettes

- Create device_palette_interface, which takes over most functionality from palette_device except for the initialization/decoding routines and RAM interface.
- Update screen_device and device_gfx_interface to use a device_palette_interface object rather than a palette_device. This necessitates slight alterations to a few drivers and devices.
- Modify v9938 and v9958 to use the new device_palette_interface rather than a subdevice. This entails breaking a cyclic dependency between device_video_interface and screen_device for this case.
This commit is contained in:
AJR 2017-04-05 16:48:43 -04:00 committed by Vas Crabb
parent fbb7d927d3
commit 8fe18e9ecc
25 changed files with 808 additions and 671 deletions

View File

@ -82,6 +82,8 @@ files {
MAME_DIR .. "src/emu/dinvram.h",
MAME_DIR .. "src/emu/dioutput.cpp",
MAME_DIR .. "src/emu/dioutput.h",
MAME_DIR .. "src/emu/dipalette.cpp",
MAME_DIR .. "src/emu/dipalette.h",
MAME_DIR .. "src/emu/dipty.cpp",
MAME_DIR .. "src/emu/dipty.h",
MAME_DIR .. "src/emu/dirom.cpp",

View File

@ -277,7 +277,7 @@ void tc0091lvc_device::device_start()
//printf("m_gfx_index %d\n", m_gfx_index);
palette_device &palette = m_gfxdecode->palette();
device_palette_interface &palette = m_gfxdecode->palette();
m_gfxdecode->set_gfx(m_gfx_index, std::make_unique<gfx_element>(palette, char_layout, (uint8_t *)m_pcg_ram, 0, palette.entries() / 16, 0));
}

View File

@ -91,6 +91,7 @@ const device_type V9958 = device_creator<v9958_device>;
v99x8_device::v99x8_device(const machine_config &mconfig, device_type type, const char *name, const char *shortname, const char *tag, device_t *owner, uint32_t clock)
: device_t(mconfig, type, name, tag, owner, clock, shortname, __FILE__),
device_memory_interface(mconfig, *this),
device_palette_interface(mconfig, *this),
device_video_interface(mconfig, *this),
m_space_config("vram", ENDIANNESS_BIG, 8, 18),
m_model(0),
@ -116,7 +117,6 @@ v99x8_device::v99x8_device(const machine_config &mconfig, device_type type, cons
m_button_state(0),
m_vdp_ops_count(0),
m_vdp_engine(nullptr),
m_palette(*this, "palette"),
m_pal_ntsc(0)
{
static_set_addrmap(*this, AS_DATA, ADDRESS_MAP_NAME(memmap));
@ -301,13 +301,13 @@ b0 is set if b2 and b1 are set (remember, color bus is 3 bits)
*/
PALETTE_INIT_MEMBER(v9938_device, v9938)
void v9938_device::palette_init()
{
int i;
// create the full 512 colour palette
for (i=0;i<512;i++)
palette.set_pen_color(i, pal3bit(i >> 6), pal3bit(i >> 3), pal3bit(i >> 0));
set_pen_color(i, pal3bit(i >> 6), pal3bit(i >> 3), pal3bit(i >> 0));
}
/*
@ -323,17 +323,16 @@ to emulate this. Also it keeps the palette a reasonable size. :)
uint16_t v99x8_device::s_pal_indYJK[0x20000];
PALETTE_INIT_MEMBER(v9958_device, v9958)
void v9958_device::palette_init()
{
int r,g,b,y,j,k,i,k0,j0,n;
uint8_t pal[19268*3];
// init v9938 512-color palette
for (i=0;i<512;i++)
palette.set_pen_color(i, pal3bit(i >> 6), pal3bit(i >> 3), pal3bit(i >> 0));
set_pen_color(i, pal3bit(i >> 6), pal3bit(i >> 3), pal3bit(i >> 0));
if(palette.entries() != 19780)
if (entries() != 19780)
fatalerror("V9958: not enough palette, must be 19780");
// set up YJK table
@ -372,7 +371,7 @@ PALETTE_INIT_MEMBER(v9958_device, v9958)
pal[i*3+0] = r;
pal[i*3+1] = g;
pal[i*3+2] = b;
palette.set_pen_color(i+512, rgb_t(pal5bit(r), pal5bit(g), pal5bit(b)));
set_pen_color(i+512, rgb_t(pal5bit(r), pal5bit(g), pal5bit(b)));
v99x8_device::s_pal_indYJK[y | j << 5 | k << (5 + 6)] = i + 512;
i++;
}
@ -639,6 +638,8 @@ void v99x8_device::device_start()
m_line_timer = timer_alloc(TIMER_LINE);
palette_init();
save_item(NAME(m_offset_x));
save_item(NAME(m_offset_y));
save_item(NAME(m_visible_y));
@ -1853,7 +1854,6 @@ void v99x8_device::set_mode()
void v99x8_device::refresh_16(int line)
{
const pen_t *pens = m_palette->pens();
bool double_lines = false;
uint8_t col[256];
uint16_t *ln, *ln2 = nullptr;
@ -1871,15 +1871,15 @@ void v99x8_device::refresh_16(int line)
if ( !(m_cont_reg[1] & 0x40) || (m_stat_reg[2] & 0x40) )
{
(this->*s_modes[m_mode].border_16)(pens, ln);
(this->*s_modes[m_mode].border_16)(pens(), ln);
}
else
{
(this->*s_modes[m_mode].visible_16)(pens, ln, line);
(this->*s_modes[m_mode].visible_16)(pens(), ln, line);
if (s_modes[m_mode].sprites)
{
(this->*s_modes[m_mode].sprites)(line, col);
(this->*s_modes[m_mode].draw_sprite_16)(pens, ln, col);
(this->*s_modes[m_mode].draw_sprite_16)(pens(), ln, col);
}
}
@ -3050,33 +3050,3 @@ void v99x8_device::update_command()
if(m_vdp_engine) (this->*m_vdp_engine)();
}
}
static MACHINE_CONFIG_FRAGMENT( v9938 )
MCFG_PALETTE_ADD("palette", 512)
MCFG_PALETTE_INIT_OWNER(v9938_device, v9938)
MACHINE_CONFIG_END
//-------------------------------------------------
// machine_config_additions - return a pointer to
// the device's machine fragment
//-------------------------------------------------
machine_config_constructor v9938_device::device_mconfig_additions() const
{
return MACHINE_CONFIG_NAME( v9938 );
}
static MACHINE_CONFIG_FRAGMENT( v9958 )
MCFG_PALETTE_ADD("palette", 19780)
MCFG_PALETTE_INIT_OWNER(v9958_device, v9958)
MACHINE_CONFIG_END
//-------------------------------------------------
// machine_config_additions - return a pointer to
// the device's machine fragment
//-------------------------------------------------
machine_config_constructor v9958_device::device_mconfig_additions() const
{
return MACHINE_CONFIG_NAME( v9958 );
}

View File

@ -37,7 +37,7 @@
v99x8_device::VERTICAL_ADJUST * 2, \
v99x8_device::VVISIBLE_NTSC * 2 - 1 - v99x8_device::VERTICAL_ADJUST * 2) \
MCFG_SCREEN_UPDATE_DEVICE(_v9938_tag, v9938_device, screen_update) \
MCFG_SCREEN_PALETTE(_v9938_tag":palette")
MCFG_SCREEN_PALETTE(_v9938_tag)
#define MCFG_V99X8_SCREEN_ADD_PAL(_screen_tag, _v9938_tag, _clock) \
MCFG_SCREEN_ADD(_screen_tag, RASTER) \
@ -49,7 +49,7 @@
v99x8_device::VERTICAL_ADJUST * 2, \
v99x8_device::VVISIBLE_PAL * 2 - 1 - v99x8_device::VERTICAL_ADJUST * 2) \
MCFG_SCREEN_UPDATE_DEVICE(_v9938_tag, v9938_device, screen_update) \
MCFG_SCREEN_PALETTE(_v9938_tag":palette")
MCFG_SCREEN_PALETTE(_v9938_tag)
#define MCFG_V99X8_INTERRUPT_CALLBACK(_irq) \
devcb = &downcast<v99x8_device *>(device)->set_interrupt_callback(DEVCB_##_irq);
@ -73,6 +73,7 @@ extern const device_type V9958;
class v99x8_device : public device_t,
public device_memory_interface,
public device_palette_interface,
public device_video_interface
{
protected:
@ -133,6 +134,8 @@ protected:
// device_memory_interface overrides
virtual const address_space_config *memory_space_config(address_spacenum spacenum = AS_DATA) const override { return (spacenum == AS_DATA) ? &m_space_config : nullptr; }
virtual void palette_init() = 0;
void configure_pal_ntsc();
void set_screen_parameters();
@ -263,7 +266,6 @@ private:
void (v99x8_device::*draw_sprite_16)(const pen_t *, uint16_t*, uint8_t*);
} ;
static const v99x8_mode s_modes[];
required_device<palette_device> m_palette;
emu_timer *m_line_timer;
uint8_t m_pal_ntsc;
int m_scanline_start;
@ -280,9 +282,9 @@ class v9938_device : public v99x8_device
public:
v9938_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
DECLARE_PALETTE_INIT(v9938);
protected:
virtual machine_config_constructor device_mconfig_additions() const override;
virtual void palette_init() override;
virtual int palette_entries() const override { return 512; }
};
class v9958_device : public v99x8_device
@ -290,10 +292,9 @@ class v9958_device : public v99x8_device
public:
v9958_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
DECLARE_PALETTE_INIT(v9958);
protected:
virtual machine_config_constructor device_mconfig_additions() const override;
virtual void palette_init() override;
virtual int palette_entries() const override { return 19780; }
};

View File

@ -79,22 +79,28 @@ void device_gfx_interface::static_set_palette(device_t &device, const char *tag)
void device_gfx_interface::interface_pre_start()
{
if (m_palette_tag == nullptr)
fatalerror("No palette specified for device '%s'\n", device().tag());
fatalerror("No palette specified for device\n");
// find our palette device, either as a sibling device or subdevice
device_t *paldev;
if (m_palette_is_sibling)
m_palette = device().owner()->subdevice<palette_device>(m_palette_tag);
paldev = device().owner()->subdevice(m_palette_tag);
else
m_palette = device().subdevice<palette_device>(m_palette_tag);
paldev = device().subdevice(m_palette_tag);
if (m_palette == nullptr)
if (paldev == nullptr)
fatalerror("Device '%s' specifies nonexistent %sdevice '%s' as palette\n",
device().tag(),
(m_palette_is_sibling ? "sibling " : "sub"),
m_palette_tag);
if (!paldev->interface(m_palette))
fatalerror("Device '%s' specifies %sdevice '%s' as palette, but it has no palette interface\n",
device().tag(),
(m_palette_is_sibling ? "sibling " : "sub"),
m_palette_tag);
// if palette device isn't started, wait for it
// if (!m_palette->started())
// if (!m_palette->device().started())
// throw device_missing_dependencies();
}
@ -295,17 +301,23 @@ void device_gfx_interface::interface_validity_check(validity_checker &valid) con
osd_printf_error("No palette specified for device '%s'\n", device().tag());
else
{
palette_device *palette;
device_t *paldev;
if (m_palette_is_sibling)
palette = device().owner()->subdevice<palette_device>(m_palette_tag);
paldev = device().owner()->subdevice(m_palette_tag);
else
palette = device().subdevice<palette_device>(m_palette_tag);
if (palette == nullptr)
osd_printf_error("Device '%s' specifies nonexistent %sdevice '%s' as palette\n",
device().tag(),
paldev = device().subdevice(m_palette_tag);
if (paldev == nullptr)
osd_printf_error("Nonexistent %sdevice '%s' specified as palette\n",
(m_palette_is_sibling ? "sibling " : "sub"),
m_palette_tag);
else
{
device_palette_interface *palintf;
if (!paldev->interface(palintf))
osd_printf_error("%sdevice '%s' specified as palette, but it has no palette interface\n",
(m_palette_is_sibling ? "Sibling " : "Sub"),
m_palette_tag);
}
}
if (!m_gfxdecodeinfo)

View File

@ -156,7 +156,7 @@ const gfx_layout name = { width, height, RGN_FRAC(1,1), 8, { GFX_RAW }, { 0 }, {
// forward declarations
class gfx_element;
class palette_device;
class device_palette_interface;
struct gfx_layout
{
@ -200,7 +200,7 @@ public:
static void static_set_palette(device_t &device, const char *tag);
// getters
palette_device &palette() const { assert(m_palette != nullptr); return *m_palette; }
device_palette_interface &palette() const { assert(m_palette != nullptr); return *m_palette; }
gfx_element *gfx(u8 index) const { assert(index < MAX_GFX_ELEMENTS); return m_gfx[index].get(); }
// decoding
@ -216,7 +216,7 @@ protected:
virtual void interface_post_start() override;
private:
palette_device * m_palette; // pointer to the palette device
device_palette_interface * m_palette; // pointer to the palette device interface
std::unique_ptr<gfx_element> m_gfx[MAX_GFX_ELEMENTS]; // array of pointers to graphic sets
// configuration

503
src/emu/dipalette.cpp Normal file
View File

@ -0,0 +1,503 @@
// license:BSD-3-Clause
// copyright-holders:Aaron Giles
/***************************************************************************
dipalette.cpp
Device palette interface.
***************************************************************************/
#include "emu.h"
#include "screen.h"
#define VERBOSE 0
//**************************************************************************
// DEVICE INTERFACE MANAGEMENT
//**************************************************************************
//-------------------------------------------------
// device_palette_interface - constructor
//-------------------------------------------------
device_palette_interface::device_palette_interface(const machine_config &mconfig, device_t &device)
: device_interface(device, "palette"),
m_palette(nullptr),
m_pens(nullptr),
m_format(),
m_shadow_table(nullptr),
m_shadow_group(0),
m_hilight_group(0),
m_white_pen(0),
m_black_pen(0)
{
}
//-------------------------------------------------
// interface_pre_start - work to be done prior to
// actually starting a device
//-------------------------------------------------
void device_palette_interface::interface_pre_start()
{
// reset all our data
screen_device *screen = device().machine().first_screen();
m_format = (screen != nullptr) ? screen->format() : BITMAP_FORMAT_INVALID;
// allocate the palette
int numentries = palette_entries();
if (numentries > 0)
{
allocate_palette(numentries);
allocate_color_tables();
allocate_shadow_tables();
// allocate indirection tables
int indirect_colors = palette_indirect_entries();
if (indirect_colors > 0)
{
m_indirect_colors.resize(indirect_colors);
for (int color = 0; color < indirect_colors; color++)
{
// alpha = 0 ensures change is detected the first time set_indirect_color() is called
m_indirect_colors[color] = rgb_t::transparent();
}
m_indirect_pens.resize(numentries);
for (int pen = 0; pen < numentries; pen++)
m_indirect_pens[pen] = pen % indirect_colors;
}
}
}
//-------------------------------------------------
// interface_post_start - work to be done after
// actually starting a device
//-------------------------------------------------
void device_palette_interface::interface_post_start()
{
// set up save/restore of the palette
m_save_pen.resize(m_palette->num_colors());
m_save_contrast.resize(m_palette->num_colors());
device().save_item(NAME(m_save_pen));
device().save_item(NAME(m_save_contrast));
// save indirection tables if we have them
if (m_indirect_colors.size() > 0)
{
device().save_item(NAME(m_indirect_colors));
device().save_item(NAME(m_indirect_pens));
}
}
//-------------------------------------------------
// interface_pre_save - prepare the save arrays
// for saving
//-------------------------------------------------
void device_palette_interface::interface_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);
}
}
//-------------------------------------------------
// interface_post_load - called after restore to
// actually update the palette
//-------------------------------------------------
void device_palette_interface::interface_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]);
}
}
//-------------------------------------------------
// interface_post_stop - final cleanup
//-------------------------------------------------
void device_palette_interface::interface_post_stop()
{
// dereference the palette
if (m_palette != nullptr)
m_palette->deref();
}
//**************************************************************************
// INDIRECTION (AKA COLORTABLES)
//**************************************************************************
//-------------------------------------------------
// set_indirect_color - set an indirect color
//-------------------------------------------------
void device_palette_interface::set_indirect_color(int index, rgb_t rgb)
{
// make sure we are in range
assert(index < m_indirect_pens.size());
// 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 (u32 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 device_palette_interface::set_pen_indirect(pen_t pen, indirect_pen_t index)
{
// make sure we are in range
assert(pen < entries() && index < 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
//-------------------------------------------------
u32 device_palette_interface::transpen_mask(gfx_element &gfx, u32 color, indirect_pen_t transcolor) const
{
u32 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 = std::min(size_t(gfx.depth()), m_indirect_pens.size() - entry);
// set a bit anywhere the transcolor matches
u32 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 device_palette_interface::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 != nullptr);
// 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)
device().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();
}
}
//**************************************************************************
// INTERNAL FUNCTIONS
//**************************************************************************
//-------------------------------------------------
// allocate_palette - allocate and configure the
// palette object itself
//-------------------------------------------------
void device_palette_interface::allocate_palette(int numentries)
{
// determine the number of groups we need
int numgroups = 1;
if (palette_shadows_enabled())
m_shadow_group = numgroups++;
if (palette_hilights_enabled())
m_hilight_group = numgroups++;
assert_always(numentries * numgroups <= 65536, "Palette has more than 65536 colors.");
// allocate a palette object containing all the colors and groups
m_palette = palette_t::alloc(numentries, numgroups);
// configure the groups
if (m_shadow_group != 0)
set_shadow_factor(PALETTE_DEFAULT_SHADOW_FACTOR);
if (m_hilight_group != 0)
set_highlight_factor(PALETTE_DEFAULT_HIGHLIGHT_FACTOR);
// set the initial colors to a standard rainbow
for (int index = 0; index < numentries; 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 device_palette_interface::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 = nullptr;
break;
}
}
//-------------------------------------------------
// allocate_shadow_tables - allocate memory for
// shadow tables
//-------------------------------------------------
void device_palette_interface::allocate_shadow_tables()
{
int numentries = m_palette->num_colors();
// if we have shadows, allocate shadow tables
if (m_shadow_group != 0)
{
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 < numentries) ? (i + numentries) : 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, PALETTE_DEFAULT_SHADOW_FACTOR);
}
}
// if we have hilights, allocate shadow tables
if (m_hilight_group != 0)
{
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 < numentries) ? (i + 2 * numentries) : 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, 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 device_palette_interface::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 != nullptr);
// regenerate the table
int ifactor = int(factor * 256.0f);
for (int rgb555 = 0; rgb555 < 32768; rgb555++)
{
u8 const r = rgb_t::clamp((pal5bit(rgb555 >> 10) * ifactor) >> 8);
u8 const g = rgb_t::clamp((pal5bit(rgb555 >> 5) * ifactor) >> 8);
u8 const 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();
}
}

144
src/emu/dipalette.h Normal file
View File

@ -0,0 +1,144 @@
// license:BSD-3-Clause
// copyright-holders:Aaron Giles
/***************************************************************************
dipalette.h
Device palette interface.
******************************************************************************/
#pragma once
#ifndef __EMU_H__
#error Dont include this file directly; include emu.h instead.
#endif
#ifndef MAME_EMU_DIPALETTE_H
#define MAME_EMU_DIPALETTE_H
//**************************************************************************
// CONSTANTS
//**************************************************************************
constexpr float PALETTE_DEFAULT_SHADOW_FACTOR = 0.6;
constexpr float PALETTE_DEFAULT_HIGHLIGHT_FACTOR = 1/PALETTE_DEFAULT_SHADOW_FACTOR;
//**************************************************************************
// TYPE DEFINITIONS
//**************************************************************************
class gfx_element;
typedef u16 indirect_pen_t;
// ======================> device_palette_interface
class device_palette_interface : public device_interface
{
static constexpr int MAX_SHADOW_PRESETS = 4;
public:
// construction/destruction
device_palette_interface(const machine_config &mconfig, device_t &device);
// getters
int entries() const { return (m_palette != nullptr) ? m_palette->num_colors() : 0; }
int indirect_entries() const { return m_indirect_colors.size(); }
palette_t *palette() const { return m_palette; }
const pen_t &pen(int index) const { return m_pens[index]; }
const pen_t *pens() const { return m_pens; }
pen_t *shadow_table() const { return m_shadow_table; }
rgb_t pen_color(pen_t pen) const { return m_palette->entry_color(pen); }
double pen_contrast(pen_t pen) const { return m_palette->entry_contrast(pen); }
pen_t black_pen() const { return m_black_pen; }
pen_t white_pen() const { return m_white_pen; }
bool shadows_enabled() const { return m_shadow_group != 0; }
bool hilights_enabled() const { return m_hilight_group != 0; }
// setters
void set_pen_color(pen_t pen, rgb_t rgb) { m_palette->entry_set_color(pen, rgb); }
void set_pen_red_level(pen_t pen, u8 level) { m_palette->entry_set_red_level(pen, level); }
void set_pen_green_level(pen_t pen, u8 level) { m_palette->entry_set_green_level(pen, level); }
void set_pen_blue_level(pen_t pen, u8 level) { m_palette->entry_set_blue_level(pen, level); }
void set_pen_color(pen_t pen, u8 r, u8 g, u8 b) { m_palette->entry_set_color(pen, rgb_t(r, g, b)); }
void set_pen_colors(pen_t color_base, const rgb_t *colors, int color_count) { while (color_count--) set_pen_color(color_base++, *colors++); }
void set_pen_colors(pen_t color_base, const std::vector<rgb_t> &colors) { for (unsigned int i=0; i != colors.size(); i++) set_pen_color(color_base+i, colors[i]); }
void set_pen_contrast(pen_t pen, double bright) { m_palette->entry_set_contrast(pen, bright); }
// indirection (aka colortables)
indirect_pen_t pen_indirect(int index) const { return m_indirect_pens[index]; }
rgb_t indirect_color(int index) const { return m_indirect_colors[index]; }
void set_indirect_color(int index, rgb_t rgb);
void set_pen_indirect(pen_t pen, indirect_pen_t index);
u32 transpen_mask(gfx_element &gfx, u32 color, indirect_pen_t transcolor) const;
// shadow config
void set_shadow_factor(double factor) { assert(m_shadow_group != 0); m_palette->group_set_contrast(m_shadow_group, factor); }
void set_highlight_factor(double factor) { assert(m_hilight_group != 0); m_palette->group_set_contrast(m_hilight_group, factor); }
void set_shadow_mode(int mode) { assert(mode >= 0 && mode < MAX_SHADOW_PRESETS); m_shadow_table = m_shadow_tables[mode].base; }
protected:
// interface-level overrides
virtual void interface_pre_start() override;
virtual void interface_post_start() override;
virtual void interface_pre_save() override;
virtual void interface_post_load() override;
virtual void interface_post_stop() override;
// configuration-related overrides
virtual int palette_entries() const = 0;
virtual int palette_indirect_entries() const { return 0; }
virtual bool palette_shadows_enabled() const { return false; }
virtual bool palette_hilights_enabled() const { return false; }
private:
// internal helpers
void allocate_palette(int numentries);
void allocate_color_tables();
void allocate_shadow_tables();
public: // needed by konamigx
void set_shadow_dRGB32(int mode, int dr, int dg, int db, bool noclip);
private:
void configure_rgb_shadows(int mode, float factor);
// internal state
palette_t * m_palette; // the palette itself
const pen_t * m_pens; // remapped palette pen numbers
bitmap_format m_format; // format assumed for palette data
pen_t * m_shadow_table; // table for looking up a shadowed pen
u32 m_shadow_group; // index of the shadow group, or 0 if none
u32 m_hilight_group; // index of the hilight group, or 0 if none
pen_t m_white_pen; // precomputed white pen value
pen_t m_black_pen; // precomputed black pen value
// indirection state
std::vector<rgb_t> m_indirect_colors; // actual colors set for indirection
std::vector<indirect_pen_t> m_indirect_pens; // indirection values
struct shadow_table_data
{
pen_t * base; // pointer to the base of the table
s16 dr; // delta red value
s16 dg; // delta green value
s16 db; // delta blue value
bool noclip; // clip?
};
shadow_table_data m_shadow_tables[MAX_SHADOW_PRESETS]; // array of shadow table data
std::vector<pen_t> m_save_pen; // pens for save/restore
std::vector<float> m_save_contrast; // brightness for save/restore
std::vector<pen_t> m_pen_array;
std::vector<pen_t> m_shadow_array;
std::vector<pen_t> m_hilight_array;
};
// interface type iterator
typedef device_interface_iterator<device_palette_interface> palette_interface_iterator;
#endif // MAME_EMU_DIPALETTE_H

View File

@ -126,6 +126,20 @@ void device_video_interface::interface_pre_start()
throw emu_fatalerror("Device '%s' requires a screen", device().tag());
// if we have a screen and it's not started, wait for it
device_palette_interface *palintf;
if (m_screen != nullptr && !m_screen->started())
throw device_missing_dependencies();
{
// avoid circular dependency if we are also a palette device
if (!device().interface(palintf))
throw device_missing_dependencies();
else
{
// resolve the palette for the sake of register_screen_bitmap
m_screen->resolve_palette();
// no other palette may be specified
if (m_screen->has_palette() && palintf != &m_screen->palette())
throw emu_fatalerror("Device '%s' cannot control screen '%s' with palette '%s'", m_screen_tag, device().tag(), m_screen->palette().device().tag());
}
}
}

View File

@ -86,7 +86,7 @@ gfxdecode_device::gfxdecode_device(const machine_config &mconfig, const char *ta
// gfx_element - constructor
//-------------------------------------------------
gfx_element::gfx_element(palette_device &palette, u8 *base, u16 width, u16 height, u32 rowbytes, u32 total_colors, u32 color_base, u32 color_granularity)
gfx_element::gfx_element(device_palette_interface &palette, u8 *base, u16 width, u16 height, u32 rowbytes, u32 total_colors, u32 color_base, u32 color_granularity)
: m_palette(&palette),
m_width(width),
m_height(height),
@ -111,7 +111,7 @@ gfx_element::gfx_element(palette_device &palette, u8 *base, u16 width, u16 heigh
{
}
gfx_element::gfx_element(palette_device &palette, const gfx_layout &gl, const u8 *srcdata, u32 xormask, u32 total_colors, u32 color_base)
gfx_element::gfx_element(device_palette_interface &palette, const gfx_layout &gl, const u8 *srcdata, u32 xormask, u32 total_colors, u32 color_base)
: m_palette(&palette),
m_width(0),
m_height(0),

View File

@ -151,11 +151,11 @@ public:
#ifdef UNUSED_FUNCTION
gfx_element();
#endif
gfx_element(palette_device &palette, const gfx_layout &gl, const u8 *srcdata, u32 xormask, u32 total_colors, u32 color_base);
gfx_element(palette_device &palette, u8 *base, u16 width, u16 height, u32 rowbytes, u32 total_colors, u32 color_base, u32 color_granularity);
gfx_element(device_palette_interface &palette, const gfx_layout &gl, const u8 *srcdata, u32 xormask, u32 total_colors, u32 color_base);
gfx_element(device_palette_interface &palette, u8 *base, u16 width, u16 height, u32 rowbytes, u32 total_colors, u32 color_base, u32 color_granularity);
// getters
palette_device &palette() const { return *m_palette; }
device_palette_interface &palette() const { return *m_palette; }
u16 width() const { return m_width; }
u16 height() const { return m_height; }
u32 elements() const { return m_total_elements; }
@ -175,7 +175,7 @@ public:
void set_source(const u8 *source);
void set_source_and_total(const u8 *source, u32 total);
void set_xormask(u32 xormask) { m_layout_xormask = xormask; }
void set_palette(palette_device &palette) { m_palette = &palette; }
void set_palette(device_palette_interface &palette) { m_palette = &palette; }
void set_colors(u32 colors) { m_total_colors = colors; }
void set_colorbase(u16 colorbase) { m_color_base = colorbase; }
void set_granularity(u16 granularity) { m_color_granularity = granularity; }
@ -269,7 +269,7 @@ private:
void decode(u32 code);
// internal state
palette_device *m_palette; // palette used for drawing
device_palette_interface *m_palette; // palette used for drawing
u16 m_width; // current pixel width of each element (changeable with source clipping)
u16 m_height; // current pixel height of each element (changeable with source clipping)

View File

@ -89,8 +89,6 @@
//**************************************************************************
// forward declarations
class gfxdecode_device;
class palette_device;
typedef delegate<void ()> driver_callback_delegate;

View File

@ -73,6 +73,7 @@ typedef device_t * (*machine_config_constructor)(machine_config &config, device_
#include "dirom.h"
#include "diexec.h"
#include "opresolv.h"
#include "dipalette.h"
#include "digfx.h"
#include "diimage.h"
#include "dioutput.h"

View File

@ -9,9 +9,6 @@
***************************************************************************/
#include "emu.h"
#include "screen.h"
#define VERBOSE 0
//**************************************************************************
@ -22,6 +19,7 @@ const device_type PALETTE = device_creator<palette_device>;
palette_device::palette_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
: device_t(mconfig, PALETTE, "palette", tag, owner, clock, "palette", __FILE__),
device_palette_interface(mconfig, *this),
m_entries(0),
m_indirect_entries(0),
m_enable_shadows(0),
@ -30,16 +28,8 @@ palette_device::palette_device(const machine_config &mconfig, const char *tag, d
m_membits_supplied(false),
m_endianness(),
m_endianness_supplied(false),
m_raw_to_rgb(raw_to_rgb_converter()),
m_palette(nullptr),
m_pens(nullptr),
m_format(),
m_shadow_table(nullptr),
m_shadow_group(0),
m_hilight_group(0),
m_white_pen(0),
m_black_pen(0),
m_init(palette_init_delegate())
m_init(palette_init_delegate()),
m_raw_to_rgb(raw_to_rgb_converter())
{
}
@ -101,184 +91,6 @@ void palette_device::static_enable_hilights(device_t &device)
//**************************************************************************
// 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 (u32 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, indirect_pen_t 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
//-------------------------------------------------
u32 palette_device::transpen_mask(gfx_element &gfx, u32 color, indirect_pen_t transcolor)
{
u32 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 = std::min(size_t(gfx.depth()), m_indirect_pens.size() - entry);
// set a bit anywhere the transcolor matches
u32 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 != nullptr);
// 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
//**************************************************************************
@ -305,7 +117,7 @@ inline void palette_device::update_for_write(offs_t byte_offset, int bytes_modif
if (indirect)
set_indirect_color(base + index, m_raw_to_rgb(read_entry(base + index)));
else
m_palette->entry_set_color(base + index, m_raw_to_rgb(read_entry(base + index)));
set_pen_color(base + index, m_raw_to_rgb(read_entry(base + index)));
}
}
@ -445,288 +257,9 @@ void palette_device::device_start()
}
}
// reset all our data
screen_device *device = machine().first_screen();
m_format = (device != nullptr) ? 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::transparent();
}
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 != nullptr)
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 = nullptr;
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 != nullptr);
// regenerate the table
int ifactor = int(factor * 256.0f);
for (int rgb555 = 0; rgb555 < 32768; rgb555++)
{
u8 const r = rgb_t::clamp((pal5bit(rgb555 >> 10) * ifactor) >> 8);
u8 const g = rgb_t::clamp((pal5bit(rgb555 >> 5) * ifactor) >> 8);
u8 const 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();
}
}

View File

@ -104,9 +104,6 @@
// CONSTANTS
//**************************************************************************
#define PALETTE_DEFAULT_SHADOW_FACTOR (0.6)
#define PALETTE_DEFAULT_HIGHLIGHT_FACTOR (1/PALETTE_DEFAULT_SHADOW_FACTOR)
#define PALETTE_INIT_NAME(_Name) palette_init_##_Name
#define DECLARE_PALETTE_INIT(_Name) void PALETTE_INIT_NAME(_Name)(palette_device &palette)
#define PALETTE_INIT_MEMBER(_Class, _Name) void _Class::PALETTE_INIT_NAME(_Name)(palette_device &palette)
@ -288,10 +285,9 @@
// TYPE DEFINITIONS
//**************************************************************************
class palette_device; // forward declaration
typedef device_delegate<void (palette_device &)> palette_init_delegate;
typedef u16 indirect_pen_t;
// ======================> raw_to_rgb_converter
@ -360,10 +356,8 @@ private:
// device type definition
extern const device_type PALETTE;
class palette_device : public device_t
class palette_device : public device_t, public device_palette_interface
{
static const int MAX_SHADOW_PRESETS = 4;
public:
// construction/destruction
palette_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
@ -378,21 +372,9 @@ public:
static void static_enable_shadows(device_t &device);
static void static_enable_hilights(device_t &device);
// getters
int entries() const { return m_entries; }
int indirect_entries() const { return m_indirect_entries; }
palette_t *palette() const { return m_palette; }
const pen_t &pen(int index) const { return m_pens[index]; }
const pen_t *pens() const { return m_pens; }
pen_t *shadow_table() const { return m_shadow_table; }
rgb_t pen_color(pen_t pen) { return m_palette->entry_color(pen); }
double pen_contrast(pen_t pen) { return m_palette->entry_contrast(pen); }
pen_t black_pen() const { return m_black_pen; }
pen_t white_pen() const { return m_white_pen; }
// palette RAM accessors
memory_array &basemem() { return m_paletteram; }
memory_array &extmem() { return m_paletteram_ext; }
bool shadows_enabled() { return m_enable_shadows; }
bool hilights_enabled() { return m_enable_hilights; }
// raw entry reading
u32 read_entry(pen_t pen) const
@ -403,28 +385,6 @@ public:
return data;
}
// setters
void set_pen_color(pen_t pen, rgb_t rgb) { m_palette->entry_set_color(pen, rgb); }
void set_pen_red_level(pen_t pen, u8 level) { m_palette->entry_set_red_level(pen, level); }
void set_pen_green_level(pen_t pen, u8 level) { m_palette->entry_set_green_level(pen, level); }
void set_pen_blue_level(pen_t pen, u8 level) { m_palette->entry_set_blue_level(pen, level); }
void set_pen_color(pen_t pen, u8 r, u8 g, u8 b) { m_palette->entry_set_color(pen, rgb_t(r, g, b)); }
void set_pen_colors(pen_t color_base, const rgb_t *colors, int color_count) { while (color_count--) set_pen_color(color_base++, *colors++); }
void set_pen_colors(pen_t color_base, const std::vector<rgb_t> &colors) { for(unsigned int i=0; i != colors.size(); i++) set_pen_color(color_base+i, colors[i]); }
void set_pen_contrast(pen_t pen, double bright) { m_palette->entry_set_contrast(pen, bright); }
// indirection (aka colortables)
indirect_pen_t pen_indirect(int index) const { return m_indirect_pens[index]; }
rgb_t indirect_color(int index) const { return m_indirect_colors[index]; }
void set_indirect_color(int index, rgb_t rgb);
void set_pen_indirect(pen_t pen, indirect_pen_t index);
u32 transpen_mask(gfx_element &gfx, u32 color, indirect_pen_t transcolor);
// shadow config
void set_shadow_factor(double factor) { assert(m_shadow_group != 0); m_palette->group_set_contrast(m_shadow_group, factor); }
void set_highlight_factor(double factor) { assert(m_hilight_group != 0); m_palette->group_set_contrast(m_hilight_group, factor); }
void set_shadow_mode(int mode) { assert(mode >= 0 && mode < MAX_SHADOW_PRESETS); m_shadow_table = m_shadow_tables[mode].base; }
// generic read/write handlers
DECLARE_READ8_MEMBER(read);
DECLARE_WRITE8_MEMBER(write);
@ -455,25 +415,20 @@ public:
// helper to update palette when data changed
void update() { if (!m_init.isnull()) m_init(*this); }
protected:
// device-level overrides
virtual void device_validity_check(validity_checker &valid) const override;
virtual void device_start() override;
virtual void device_pre_save() override;
virtual void device_post_load() override;
virtual void device_stop() override;
void allocate_palette();
void allocate_color_tables();
void allocate_shadow_tables();
void update_for_write(offs_t byte_offset, int bytes_modified, bool indirect = false);
public: // needed by konamigx
void set_shadow_dRGB32(int mode, int dr, int dg, int db, bool noclip);
protected:
void configure_rgb_shadows(int mode, float factor);
// device_palette_interface overrides
virtual int palette_entries() const override { return m_entries; }
virtual int palette_indirect_entries() const override { return m_indirect_entries; }
virtual bool palette_shadows_enabled() const override { return m_enable_shadows; }
virtual bool palette_hilights_enabled() const override { return m_enable_hilights; }
private:
void update_for_write(offs_t byte_offset, int bytes_modified, bool indirect = false);
// configuration state
int m_entries; // number of entries in the palette
int m_indirect_entries; // number of indirect colors in the palette
@ -483,47 +438,13 @@ private:
bool m_membits_supplied; // true if membits forced in static config
endianness_t m_endianness; // endianness of palette RAM, if different from native
bool m_endianness_supplied; // true if endianness forced in static config
palette_init_delegate m_init;
// palette RAM
raw_to_rgb_converter m_raw_to_rgb; // format of palette RAM
memory_array m_paletteram; // base memory
memory_array m_paletteram_ext; // extended memory
// internal state
palette_t * m_palette; // the palette itself
const pen_t * m_pens; // remapped palette pen numbers
bitmap_format m_format; // format assumed for palette data
pen_t * m_shadow_table; // table for looking up a shadowed pen
u32 m_shadow_group; // index of the shadow group, or 0 if none
u32 m_hilight_group; // index of the hilight group, or 0 if none
pen_t m_white_pen; // precomputed white pen value
pen_t m_black_pen; // precomputed black pen value
// indirection state
std::vector<rgb_t> m_indirect_colors; // actual colors set for indirection
std::vector<indirect_pen_t> m_indirect_pens; // indirection values
struct shadow_table_data
{
pen_t * base; // pointer to the base of the table
s16 dr; // delta red value
s16 dg; // delta green value
s16 db; // delta blue value
bool noclip; // clip?
};
shadow_table_data m_shadow_tables[MAX_SHADOW_PRESETS]; // array of shadow table data
std::vector<pen_t> m_save_pen; // pens for save/restore
std::vector<float> m_save_contrast; // brightness for save/restore
std::vector<pen_t> m_pen_array;
std::vector<pen_t> m_shadow_array;
std::vector<pen_t> m_hilight_array;
palette_init_delegate m_init;
};
// device type iterator
typedef device_type_iterator<palette_device> palette_device_iterator;
#endif // MAME_EMU_EMUPAL_H

View File

@ -558,7 +558,8 @@ screen_device::screen_device(const machine_config &mconfig, const char *tag, dev
m_xscale(1.0f),
m_yscale(1.0f),
m_screen_vblank(*this),
m_palette(*this, finder_base::DUMMY_TAG),
m_palette(nullptr),
m_palette_tag(nullptr),
m_video_attributes(0),
m_svg_region(nullptr),
m_container(nullptr),
@ -727,7 +728,7 @@ void screen_device::static_set_screen_update(device_t &device, screen_update_rgb
void screen_device::static_set_palette(device_t &device, const char *tag)
{
downcast<screen_device &>(device).m_palette.set_tag(tag);
downcast<screen_device &>(device).m_palette_tag = tag;
}
@ -785,10 +786,23 @@ void screen_device::device_validity_check(validity_checker &valid) const
osd_printf_error("Invalid (zero) refresh rate\n");
texture_format texformat = !m_screen_update_ind16.isnull() ? TEXFORMAT_PALETTE16 : TEXFORMAT_RGB32;
if (m_palette == nullptr && texformat == TEXFORMAT_PALETTE16)
if (m_palette_tag != nullptr)
{
if (texformat == TEXFORMAT_RGB32)
osd_printf_warning("Screen does not need palette defined\n");
device_t *paldev = owner()->subdevice(m_palette_tag);
if (paldev == nullptr)
osd_printf_error("Nonexistent device '%s' specified as palette\n", m_palette_tag);
else
{
device_palette_interface *palintf;
if (!paldev->interface(palintf))
osd_printf_error("Device '%s' specified as palette, but it has no palette interface\n", m_palette_tag);
}
}
else if (texformat == TEXFORMAT_PALETTE16)
osd_printf_error("Screen does not have palette defined\n");
if (m_palette != nullptr && texformat == TEXFORMAT_RGB32)
osd_printf_warning("Screen does not need palette defined\n");
}
@ -821,7 +835,8 @@ void screen_device::device_start()
m_screen_vblank.resolve_safe();
// if we have a palette and it's not started, wait for it
if (m_palette != nullptr && !m_palette->started())
resolve_palette();
if (m_palette != nullptr && !m_palette->device().started())
throw device_missing_dependencies();
// configure bitmap formats and allocate screen bitmaps
@ -1469,6 +1484,28 @@ void screen_device::register_screen_bitmap(bitmap_t &bitmap)
}
//-------------------------------------------------
// resolve_palette - find the specified palette
//-------------------------------------------------
void screen_device::resolve_palette()
{
if (m_palette_tag != nullptr && m_palette == nullptr)
{
// find our palette as a sibling device
device_t *palette = owner()->subdevice(m_palette_tag);
if (palette == nullptr)
fatalerror("Screen '%s' specifies nonexistent device '%s' as palette\n",
tag(),
m_palette_tag);
if (!palette->interface(m_palette))
fatalerror("Screen '%s' specifies device '%s' as palette, but it has no palette interface\n",
tag(),
m_palette_tag);
}
}
//-------------------------------------------------
// vblank_begin - call any external callbacks to
// signal the VBLANK period has begun

View File

@ -213,8 +213,8 @@ public:
// information getters
render_container &container() const { assert(m_container != nullptr); return *m_container; }
bitmap_ind8 &priority() { return m_priority; }
palette_device &palette() const { assert(m_palette.found()); return *m_palette; }
bool has_palette() const { return m_palette.found(); }
device_palette_interface &palette() const { assert(m_palette != nullptr); return *m_palette; }
bool has_palette() const { return m_palette != nullptr; }
// dynamic configuration
void configure(int width, int height, const rectangle &visarea, attoseconds_t frame_period);
@ -247,6 +247,7 @@ public:
// additional helpers
void register_vblank_callback(vblank_state_delegate vblank_callback);
void register_screen_bitmap(bitmap_t &bitmap);
void resolve_palette();
// internal to the video system
bool update_quads();
@ -292,7 +293,8 @@ private:
screen_update_ind16_delegate m_screen_update_ind16; // screen update callback (16-bit palette)
screen_update_rgb32_delegate m_screen_update_rgb32; // screen update callback (32-bit RGB)
devcb_write_line m_screen_vblank; // screen vblank line callback
optional_device<palette_device> m_palette; // our palette
device_palette_interface *m_palette; // our palette
const char * m_palette_tag; // configured tag for palette device
u32 m_video_attributes; // flags describing the video system
const char * m_svg_region; // the region in which the svg data is in
@ -496,9 +498,9 @@ extern template class device_finder<screen_device, true>;
#define MCFG_SCREEN_VBLANK_CALLBACK(_devcb) \
devcb = &screen_device::static_set_screen_vblank(*device, DEVCB_##_devcb);
#define MCFG_SCREEN_PALETTE(_palette_tag) \
screen_device::static_set_palette(*device, "^" _palette_tag);
screen_device::static_set_palette(*device, _palette_tag);
#define MCFG_SCREEN_NO_PALETTE \
screen_device::static_set_palette(*device, finder_base::DUMMY_TAG);
screen_device::static_set_palette(*device, nullptr);
#define MCFG_SCREEN_VIDEO_ATTRIBUTES(_flags) \
screen_device::static_set_video_attributes(*device, _flags);
#define MCFG_SCREEN_COLOR(_color) \

View File

@ -502,7 +502,7 @@ public:
// getters
running_machine &machine() const;
tilemap_device *device() const { return m_device; }
palette_device &palette() const { return *m_palette; }
device_palette_interface &palette() const { return *m_palette; }
device_gfx_interface &decoder() const { return *m_tileinfo.decoder; }
tilemap_t *next() const { return m_next; }
@ -530,7 +530,7 @@ public:
// setters
void enable(bool enable = true) { m_enable = enable; }
void set_user_data(void *user_data) { m_user_data = user_data; }
void set_palette(palette_device &palette) { m_palette = &palette; }
void set_palette(device_palette_interface &palette) { m_palette = &palette; }
void set_palette_offset(u32 offset) { m_palette_offset = offset; }
void set_scrolldx(int dx, int dx_flipped) { m_dx = dx; m_dx_flipped = dx_flipped; }
void set_scrolldy(int dy, int dy_flipped) { m_dy = dy; m_dy_flipped = dy_flipped; }
@ -634,7 +634,7 @@ private:
// managers and devices
tilemap_manager * m_manager; // reference to the owning manager
tilemap_device * m_device; // pointer to our owning device
palette_device * m_palette; // palette used for drawing
device_palette_interface * m_palette; // palette used for drawing
tilemap_t * m_next; // pointer to next tilemap
void * m_user_data; // user data value

View File

@ -61,7 +61,7 @@ struct ui_gfx_state
// palette-specific data
struct
{
palette_device *device; // pointer to current device
device_palette_interface *interface; // pointer to current palette
int devcount; // how many palette devices exist
int devindex; // which palette device is visible
uint8_t which; // which subset (pens or indirect colors)?
@ -169,7 +169,7 @@ void ui_gfx_init(running_machine &machine)
static void ui_gfx_count_devices(running_machine &machine, ui_gfx_state &state)
{
// count the palette devices
state.palette.devcount = palette_device_iterator(machine.root_device()).count();
state.palette.devcount = palette_interface_iterator(machine.root_device()).count();
// set the pointer to the first palette
if (state.palette.devcount > 0)
@ -330,8 +330,8 @@ cancel:
static void palette_set_device(running_machine &machine, ui_gfx_state &state)
{
palette_device_iterator pal_iter(machine.root_device());
state.palette.device = pal_iter.byindex(state.palette.devindex);
palette_interface_iterator pal_iter(machine.root_device());
state.palette.interface = pal_iter.byindex(state.palette.devindex);
}
@ -342,7 +342,8 @@ static void palette_set_device(running_machine &machine, ui_gfx_state &state)
static void palette_handler(mame_ui_manager &mui, render_container &container, ui_gfx_state &state)
{
palette_device *palette = state.palette.device;
device_palette_interface *palette = state.palette.interface;
palette_device *paldev = dynamic_cast<palette_device *>(&palette->device());
int total = state.palette.which ? palette->indirect_entries() : palette->entries();
const rgb_t *raw_color = palette->palette()->entry_list_raw();
@ -381,7 +382,7 @@ static void palette_handler(mame_ui_manager &mui, render_container &container, u
// figure out the title
std::ostringstream title_buf;
util::stream_format(title_buf, "'%s'", palette->tag());
util::stream_format(title_buf, "'%s'", palette->device().tag());
if (palette->indirect_entries() > 0)
title_buf << (state.palette.which ? _(" COLORS") : _(" PENS"));
@ -400,8 +401,8 @@ static void palette_handler(mame_ui_manager &mui, render_container &container, u
util::stream_format(title_buf, " #%X", index);
if (palette->indirect_entries() > 0 && !state.palette.which)
util::stream_format(title_buf, " => %X", palette->pen_indirect(index));
else if (palette->basemem().base() != nullptr)
util::stream_format(title_buf, " = %X", palette->read_entry(index));
else if (paldev != nullptr && paldev->basemem().base() != nullptr)
util::stream_format(title_buf, " = %X", paldev->read_entry(index));
rgb_t col = state.palette.which ? palette->indirect_color(index) : raw_color[index];
util::stream_format(title_buf, " (R:%X G:%X B:%X)", col.r(), col.g(), col.b());
@ -492,7 +493,7 @@ static void palette_handler(mame_ui_manager &mui, render_container &container, u
static void palette_handle_keys(running_machine &machine, ui_gfx_state &state)
{
palette_device *palette = state.palette.device;
device_palette_interface *palette = state.palette.interface;
int rowcount, screencount;
int total;
@ -517,7 +518,7 @@ static void palette_handle_keys(running_machine &machine, ui_gfx_state &state)
{
state.palette.devindex--;
palette_set_device(machine, state);
palette = state.palette.device;
palette = state.palette.interface;
state.palette.which = (palette->indirect_entries() > 0);
}
}
@ -529,7 +530,7 @@ static void palette_handle_keys(running_machine &machine, ui_gfx_state &state)
{
state.palette.devindex++;
palette_set_device(machine, state);
palette = state.palette.device;
palette = state.palette.interface;
state.palette.which = 0;
}
}

View File

@ -201,7 +201,6 @@ public:
m_microtouch(*this, "microtouch") ,
m_uart(*this, "ns16550"),
m_maincpu(*this, "maincpu"),
m_palette(*this, "v9938_0:palette"),
m_bank1(*this, "bank1"),
m_bank2(*this, "bank2"),
m_bank3(*this, "bank3"),
@ -217,7 +216,6 @@ public:
optional_device<microtouch_device> m_microtouch;
optional_device<ns16550_device> m_uart;
required_device<cpu_device> m_maincpu;
required_device<palette_device> m_palette;
required_memory_bank m_bank1;
optional_memory_bank m_bank2;
optional_memory_bank m_bank3;
@ -347,7 +345,7 @@ uint32_t meritm_state::screen_update_meritm(screen_device &screen, bitmap_ind16
popmessage("Layer 1 %sabled",m_layer1_enabled ? "en" : "dis");
}
bitmap.fill(m_palette->black_pen(), cliprect);
bitmap.fill(m_v9938_0->black_pen(), cliprect);
if ( m_layer0_enabled )
{

View File

@ -24,7 +24,7 @@
void atari_common_state::video_start()
{
palette_device &palette = machine().first_screen()->palette();
device_palette_interface &palette = machine().first_screen()->palette();
for (int i = 0; i < 256; i++)
m_gtia->set_color_lookup(i, (palette.pen(0) << 8) + palette.pen(0));

View File

@ -215,7 +215,7 @@ void bfm_adder2_device::device_reset()
void bfm_adder2_device::device_start()
{
if (!palette().started())
if (!palette().device().started())
throw device_missing_dependencies();
adder2_decode_char_roms();

View File

@ -219,7 +219,7 @@ WRITE8_MEMBER( k007121_device::ctrl_w )
*
*/
void k007121_device::sprites_draw( bitmap_ind16 &bitmap, const rectangle &cliprect, gfx_element *gfx, palette_device &palette,
void k007121_device::sprites_draw( bitmap_ind16 &bitmap, const rectangle &cliprect, gfx_element *gfx, device_palette_interface &palette,
const uint8_t *source, int base_color, int global_x_offset, int bank_base, bitmap_ind8 &priority_bitmap, uint32_t pri_mask, bool is_flakatck )
{
// gfx_element *gfx = gfxs[chip];

View File

@ -17,7 +17,7 @@ public:
/* shall we move source in the interface? */
/* also notice that now we directly pass *gfx[chip] instead of **gfx !! */
void sprites_draw( bitmap_ind16 &bitmap, const rectangle &cliprect, gfx_element *gfx, palette_device &palette, const uint8_t *source, int base_color, int global_x_offset, int bank_base, bitmap_ind8 &priority_bitmap, uint32_t pri_mask, bool is_flakatck = false );
void sprites_draw( bitmap_ind16 &bitmap, const rectangle &cliprect, gfx_element *gfx, device_palette_interface &palette, const uint8_t *source, int base_color, int global_x_offset, int bank_base, bitmap_ind8 &priority_bitmap, uint32_t pri_mask, bool is_flakatck = false );
protected:
// device-level overrides

View File

@ -8,7 +8,7 @@
void konami_decode_gfx(device_gfx_interface &gfxdecode, int gfx_index, uint8_t *data, uint32_t total, const gfx_layout *layout, int bpp)
{
gfx_layout gl;
palette_device &palette = gfxdecode.palette();
device_palette_interface &palette = gfxdecode.palette();
memcpy(&gl, layout, sizeof(gl));
gl.total = total;