1 /***************************************************************************
2 
3   vidhrdw.c
4 
5   Functions to emulate the video hardware of the machine.
6 
7 ***************************************************************************/
8 
9 #include "driver.h"
10 #include "fastfred.h"
11 
12 extern UINT8 galaxian_stars_on;
13 extern void galaxian_init_stars(int colors_offset);
14 extern void galaxian_draw_stars(struct mame_bitmap *bitmap);
15 
16 data8_t *fastfred_videoram;
17 data8_t *fastfred_spriteram;
18 size_t fastfred_spriteram_size;
19 data8_t *fastfred_attributesram;
20 data8_t *imago_fg_videoram;
21 
22 
23 static struct rectangle spritevisiblearea =
24 {
25       2*8, 32*8-1,
26       2*8, 30*8-1
27 };
28 
29 static struct rectangle spritevisibleareaflipx =
30 {
31         0*8, 30*8-1,
32         2*8, 30*8-1
33 };
34 
35 static data16_t charbank;
36 static data8_t colorbank;
37 static int flip_screen_x;
38 static int flip_screen_y;
39 int fastfred_hardware_type;
40 static const UINT8 *fastfred_color_prom;
41 static struct tilemap *bg_tilemap, *fg_tilemap, *web_tilemap;
42 
43 /***************************************************************************
44 
45   Convert the color PROMs into a more useable format.
46 
47   bit 0 -- 1  kohm resistor  -- RED/GREEN/BLUE
48         -- 470 ohm resistor  -- RED/GREEN/BLUE
49         -- 220 ohm resistor  -- RED/GREEN/BLUE
50   bit 3 -- 100 ohm resistor  -- RED/GREEN/BLUE
51 
52 ***************************************************************************/
53 
set_color(pen_t pen,int i)54 static void set_color(pen_t pen, int i)
55 {
56 	UINT8 r,g,b;
57 	int bit0, bit1, bit2, bit3;
58 
59 	bit0 = (fastfred_color_prom[i] >> 0) & 0x01;
60 	bit1 = (fastfred_color_prom[i] >> 1) & 0x01;
61 	bit2 = (fastfred_color_prom[i] >> 2) & 0x01;
62 	bit3 = (fastfred_color_prom[i] >> 3) & 0x01;
63 	r = 0x0e * bit0 + 0x1f * bit1 + 0x43 * bit2 + 0x8f * bit3;
64 	bit0 = (fastfred_color_prom[i + 0x100] >> 0) & 0x01;
65 	bit1 = (fastfred_color_prom[i + 0x100] >> 1) & 0x01;
66 	bit2 = (fastfred_color_prom[i + 0x100] >> 2) & 0x01;
67 	bit3 = (fastfred_color_prom[i + 0x100] >> 3) & 0x01;
68 	g = 0x0e * bit0 + 0x1f * bit1 + 0x43 * bit2 + 0x8f * bit3;
69 	bit0 = (fastfred_color_prom[i + 0x200] >> 0) & 0x01;
70 	bit1 = (fastfred_color_prom[i + 0x200] >> 1) & 0x01;
71 	bit2 = (fastfred_color_prom[i + 0x200] >> 2) & 0x01;
72 	bit3 = (fastfred_color_prom[i + 0x200] >> 3) & 0x01;
73 	b = 0x0e * bit0 + 0x1f * bit1 + 0x43 * bit2 + 0x8f * bit3;
74 
75 	palette_set_color(pen,r,g,b);
76 }
77 
PALETTE_INIT(fastfred)78 PALETTE_INIT( fastfred )
79 {
80 	pen_t i;
81 	#define COLOR(gfxn,offs) (colortable[Machine->drv->gfxdecodeinfo[gfxn].color_codes_start + offs])
82 
83 
84 	fastfred_color_prom = color_prom;	/* we'll need this later */
85 
86 	for (i = 0;i < 256;i++)
87 	{
88 		set_color(i, i);
89 	}
90 
91 
92 	/* characters and sprites use the same palette */
93 	for (i = 0; i < 256; i++)
94 	{
95 		pen_t color;
96 
97 		if ((i & 0x07) == 0)
98 			color = 0;
99 		else
100 			color = i;
101 
102 		COLOR(0,i) = COLOR(1,i) = color;
103 	}
104 }
105 
106 
107 /***************************************************************************
108 
109   Callbacks for the TileMap code
110 
111 ***************************************************************************/
112 
get_tile_info(int tile_index)113 static void get_tile_info(int tile_index)
114 {
115 	data8_t x = tile_index & 0x1f;
116 
117 	data16_t code = charbank | fastfred_videoram[tile_index];
118 	data8_t color = colorbank | (fastfred_attributesram[2 * x + 1] & 0x07);
119 
120 	SET_TILE_INFO(0, code, color, 0)
121 }
122 
123 
124 
125 /*************************************
126  *
127  *	Video system start
128  *
129  *************************************/
130 
VIDEO_START(fastfred)131 VIDEO_START( fastfred )
132 {
133 	bg_tilemap = tilemap_create(get_tile_info,tilemap_scan_rows,TILEMAP_OPAQUE,8,8,32,32);
134 
135 	if (!bg_tilemap)
136 		return 1;
137 
138 	tilemap_set_scroll_cols(bg_tilemap, 32);
139 
140 	return 0;
141 }
142 
143 
144 /*************************************
145  *
146  *	Memory handlers
147  *
148  *************************************/
149 
WRITE_HANDLER(fastfred_videoram_w)150 WRITE_HANDLER( fastfred_videoram_w )
151 {
152 	if (fastfred_videoram[offset] != data)
153 	{
154 		fastfred_videoram[offset] = data;
155 
156 		tilemap_mark_tile_dirty(bg_tilemap, offset);
157 	}
158 }
159 
160 
WRITE_HANDLER(fastfred_attributes_w)161 WRITE_HANDLER( fastfred_attributes_w )
162 {
163 	if (fastfred_attributesram[offset] != data)
164 	{
165 		if (offset & 0x01)
166 		{
167 			/* color change */
168 			int i;
169 
170 			for (i = offset / 2; i < 0x0400; i += 32)
171 				tilemap_mark_tile_dirty(bg_tilemap, i);
172 		}
173 		else
174 		{
175 			/* coloumn scroll */
176 			tilemap_set_scrolly(bg_tilemap, offset / 2, data);
177 		}
178 
179 		fastfred_attributesram[offset] = data;
180 	}
181 }
182 
183 
WRITE_HANDLER(fastfred_charbank1_w)184 WRITE_HANDLER( fastfred_charbank1_w )
185 {
186 	data16_t new_data = (charbank & 0x0200) | ((data & 0x01) << 8);
187 
188 	if (new_data != charbank)
189 	{
190 		tilemap_mark_all_tiles_dirty(bg_tilemap);
191 
192 		charbank = new_data;
193 	}
194 }
195 
WRITE_HANDLER(fastfred_charbank2_w)196 WRITE_HANDLER( fastfred_charbank2_w )
197 {
198 	data16_t new_data = (charbank & 0x0100) | ((data & 0x01) << 9);
199 
200 	if (new_data != charbank)
201 	{
202 		tilemap_mark_all_tiles_dirty(bg_tilemap);
203 
204 		charbank = new_data;
205 	}
206 }
207 
208 
WRITE_HANDLER(fastfred_colorbank1_w)209 WRITE_HANDLER( fastfred_colorbank1_w )
210 {
211 	data8_t new_data = (colorbank & 0x10) | ((data & 0x01) << 3);
212 
213 	if (new_data != colorbank)
214 	{
215 		tilemap_mark_all_tiles_dirty(bg_tilemap);
216 
217 		colorbank = new_data;
218 	}
219 }
220 
WRITE_HANDLER(fastfred_colorbank2_w)221 WRITE_HANDLER( fastfred_colorbank2_w )
222 {
223 	data8_t new_data = (colorbank & 0x08) | ((data & 0x01) << 4);
224 
225 	if (new_data != colorbank)
226 	{
227 		tilemap_mark_all_tiles_dirty(bg_tilemap);
228 
229 		colorbank = new_data;
230 	}
231 }
232 
233 
WRITE_HANDLER(fastfred_background_color_w)234 WRITE_HANDLER( fastfred_background_color_w )
235 {
236 	set_color(0, data);
237 }
238 
239 
WRITE_HANDLER(fastfred_flip_screen_x_w)240 WRITE_HANDLER( fastfred_flip_screen_x_w )
241 {
242 	if (flip_screen_x != (data & 0x01))
243 	{
244 		flip_screen_x = data & 0x01;
245 
246 		tilemap_set_flip(bg_tilemap, (flip_screen_x ? TILEMAP_FLIPX : 0) | (flip_screen_y ? TILEMAP_FLIPY : 0));
247 	}
248 }
249 
WRITE_HANDLER(fastfred_flip_screen_y_w)250 WRITE_HANDLER( fastfred_flip_screen_y_w )
251 {
252 	if (flip_screen_y != (data & 0x01))
253 	{
254 		flip_screen_y = data & 0x01;
255 
256 		tilemap_set_flip(bg_tilemap, (flip_screen_x ? TILEMAP_FLIPX : 0) | (flip_screen_y ? TILEMAP_FLIPY : 0));
257 	}
258 }
259 
260 
261 
262 /*************************************
263  *
264  *	Video update
265  *
266  *************************************/
267 
draw_sprites(struct mame_bitmap * bitmap,const struct rectangle * cliprect)268 static void draw_sprites(struct mame_bitmap *bitmap, const struct rectangle *cliprect)
269 {
270 	int offs;
271 
272 	for (offs = fastfred_spriteram_size - 4; offs >= 0; offs -= 4)
273 	{
274 		UINT8 code,sx,sy;
275 		int flipx,flipy;
276 
277 		sx = fastfred_spriteram[offs + 3];
278 		sy = 240 - fastfred_spriteram[offs];
279 
280 		if (fastfred_hardware_type == 3)
281 		{
282 			/* Imago*/
283 			code  = (fastfred_spriteram[offs + 1]) & 0x3f;
284 
285 			flipx = 0;
286 			flipy = 0;
287 		}
288 		else if (fastfred_hardware_type == 2)
289 		{
290 			/* Boggy 84*/
291 			code  =  fastfred_spriteram[offs + 1] & 0x7f;
292 			flipx =  0;
293 			flipy =  fastfred_spriteram[offs + 1] & 0x80;
294 		}
295 		else if (fastfred_hardware_type == 1)
296 		{
297 			/* Fly-Boy/Fast Freddie/Red Robin*/
298 			code  =  fastfred_spriteram[offs + 1] & 0x7f;
299 			flipx =  0;
300 			flipy = ~fastfred_spriteram[offs + 1] & 0x80;
301 		}
302 		else
303 		{
304 			/* Jump Coaster*/
305 			code  = (fastfred_spriteram[offs + 1] & 0x3f) | 0x40;
306 			flipx = ~fastfred_spriteram[offs + 1] & 0x40;
307 			flipy =  fastfred_spriteram[offs + 1] & 0x80;
308 		}
309 
310 
311 		if (flip_screen_x)
312 		{
313 			sx = 240 - sx;
314 			flipx = !flipx;
315 		}
316 		if (flip_screen_y)
317 		{
318 			sy = 240 - sy;
319 			flipy = !flipy;
320 		}
321 
322 		drawgfx(bitmap,Machine->gfx[1],
323 				code,
324 				colorbank | (fastfred_spriteram[offs + 2] & 0x07),
325 				flipx,flipy,
326 				sx,sy,
327 				flip_screen_x ? &spritevisibleareaflipx : &spritevisiblearea,TRANSPARENCY_PEN,0);
328 	}
329 }
330 
331 
VIDEO_UPDATE(fastfred)332 VIDEO_UPDATE( fastfred )
333 {
334 	tilemap_draw(bitmap,cliprect,bg_tilemap,0,0);
335 
336 	draw_sprites(bitmap, cliprect);
337 }
338 
339 
imago_get_tile_info_bg(int tile_index)340 static void imago_get_tile_info_bg(int tile_index)
341 {
342 	data8_t x = tile_index & 0x1f;
343 
344 	data16_t code = charbank * 0x100 + fastfred_videoram[tile_index];
345 	data8_t color = colorbank | (fastfred_attributesram[2 * x + 1] & 0x07);
346 
347 	SET_TILE_INFO(0, code, color, 0)
348 }
349 
imago_get_tile_info_fg(int tile_index)350 static void imago_get_tile_info_fg(int tile_index)
351 {
352 	int code = imago_fg_videoram[tile_index];
353 	SET_TILE_INFO(2, code, 2, 0)
354 }
355 
imago_get_tile_info_web(int tile_index)356 static void imago_get_tile_info_web(int tile_index)
357 {
358 	SET_TILE_INFO(3, tile_index & 0x1ff, 0, 0);
359 }
360 
WRITE_HANDLER(imago_fg_videoram_w)361 WRITE_HANDLER( imago_fg_videoram_w )
362 {
363 	if( imago_fg_videoram[offset] != data)
364 	{
365 		imago_fg_videoram[offset] = data;
366 		tilemap_mark_tile_dirty(fg_tilemap, offset);
367 	}
368 }
369 
WRITE_HANDLER(imago_charbank_w)370 WRITE_HANDLER( imago_charbank_w )
371 {
372 	if( charbank != data )
373 	{
374 		charbank = data;
375 		tilemap_mark_all_tiles_dirty(bg_tilemap);
376 	}
377 }
378 
VIDEO_START(imago)379 VIDEO_START( imago )
380 {
381 	web_tilemap = tilemap_create(imago_get_tile_info_web,tilemap_scan_rows,TILEMAP_OPAQUE,8,8,32,32);
382 	bg_tilemap  = tilemap_create(imago_get_tile_info_bg, tilemap_scan_rows,TILEMAP_TRANSPARENT,8,8,32,32);
383 	fg_tilemap  = tilemap_create(imago_get_tile_info_fg, tilemap_scan_rows,TILEMAP_TRANSPARENT,8,8,32,32);
384 
385 	if( !web_tilemap || !bg_tilemap || !fg_tilemap )
386 		return 1;
387 
388 	tilemap_set_transparent_pen(bg_tilemap, 0);
389 	tilemap_set_transparent_pen(fg_tilemap, 0);
390 
391 	/* the game has a galaxian starfield */
392 	galaxian_init_stars(256);
393 	galaxian_stars_on = 1;
394 
395 	/* web colors */
396 	palette_set_color(256+64+0, 0x50, 0x00, 0x00);
397 	palette_set_color(256+64+1, 0x00, 0x00, 0x00);
398 
399 	return 0;
400 }
401 
VIDEO_UPDATE(imago)402 VIDEO_UPDATE( imago )
403 {
404 	tilemap_draw(bitmap,cliprect,web_tilemap,0,0);
405 
406 	galaxian_draw_stars(bitmap);
407 
408 	tilemap_draw(bitmap,cliprect,bg_tilemap,0,0);
409 
410 	draw_sprites(bitmap, cliprect);
411 
412 	tilemap_draw(bitmap,cliprect,fg_tilemap,0,0);
413 }
414