mirror of
https://github.com/holub/mame
synced 2025-04-23 00:39:36 +03:00
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:
parent
fbb7d927d3
commit
8fe18e9ecc
@ -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",
|
||||
|
@ -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));
|
||||
}
|
||||
|
||||
|
@ -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 );
|
||||
}
|
||||
|
@ -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; }
|
||||
};
|
||||
|
||||
|
||||
|
@ -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)
|
||||
|
@ -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
503
src/emu/dipalette.cpp
Normal 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
144
src/emu/dipalette.h
Normal 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
|
@ -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());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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),
|
||||
|
@ -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)
|
||||
|
@ -89,8 +89,6 @@
|
||||
//**************************************************************************
|
||||
|
||||
// forward declarations
|
||||
class gfxdecode_device;
|
||||
class palette_device;
|
||||
typedef delegate<void ()> driver_callback_delegate;
|
||||
|
||||
|
||||
|
@ -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"
|
||||
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
103
src/emu/emupal.h
103
src/emu/emupal.h
@ -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
|
||||
|
@ -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
|
||||
|
@ -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) \
|
||||
|
@ -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
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
@ -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 )
|
||||
{
|
||||
|
@ -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));
|
||||
|
@ -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();
|
||||
|
@ -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];
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
Loading…
Reference in New Issue
Block a user