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