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