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