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