1 // license:BSD-3-Clause
2 // copyright-holders:David Haywood
3 
4 #include "emu.h"
5 #include "k054338.h"
6 
7 #define VERBOSE 0
8 #include "logmacro.h"
9 
10 
11 /***************************************************************************/
12 /*                                                                         */
13 /*                                 054338                                  */
14 /*                                                                         */
15 /***************************************************************************/
16 
17 // k054338 alpha blend / final mixer (normally used with the 55555)
18 // because the implementation is video dependant, this is just a
19 // register-handling shell.
20 
21 DEFINE_DEVICE_TYPE(K054338, k054338_device, "k054338", "K054338 Mixer")
22 
k054338_device(const machine_config & mconfig,const char * tag,device_t * owner,uint32_t clock)23 k054338_device::k054338_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
24 	: device_t(mconfig, K054338, tag, owner, clock),
25 	device_video_interface(mconfig, *this),
26 	m_alpha_inv(0),
27 	m_k055555(*this, finder_base::DUMMY_TAG)
28 {
29 	memset(&m_regs, 0, sizeof(m_regs));
30 	memset(&m_shd_rgb, 0, sizeof(m_shd_rgb));
31 }
32 
33 //-------------------------------------------------
34 //  device_start - device-specific startup
35 //-------------------------------------------------
36 
device_start()37 void k054338_device::device_start()
38 {
39 	save_item(NAME(m_regs));
40 	save_item(NAME(m_shd_rgb));
41 }
42 
43 //-------------------------------------------------
44 //  device_reset - device-specific reset
45 //-------------------------------------------------
46 
device_reset()47 void k054338_device::device_reset()
48 {
49 	memset(m_regs, 0, sizeof(uint16_t)*32);
50 	memset(m_shd_rgb, 0, sizeof(int)*9);
51 }
52 
53 /*****************************************************************************
54     DEVICE HANDLERS
55 *****************************************************************************/
56 
word_w(offs_t offset,u16 data,u16 mem_mask)57 void k054338_device::word_w(offs_t offset, u16 data, u16 mem_mask)
58 {
59 	COMBINE_DATA(m_regs + offset);
60 }
61 
62 // returns a 16-bit '338 register
register_r(offs_t offset)63 u16 k054338_device::register_r(offs_t offset)
64 {
65 	return m_regs[offset];
66 }
67 
update_all_shadows(int rushingheroes_hack,palette_device & palette)68 void k054338_device::update_all_shadows( int rushingheroes_hack, palette_device &palette )
69 {
70 	int i, d;
71 	int noclip = m_regs[K338_REG_CONTROL] & K338_CTL_CLIPSL;
72 
73 	for (i = 0; i < 9; i++)
74 	{
75 		d = m_regs[K338_REG_SHAD1R + i] & 0x1ff;
76 		if (d >= 0x100)
77 			d -= 0x200;
78 		m_shd_rgb[i] = d;
79 	}
80 
81 	if (!rushingheroes_hack)
82 	{
83 		palette.set_shadow_dRGB32(0, m_shd_rgb[0], m_shd_rgb[1], m_shd_rgb[2], noclip);
84 		palette.set_shadow_dRGB32(1, m_shd_rgb[3], m_shd_rgb[4], m_shd_rgb[5], noclip);
85 		palette.set_shadow_dRGB32(2, m_shd_rgb[6], m_shd_rgb[7], m_shd_rgb[8], noclip);
86 	}
87 	else // rushing heroes seems to specify shadows in another format, or it's not being interpreted properly.
88 	{
89 		palette.set_shadow_dRGB32(0, -80, -80, -80, 0);
90 		palette.set_shadow_dRGB32(1, -80, -80, -80, 0);
91 		palette.set_shadow_dRGB32(2, -80, -80, -80, 0);
92 	}
93 }
94 
95 // k054338 BG color fill
fill_solid_bg(bitmap_rgb32 & bitmap,const rectangle & cliprect)96 void k054338_device::fill_solid_bg( bitmap_rgb32 &bitmap, const rectangle &cliprect )
97 {
98 	uint32_t bgcolor = (register_r(K338_REG_BGC_R) & 0xff) << 16;
99 	bgcolor |= register_r(K338_REG_BGC_GB);
100 
101 	bitmap.fill(bgcolor, cliprect);
102 }
103 
104 // Unified k054338/K055555 BG color fill (see p.67)
fill_backcolor(bitmap_rgb32 & bitmap,const rectangle & cliprect,const pen_t * pal_ptr,int mode)105 void k054338_device::fill_backcolor(bitmap_rgb32 &bitmap, const rectangle &cliprect, const pen_t *pal_ptr, int mode)
106 {
107 	if ((mode & 0x02) == 0) // solid fill
108 	{
109 		bitmap.fill(*pal_ptr, cliprect);
110 	}
111 	else
112 	{
113 		uint32_t *dst_ptr = &bitmap.pix(cliprect.min_y);
114 		int dst_pitch = bitmap.rowpixels();
115 
116 		if ((mode & 0x01) == 0) // vertical gradient fill
117 		{
118 			pal_ptr += cliprect.min_y;
119 			for(int y = cliprect.min_y; y <= cliprect.max_y; y++)
120 			{
121 				for(int x = cliprect.min_x; x <= cliprect.max_x; x++)
122 				{
123 					dst_ptr[x] = *pal_ptr;
124 				}
125 
126 				pal_ptr++;
127 				dst_ptr += dst_pitch;
128 			}
129 		}
130 		else    // horizontal gradient fill
131 		{
132 			int width = cliprect.width() * sizeof(uint32_t);
133 			pal_ptr += cliprect.min_x;
134 			dst_ptr += cliprect.min_x;
135 			for(int y = cliprect.min_y; y<= cliprect.max_y; y++)
136 			{
137 				memcpy(dst_ptr, pal_ptr, width);
138 				dst_ptr += dst_pitch;
139 			}
140 		}
141 	}
142 }
143 
144 // addition blending unimplemented (requires major changes to drawgfx and tilemap.cpp)
set_alpha_level(int pblend)145 int k054338_device::set_alpha_level( int pblend )
146 {
147 	uint16_t *regs;
148 	int ctrl, mixpri, mixset, mixlv;
149 
150 	if (pblend <= 0 || pblend > 3)
151 	{
152 		return (255);
153 	}
154 
155 	regs   = m_regs;
156 	ctrl   = m_regs[K338_REG_CONTROL];
157 	mixpri = ctrl & K338_CTL_MIXPRI;
158 	mixset = regs[K338_REG_PBLEND + (pblend >> 1 & 1)] >> (~pblend << 3 & 8);
159 	mixlv  = mixset & 0x1f;
160 
161 	if (m_alpha_inv)
162 		mixlv = 0x1f - mixlv;
163 
164 	if (!(mixset & 0x20))
165 	{
166 		mixlv = (mixlv << 3) | (mixlv >> 2);
167 	}
168 	else
169 	{
170 		if (!mixpri)
171 		{
172 			// source x alpha  +  target (clipped at 255)
173 		}
174 		else
175 		{
176 			// source  +  target x alpha (clipped at 255)
177 		}
178 
179 		// DUMMY
180 		if (mixlv && mixlv < 0x1f)
181 			mixlv = 0x10;
182 
183 		mixlv = (mixlv << 3) | (mixlv >> 2);
184 
185 		if (VERBOSE)
186 			popmessage("MIXSET%1d %s addition mode: %02x", pblend, (mixpri) ? "dst" : "src", mixset & 0x1f);
187 	}
188 
189 	return mixlv;
190 }
191 
invert_alpha(int invert)192 void k054338_device::invert_alpha( int invert )
193 {
194 	m_alpha_inv = invert;
195 }
196 
197 
export_config(int ** shd_rgb)198 void k054338_device::export_config( int **shd_rgb )
199 {
200 	*shd_rgb = m_shd_rgb;
201 }
202