summaryrefslogtreecommitdiffstatshomepage
path: root/src/mame/video/decrmc3.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/mame/video/decrmc3.cpp')
-rw-r--r--src/mame/video/decrmc3.cpp253
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);
+}