diff options
Diffstat (limited to 'src/mame/video/decrmc3.cpp')
-rw-r--r-- | src/mame/video/decrmc3.cpp | 253 |
1 files changed, 253 insertions, 0 deletions
diff --git a/src/mame/video/decrmc3.cpp b/src/mame/video/decrmc3.cpp new file mode 100644 index 00000000000..fd9a62467b1 --- /dev/null +++ b/src/mame/video/decrmc3.cpp @@ -0,0 +1,253 @@ +// license:BSD-3-Clause +// copyright-holders:Bryan McPhail +/*************************************************************************** + + decrmc3.cpp + + Data East custom palette device. + +***************************************************************************/ + +#include "emu.h" +#include "decrmc3.h" + + +//************************************************************************** +// DEVICE DEFINITIONS +//************************************************************************** + +DEFINE_DEVICE_TYPE(DECO_RMC3, deco_rmc3_device, "deco_rmc3", "DECO RM-C3 PALETTE") + +deco_rmc3_device::deco_rmc3_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock) + : device_t(mconfig, DECO_RMC3, tag, owner, clock), + device_palette_interface(mconfig, *this), + m_entries(0), + m_indirect_entries(0), + m_prom_region(*this, finder_base::DUMMY_TAG), + m_init(deco_rmc3_palette_init_delegate()) +{ +} + + +//************************************************************************** +// INITIALIZATION AND CONFIGURATION +//************************************************************************** + +void deco_rmc3_device::static_set_init(device_t &device, deco_rmc3_palette_init_delegate init) +{ + downcast<deco_rmc3_device &>(device).m_init = init; +} + + +void deco_rmc3_device::static_set_entries(device_t &device, u32 entries) +{ + downcast<deco_rmc3_device &>(device).m_entries = entries; +} + + +void deco_rmc3_device::static_set_indirect_entries(device_t &device, u32 entries) +{ + downcast<deco_rmc3_device &>(device).m_indirect_entries = entries; +} + +void deco_rmc3_device::static_set_prom_region(device_t &device, const char *region) +{ + downcast<deco_rmc3_device &>(device).m_prom_region.set_tag(region); +} + + + +//************************************************************************** +// GENERIC WRITE HANDLERS +//************************************************************************** + +//------------------------------------------------- +// update_for_write - given a write of a given +// length to a given byte offset, update all +// potentially modified palette entries +//------------------------------------------------- + +inline void deco_rmc3_device::update_for_write(offs_t byte_offset, int bytes_modified, bool indirect) +{ + assert((m_indirect_entries != 0) == indirect); + + // determine how many entries were modified + int bpe = m_paletteram.bytes_per_entry(); + assert(bpe != 0); + int count = (bytes_modified + bpe - 1) / bpe; + + // for each entry modified, fetch the palette data and set the pen color or indirect color + offs_t base = byte_offset / bpe; + for (int index = 0; index < count; index++) + { + if (indirect) + set_indirect_color(base + index, deco_rgb_decoder(read_entry(base + index))); + else + set_pen_color(base + index, deco_rgb_decoder(read_entry(base + index))); + } +} + + +//------------------------------------------------- +// write - write a byte to the base paletteram +//------------------------------------------------- + +WRITE8_MEMBER(deco_rmc3_device::write) +{ + m_paletteram.write8(offset, data); + update_for_write(offset, 1); +} + +WRITE16_MEMBER(deco_rmc3_device::write) +{ + m_paletteram.write16(offset, data, mem_mask); + update_for_write(offset * 2, 2); +} + +WRITE32_MEMBER(deco_rmc3_device::write) +{ + m_paletteram.write32(offset, data, mem_mask); + update_for_write(offset * 4, 4); +} + +READ8_MEMBER(deco_rmc3_device::read) +{ + return m_paletteram.read8(offset); +} + +READ16_MEMBER(deco_rmc3_device::read) +{ + return m_paletteram.read16(offset); +} + +READ32_MEMBER(deco_rmc3_device::read) +{ + return m_paletteram.read32(offset); +} + + +//------------------------------------------------- +// write_ext - write a byte to the extended +// paletteram +//------------------------------------------------- + +WRITE8_MEMBER(deco_rmc3_device::write_ext) +{ + m_paletteram_ext.write8(offset, data); + update_for_write(offset, 1); +} + + +WRITE16_MEMBER(deco_rmc3_device::write_ext) +{ + m_paletteram_ext.write16(offset, data, mem_mask); + update_for_write(offset * 2, 2); +} + + +//------------------------------------------------- +// write_indirect - write a byte to the base +// paletteram, updating indirect colors +//------------------------------------------------- + +WRITE8_MEMBER(deco_rmc3_device::write_indirect) +{ + m_paletteram.write8(offset, data); + update_for_write(offset, 1, true); +} + + +//------------------------------------------------- +// write_ext - write a byte to the extended +// paletteram, updating indirect colors +//------------------------------------------------- + +WRITE8_MEMBER(deco_rmc3_device::write_indirect_ext) +{ + m_paletteram_ext.write8(offset, data); + update_for_write(offset, 1, true); +} + + + +//************************************************************************** +// DEVICE MANAGEMENT +//************************************************************************** + +//------------------------------------------------- +// device_start - start up the device +//------------------------------------------------- + +void deco_rmc3_device::device_start() +{ + // bind the init function + m_init.bind_relative_to(*owner()); + + // find the memory, if present + const memory_share *share = memshare(tag()); + if (share != nullptr) + { + // find the extended (split) memory, if present + std::string tag_ext = std::string(tag()).append("_ext"); + const memory_share *share_ext = memshare(tag_ext.c_str()); + + // determine bytes per entry and configure + int bytes_per_entry = 2; + if (share_ext == nullptr) + m_paletteram.set(*share, bytes_per_entry); + else + { + m_paletteram.set(*share, bytes_per_entry / 2); + m_paletteram_ext.set(*share_ext, bytes_per_entry / 2); + } + + + } + + // call the initialization helper if present + if (!m_init.isnull()) + m_init(*this); +} + + + +// This conversion mimics the specific weighting used by the Data East +// custom resistor pack marked DECO RM-C3 to convert the digital +// palette for analog output. It is used on games such as The Real +// Ghostbusters, Gondomania, Cobra Command, Psychonics Oscar. +// +// Resistor values are 220 ohms (MSB), 470 ohms, 1 kohm, 2.2 kohm (LSB) + +void deco_rmc3_device::palette_init_proms(deco_rmc3_device &palette) +{ + if (!m_prom_region.found()) + throw emu_fatalerror("Unable to find color PROM region '%s'.", m_prom_region.finder_tag()); + + const u8 *colors = m_prom_region->base(); + + for (int i = 0; i < palette.entries(); i++) + { + u8 r = colors[i]&0xf; + u8 g = (colors[i]>>4)&0xf; + u8 b = colors[i + palette.entries()]&0xf; + + r = 0x0e * BIT(r,0) + 0x1f * BIT(r,1) + 0x43 * BIT(r,2) + 0x8f * BIT(r,3); + g = 0x0e * BIT(g,0) + 0x1f * BIT(g,1) + 0x43 * BIT(g,2) + 0x8f * BIT(g,3); + b = 0x0e * BIT(b,0) + 0x1f * BIT(b,1) + 0x43 * BIT(b,2) + 0x8f * BIT(b,3); + + palette.set_pen_color(i, rgb_t(r,g,b)); + } +} + +rgb_t deco_rmc3_device::deco_rgb_decoder(u32 raw) +{ + u8 r = raw&0xf; + u8 g = (raw>>4)&0xf; + u8 b = (raw>>8)&0xf; + + r = 0x0e * BIT(r,0) + 0x1f * BIT(r,1) + 0x43 * BIT(r,2) + 0x8f * BIT(r,3); + g = 0x0e * BIT(g,0) + 0x1f * BIT(g,1) + 0x43 * BIT(g,2) + 0x8f * BIT(g,3); + b = 0x0e * BIT(b,0) + 0x1f * BIT(b,1) + 0x43 * BIT(b,2) + 0x8f * BIT(b,3); + + return rgb_t(r, g, b); +} |