1 // license:BSD-3-Clause
2 // copyright-holders:David Haywood
3 /***************************************************************************
4 
5   redclash.cpp
6 
7   Functions to emulate the video hardware of the machine.
8 
9 ***************************************************************************/
10 
11 #include "emu.h"
12 #include "includes/redclash.h"
13 #include "video/resnet.h"
14 
15 /***************************************************************************
16 
17   Convert the color PROMs into a more useable format.
18 
19   I'm using the same palette conversion as Lady Bug, but the Zero Hour
20   schematics show a different resistor network.
21 
22 ***************************************************************************/
23 
palette(palette_device & palette) const24 void redclash_state::palette(palette_device &palette) const
25 {
26 	const uint8_t *color_prom = memregion("proms")->base();
27 
28 	// create a lookup table for the palette
29 	for (int i = 0; i < 0x20; i++)
30 	{
31 		int bit0, bit1;
32 
33 		// red component
34 		bit0 = BIT(color_prom[i], 0);
35 		bit1 = BIT(color_prom[i], 5);
36 		int const r = 0x47 * bit0 + 0x97 * bit1;
37 
38 		// green component
39 		bit0 = BIT(color_prom[i], 2);
40 		bit1 = BIT(color_prom[i], 6);
41 		int const g = 0x47 * bit0 + 0x97 * bit1;
42 
43 		// blue component
44 		bit0 = BIT(color_prom[i], 4);
45 		bit1 = BIT(color_prom[i], 7);
46 		int const b = 0x47 * bit0 + 0x97 * bit1;
47 
48 		palette.set_indirect_color(i, rgb_t(r, g, b));
49 	}
50 
51 	// star colors
52 	for (int i = 0; i < 0x20; i++)
53 	{
54 		int bit0, bit1;
55 
56 		// red component
57 		bit0 = BIT(i, 3);
58 		bit1 = BIT(i, 4);
59 		int const b = 0x47 * bit0 + 0x97 * bit1;
60 
61 		// green component
62 		bit0 = BIT(i, 1);
63 		bit1 = BIT(i, 2);
64 		int const g = 0x47 * bit0 + 0x97 * bit1;
65 
66 		// blue component
67 		bit0 = BIT(i, 0);
68 		int const r = 0x47 * bit0;
69 
70 		palette.set_indirect_color(i + 0x20, rgb_t(r, g, b));
71 	}
72 
73 	// color_prom now points to the beginning of the lookup table
74 	color_prom += 0x20;
75 
76 	// characters
77 	for (int i = 0; i < 0x20; i++)
78 	{
79 		uint8_t const ctabentry = ((i << 3) & 0x18) | ((i >> 2) & 0x07);
80 		palette.set_pen_indirect(i, ctabentry);
81 	}
82 
83 	// sprites
84 	for (int i = 0; i < 0x20; i++)
85 	{
86 		uint8_t ctabentry;
87 
88 		ctabentry = bitswap<4>((color_prom[i] >> 0) & 0x0f, 0,1,2,3);
89 		palette.set_pen_indirect(i + 0x20, ctabentry);
90 
91 		ctabentry = bitswap<4>((color_prom[i] >> 4) & 0x0f, 0,1,2,3);
92 		palette.set_pen_indirect(i + 0x40, ctabentry);
93 	}
94 
95 	// stars
96 	for (int i = 0; i < 0x20; i++)
97 		palette.set_pen_indirect(i + 0x60, i + 0x20);
98 }
99 
100 
videoram_w(offs_t offset,uint8_t data)101 void redclash_state::videoram_w(offs_t offset, uint8_t data)
102 {
103 	m_videoram[offset] = data;
104 	m_fg_tilemap->mark_tile_dirty(offset);
105 }
106 
gfxbank_w(uint8_t data)107 void redclash_state::gfxbank_w(uint8_t data)
108 {
109 	if (m_gfxbank != (data & 0x01))
110 	{
111 		m_gfxbank = data & 0x01;
112 		machine().tilemap().mark_all_dirty();
113 	}
114 }
115 
flipscreen_w(uint8_t data)116 void redclash_state::flipscreen_w(uint8_t data)
117 {
118 	flip_screen_set(data & 0x01);
119 }
120 
star_reset_w(uint8_t data)121 void redclash_state::star_reset_w(uint8_t data)
122 {
123 	m_stars->set_enable(true);
124 }
125 
TILE_GET_INFO_MEMBER(redclash_state::get_fg_tile_info)126 TILE_GET_INFO_MEMBER(redclash_state::get_fg_tile_info)
127 {
128 	int code = m_videoram[tile_index];
129 	int color = (m_videoram[tile_index] & 0x70) >> 4; // ??
130 
131 	tileinfo.set(0, code, color, 0);
132 }
133 
134 
video_start()135 void redclash_state::video_start()
136 {
137 	m_fg_tilemap = &machine().tilemap().create(*m_gfxdecode, tilemap_get_info_delegate(*this, FUNC(redclash_state::get_fg_tile_info)), TILEMAP_SCAN_ROWS, 8, 8, 32, 32);
138 	m_fg_tilemap->set_transparent_pen(0);
139 }
140 
draw_sprites(bitmap_ind16 & bitmap,const rectangle & cliprect)141 void redclash_state::draw_sprites(bitmap_ind16 &bitmap, const rectangle &cliprect)
142 {
143 	for (int offs = m_spriteram.bytes() - 0x20; offs >= 0; offs -= 0x20)
144 	{
145 		int i = 0;
146 		while (i < 0x20 && m_spriteram[offs + i] != 0)
147 			i += 4;
148 
149 		while (i > 0)
150 		{
151 			i -= 4;
152 
153 			if (m_spriteram[offs + i] & 0x80)
154 			{
155 				int color = m_spriteram[offs + i + 2] & 0x0f;
156 				int sx = m_spriteram[offs + i + 3];
157 				int sy = offs / 4 + (m_spriteram[offs + i] & 0x07);
158 
159 
160 				switch ((m_spriteram[offs + i] & 0x18) >> 3)
161 				{
162 					case 3: /* 24x24 */
163 					{
164 						int code = ((m_spriteram[offs + i + 1] & 0xf0) >> 4) + ((m_gfxbank & 1) << 4);
165 
166 						m_gfxdecode->gfx(3)->transpen(bitmap,cliprect,
167 								code,
168 								color,
169 								0,0,
170 								sx,sy - 16,0);
171 						/* wraparound */
172 						m_gfxdecode->gfx(3)->transpen(bitmap,cliprect,
173 								code,
174 								color,
175 								0,0,
176 								sx - 256,sy - 16,0);
177 						break;
178 					}
179 
180 					case 2: /* 16x16 */
181 						if (m_spriteram[offs + i] & 0x20) /* zero hour spaceships */
182 						{
183 							int code = ((m_spriteram[offs + i + 1] & 0xf8) >> 3) + ((m_gfxbank & 1) << 5);
184 							int bank = (m_spriteram[offs + i + 1] & 0x02) >> 1;
185 
186 							m_gfxdecode->gfx(4+bank)->transpen(bitmap,cliprect,
187 									code,
188 									color,
189 									0,0,
190 									sx,sy - 16,0);
191 						}
192 						else
193 						{
194 							int code = ((m_spriteram[offs + i + 1] & 0xf0) >> 4) + ((m_gfxbank & 1) << 4);
195 
196 							m_gfxdecode->gfx(2)->transpen(bitmap,cliprect,
197 									code,
198 									color,
199 									0,0,
200 									sx,sy - 16,0);
201 						}
202 						break;
203 
204 					case 1: /* 8x8 */
205 						m_gfxdecode->gfx(1)->transpen(bitmap,cliprect,
206 								m_spriteram[offs + i + 1],// + 4 * (m_spriteram[offs + i + 2] & 0x10),
207 								color,
208 								0,0,
209 								sx,sy - 16,0);
210 						break;
211 
212 					case 0:
213 						popmessage("unknown sprite size 0");
214 						break;
215 				}
216 			}
217 		}
218 	}
219 }
220 
draw_bullets(bitmap_ind16 & bitmap,const rectangle & cliprect)221 void redclash_state::draw_bullets( bitmap_ind16 &bitmap, const rectangle &cliprect )
222 {
223 	for (int offs = 0; offs < 0x20; offs++)
224 	{
225 //      sx = m_videoramoffs];
226 		int sx = 8 * offs + (m_videoram[offs] & 0x07);   /* ?? */
227 		int sy = 0xff - m_videoram[offs + 0x20];
228 
229 		if (flip_screen())
230 		{
231 			sx = 240 - sx;
232 		}
233 
234 		if (cliprect.contains(sx, sy))
235 			bitmap.pix(sy, sx) = 0x19;
236 	}
237 }
238 
WRITE_LINE_MEMBER(redclash_state::screen_vblank)239 WRITE_LINE_MEMBER(redclash_state::screen_vblank)
240 {
241 	// falling edge
242 	if (!state)
243 		m_stars->update_state();
244 }
245 
screen_update(screen_device & screen,bitmap_ind16 & bitmap,const rectangle & cliprect)246 uint32_t redclash_state::screen_update(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect)
247 {
248 	bitmap.fill(m_palette->black_pen(), cliprect);
249 	m_stars->draw(bitmap, cliprect, 0x60, true, 0x00, 0xff);
250 	draw_sprites(bitmap, cliprect);
251 	draw_bullets(bitmap, cliprect);
252 	m_fg_tilemap->draw(screen, bitmap, cliprect, 0, 0);
253 	return 0;
254 }
255