1 #include "driver.h"
2 #include "state.h"
3 #include "vidhrdw/generic.h"
4 #include "namcos2.h" /* for game-specific hacks */
5 #include "namcoic.h"
6
7 static data16_t mSpritePos[4];
8
WRITE16_HANDLER(namco_spritepos16_w)9 WRITE16_HANDLER( namco_spritepos16_w )
10 {
11 COMBINE_DATA( &mSpritePos[offset] );
12 }
READ16_HANDLER(namco_spritepos16_r)13 READ16_HANDLER( namco_spritepos16_r )
14 {
15 return mSpritePos[offset];
16 }
17
WRITE32_HANDLER(namco_spritepos32_w)18 WRITE32_HANDLER( namco_spritepos32_w )
19 {
20 data32_t v;
21 offset *= 2;
22 v = (mSpritePos[offset]<<16)|mSpritePos[offset+1];
23 COMBINE_DATA( &v );
24 mSpritePos[offset+0] = v>>16;
25 mSpritePos[offset+1] = v&0xffff;
26 }
READ32_HANDLER(namco_spritepos32_r)27 READ32_HANDLER( namco_spritepos32_r )
28 {
29 offset *= 2;
30 return (mSpritePos[offset]<<16)|mSpritePos[offset+1];
31 }
32
33 static INLINE data8_t
nth_byte16(const data16_t * pSource,int which)34 nth_byte16( const data16_t *pSource, int which )
35 {
36 data16_t data = pSource[which/2];
37 if( which&1 )
38 {
39 return data&0xff;
40 }
41 else
42 {
43 return data>>8;
44 }
45 } /* nth_byte16 */
46
47 /* nth_word32 is a general-purpose utility function, which allows us to
48 * read from 32-bit aligned memory as if it were an array of 16 bit words.
49 */
50 static INLINE data16_t
nth_word32(const data32_t * pSource,int which)51 nth_word32( const data32_t *pSource, int which )
52 {
53 data32_t data = pSource[which/2];
54 if( which&1 )
55 {
56 return data&0xffff;
57 }
58 else
59 {
60 return data>>16;
61 }
62 } /* nth_word32 */
63
64 /* nth_byte32 is a general-purpose utility function, which allows us to
65 * read from 32-bit aligned memory as if it were an array of bytes.
66 */
67 static INLINE data8_t
nth_byte32(const data32_t * pSource,int which)68 nth_byte32( const data32_t *pSource, int which )
69 {
70 data32_t data = pSource[which/4];
71 switch( which&3 )
72 {
73 case 0: return data>>24;
74 case 1: return (data>>16)&0xff;
75 case 2: return (data>>8)&0xff;
76 default: return data&0xff;
77 }
78 } /* nth_byte32 */
79
80 /**************************************************************************************************************/
81
82 static int (*mpCodeToTile)( int code ); /* sprite banking callback */
83 static int mGfxC355; /* gfx bank for sprites */
84 static int mPalXOR; /* XOR'd with palette select register; needed for System21 */
85
86 /**
87 * 0x00000 sprite attr (page0)
88 * 0x02000 sprite list (page0)
89 * 0x02400 window attributes
90 * 0x04000 format
91 * 0x08000 tile
92 * 0x10000 sprite attr (page1)
93 * 0x14000 sprite list (page1)
94 */
95 static void
draw_spriteC355(int page,struct mame_bitmap * bitmap,const struct rectangle * cliprect,const data16_t * pSource,int pri,int zpos)96 draw_spriteC355( int page, struct mame_bitmap *bitmap, const struct rectangle *cliprect, const data16_t *pSource, int pri, int zpos )
97 {
98 unsigned screen_height_remaining, screen_width_remaining;
99 unsigned source_height_remaining, source_width_remaining;
100 INT32 hpos,vpos;
101 data16_t hsize,vsize;
102 data16_t palette;
103 data16_t linkno;
104 data16_t offset;
105 data16_t format;
106 int tile_index;
107 int num_cols,num_rows;
108 int dx,dy;
109 int row,col;
110 int sx,sy,tile;
111 int flipx,flipy;
112 UINT32 zoomx, zoomy;
113 int tile_screen_width;
114 int tile_screen_height;
115 const data16_t *spriteformat16 = &spriteram16[0x4000/2];
116 const data16_t *spritetile16 = &spriteram16[0x8000/2];
117 int color;
118
119 struct rectangle clip;
120
121 /**
122 * ----xxxx-------- window select
123 * --------xxxx---- priority
124 * ------------xxxx palette select
125 */
126 palette = pSource[6];
127 switch( namcos2_gametype )
128 {
129 case NAMCONB2_OUTFOXIES:
130 case NAMCONB2_MACH_BREAKERS:
131 case NAMCOS2_SUZUKA_8_HOURS_2:
132 case NAMCOS2_SUZUKA_8_HOURS:
133 case NAMCOS2_LUCKY_AND_WILD:
134 if( pri != ((palette>>5)&7) ) return;
135 break;
136
137 default:
138 if( pri != ((palette>>4)&0x7) ) return;
139 break;
140 }
141
142 linkno = pSource[0]; /* LINKNO */
143 offset = pSource[1]; /* OFFSET */
144 hpos = pSource[2]; /* HPOS 0x000..0x7ff (signed) */
145 vpos = pSource[3]; /* VPOS 0x000..0x7ff (signed) */
146 hsize = pSource[4]; /* HSIZE max 0x3ff pixels */
147 vsize = pSource[5]; /* VSIZE max 0x3ff pixels */
148 /* pSource[6] contains priority/palette */
149 /* pSource[7] is used in Lucky & Wild, possibly for sprite-road priority */
150
151 if( linkno*4>=0x4000/2 ) return; /* avoid garbage memory read */
152
153 switch( namcos2_gametype )
154 {
155 case NAMCOS21_SOLVALOU: /* hack */
156 hpos -= 0x80;
157 vpos -= 0x40;
158 clip = Machine->visible_area;
159 break;
160
161 case NAMCOS21_CYBERSLED: /* hack */
162 hpos -= 0x110;
163 vpos -= 2+32;
164 clip = Machine->visible_area;
165 break;
166
167 case NAMCOS21_AIRCOMBAT: /* hack */
168 vpos -= 0x22;
169 hpos -= 0x02;
170 clip = Machine->visible_area;
171 break;
172
173 case NAMCOS21_STARBLADE: /* hack */
174 if( page )
175 {
176 hpos -= 0x80;
177 vpos -= 0x20;
178 }
179 clip = Machine->visible_area;
180 break;
181
182 case NAMCONB1_NEBULRAY:
183 case NAMCONB1_GUNBULET:
184 case NAMCONB1_GSLGR94U:
185 case NAMCONB1_SWS95:
186 case NAMCONB1_SWS96:
187 case NAMCONB1_SWS97:
188 case NAMCONB2_OUTFOXIES:
189 case NAMCONB2_MACH_BREAKERS:
190 case NAMCONB1_VSHOOT:
191 case NAMCOS2_SUZUKA_8_HOURS_2:
192 case NAMCOS2_SUZUKA_8_HOURS:
193 case NAMCOS2_LUCKY_AND_WILD:
194 case NAMCOS2_STEEL_GUNNER_2:
195 default:
196 {
197 int dh = mSpritePos[1];
198 int dv = mSpritePos[0];
199 const data16_t *pWinAttr = &spriteram16[0x2400/2+((palette>>8)&0xf)*4];
200
201 dh &= 0x1ff; if( dh&0x100 ) dh |= ~0x1ff;
202 dv &= 0x1ff; if( dv&0x100 ) dv |= ~0x1ff;
203 vpos&=0x7ff; if( vpos&0x400 ) vpos |= ~0x7ff;
204 hpos&=0x7ff; if( hpos&0x400 ) hpos |= ~0x7ff;
205 hpos += -0x26 - dh;
206 vpos += -0x19 - dv;
207 /* 0026 0145 0019 00f8 (lucky&wild)*/
208 /* 0025 0145 0019 00f8 (point blank)*/
209 clip.min_x = pWinAttr[0] - 0x26 - dh;
210 clip.max_x = pWinAttr[1] - 0x26 - dh;
211 clip.min_y = pWinAttr[2] - 0x19 - dv;
212 clip.max_y = pWinAttr[3] - 0x19 - dv;
213 if( clip.min_x < cliprect->min_x ) clip.min_x = cliprect->min_x;
214 if( clip.min_y < cliprect->min_y ) clip.min_y = cliprect->min_y;
215 if( clip.max_x > cliprect->max_x ) clip.max_x = cliprect->max_x;
216 if( clip.max_y > cliprect->max_y ) clip.max_y = cliprect->max_y;
217 }
218 break;
219 }
220 tile_index = spriteformat16[linkno*4+0];
221 format = spriteformat16[linkno*4+1];
222 dx = spriteformat16[linkno*4+2];
223 dy = spriteformat16[linkno*4+3];
224 num_cols = (format>>4)&0xf;
225 num_rows = (format)&0xf;
226
227 if( num_cols == 0 ) num_cols = 0x10;
228 flipx = (hsize&0x8000)?1:0;
229 hsize &= 0x1ff;
230 if( hsize == 0 ) return;
231
232 zoomx = (hsize<<16)/(num_cols*16);
233 dx = (dx*zoomx+0x8000)>>16;
234 if( flipx )
235 {
236 hpos += dx;
237 }
238 else
239 {
240 hpos -= dx;
241 }
242
243 if( num_rows == 0 ) num_rows = 0x10;
244 flipy = (vsize&0x8000)?1:0;
245 vsize&=0x1ff;
246 if( vsize == 0 ) return;
247
248 zoomy = (vsize<<16)/(num_rows*16);
249 dy = (dy*zoomy+0x8000)>>16;
250 if( flipy )
251 {
252 vpos += dy;
253 }
254 else
255 {
256 vpos -= dy;
257 }
258
259 color = (palette&0xf)^mPalXOR;
260
261 source_height_remaining = num_rows*16;
262 screen_height_remaining = vsize;
263 sy = vpos;
264 for( row=0; row<num_rows; row++ )
265 {
266 tile_screen_height = 16*screen_height_remaining/source_height_remaining;
267 zoomy = (screen_height_remaining<<16)/source_height_remaining;
268 if( flipy )
269 {
270 sy -= tile_screen_height;
271 }
272 source_width_remaining = num_cols*16;
273 screen_width_remaining = hsize;
274 sx = hpos;
275 for( col=0; col<num_cols; col++ )
276 {
277 tile_screen_width = 16*screen_width_remaining/source_width_remaining;
278 zoomx = (screen_width_remaining<<16)/source_width_remaining;
279 if( flipx )
280 {
281 sx -= tile_screen_width;
282 }
283 tile = spritetile16[tile_index++];
284 if( (tile&0x8000)==0 )
285 {
286 /*z*/drawgfxzoom(bitmap,Machine->gfx[mGfxC355],
287 mpCodeToTile(tile) + offset,
288 color,
289 flipx,flipy,
290 sx,sy,
291 &clip,
292 TRANSPARENCY_PEN,0xff,
293 zoomx, zoomy/*, zpos*/ );
294 }
295 if( !flipx )
296 {
297 sx += tile_screen_width;
298 }
299 screen_width_remaining -= tile_screen_width;
300 source_width_remaining -= 16;
301 } /* next col */
302 if( !flipy )
303 {
304 sy += tile_screen_height;
305 }
306 screen_height_remaining -= tile_screen_height;
307 source_height_remaining -= 16;
308 } /* next row */
309 } /* draw_spriteC355 */
310
311
DefaultCodeToTile(int code)312 static int DefaultCodeToTile( int code )
313 {
314 return code;
315 }
316
namco_obj_init(int gfxbank,int palXOR,int (* codeToTile)(int code))317 void namco_obj_init( int gfxbank, int palXOR, int (*codeToTile)( int code ) )
318 {
319 mGfxC355 = gfxbank;
320 mPalXOR = palXOR;
321 if( codeToTile )
322 {
323 mpCodeToTile = codeToTile;
324 }
325 else
326 {
327 mpCodeToTile = DefaultCodeToTile;
328 }
329 spriteram16 = auto_malloc(0x14200);
330 memset( mSpritePos,0x00,sizeof(mSpritePos) );
331 } /* namcosC355_init */
332
333 static void
DrawObjectList(struct mame_bitmap * bitmap,const struct rectangle * cliprect,int pri,const data16_t * pSpriteList16,const data16_t * pSpriteTable,int n)334 DrawObjectList(
335 struct mame_bitmap *bitmap,
336 const struct rectangle *cliprect,
337 int pri,
338 const data16_t *pSpriteList16,
339 const data16_t *pSpriteTable,
340 int n )
341 {
342 data16_t which;
343 int i;
344 int count = 0;
345 /* count the sprites */
346 for( i=0; i<256; i++ )
347 {
348 which = pSpriteList16[i];
349 count++;
350 if( which&0x100 ) break;
351 }
352 /* draw the sprites */
353 for( i=0; i<count; i++ )
354 {
355 which = pSpriteList16[i];
356 draw_spriteC355( n, bitmap, cliprect, &pSpriteTable[(which&0xff)*8], pri, i );
357 }
358 } /* DrawObjectList */
359
360 void
namco_obj_draw(struct mame_bitmap * bitmap,const struct rectangle * cliprect,int pri)361 namco_obj_draw( struct mame_bitmap *bitmap, const struct rectangle *cliprect, int pri )
362 {
363 DrawObjectList( bitmap,cliprect,pri,&spriteram16[0x02000/2], &spriteram16[0x00000/2],0 );
364 DrawObjectList( bitmap,cliprect,pri,&spriteram16[0x14000/2], &spriteram16[0x10000/2],1 );
365 } /* namco_obj_draw */
366
WRITE16_HANDLER(namco_obj16_w)367 WRITE16_HANDLER( namco_obj16_w )
368 {
369 COMBINE_DATA( &spriteram16[offset] );
370 } /* namco_obj16_w */
371
READ16_HANDLER(namco_obj16_r)372 READ16_HANDLER( namco_obj16_r )
373 {
374 return spriteram16[offset];
375 } /* namco_obj16_r */
376
WRITE32_HANDLER(namco_obj32_w)377 WRITE32_HANDLER( namco_obj32_w )
378 {
379 data32_t v;
380 offset *= 2;
381 v = (spriteram16[offset]<<16)|spriteram16[offset+1];
382 COMBINE_DATA( &v );
383 spriteram16[offset] = v>>16;
384 spriteram16[offset+1] = v&0xffff;
385 } /* namco_obj32_w */
386
READ32_HANDLER(namco_obj32_r)387 READ32_HANDLER( namco_obj32_r )
388 {
389 offset *= 2;
390 return (spriteram16[offset]<<16)|spriteram16[offset+1];
391 } /* namco_obj32_r */
392
393 /**************************************************************************************************************/
394
395 /* ROZ abstraction (preliminary)
396 *
397 * Used by:
398 * Namco NB2 - The Outfoxies, Mach Breakers
399 * Namco System 2 - Metal Hawk, Lucky and Wild
400 */
401 static data16_t *rozbank16;
402 static data16_t *rozvideoram16;
403 static data16_t *rozcontrol16;
404 static int mRozGfxBank;
405 static int mRozMaskRegion;
406 static struct tilemap *mRozTilemap[2];
407 static int mRozPage[2]; /* base addr for tilemap */
408
409 /* It looks like the ROZ tilemap attributes also encode
410 * the source size. Right now, the implementation assumes ROZ
411 * layers are always 128x128 tiles.
412 */
413 static void
roz_get_info(int tile_index,int which)414 roz_get_info( int tile_index,int which )
415 {
416 data16_t tile;
417 int bank;
418 int mangle;
419 /* when size control is understood, we can simulate it by masking column and row, which will
420 * mirror the contents of the ROZ tilemap.
421 */
422 tile = rozvideoram16[mRozPage[which]+tile_index];
423
424 switch( namcos2_gametype )
425 {
426 case NAMCONB2_MACH_BREAKERS:
427 bank = nth_byte16( &rozbank16[which*8/2], (tile>>11)&0x7 );
428 tile = (tile&0x7ff)|(bank*0x800);
429 mangle = tile;
430 break;
431
432 case NAMCONB2_OUTFOXIES:
433 bank = nth_byte16( &rozbank16[which*8/2], (tile>>11)&0x7 );
434 tile = (tile&0x7ff)|(bank*0x800);
435 mangle = tile&~(0x50);
436 /* the pixmap index is mangled, the transparency bitmask index is not */
437 if( tile&0x10 ) mangle |= 0x40;
438 if( tile&0x40 ) mangle |= 0x10;
439 break;
440
441 case NAMCOS2_LUCKY_AND_WILD:
442 mangle = tile&0x01ff;
443 tile &= 0x3fff;
444 switch( tile>>9 )
445 {
446 case 0x00: mangle |= 0x1c00; break;
447 case 0x01: mangle |= 0x0800; break;
448 case 0x02: mangle |= 0x0000; break;
449
450 case 0x08: mangle |= 0x1e00; break;
451 case 0x09: mangle |= 0x0a00; break;
452 case 0x0a: mangle |= 0x0200; break;
453
454 case 0x10: mangle |= 0x2000; break;
455 case 0x11: mangle |= 0x0c00; break;
456 case 0x12: mangle |= 0x0400; break;
457
458 case 0x18: mangle |= 0x2200; break;
459 case 0x19: mangle |= 0x0e00; break;
460 case 0x1a: mangle |= 0x0600; break;
461 }
462 break;
463
464 case NAMCOS2_METAL_HAWK:
465 default:
466 mangle = tile&0x01ff;
467 if( tile&0x1000 ) mangle |= 0x0200;
468 if( tile&0x0200 ) mangle |= 0x0400;
469 if( tile&0x0400 ) mangle |= 0x0800;
470 if( tile&0x0800 ) mangle |= 0x1000;
471 break;
472 }
473 SET_TILE_INFO( mRozGfxBank,mangle,0/*color*/,0 );
474 tile_info.mask_data = 32*tile + (UINT8 *)memory_region( mRozMaskRegion );
475 } /* roz_get_info */
476
roz_get_info0(int tile_index)477 static void roz_get_info0( int tile_index )
478 {
479 roz_get_info( tile_index,0 );
480 }
roz_get_info1(int tile_index)481 static void roz_get_info1( int tile_index )
482 {
483 roz_get_info( tile_index,1 );
484 }
485
486 int
namco_roz_init(int gfxbank,int maskregion)487 namco_roz_init( int gfxbank, int maskregion )
488 {
489 /* allocate both ROZ layers */
490 int i;
491 static void (*roz_info[2])(int tile_index) = { roz_get_info0, roz_get_info1 };
492
493 mRozGfxBank = gfxbank;
494 mRozMaskRegion = maskregion;
495
496 rozbank16 = auto_malloc(0x10);
497 rozvideoram16 = auto_malloc(0x20000);
498 rozcontrol16 = auto_malloc(0x20);
499 if( rozbank16 && rozvideoram16 && rozcontrol16 )
500 {
501 for( i=0; i<2; i++ )
502 {
503 mRozPage[i] = -1;
504 mRozTilemap[i] = tilemap_create( roz_info[i], tilemap_scan_rows,
505 TILEMAP_BITMASK,16,16,128,128 );
506
507 if( mRozTilemap[i] == NULL ) return 1; /* error */
508 }
509 return 0;
510 }
511 return -1;
512 } /* namco_roz_init */
513
514 /**
515 * ROZ control attributes:
516 *
517 * unk attr xx xy yx yy x0 y0
518 *
519 * Lucky & Wild:
520 * 0000 080e 2100 0000 0000 0100 38e0 fde0 0:badge
521 * 1000 084e 00fe 0000 0000 00fe f9f6 fd96 0:zooming car
522 * 0000 080e 1100 0000 0000 0000 26d0 0450 0:"LUCKY & WILD"
523 * 0000 03bf 0100 0000 0000 0100 fde0 7fe0 1:talking heads
524 * 1000 080a 0100 0000 0000 0100 fde0 ffe0 0:player select
525 *
526 * Outfoxies:
527 * 1000 0211 02ff 02ff 0000 0000 02ff f97b ffa7 (tv)
528 * 0000 0211 00ff 0000 0000 0000 00ff fddb 0de7 (char select)
529 * 1000 0271 0101 0000 0000 0101 0fc4 56d7 (stage)
530 * 0000 0252 0101 4000 0000 0101 0fc4 d6d7 (stage)
531 *
532 * Mach Breakers:
533 * 1000 0871 4100 0000 0000 0100 f4d0 f8e0
534 * 0000 0210 0100 0000 0000 0100 40d0 38e0
535 * 0000 0000 0100 0000 0000 0100 f4d0 f8e0 // charsel (512x512)
536 * 0000 0020 0100 0000 0000 0100 f4d0 f8e0 // map
537 */
namco_roz_draw(struct mame_bitmap * bitmap,const struct rectangle * cliprect,int pri)538 void namco_roz_draw(
539 struct mame_bitmap *bitmap,
540 const struct rectangle *cliprect,
541 int pri )
542 {
543 const int xoffset = 38-2,yoffset = 3;
544 int which;
545 for( which=0; which<2; which++ )
546 {
547 const data16_t *pSource = &rozcontrol16[which*8];
548 data16_t attrs = pSource[1];
549 if( (attrs&0x8000)==0 )
550 { /* layer is enabled */
551 int color = attrs&0xf;
552 int page;
553 int roz_pri;
554 /*int roz_size = 128;*/
555 switch( namcos2_gametype )
556 {
557 case NAMCONB2_OUTFOXIES:
558 roz_pri = 4-which; /* ? */
559 page = pSource[3]&0x4000;
560 if( attrs == 0x0211 ) roz_pri = 1; /* hack */
561 break;
562
563 case NAMCONB2_MACH_BREAKERS:
564 roz_pri = 4-which; /* ? */
565 page = (pSource[2]&0x6000)*2;
566 break;
567
568 case NAMCOS2_LUCKY_AND_WILD:
569 roz_pri = 5-which; /* ? */
570 page = (attrs&0x0800)?0:0x4000; /* ? */
571 break;
572
573 case NAMCOS2_METAL_HAWK:
574 default:
575 roz_pri = which; /* ? */
576 page = pSource[3]&0x4000;
577 break;
578 }
579 if( roz_pri==pri )
580 {
581 int bDirty;
582 UINT32 startx,starty;
583 int incxx,incxy,incyx,incyy;
584 data16_t temp;
585
586 temp = pSource[2];
587 if( temp&0x8000 ) temp |= 0xf000; else temp&=0x0fff; /* sign extend */
588 incxx = (INT16)temp;
589
590 temp = pSource[3];
591 if( temp&0x8000 ) temp |= 0xf000; else temp&=0x0fff; /* sign extend */
592 incxy = (INT16)temp;
593
594 temp = pSource[4];
595 if( temp&0x8000 ) temp |= 0xf000; else temp&=0x0fff; /* sign extend */
596 incyx = (INT16)temp;
597
598 incyy = (INT16)pSource[5];
599 startx = (INT16)pSource[6];
600 starty = (INT16)pSource[7];
601
602 startx <<= 4;
603 starty <<= 4;
604 startx += xoffset * incxx + yoffset * incyx;
605 starty += xoffset * incxy + yoffset * incyy;
606
607 bDirty = 0;
608 tilemap_set_palette_offset(mRozTilemap[which],color*256);
609 if( mRozPage[which] != page )
610 {
611 mRozPage[which] = page;
612 bDirty = 1;
613 }
614 if( bDirty )
615 {
616 tilemap_mark_all_tiles_dirty( mRozTilemap[which] );
617 }
618
619 tilemap_draw_roz(bitmap,cliprect,mRozTilemap[which],
620 startx << 8,
621 starty << 8,
622 incxx << 8,
623 incxy << 8,
624 incyx << 8,
625 incyy << 8,
626 1, /* copy with wraparound */
627 0,0);
628 }
629 }
630 }
631 } /* namco_roz_draw */
632
READ16_HANDLER(namco_rozcontrol16_r)633 READ16_HANDLER( namco_rozcontrol16_r )
634 {
635 return rozcontrol16[offset];
636 }
637
WRITE16_HANDLER(namco_rozcontrol16_w)638 WRITE16_HANDLER( namco_rozcontrol16_w )
639 {
640 COMBINE_DATA( &rozcontrol16[offset] );
641 }
642
READ16_HANDLER(namco_rozbank16_r)643 READ16_HANDLER( namco_rozbank16_r )
644 {
645 return rozbank16[offset];
646 }
647
WRITE16_HANDLER(namco_rozbank16_w)648 WRITE16_HANDLER( namco_rozbank16_w )
649 {
650 data16_t old_data;
651
652 old_data = rozbank16[offset];
653 COMBINE_DATA( &rozbank16[offset] );
654 if( rozbank16[offset]!=old_data )
655 {
656 tilemap_mark_all_tiles_dirty( mRozTilemap[0] );
657 tilemap_mark_all_tiles_dirty( mRozTilemap[1] );
658 }
659 }
660
writerozvideo(int offset,data16_t data)661 static void writerozvideo( int offset, data16_t data )
662 {
663 int i;
664 if( rozvideoram16[offset]!=data )
665 {
666 rozvideoram16[offset] = data;
667 for( i=0; i<2; i++ )
668 {
669 if( mRozPage[i]==(offset&0xc000) )
670 {
671 tilemap_mark_tile_dirty( mRozTilemap[i], offset&0x3fff );
672 }
673 }
674 }
675 }
676
READ16_HANDLER(namco_rozvideoram16_r)677 READ16_HANDLER( namco_rozvideoram16_r )
678 {
679 return rozvideoram16[offset];
680 }
681
WRITE16_HANDLER(namco_rozvideoram16_w)682 WRITE16_HANDLER( namco_rozvideoram16_w )
683 {
684 data16_t v;
685
686 v = rozvideoram16[offset];
687 COMBINE_DATA( &v );
688 writerozvideo( offset, v );
689 }
690
READ32_HANDLER(namco_rozcontrol32_r)691 READ32_HANDLER( namco_rozcontrol32_r )
692 {
693 offset *= 2;
694 return (rozcontrol16[offset]<<16)|rozcontrol16[offset+1];
695 }
696
WRITE32_HANDLER(namco_rozcontrol32_w)697 WRITE32_HANDLER( namco_rozcontrol32_w )
698 {
699 data32_t v;
700 offset *=2;
701 v = (rozcontrol16[offset]<<16)|rozcontrol16[offset+1];
702 COMBINE_DATA(&v);
703 rozcontrol16[offset] = v>>16;
704 rozcontrol16[offset+1] = v&0xffff;
705 }
706
READ32_HANDLER(namco_rozbank32_r)707 READ32_HANDLER( namco_rozbank32_r )
708 {
709 offset *= 2;
710 return (rozbank16[offset]<<16)|rozbank16[offset+1];
711 }
712
WRITE32_HANDLER(namco_rozbank32_w)713 WRITE32_HANDLER( namco_rozbank32_w )
714 {
715 data32_t v;
716 offset *=2;
717 v = (rozbank16[offset]<<16)|rozbank16[offset+1];
718 COMBINE_DATA(&v);
719 rozbank16[offset] = v>>16;
720 rozbank16[offset+1] = v&0xffff;
721 }
722
READ32_HANDLER(namco_rozvideoram32_r)723 READ32_HANDLER( namco_rozvideoram32_r )
724 {
725 offset *= 2;
726 return (rozvideoram16[offset]<<16)|rozvideoram16[offset+1];
727 }
728
WRITE32_HANDLER(namco_rozvideoram32_w)729 WRITE32_HANDLER( namco_rozvideoram32_w )
730 {
731 data32_t v;
732 offset *= 2;
733 v = (rozvideoram16[offset]<<16)|rozvideoram16[offset+1];
734 COMBINE_DATA( &v );
735 writerozvideo(offset,v>>16);
736 writerozvideo(offset+1,v&0xffff);
737 }
738
739 /**************************************************************************************************************/
740 /*
741 Land Line Buffer
742 Land Generator
743 0xf,0x7,0xe,0x6,0xd,0x5,0xc,0x4,
744 0xb,0x3,0xa,0x2,0x9,0x1,0x8,0x0
745
746 */
747
748 /* Preliminary! The road circuitry is identical for all the driving games.
749 *
750 * There are several chunks of RAM
751 *
752 * Road Tilemap:
753 * 0x00000..0x0ffff 64x512 tilemap
754 *
755 * Road Tiles:
756 * 0x10000..0x1f9ff 16x16x2bpp tiles
757 *
758 *
759 * Line Attributes:
760 *
761 * 0x1fa00..0x1fbdf xxx- ---- ---- ---- priority
762 * ---- xxxx xxxx xxxx xscroll
763 *
764 * 0x1fbfe horizontal adjust?
765 * 0x0017
766 * 0x0018 (Final Lap3)
767 *
768 * 0x1fc00..0x1fddf selects line in source bitmap
769 * 0x1fdfe yscroll
770 *
771 * 0x1fe00..0x1ffdf ---- --xx xxxx xxxx zoomx
772 * 0x1fffd always 0xffff 0xffff?
773 */
774 static data16_t *mpRoadRAM; /* at 0x880000 in Final Lap; at 0xa00000 in Lucky&Wild */
775 static unsigned char *mpRoadDirty;
776 static int mbRoadSomethingIsDirty;
777 static int mRoadGfxBank;
778 static struct tilemap *mpRoadTilemap;
779 static pen_t mRoadTransparentColor;
780 static int mbRoadNeedTransparent;
781
782 #define ROAD_COLS 64
783 #define ROAD_ROWS 512
784 #define ROAD_TILE_SIZE 16
785 #define ROAD_TILEMAP_WIDTH (ROAD_TILE_SIZE*ROAD_COLS)
786 #define ROAD_TILEMAP_HEIGHT (ROAD_TILE_SIZE*ROAD_ROWS)
787
788 #define ROAD_TILE_COUNT_MAX (0xfa00/0x40) /* 0x3e8 */
789 #define WORDS_PER_ROAD_TILE (0x40/2)
790
791 static struct GfxLayout RoadTileLayout =
792 {
793 ROAD_TILE_SIZE,
794 ROAD_TILE_SIZE,
795 ROAD_TILE_COUNT_MAX,
796 2,
797 {
798 #ifdef MSB_FIRST
799 0,8
800 #else
801 8,0
802 #endif
803 },
804 {/* x offset */
805 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,
806 0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17
807 },
808 {/* y offset */
809 0x000,0x020,0x040,0x060,0x080,0x0a0,0x0c0,0x0e0,
810 0x100,0x120,0x140,0x160,0x180,0x1a0,0x1c0,0x1e0
811 },
812 0x200, /* offset to next tile */
813 };
814
get_road_info(int tile_index)815 void get_road_info( int tile_index )
816 {
817 data16_t data = mpRoadRAM[tile_index];
818 /* ------xx xxxxxxxx tile number
819 * xxxxxx-- -------- palette select
820 */
821 int tile = (data&0x3ff);
822 int color = (data>>10);
823
824 SET_TILE_INFO( mRoadGfxBank, tile, color , 0 )
825 } /* get_road_info */
826
READ16_HANDLER(namco_road16_r)827 READ16_HANDLER( namco_road16_r )
828 {
829 return mpRoadRAM[offset];
830 }
831
WRITE16_HANDLER(namco_road16_w)832 WRITE16_HANDLER( namco_road16_w )
833 {
834 COMBINE_DATA( &mpRoadRAM[offset] );
835 if( offset<0x10000/2 )
836 {
837 tilemap_mark_tile_dirty( mpRoadTilemap, offset );
838 }
839 else
840 {
841 offset -= 0x10000/2;
842 if( offset<ROAD_TILE_COUNT_MAX*WORDS_PER_ROAD_TILE )
843 {
844 mpRoadDirty[offset/WORDS_PER_ROAD_TILE] = 1;
845 mbRoadSomethingIsDirty = 1;
846 }
847 }
848 }
849
850 static void
UpdateRoad(void)851 UpdateRoad( void )
852 {
853 int i;
854 if( mbRoadSomethingIsDirty )
855 {
856 for( i=0; i<ROAD_TILE_COUNT_MAX; i++ )
857 {
858 if( mpRoadDirty[i] )
859 {
860 decodechar(
861 Machine->gfx[mRoadGfxBank],
862 i,
863 0x10000+(UINT8 *)mpRoadRAM,
864 &RoadTileLayout );
865 mpRoadDirty[i] = 0;
866 }
867 }
868 tilemap_mark_all_tiles_dirty( mpRoadTilemap );
869 mbRoadSomethingIsDirty = 0;
870 }
871 }
872
873 static void
RoadMarkAllDirty(void)874 RoadMarkAllDirty(void)
875 {
876 memset( mpRoadDirty,0x01,ROAD_TILE_COUNT_MAX );
877 mbRoadSomethingIsDirty = 1;
878 }
879
880 int
namco_road_init(int gfxbank)881 namco_road_init( int gfxbank )
882 {
883 mbRoadNeedTransparent = 0;
884 mRoadGfxBank = gfxbank;
885 mpRoadDirty = auto_malloc(ROAD_TILE_COUNT_MAX);
886 if( mpRoadDirty )
887 {
888 memset( mpRoadDirty,0x00,ROAD_TILE_COUNT_MAX );
889 mbRoadSomethingIsDirty = 0;
890 mpRoadRAM = auto_malloc(0x20000);
891 if( mpRoadRAM )
892 {
893 struct GfxElement *pGfx = decodegfx( 0x10000+(UINT8 *)mpRoadRAM, &RoadTileLayout );
894 if( pGfx )
895 {
896 pGfx->colortable = &Machine->remapped_colortable[0xf00];
897 pGfx->total_colors = 0x3f;
898
899 Machine->gfx[gfxbank] = pGfx;
900 mpRoadTilemap = tilemap_create(
901 get_road_info,tilemap_scan_rows,
902 TILEMAP_OPAQUE,
903 ROAD_TILE_SIZE,ROAD_TILE_SIZE,
904 ROAD_COLS,ROAD_ROWS);
905
906 if( mpRoadTilemap )
907 {
908 state_save_register_UINT8 ("namco_road", 0, "RoadDirty", mpRoadDirty, ROAD_TILE_COUNT_MAX);
909 state_save_register_UINT16("namco_road", 0, "RoadRAM", mpRoadRAM, 0x20000 / 2);
910 state_save_register_func_postload(RoadMarkAllDirty);
911
912 return 0;
913 }
914 }
915 }
916 }
917 return -1;
918 } /* namco_road_init */
919
920 void
namco_road_set_transparent_color(pen_t pen)921 namco_road_set_transparent_color(pen_t pen)
922 {
923 mbRoadNeedTransparent = 1;
924 mRoadTransparentColor = pen;
925 }
926
927 void
namco_road_draw(struct mame_bitmap * bitmap,const struct rectangle * cliprect,int pri)928 namco_road_draw( struct mame_bitmap *bitmap, const struct rectangle *cliprect, int pri )
929 {
930 struct mame_bitmap *pSourceBitmap;
931 unsigned yscroll;
932 int i;
933
934 UpdateRoad();
935
936 pSourceBitmap = tilemap_get_pixmap(mpRoadTilemap);
937 yscroll = mpRoadRAM[0x1fdfe/2];
938
939 for( i=cliprect->min_y; i<=cliprect->max_y; i++ )
940 {
941 UINT16 *pDest = bitmap->line[i];
942 int screenx = mpRoadRAM[0x1fa00/2+i+15];
943
944 if( pri == ((screenx&0xe000)>>13) )
945 {
946 unsigned zoomx = mpRoadRAM[0x1fe00/2+i+15]&0x3ff;
947 if( zoomx )
948 {
949 unsigned sourcey = mpRoadRAM[0x1fc00/2+i+15]+yscroll;
950 const UINT16 *pSourceGfx = pSourceBitmap->line[sourcey&(ROAD_TILEMAP_HEIGHT-1)];
951 unsigned dsourcex = (ROAD_TILEMAP_WIDTH<<16)/zoomx;
952 unsigned sourcex = 0;
953 int numpixels = (44*ROAD_TILE_SIZE<<16)/dsourcex;
954
955 /* draw this scanline */
956 screenx &= 0x0fff; /* mask off priority bits */
957 if( screenx&0x0800 )
958 {
959 /* sign extend */
960 screenx -= 0x1000;
961 }
962
963 /* adjust the horizontal placement */
964 screenx -= 64; /*needs adjustment to left*/
965
966 if( screenx<0 )
967 { /* crop left */
968 numpixels += screenx;
969 sourcex -= dsourcex*screenx;
970 screenx = 0;
971 }
972
973 if( screenx + numpixels > bitmap->width )
974 { /* crop right */
975 numpixels = bitmap->width - screenx;
976 }
977
978 /* BUT: support transparent color for Thunder Ceptor */
979 if (mbRoadNeedTransparent)
980 {
981 while( numpixels-- > 0 )
982 {
983 int pen = pSourceGfx[sourcex>>16];
984 /* TBA: work out palette mapping for Final Lap, Suzuka */
985 if (pen != mRoadTransparentColor)
986 pDest[screenx] = pen;
987 screenx++;
988 sourcex += dsourcex;
989 }
990 }
991 else
992 {
993 while( numpixels-- > 0 )
994 {
995 int pen = pSourceGfx[sourcex>>16];
996 /* TBA: work out palette mapping for Final Lap, Suzuka */
997 pDest[screenx++] = pen;
998 sourcex += dsourcex;
999 }
1000 }
1001 }
1002 }
1003 }
1004 } /* namco_road_draw */
1005