summaryrefslogblamecommitdiffstatshomepage
path: root/src/mame/video/decrmc3.cpp
blob: 66e7fc1391be83638802af0f26449704dac18585 (plain) (tree)




















                                                                                                              





                                                         




                                                                            

































                                                                                                     
                                       




                                          
                                         




                                                     
                                         




                                                     
                                     



                                          
                                       



                                           
                                       









                                                   
                                           





                                              
                                             









































                                                                            
                         




























                                                                              

                                                                      






























                                                                                                           
 





                                                                                  
// 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(*this)
{
}


//**************************************************************************
//  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::write8)
{
	m_paletteram.write8(offset, data);
	update_for_write(offset, 1);
}

WRITE16_MEMBER(deco_rmc3_device::write16)
{
	m_paletteram.write16(offset, data, mem_mask);
	update_for_write(offset * 2, 2);
}

WRITE32_MEMBER(deco_rmc3_device::write32)
{
	m_paletteram.write32(offset, data, mem_mask);
	update_for_write(offset * 4, 4);
}

READ8_MEMBER(deco_rmc3_device::read8)
{
	return m_paletteram.read8(offset);
}

READ16_MEMBER(deco_rmc3_device::read16)
{
	return m_paletteram.read16(offset);
}

READ32_MEMBER(deco_rmc3_device::read32)
{
	return m_paletteram.read32(offset);
}


//-------------------------------------------------
//  write_ext - write a byte to the extended
//  paletteram
//-------------------------------------------------

WRITE8_MEMBER(deco_rmc3_device::write8_ext)
{
	m_paletteram_ext.write8(offset, data);
	update_for_write(offset, 1);
}


WRITE16_MEMBER(deco_rmc3_device::write16_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.resolve();

	// 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);
}