1 /***************************************************************************
2
3 Crude Buster Video emulation - Bryan McPhail, mish@tendril.co.uk
4
5 ***************************************************************************/
6
7 #include "driver.h"
8 #include "vidhrdw/generic.h"
9
10 unsigned char *twocrude_pf1_data,*twocrude_pf2_data,*twocrude_pf3_data,*twocrude_pf4_data;
11
12 static struct tilemap *pf1_tilemap,*pf2_tilemap,*pf3_tilemap,*pf4_tilemap;
13 static unsigned char *gfx_base;
14 static int gfx_bank,twocrude_pri,flipscreen,last_flip;
15
16 static unsigned char twocrude_control_0[16];
17 static unsigned char twocrude_control_1[16];
18
19 unsigned char *twocrude_pf1_rowscroll,*twocrude_pf2_rowscroll;
20 unsigned char *twocrude_pf3_rowscroll,*twocrude_pf4_rowscroll;
21
22 static unsigned char *twocrude_spriteram;
23
24
25
26 /* Function for all 16x16 1024 by 512 layers */
back_scan(UINT32 col,UINT32 row,UINT32 num_cols,UINT32 num_rows)27 static UINT32 back_scan(UINT32 col,UINT32 row,UINT32 num_cols,UINT32 num_rows)
28 {
29 /* logical (col,row) -> memory offset */
30 return (col & 0x1f) + ((row & 0x1f) << 5) + ((col & 0x20) << 5);
31 }
32
get_back_tile_info(int tile_index)33 static void get_back_tile_info(int tile_index)
34 {
35 int tile,color;
36
37 tile=READ_WORD(&gfx_base[2*tile_index]);
38 color=tile >> 12;
39 tile=tile&0xfff;
40
41 SET_TILE_INFO(gfx_bank,tile,color)
42 }
43
44 /* 8x8 top layer */
get_fore_tile_info(int tile_index)45 static void get_fore_tile_info(int tile_index)
46 {
47 int tile=READ_WORD(&twocrude_pf1_data[2*tile_index]);
48 int color=tile >> 12;
49
50 tile=tile&0xfff;
51
52 SET_TILE_INFO(0,tile,color)
53 }
54
55 /******************************************************************************/
56
twocrude_vh_stop(void)57 void twocrude_vh_stop (void)
58 {
59 free(twocrude_spriteram);
60 }
61
twocrude_vh_start(void)62 int twocrude_vh_start(void)
63 {
64 pf2_tilemap = tilemap_create(get_back_tile_info,back_scan, TILEMAP_OPAQUE,16,16,64,32);
65 pf3_tilemap = tilemap_create(get_back_tile_info,back_scan, TILEMAP_TRANSPARENT,16,16,64,32);
66 pf4_tilemap = tilemap_create(get_back_tile_info,back_scan, TILEMAP_TRANSPARENT,16,16,64,32);
67 pf1_tilemap = tilemap_create(get_fore_tile_info,tilemap_scan_rows,TILEMAP_TRANSPARENT,8,8,64,32);
68
69 if (!pf1_tilemap || !pf2_tilemap || !pf3_tilemap || !pf4_tilemap)
70 return 1;
71
72 pf1_tilemap->transparent_pen = 0;
73 pf3_tilemap->transparent_pen = 0;
74 pf4_tilemap->transparent_pen = 0;
75
76 twocrude_spriteram = (unsigned char*)malloc(0x800);
77
78 return 0;
79 }
80
81 /******************************************************************************/
82
WRITE_HANDLER(twocrude_update_sprites_w)83 WRITE_HANDLER( twocrude_update_sprites_w )
84 {
85 memcpy(twocrude_spriteram,spriteram,0x800);
86 }
87
update_24bitcol(int offset)88 static void update_24bitcol(int offset)
89 {
90 int r,g,b;
91
92 r = (READ_WORD(&paletteram[offset]) >> 0) & 0xff;
93 g = (READ_WORD(&paletteram[offset]) >> 8) & 0xff;
94 b = (READ_WORD(&paletteram_2[offset]) >> 0) & 0xff;
95
96 palette_change_color(offset / 2,r,g,b);
97 }
98
WRITE_HANDLER(twocrude_palette_24bit_rg_w)99 WRITE_HANDLER( twocrude_palette_24bit_rg_w )
100 {
101 COMBINE_WORD_MEM(&paletteram[offset],data);
102 update_24bitcol(offset);
103 }
104
WRITE_HANDLER(twocrude_palette_24bit_b_w)105 WRITE_HANDLER( twocrude_palette_24bit_b_w )
106 {
107 COMBINE_WORD_MEM(&paletteram_2[offset],data);
108 update_24bitcol(offset);
109 }
110
READ_HANDLER(twocrude_palette_24bit_rg_r)111 READ_HANDLER( twocrude_palette_24bit_rg_r )
112 {
113 return READ_WORD(&paletteram[offset]);
114 }
115
READ_HANDLER(twocrude_palette_24bit_b_r)116 READ_HANDLER( twocrude_palette_24bit_b_r )
117 {
118 return READ_WORD(&paletteram_2[offset]);
119 }
120
121 /******************************************************************************/
122
twocrude_pri_w(int pri)123 void twocrude_pri_w(int pri)
124 {
125 twocrude_pri=pri;
126 }
127
WRITE_HANDLER(twocrude_pf1_data_w)128 WRITE_HANDLER( twocrude_pf1_data_w )
129 {
130 int oldword = READ_WORD(&twocrude_pf1_data[offset]);
131 int newword = COMBINE_WORD(oldword,data);
132
133 if (oldword != newword)
134 {
135 WRITE_WORD(&twocrude_pf1_data[offset],newword);
136 tilemap_mark_tile_dirty(pf1_tilemap,offset/2);
137 }
138 }
139
WRITE_HANDLER(twocrude_pf2_data_w)140 WRITE_HANDLER( twocrude_pf2_data_w )
141 {
142 int oldword = READ_WORD(&twocrude_pf2_data[offset]);
143 int newword = COMBINE_WORD(oldword,data);
144
145 if (oldword != newword)
146 {
147 WRITE_WORD(&twocrude_pf2_data[offset],newword);
148 tilemap_mark_tile_dirty(pf2_tilemap,offset/2);
149 }
150 }
151
WRITE_HANDLER(twocrude_pf3_data_w)152 WRITE_HANDLER( twocrude_pf3_data_w )
153 {
154 int oldword = READ_WORD(&twocrude_pf3_data[offset]);
155 int newword = COMBINE_WORD(oldword,data);
156
157 if (oldword != newword)
158 {
159 WRITE_WORD(&twocrude_pf3_data[offset],newword);
160 tilemap_mark_tile_dirty(pf3_tilemap,offset/2);
161 }
162 }
163
WRITE_HANDLER(twocrude_pf4_data_w)164 WRITE_HANDLER( twocrude_pf4_data_w )
165 {
166 int oldword = READ_WORD(&twocrude_pf4_data[offset]);
167 int newword = COMBINE_WORD(oldword,data);
168
169 if (oldword != newword)
170 {
171 WRITE_WORD(&twocrude_pf4_data[offset],newword);
172 tilemap_mark_tile_dirty(pf4_tilemap,offset/2);
173 }
174 }
175
WRITE_HANDLER(twocrude_control_0_w)176 WRITE_HANDLER( twocrude_control_0_w )
177 {
178 COMBINE_WORD_MEM(&twocrude_control_0[offset],data);
179 }
180
WRITE_HANDLER(twocrude_control_1_w)181 WRITE_HANDLER( twocrude_control_1_w )
182 {
183 COMBINE_WORD_MEM(&twocrude_control_1[offset],data);
184 }
185
WRITE_HANDLER(twocrude_pf1_rowscroll_w)186 WRITE_HANDLER( twocrude_pf1_rowscroll_w )
187 {
188 COMBINE_WORD_MEM(&twocrude_pf1_rowscroll[offset],data);
189 }
190
WRITE_HANDLER(twocrude_pf2_rowscroll_w)191 WRITE_HANDLER( twocrude_pf2_rowscroll_w )
192 {
193 COMBINE_WORD_MEM(&twocrude_pf2_rowscroll[offset],data);
194 }
195
WRITE_HANDLER(twocrude_pf3_rowscroll_w)196 WRITE_HANDLER( twocrude_pf3_rowscroll_w )
197 {
198 COMBINE_WORD_MEM(&twocrude_pf3_rowscroll[offset],data);
199 }
200
WRITE_HANDLER(twocrude_pf4_rowscroll_w)201 WRITE_HANDLER( twocrude_pf4_rowscroll_w )
202 {
203 COMBINE_WORD_MEM(&twocrude_pf4_rowscroll[offset],data);
204 }
205
206 /******************************************************************************/
207
twocrude_update_palette(void)208 static void twocrude_update_palette(void)
209 {
210 int offs,color,i,pal_base;
211 int colmask[32];
212
213 palette_init_used_colors();
214
215 /* Sprites */
216 pal_base = Machine->drv->gfxdecodeinfo[4].color_codes_start;
217 for (color = 0;color < 32;color++) colmask[color] = 0;
218 for (offs = 0;offs < 0x800;offs += 8)
219 {
220 int x,y,sprite,multi;
221
222 sprite = READ_WORD (&twocrude_spriteram[offs+2]) & 0x7fff;
223 if (!sprite) continue;
224
225 y = READ_WORD(&twocrude_spriteram[offs]);
226 x = READ_WORD(&twocrude_spriteram[offs+4]);
227 color = (x >> 9) &0x1f;
228
229 multi = (1 << ((y & 0x0600) >> 9)) - 1; /* 1x, 2x, 4x, 8x height */
230 sprite &= ~multi;
231
232 while (multi >= 0)
233 {
234 colmask[color] |= Machine->gfx[4]->pen_usage[sprite + multi];
235 multi--;
236 }
237 }
238
239 for (color = 0;color < 16;color++)
240 {
241 for (i = 1;i < 16;i++)
242 {
243 if (colmask[color] & (1 << i))
244 palette_used_colors[pal_base + 16 * color + i] = PALETTE_COLOR_USED;
245 }
246 }
247
248 for (color = 16;color < 32;color++)
249 {
250 for (i = 1;i < 16;i++)
251 {
252 if (colmask[color] & (1 << i))
253 palette_used_colors[256 + 1024 + 16 * (color-16) + i] = PALETTE_COLOR_USED;
254 }
255 }
256
257 if (palette_recalc())
258 tilemap_mark_all_pixels_dirty(ALL_TILEMAPS);
259 }
260
twocrude_drawsprites(struct osd_bitmap * bitmap,int pri)261 static void twocrude_drawsprites(struct osd_bitmap *bitmap, int pri)
262 {
263 int offs;
264
265 for (offs = 0;offs < 0x800;offs += 8)
266 {
267 int x,y,sprite,colour,multi,fx,fy,inc,flash,mult;
268
269 sprite = READ_WORD (&twocrude_spriteram[offs+2]) & 0x7fff;
270 if (!sprite) continue;
271
272 y = READ_WORD(&twocrude_spriteram[offs]);
273 x = READ_WORD(&twocrude_spriteram[offs+4]);
274
275 if ((y&0x8000) && pri==1) continue;
276 if (!(y&0x8000) && pri==0) continue;
277
278 colour = (x >> 9) &0xf;
279 if (x&0x2000) colour+=64;
280
281 flash=y&0x1000;
282 if (flash && (cpu_getcurrentframe() & 1)) continue;
283
284 fx = y & 0x2000;
285 fy = y & 0x4000;
286 multi = (1 << ((y & 0x0600) >> 9)) - 1; /* 1x, 2x, 4x, 8x height */
287
288 x = x & 0x01ff;
289 y = y & 0x01ff;
290 if (x >= 256) x -= 512;
291 if (y >= 256) y -= 512;
292 x = 240 - x;
293 y = 240 - y;
294
295 if (x>256) continue; /* Speedup */
296
297 sprite &= ~multi;
298 if (fy)
299 inc = -1;
300 else
301 {
302 sprite += multi;
303 inc = 1;
304 }
305
306 if (flipscreen) {
307 y=240-y;
308 x=240-x;
309 if (fx) fx=0; else fx=1;
310 if (fy) fy=0; else fy=1;
311 mult=16;
312 }
313 else mult=-16;
314
315 while (multi >= 0)
316 {
317 drawgfx(bitmap,Machine->gfx[4],
318 sprite - multi * inc,
319 colour,
320 fx,fy,
321 x,y + mult * multi,
322 &Machine->visible_area,TRANSPARENCY_PEN,0);
323
324 multi--;
325 }
326 }
327 }
328
329 /******************************************************************************/
330
twocrude_vh_screenrefresh(struct osd_bitmap * bitmap,int full_refresh)331 void twocrude_vh_screenrefresh(struct osd_bitmap *bitmap,int full_refresh)
332 {
333 int offs;
334 int pf23_control,pf14_control;
335
336 /* Update flipscreen */
337 if (READ_WORD(&twocrude_control_1[0])&0x80)
338 flipscreen=0;
339 else
340 flipscreen=1;
341
342 if (last_flip!=flipscreen)
343 tilemap_set_flip(ALL_TILEMAPS,flipscreen ? (TILEMAP_FLIPY | TILEMAP_FLIPX) : 0);
344 last_flip=flipscreen;
345
346 pf23_control=READ_WORD (&twocrude_control_0[0xc]);
347 pf14_control=READ_WORD (&twocrude_control_1[0xc]);
348
349 /* Background - Rowscroll enable */
350 if (pf23_control&0x4000) {
351 int scrollx=READ_WORD(&twocrude_control_0[6]),rows;
352 tilemap_set_scroll_cols(pf2_tilemap,1);
353 tilemap_set_scrolly( pf2_tilemap,0, READ_WORD(&twocrude_control_0[8]) );
354
355 /* Several different rowscroll styles! */
356 switch ((READ_WORD (&twocrude_control_0[0xa])>>11)&7) {
357 case 0: rows=512; break;/* Every line of 512 height bitmap */
358 case 1: rows=256; break;
359 case 2: rows=128; break;
360 case 3: rows=64; break;
361 case 4: rows=32; break;
362 case 5: rows=16; break;
363 case 6: rows=8; break;
364 case 7: rows=4; break;
365 default: rows=1; break;
366 }
367
368 tilemap_set_scroll_rows(pf2_tilemap,rows);
369 for (offs = 0;offs < rows;offs++)
370 tilemap_set_scrollx( pf2_tilemap,offs, scrollx + READ_WORD(&twocrude_pf2_rowscroll[2*offs]) );
371 }
372 else {
373 tilemap_set_scroll_rows(pf2_tilemap,1);
374 tilemap_set_scroll_cols(pf2_tilemap,1);
375 tilemap_set_scrollx( pf2_tilemap,0, READ_WORD(&twocrude_control_0[6]) );
376 tilemap_set_scrolly( pf2_tilemap,0, READ_WORD(&twocrude_control_0[8]) );
377 }
378
379 /* Playfield 3 */
380 if (pf23_control&0x40) { /* Rowscroll */
381 int scrollx=READ_WORD(&twocrude_control_0[2]),rows;
382 tilemap_set_scroll_cols(pf3_tilemap,1);
383 tilemap_set_scrolly( pf3_tilemap,0, READ_WORD(&twocrude_control_0[4]) );
384
385 /* Several different rowscroll styles! */
386 switch ((READ_WORD (&twocrude_control_0[0xa])>>3)&7) {
387 case 0: rows=512; break;/* Every line of 512 height bitmap */
388 case 1: rows=256; break;
389 case 2: rows=128; break;
390 case 3: rows=64; break;
391 case 4: rows=32; break;
392 case 5: rows=16; break;
393 case 6: rows=8; break;
394 case 7: rows=4; break;
395 default: rows=1; break;
396 }
397
398 tilemap_set_scroll_rows(pf3_tilemap,rows);
399 for (offs = 0;offs < rows;offs++)
400 tilemap_set_scrollx( pf3_tilemap,offs, scrollx + READ_WORD(&twocrude_pf3_rowscroll[2*offs]) );
401 }
402 else if (pf23_control&0x20) { /* Colscroll */
403 int scrolly=READ_WORD(&twocrude_control_0[4]),cols;
404 tilemap_set_scroll_rows(pf3_tilemap,1);
405 tilemap_set_scrollx( pf3_tilemap,0, READ_WORD(&twocrude_control_0[2]) );
406
407 /* Several different colscroll styles! */
408 switch ((READ_WORD (&twocrude_control_0[0xa])>>0)&7) {
409 case 0: cols=64; break;
410 case 1: cols=32; break;
411 case 2: cols=16; break;
412 case 3: cols=8; break;
413 case 4: cols=4; break;
414 case 5: cols=2; break;
415 case 6: cols=1; break;
416 case 7: cols=1; break;
417 default: cols=1; break;
418 }
419
420 tilemap_set_scroll_cols(pf3_tilemap,cols);
421 for (offs = 0;offs < cols;offs++)
422 tilemap_set_scrolly( pf3_tilemap,offs,scrolly + READ_WORD(&twocrude_pf3_rowscroll[2*offs+0x400]) );
423 }
424 else {
425 tilemap_set_scroll_rows(pf3_tilemap,1);
426 tilemap_set_scroll_cols(pf3_tilemap,1);
427 tilemap_set_scrollx( pf3_tilemap,0, READ_WORD(&twocrude_control_0[2]) );
428 tilemap_set_scrolly( pf3_tilemap,0, READ_WORD(&twocrude_control_0[4]) );
429 }
430
431 /* Playfield 4 - Rowscroll enable */
432 if (pf14_control&0x4000) {
433 int scrollx=READ_WORD(&twocrude_control_1[6]),rows;
434 tilemap_set_scroll_cols(pf4_tilemap,1);
435 tilemap_set_scrolly( pf4_tilemap,0, READ_WORD(&twocrude_control_1[8]) );
436
437 /* Several different rowscroll styles! */
438 switch ((READ_WORD (&twocrude_control_1[0xa])>>11)&7) {
439 case 0: rows=512; break;/* Every line of 512 height bitmap */
440 case 1: rows=256; break;
441 case 2: rows=128; break;
442 case 3: rows=64; break;
443 case 4: rows=32; break;
444 case 5: rows=16; break;
445 case 6: rows=8; break;
446 case 7: rows=4; break;
447 default: rows=1; break;
448 }
449
450 tilemap_set_scroll_rows(pf4_tilemap,rows);
451 for (offs = 0;offs < rows;offs++)
452 tilemap_set_scrollx( pf4_tilemap,offs, scrollx + READ_WORD(&twocrude_pf4_rowscroll[2*offs]) );
453 }
454 else {
455 tilemap_set_scroll_rows(pf4_tilemap,1);
456 tilemap_set_scroll_cols(pf4_tilemap,1);
457 tilemap_set_scrollx( pf4_tilemap,0, READ_WORD(&twocrude_control_1[6]) );
458 tilemap_set_scrolly( pf4_tilemap,0, READ_WORD(&twocrude_control_1[8]) );
459 }
460
461 /* Playfield 1 */
462 if (pf14_control&0x40) { /* Rowscroll */
463 int scrollx=READ_WORD(&twocrude_control_1[2]),rows;
464 tilemap_set_scroll_cols(pf1_tilemap,1);
465 tilemap_set_scrolly( pf1_tilemap,0, READ_WORD(&twocrude_control_1[4]) );
466
467 /* Several different rowscroll styles! */
468 switch ((READ_WORD (&twocrude_control_1[0xa])>>3)&7) {
469 case 0: rows=256; break;/* Every line of 256 height bitmap */
470 case 1: rows=128; break;
471 case 2: rows=64; break;
472 case 3: rows=32; break;
473 case 4: rows=16; break;
474 case 5: rows=8; break;
475 case 6: rows=4; break;
476 case 7: rows=2; break;
477 default: rows=1; break;
478 }
479
480 tilemap_set_scroll_rows(pf1_tilemap,rows);
481 for (offs = 0;offs < rows;offs++)
482 tilemap_set_scrollx( pf1_tilemap,offs, scrollx + READ_WORD(&twocrude_pf1_rowscroll[2*offs]) );
483 }
484 else {
485 tilemap_set_scroll_rows(pf1_tilemap,1);
486 tilemap_set_scroll_cols(pf1_tilemap,1);
487 tilemap_set_scrollx( pf1_tilemap,0, READ_WORD(&twocrude_control_1[2]) );
488 tilemap_set_scrolly( pf1_tilemap,0, READ_WORD(&twocrude_control_1[4]) );
489 }
490
491 /* Update playfields */
492 gfx_bank=1;
493 gfx_base=twocrude_pf2_data;
494 tilemap_update(pf2_tilemap);
495
496 gfx_bank=2;
497 gfx_base=twocrude_pf3_data;
498 tilemap_update(pf3_tilemap);
499
500 gfx_bank=3;
501 gfx_base=twocrude_pf4_data;
502 tilemap_update(pf4_tilemap);
503 tilemap_update(pf1_tilemap);
504 twocrude_update_palette();
505
506 /* Draw playfields & sprites */
507 tilemap_render(ALL_TILEMAPS);
508 tilemap_draw(bitmap,pf2_tilemap,0);
509 twocrude_drawsprites(bitmap,0);
510
511 if (twocrude_pri) {
512 tilemap_draw(bitmap,pf4_tilemap,0);
513 tilemap_draw(bitmap,pf3_tilemap,0);
514 }
515 else {
516 tilemap_draw(bitmap,pf3_tilemap,0);
517 tilemap_draw(bitmap,pf4_tilemap,0);
518 }
519
520 twocrude_drawsprites(bitmap,1);
521 tilemap_draw(bitmap,pf1_tilemap,0);
522 }
523