1 /***************************************************************************
2 
3   vidhrdw.c
4 
5   Functions to emulate the video hardware of the machine.
6 
7   CHANGES:
8   MAB 05 MAR 99 - changed overlay support to use artwork functions
9   AAT 12 MAY 02 - rewrote Ripcord and added pixel-wise collision
10 
11 ***************************************************************************/
12 
13 #include "driver.h"
14 #include "vidhrdw/generic.h"
15 #include "artwork.h"
16 
17 static int clown_x=0,clown_y=0,clown_z=0;
18 
19 static struct tilemap *bg_tilemap;
20 
21 /***************************************************************************
22 ***************************************************************************/
23 
24 static const char *circus_sample_names[] =
25 {
26 	"*circus",
27 	"pop.wav",
28 	"miss.wav",
29 	"bounce.wav",
30 	0       /* end of array */
31 };
32 
33 struct Samplesinterface circus_samples_interface =
34 {
35 	3,	/* 3 channels */
36 	25,	/* volume */
37 	circus_sample_names
38 };
39 
WRITE_HANDLER(circus_videoram_w)40 WRITE_HANDLER( circus_videoram_w )
41 {
42 	if (videoram[offset] != data)
43 	{
44 		videoram[offset] = data;
45 		tilemap_mark_tile_dirty(bg_tilemap, offset);
46 	}
47 }
48 
WRITE_HANDLER(circus_clown_x_w)49 WRITE_HANDLER( circus_clown_x_w )
50 {
51 	clown_x = 240-data;
52 }
53 
WRITE_HANDLER(circus_clown_y_w)54 WRITE_HANDLER( circus_clown_y_w )
55 {
56 	clown_y = 240-data;
57 }
58 
59 /* This register controls the clown image currently displayed */
60 /* and also is used to enable the amplifier and trigger the   */
61 /* discrete circuitry that produces sound effects and music   */
62 
WRITE_HANDLER(circus_clown_z_w)63 WRITE_HANDLER( circus_clown_z_w )
64 {
65 	clown_z = (data & 0x0f);
66 *(memory_region(REGION_CPU1)+0x8000)=data; logerror("Z:%02x\n",data); //DEBUG
67 	/* Bits 4-6 enable/disable trigger different events */
68 	/* descriptions are based on Circus schematics      */
69 
70 	switch ((data & 0x70) >> 4)
71 	{
72 		case 0 : /* All Off */
73 			DAC_data_w (0,0);
74 			break;
75 
76 		case 1 : /* Music */
77 			DAC_data_w (0,0x7f);
78 			break;
79 
80 		case 2 : /* Pop */
81 			sample_start (0, 0, 0);
82 			break;
83 
84 		case 3 : /* Normal Video */
85 			break;
86 
87 		case 4 : /* Miss */
88 			sample_start (1, 1, 0);
89 			break;
90 
91 		case 5 : /* Invert Video */
92 			break;
93 
94 		case 6 : /* Bounce */
95 			sample_start (2, 2, 0);
96 			break;
97 
98 		case 7 : /* Don't Know */
99 			break;
100 	};
101 
102 	/* Bit 7 enables amplifier (1 = on) */
103 
104 //  logerror("clown Z = %02x\n",data);
105 }
106 
get_bg_tile_info(int tile_index)107 static void get_bg_tile_info(int tile_index)
108 {
109 	int code = videoram[tile_index];
110 
111 	SET_TILE_INFO(0, code, 0, 0)
112 }
113 
VIDEO_START(circus)114 VIDEO_START( circus )
115 {
116 	bg_tilemap = tilemap_create(get_bg_tile_info, tilemap_scan_rows,
117 		TILEMAP_OPAQUE, 8, 8, 32, 32);
118 
119 	if ( !bg_tilemap )
120 		return 1;
121 
122 	return 0;
123 }
124 
draw_line(struct mame_bitmap * bitmap,int x1,int y1,int x2,int y2,int dotted)125 static void draw_line(struct mame_bitmap *bitmap, int x1, int y1, int x2, int y2, int dotted)
126 {
127 	/* Draws horizontal and Vertical lines only! */
128 	int col = Machine->pens[1];
129 
130 	int count, skip;
131 
132 	/* Draw the Line */
133 
134 	if (dotted > 0)
135 		skip = 2;
136 	else
137 		skip = 1;
138 
139 	if (x1 == x2)
140 	{
141 		for (count = y2; count >= y1; count -= skip)
142 		{
143 			plot_pixel(bitmap, x1, count, col);
144 		}
145 	}
146 	else
147 	{
148 		for (count = x2; count >= x1; count -= skip)
149 		{
150 			plot_pixel(bitmap, count, y1, col);
151 		}
152 	}
153 }
154 
draw_robot_box(struct mame_bitmap * bitmap,int x,int y)155 static void draw_robot_box (struct mame_bitmap *bitmap, int x, int y)
156 {
157 	/* Box */
158 
159 	int ex = x + 24;
160 	int ey = y + 26;
161 
162 	draw_line(bitmap,x,y,ex,y,0);       /* Top */
163 	draw_line(bitmap,x,ey,ex,ey,0);     /* Bottom */
164 	draw_line(bitmap,x,y,x,ey,0);       /* Left */
165 	draw_line(bitmap,ex,y,ex,ey,0);     /* Right */
166 
167 	/* Score Grid */
168 
169 	ey = y + 10;
170 	draw_line(bitmap,x+8,ey,ex,ey,0);   /* Horizontal Divide Line */
171 	draw_line(bitmap,x+8,y,x+8,ey,0);
172 	draw_line(bitmap,x+16,y,x+16,ey,0);
173 }
174 
circus_draw_fg(struct mame_bitmap * bitmap)175 static void circus_draw_fg( struct mame_bitmap *bitmap )
176 {
177 	/* The sync generator hardware is used to   */
178 	/* draw the border and diving boards        */
179 
180 	draw_line (bitmap,0,18,255,18,0);
181 	draw_line (bitmap,0,249,255,249,1);
182 	draw_line (bitmap,0,18,0,248,0);
183 	draw_line (bitmap,247,18,247,248,0);
184 
185 	draw_line (bitmap,0,137,17,137,0);
186 	draw_line (bitmap,231,137,248,137,0);
187 	draw_line (bitmap,0,193,17,193,0);
188 	draw_line (bitmap,231,193,248,193,0);
189 
190 	drawgfx(bitmap,Machine->gfx[1],
191 			clown_z,
192 			0,
193 			0,0,
194 			clown_y,clown_x,
195 			&Machine->visible_area,TRANSPARENCY_PEN,0);
196 }
197 
VIDEO_UPDATE(circus)198 VIDEO_UPDATE( circus )
199 {
200 	tilemap_draw(bitmap, &Machine->visible_area, bg_tilemap, 0, 0);
201 	circus_draw_fg(bitmap);
202 }
203 
robotbwl_draw_scoreboard(struct mame_bitmap * bitmap)204 static void robotbwl_draw_scoreboard( struct mame_bitmap *bitmap )
205 {
206 	int offs;
207 
208 	/* The sync generator hardware is used to   */
209 	/* draw the bowling alley & scorecards      */
210 
211 	for(offs=15;offs<=63;offs+=24)
212 	{
213 		draw_robot_box(bitmap, offs, 31);
214 		draw_robot_box(bitmap, offs, 63);
215 		draw_robot_box(bitmap, offs, 95);
216 
217 		draw_robot_box(bitmap, offs+152, 31);
218 		draw_robot_box(bitmap, offs+152, 63);
219 		draw_robot_box(bitmap, offs+152, 95);
220 	}
221 
222 	draw_robot_box(bitmap, 39, 127);                  /* 10th Frame */
223 	draw_line(bitmap, 39,137,47,137,0);          /* Extra digit box */
224 
225 	draw_robot_box(bitmap, 39+152, 127);
226 	draw_line(bitmap, 39+152,137,47+152,137,0);
227 }
228 
robotbwl_draw_bowling_alley(struct mame_bitmap * bitmap)229 static void robotbwl_draw_bowling_alley( struct mame_bitmap *bitmap )
230 {
231 	draw_line(bitmap, 103,17,103,205,0);
232 	draw_line(bitmap, 111,17,111,203,1);
233 	draw_line(bitmap, 152,17,152,205,0);
234 	draw_line(bitmap, 144,17,144,203,1);
235 }
236 
robotbwl_draw_ball(struct mame_bitmap * bitmap)237 static void robotbwl_draw_ball( struct mame_bitmap *bitmap )
238 {
239 	drawgfx(bitmap,Machine->gfx[1],
240 			clown_z,
241 			0,
242 			0,0,
243 			clown_y+8,clown_x+8, /* Y is horizontal position */
244 			&Machine->visible_area,TRANSPARENCY_PEN,0);
245 }
246 
VIDEO_UPDATE(robotbwl)247 VIDEO_UPDATE( robotbwl )
248 {
249 	tilemap_draw(bitmap, &Machine->visible_area, bg_tilemap, 0, 0);
250 	robotbwl_draw_scoreboard(bitmap);
251 	robotbwl_draw_bowling_alley(bitmap);
252 	robotbwl_draw_ball(bitmap);
253 }
254 
crash_draw_car(struct mame_bitmap * bitmap)255 static void crash_draw_car( struct mame_bitmap *bitmap )
256 {
257 	drawgfx(bitmap,Machine->gfx[1],
258 		clown_z,
259 		0,
260 		0,0,
261 		clown_y,clown_x, /* Y is horizontal position */
262 		&Machine->visible_area,TRANSPARENCY_PEN,0);
263 }
264 
VIDEO_UPDATE(crash)265 VIDEO_UPDATE( crash )
266 {
267 	tilemap_draw(bitmap, &Machine->visible_area, bg_tilemap, 0, 0);
268 	crash_draw_car(bitmap);
269 }
270 
ripcord_draw_skydiver(struct mame_bitmap * bitmap)271 static void ripcord_draw_skydiver( struct mame_bitmap *bitmap )
272 {
273 	const struct GfxElement *gfx;
274 	const struct rectangle *clip;
275 	pen_t *pal_ptr;
276 	UINT8  *src_lineptr, *src_pixptr;
277 	UINT16 *dst_lineptr, *dst_lineend;
278 	unsigned int code, color;
279 	int sx, sy;
280 	int src_pitch, dst_width, dst_height, dst_pitch, dst_pixoffs, dst_pixend;
281 	int collision, eax, edx;
282 
283 	gfx = Machine->gfx[0];
284 	clip = &Machine->visible_area;
285 
286 	code = clown_z;
287 	color = 0;
288 
289 	sx = clown_y;
290 	sy = clown_x - 1;
291 	dst_width = 16;
292 	dst_height = 16;
293 	edx = 1;
294 
295 	gfx = Machine->gfx[1];
296 	pal_ptr = gfx->colortable + color * gfx->color_granularity;
297 	src_lineptr = gfx->gfxdata + code * gfx->char_modulo;
298 	src_pitch = gfx->line_modulo;
299 	dst_pitch = bitmap->rowpixels;
300 
301 	if (Machine->orientation & ORIENTATION_FLIP_X)
302 	{
303 		sx = bitmap->width - sx;
304 		dst_width = -dst_width;
305 		edx = -edx;
306 	}
307 
308 	if (Machine->orientation & ORIENTATION_FLIP_Y)
309 	{
310 		sy = bitmap->height - sy;
311 		dst_pitch = -dst_pitch;
312 	}
313 
314 	dst_lineptr = (UINT16*)bitmap->line[sy];
315 	dst_pixend = (sx + dst_width) & 0xff;
316 	dst_lineend = dst_lineptr + dst_pitch * dst_height;
317 
318 	// draw sky diver and check collision on a pixel basis
319 	collision = 0;
320 	do
321 	{
322 		src_pixptr = src_lineptr;
323 		dst_pixoffs = sx;
324 
325 		do
326 		{
327 			eax = *src_pixptr;
328 			src_pixptr ++;
329 			if (eax)
330 			{
331 				eax = pal_ptr[eax];
332 				collision |= dst_lineptr[dst_pixoffs];
333 				dst_lineptr[dst_pixoffs] = eax;
334 			}
335 			dst_pixoffs += edx;
336 
337 		} while((dst_pixoffs &= 0xff) != dst_pixend);
338 
339 		src_lineptr += src_pitch;
340 
341 	} while((dst_lineptr += dst_pitch) != dst_lineend);
342 
343 	// report collision only when the character is not blank and within display area
344 	if (collision && code!=0xf && clown_x>0 && clown_x<240 && clown_y>-12 && clown_y<240)
345 	{
346 		cpu_set_irq_line(0, 0, ASSERT_LINE); // interrupt accuracy is critical in Ripcord
347 		cpu_set_irq_line(0, 0, CLEAR_LINE);
348 	}
349 }
350 
VIDEO_UPDATE(ripcord)351 VIDEO_UPDATE( ripcord )
352 {
353 	tilemap_draw(bitmap, &Machine->visible_area, bg_tilemap, 0, 0);
354 	ripcord_draw_skydiver(bitmap);
355 }
356