1 // license:BSD-3-Clause
2 // copyright-holders:Mike Balfour
3 /***************************************************************************
4
5 vigilant.c
6
7 Functions to emulate the video hardware of the machine.
8
9 TODO:
10
11 - Add cocktail flipping.
12
13 ***************************************************************************/
14
15 #include "emu.h"
16 #include "includes/vigilant.h"
17
18
19 static const rectangle bottomvisiblearea(16*8, 48*8-1, 6*8, 32*8-1);
20
21
video_start()22 void vigilant_state::video_start()
23 {
24 m_bg_bitmap = std::make_unique<bitmap_ind16>(512*4,256);
25
26 save_item(NAME(m_horiz_scroll_low));
27 save_item(NAME(m_horiz_scroll_high));
28 save_item(NAME(m_rear_horiz_scroll_low));
29 save_item(NAME(m_rear_horiz_scroll_high));
30 save_item(NAME(m_rear_color));
31 save_item(NAME(m_rear_disable));
32
33 m_rear_refresh = 1;
34 machine().save().register_postload(save_prepost_delegate(FUNC(vigilant_state::vigilant_postload), this));
35 }
36
vigilant_postload()37 void vigilant_state::vigilant_postload()
38 {
39 m_rear_refresh = 1;
40 }
41
video_reset()42 void vigilant_state::video_reset()
43 {
44 m_horiz_scroll_low = 0;
45 m_horiz_scroll_high = 0;
46 m_rear_horiz_scroll_low = 0;
47 m_rear_horiz_scroll_high = 0;
48 m_rear_color = 0;
49 m_rear_disable = 1;
50 }
51
52
53 /***************************************************************************
54 update_background
55
56 There are three background ROMs, each one contains a 512x256 picture.
57 **************************************************************************/
update_background()58 void vigilant_state::update_background()
59 {
60 int row,col,page;
61 int charcode;
62
63
64 charcode=0;
65
66 /* There are only three background ROMs (4 on bunccaneers!) */
67 for (page=0; page<4; page++)
68 {
69 for( row=0; row<256; row++ )
70 {
71 for( col=0; col<512; col+=32 )
72 {
73 m_gfxdecode->gfx(2)->opaque(*m_bg_bitmap,
74 m_bg_bitmap->cliprect(),
75 charcode,
76 row < 128 ? 0 : 1,
77 0,0,
78 512*page + col,row);
79 charcode++;
80 }
81 }
82 }
83 }
84
85 /***************************************************************************
86 paletteram_w
87
88 There are two palette chips, each one is labelled "KNA91H014". One is
89 used for the sprites, one is used for the two background layers.
90
91 The chip has three enables (!CS, !E0, !E1), R/W pins, A0-A7 as input,
92 'L' and 'H' inputs, and D0-D4 as input. 'L' and 'H' are used to bank
93 into Red, Green, and Blue memory. There are only 5 bits of memory for
94 each byte, and a total of 256*3 bytes memory per chip.
95
96 There are additionally two sets of D0-D7 inputs per chip labelled 'A'
97 and 'B'. There is also an 'S' pin to select between the two input sets.
98 These are used to index a color triplet of RGB. The triplet is read
99 from RAM, and output to R0-R4, G0-G4, and B0-B4.
100 **************************************************************************/
paletteram_w(offs_t offset,uint8_t data)101 void vigilant_state::paletteram_w(offs_t offset, uint8_t data)
102 {
103 int bank,r,g,b;
104
105
106 m_generic_paletteram_8[offset] = data;
107
108 bank = offset & 0x400;
109 offset &= 0xff;
110
111 r = (m_generic_paletteram_8[bank + offset + 0x000] << 3) & 0xFF;
112 g = (m_generic_paletteram_8[bank + offset + 0x100] << 3) & 0xFF;
113 b = (m_generic_paletteram_8[bank + offset + 0x200] << 3) & 0xFF;
114
115 m_palette->set_pen_color((bank >> 2) + offset,rgb_t(r,g,b));
116 }
117
118
119
120 /***************************************************************************
121 vigilant_horiz_scroll_w
122
123 horiz_scroll_low = HSPL, an 8-bit register
124 horiz_scroll_high = HSPH, a 1-bit register
125 **************************************************************************/
vigilant_horiz_scroll_w(offs_t offset,uint8_t data)126 void vigilant_state::vigilant_horiz_scroll_w(offs_t offset, uint8_t data)
127 {
128 if (offset==0)
129 m_horiz_scroll_low = data;
130 else
131 m_horiz_scroll_high = (data & 0x01) * 256;
132 }
133
134 /***************************************************************************
135 vigilant_rear_horiz_scroll_w
136
137 rear_horiz_scroll_low = RHSPL, an 8-bit register
138 rear_horiz_scroll_high = RHSPH, an 8-bit register but only 3 bits are saved
139 ***************************************************************************/
vigilant_rear_horiz_scroll_w(offs_t offset,uint8_t data)140 void vigilant_state::vigilant_rear_horiz_scroll_w(offs_t offset, uint8_t data)
141 {
142 if (offset==0)
143 m_rear_horiz_scroll_low = data;
144 else
145 m_rear_horiz_scroll_high = (data & 0x07) * 256;
146 }
147
148 /***************************************************************************
149 vigilant_rear_color_w
150
151 This is an 8-bit register labelled RCOD.
152 D6 is hooked to !ROME (rear_disable)
153 D3 = RCC2 (rear color bit 2)
154 D2 = RCC1 (rear color bit 1)
155 D0 = RCC0 (rear color bit 0)
156
157 I know it looks odd, but D1, D4, D5, and D7 are empty.
158
159 What makes this extremely odd is that RCC is supposed to hook up to the
160 palette. However, the top four bits of the palette inputs are labelled:
161 "RCC3", "RCC2", "V256E", "RCC0". Methinks there's a typo.
162 **************************************************************************/
vigilant_rear_color_w(uint8_t data)163 void vigilant_state::vigilant_rear_color_w(uint8_t data)
164 {
165 m_rear_disable = data & 0x40;
166 m_rear_color = (data & 0x0d);
167 }
168
169 /***************************************************************************
170 draw_foreground
171
172 ???
173 **************************************************************************/
174
draw_foreground(bitmap_ind16 & bitmap,const rectangle & cliprect,int priority,int opaque)175 void vigilant_state::draw_foreground(bitmap_ind16 &bitmap, const rectangle &cliprect, int priority, int opaque )
176 {
177 int scroll = -(m_horiz_scroll_low + m_horiz_scroll_high);
178
179
180 for (int offs = 0; offs < 0x1000; offs += 2)
181 {
182 int sy = 8 * ((offs/2) / 64);
183 int sx = 8 * ((offs/2) % 64);
184 int attributes = m_videoram[offs+1];
185 int color = attributes & 0x0F;
186 int tile_number = m_videoram[offs] | ((attributes & 0xF0) << 4);
187
188 if (priority) /* foreground */
189 {
190 if ((color & 0x0c) == 0x0c) /* mask sprites */
191 {
192 if (sy >= 48)
193 {
194 sx = (sx + scroll) & 0x1ff;
195
196 m_gfxdecode->gfx(0)->transmask(bitmap,bottomvisiblearea,
197 tile_number,
198 color,
199 0,0,
200 sx,sy,0x00ff);
201 }
202 }
203 }
204 else /* background */
205 {
206 if (sy >= 48)
207 sx = (sx + scroll) & 0x1ff;
208
209 m_gfxdecode->gfx(0)->transpen(bitmap,cliprect,
210 tile_number,
211 color,
212 0,0,
213 sx,sy,
214 (opaque || color >= 4) ? -1 : 0);
215 }
216 }
217 }
218
219
220
draw_background(bitmap_ind16 & bitmap,const rectangle & cliprect)221 void vigilant_state::draw_background(bitmap_ind16 &bitmap, const rectangle &cliprect)
222 {
223 int scrollx = 0x17a + 16*8 - (m_rear_horiz_scroll_low + m_rear_horiz_scroll_high);
224
225
226 if (m_rear_refresh)
227 {
228 update_background();
229 m_rear_refresh=0;
230 }
231
232 copyscrollbitmap(bitmap,*m_bg_bitmap,1,&scrollx,0,nullptr,bottomvisiblearea);
233 }
234
235
draw_sprites(bitmap_ind16 & bitmap,const rectangle & cliprect)236 void vigilant_state::draw_sprites(bitmap_ind16 &bitmap,const rectangle &cliprect)
237 {
238 for (int offs = 0;offs < m_spriteram.bytes();offs += 8)
239 {
240 int code,color,sx,sy,flipx,flipy,h,y;
241
242 code = m_spriteram[offs+4] | ((m_spriteram[offs+5] & 0x0f) << 8);
243 color = m_spriteram[offs+0] & 0x0f;
244 sx = (m_spriteram[offs+6] | ((m_spriteram[offs+7] & 0x01) << 8));
245 sy = 256+128 - (m_spriteram[offs+2] | ((m_spriteram[offs+3] & 0x01) << 8));
246 flipx = m_spriteram[offs+5] & 0x40;
247 flipy = m_spriteram[offs+5] & 0x80;
248 h = 1 << ((m_spriteram[offs+5] & 0x30) >> 4);
249 sy -= 16 * h;
250
251 code &= ~(h - 1);
252
253 for (y = 0;y < h;y++)
254 {
255 int c = code;
256
257 if (flipy) c += h-1-y;
258 else c += y;
259
260 m_gfxdecode->gfx(1)->transpen(bitmap,cliprect,
261 c,
262 color,
263 flipx,flipy,
264 sx,sy + 16*y,0);
265 }
266 }
267 }
268
screen_update_kikcubic(screen_device & screen,bitmap_ind16 & bitmap,const rectangle & cliprect)269 uint32_t vigilant_state::screen_update_kikcubic(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect)
270 {
271 for (int offs = 0; offs < 0x1000; offs += 2)
272 {
273 int sy = 8 * ((offs/2) / 64);
274 int sx = 8 * ((offs/2) % 64);
275 int attributes = m_videoram[offs+1];
276 int color = (attributes & 0xF0) >> 4;
277 int tile_number = m_videoram[offs] | ((attributes & 0x0F) << 8);
278
279 m_gfxdecode->gfx(0)->opaque(bitmap,cliprect,
280 tile_number,
281 color,
282 0,0,
283 sx,sy);
284 }
285
286 draw_sprites(bitmap,cliprect);
287 return 0;
288 }
289
screen_update_vigilant(screen_device & screen,bitmap_ind16 & bitmap,const rectangle & cliprect)290 uint32_t vigilant_state::screen_update_vigilant(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect)
291 {
292 /* copy the background palette */
293 for (int i = 0;i < 16;i++)
294 {
295 int r,g,b;
296
297
298 r = (m_generic_paletteram_8[0x400 + 16 * m_rear_color + i] << 3) & 0xFF;
299 g = (m_generic_paletteram_8[0x500 + 16 * m_rear_color + i] << 3) & 0xFF;
300 b = (m_generic_paletteram_8[0x600 + 16 * m_rear_color + i] << 3) & 0xFF;
301
302 m_palette->set_pen_color(512 + i,rgb_t(r,g,b));
303
304 r = (m_generic_paletteram_8[0x400 + 16 * m_rear_color + 32 + i] << 3) & 0xFF;
305 g = (m_generic_paletteram_8[0x500 + 16 * m_rear_color + 32 + i] << 3) & 0xFF;
306 b = (m_generic_paletteram_8[0x600 + 16 * m_rear_color + 32 + i] << 3) & 0xFF;
307
308 m_palette->set_pen_color(512 + 16 + i,rgb_t(r,g,b));
309 }
310
311 if (m_rear_disable) /* opaque foreground */
312 {
313 draw_foreground(bitmap,cliprect,0,1);
314 draw_sprites(bitmap,bottomvisiblearea);
315 draw_foreground(bitmap,cliprect,1,0);
316 }
317 else
318 {
319 draw_background(bitmap,cliprect);
320 draw_foreground(bitmap,cliprect,0,0);
321 draw_sprites(bitmap,bottomvisiblearea);
322 draw_foreground(bitmap,cliprect,1,0); // priority tiles
323 }
324 return 0;
325 }
326