1 /***************************************************************************
2
3 Ninja Gaiden / Tecmo Knights Video Hardware
4
5 ***************************************************************************/
6
7 #include "driver.h"
8 #include "vidhrdw/generic.h"
9
10 data16_t *gaiden_videoram,*gaiden_videoram2,*gaiden_videoram3;
11 int gaiden_sprite_sizey;
12 int raiga_alpha;
13
14 static struct tilemap *text_layer,*foreground,*background;
15 static struct mame_bitmap *sprite_bitmap, *tile_bitmap_bg, *tile_bitmap_fg;
16
17 /***************************************************************************
18
19 Callbacks for the TileMap code
20
21 ***************************************************************************/
22
get_bg_tile_info(int tile_index)23 static void get_bg_tile_info(int tile_index)
24 {
25 UINT16 *videoram1 = &gaiden_videoram3[0x0800];
26 UINT16 *videoram2 = gaiden_videoram3;
27 SET_TILE_INFO(
28 1,
29 videoram1[tile_index] & 0x0fff,
30 (videoram2[tile_index] & 0xf0) >> 4,
31 0)
32 }
33
get_fg_tile_info(int tile_index)34 static void get_fg_tile_info(int tile_index)
35 {
36 UINT16 *videoram1 = &gaiden_videoram2[0x0800];
37 UINT16 *videoram2 = gaiden_videoram2;
38 SET_TILE_INFO(
39 2,
40 videoram1[tile_index] & 0x0fff,
41 (videoram2[tile_index] & 0xf0) >> 4,
42 0)
43 }
44
get_fg_tile_info_raiga(int tile_index)45 static void get_fg_tile_info_raiga(int tile_index)
46 {
47 UINT16 *videoram1 = &gaiden_videoram2[0x0800];
48 UINT16 *videoram2 = gaiden_videoram2;
49
50 /* bit 3 controls blending */
51 tile_info.priority = (videoram2[tile_index] & 0x08) >> 3;
52
53 SET_TILE_INFO(
54 2,
55 videoram1[tile_index] & 0x0fff,
56 ((videoram2[tile_index] & 0xf0) >> 4) | (tile_info.priority ? 0x80 : 0x00),
57 0)
58 }
59
get_tx_tile_info(int tile_index)60 static void get_tx_tile_info(int tile_index)
61 {
62 UINT16 *videoram1 = &gaiden_videoram[0x0400];
63 UINT16 *videoram2 = gaiden_videoram;
64 SET_TILE_INFO(
65 0,
66 videoram1[tile_index] & 0x07ff,
67 (videoram2[tile_index] & 0xf0) >> 4,
68 0)
69 }
70
71
72 /***************************************************************************
73
74 Start the video hardware emulation.
75
76 ***************************************************************************/
77
VIDEO_START(gaiden)78 VIDEO_START( gaiden )
79 {
80 /* set up tile layers */
81 background = tilemap_create(get_bg_tile_info, tilemap_scan_rows, TILEMAP_TRANSPARENT, 16, 16, 64, 32);
82 foreground = tilemap_create(get_fg_tile_info, tilemap_scan_rows, TILEMAP_TRANSPARENT, 16, 16, 64, 32);
83 text_layer = tilemap_create(get_tx_tile_info, tilemap_scan_rows, TILEMAP_TRANSPARENT, 8, 8, 32, 32);
84
85 if (!text_layer || !foreground || !background)
86 return 1;
87
88 tilemap_set_transparent_pen(background, 0);
89 tilemap_set_transparent_pen(foreground, 0);
90 tilemap_set_transparent_pen(text_layer, 0);
91
92 return 0;
93 }
94
VIDEO_START(raiga)95 VIDEO_START( raiga )
96 {
97 /* set up tile layers */
98 tile_bitmap_bg = auto_bitmap_alloc_depth(Machine->drv->screen_width, Machine->drv->screen_height, 16);
99 tile_bitmap_fg = auto_bitmap_alloc_depth(Machine->drv->screen_width, Machine->drv->screen_height, 16);
100
101 if (!tile_bitmap_bg || !tile_bitmap_fg)
102 return 1;
103
104 background = tilemap_create(get_bg_tile_info, tilemap_scan_rows,TILEMAP_TRANSPARENT,16,16,64,32);
105 foreground = tilemap_create(get_fg_tile_info_raiga,tilemap_scan_rows,TILEMAP_TRANSPARENT,16,16,64,32);
106 text_layer = tilemap_create(get_tx_tile_info, tilemap_scan_rows,TILEMAP_TRANSPARENT, 8, 8,32,32);
107
108 if (!text_layer || !foreground || !background)
109 return 1;
110
111 tilemap_set_transparent_pen(background,0);
112 tilemap_set_transparent_pen(foreground,0);
113 tilemap_set_transparent_pen(text_layer,0);
114
115 /* set up sprites */
116 sprite_bitmap = auto_bitmap_alloc_depth(Machine->drv->screen_width, Machine->drv->screen_height, 16);
117
118 if (!sprite_bitmap)
119 return 1;
120
121 return 0;
122 }
123
124
125
126 /***************************************************************************
127
128 Memory handlers
129
130 ***************************************************************************/
131
WRITE16_HANDLER(gaiden_txscrollx_w)132 WRITE16_HANDLER( gaiden_txscrollx_w )
133 {
134 static data16_t scroll;
135 COMBINE_DATA(&scroll);
136 tilemap_set_scrollx(text_layer, 0, scroll);
137 }
138
WRITE16_HANDLER(gaiden_txscrolly_w)139 WRITE16_HANDLER( gaiden_txscrolly_w )
140 {
141 static data16_t scroll;
142 COMBINE_DATA(&scroll);
143 tilemap_set_scrolly(text_layer, 0, scroll);
144 }
145
WRITE16_HANDLER(gaiden_fgscrollx_w)146 WRITE16_HANDLER( gaiden_fgscrollx_w )
147 {
148 static data16_t scroll;
149 COMBINE_DATA(&scroll);
150 tilemap_set_scrollx(foreground, 0, scroll);
151 }
152
WRITE16_HANDLER(gaiden_fgscrolly_w)153 WRITE16_HANDLER( gaiden_fgscrolly_w )
154 {
155 static data16_t scroll;
156 COMBINE_DATA(&scroll);
157 tilemap_set_scrolly(foreground, 0, scroll);
158 }
159
WRITE16_HANDLER(gaiden_bgscrollx_w)160 WRITE16_HANDLER( gaiden_bgscrollx_w )
161 {
162 static data16_t scroll;
163 COMBINE_DATA(&scroll);
164 tilemap_set_scrollx(background, 0, scroll);
165 }
166
WRITE16_HANDLER(gaiden_bgscrolly_w)167 WRITE16_HANDLER( gaiden_bgscrolly_w )
168 {
169 static data16_t scroll;
170 COMBINE_DATA(&scroll);
171 tilemap_set_scrolly(background, 0, scroll);
172 }
173
WRITE16_HANDLER(gaiden_videoram3_w)174 WRITE16_HANDLER( gaiden_videoram3_w )
175 {
176 int oldword = gaiden_videoram3[offset];
177 COMBINE_DATA(&gaiden_videoram3[offset]);
178 if (oldword != gaiden_videoram3[offset])
179 tilemap_mark_tile_dirty(background,offset & 0x07ff);
180 }
181
WRITE16_HANDLER(gaiden_flip_w)182 WRITE16_HANDLER( gaiden_flip_w )
183 {
184 if (ACCESSING_LSB)
185 flip_screen_set(data & 1);
186 }
187
188
READ16_HANDLER(gaiden_videoram3_r)189 READ16_HANDLER( gaiden_videoram3_r )
190 {
191 return gaiden_videoram3[offset];
192 }
193
WRITE16_HANDLER(gaiden_videoram2_w)194 WRITE16_HANDLER( gaiden_videoram2_w )
195 {
196 int oldword = gaiden_videoram2[offset];
197 COMBINE_DATA(&gaiden_videoram2[offset]);
198 if (oldword != gaiden_videoram2[offset])
199 tilemap_mark_tile_dirty(foreground,offset & 0x07ff);
200 }
201
READ16_HANDLER(gaiden_videoram2_r)202 READ16_HANDLER( gaiden_videoram2_r )
203 {
204 return gaiden_videoram2[offset];
205 }
206
WRITE16_HANDLER(gaiden_videoram_w)207 WRITE16_HANDLER( gaiden_videoram_w )
208 {
209 int oldword = gaiden_videoram[offset];
210 COMBINE_DATA(&gaiden_videoram[offset]);
211 if (oldword != gaiden_videoram[offset])
212 tilemap_mark_tile_dirty(text_layer,offset & 0x03ff);
213 }
214
215
216
217 /***************************************************************************
218
219 Display refresh
220
221 ***************************************************************************/
222
223 /* mix & blend the paletted 16-bit tile and sprite bitmaps into an RGB 32-bit bitmap */
blendbitmaps(struct mame_bitmap * dest,struct mame_bitmap * src1,struct mame_bitmap * src2,struct mame_bitmap * src3,int sx,int sy,const struct rectangle * clip)224 static void blendbitmaps(
225 struct mame_bitmap *dest,struct mame_bitmap *src1,struct mame_bitmap *src2,struct mame_bitmap *src3,
226 int sx,int sy,const struct rectangle *clip)
227 {
228 int ox;
229 int oy;
230 int ex;
231 int ey;
232
233 /* check bounds */
234 ox = sx;
235 oy = sy;
236
237 ex = sx + src1->width - 1;
238 if (sx < 0) sx = 0;
239 if (sx < clip->min_x) sx = clip->min_x;
240 if (ex >= dest->width) ex = dest->width - 1;
241 if (ex > clip->max_x) ex = clip->max_x;
242 if (sx > ex) return;
243
244 ey = sy + src1->height - 1;
245 if (sy < 0) sy = 0;
246 if (sy < clip->min_y) sy = clip->min_y;
247 if (ey >= dest->height) ey = dest->height - 1;
248 if (ey > clip->max_y) ey = clip->max_y;
249 if (sy > ey) return;
250
251 {
252 pen_t *paldata = Machine->pens;
253 UINT32 *end;
254
255 UINT16 *sd1 = ((UINT16 *)src1->line[0]); /* source data */
256 UINT16 *sd2 = ((UINT16 *)src2->line[0]);
257 UINT16 *sd3 = ((UINT16 *)src3->line[0]);
258
259 int sw = ex-sx+1; /* source width */
260 int sh = ey-sy+1; /* source height */
261 int sm = ((UINT16 *)src1->line[1]) - ((UINT16 *)src1->line[0]); /* source modulo */
262
263 UINT32 *dd = ((UINT32 *)dest->line[sy]) + sx; /* dest data */
264 int dm = ((UINT32 *)dest->line[1]) - ((UINT32 *)dest->line[0]); /* dest modulo */
265
266 sd1 += (sx-ox);
267 sd1 += sm * (sy-oy);
268 sd2 += (sx-ox);
269 sd2 += sm * (sy-oy);
270 sd3 += (sx-ox);
271 sd3 += sm * (sy-oy);
272
273 sm -= sw;
274 dm -= sw;
275
276 while (sh)
277 {
278
279 #define BLENDPIXEL(x) if (sd3[x]) { \
280 if (sd2[x]) { \
281 dd[x] = paldata[sd2[x] | 0x0400] + paldata[sd3[x]]; \
282 } else { \
283 dd[x] = paldata[sd1[x] | 0x0400] + paldata[sd3[x]]; \
284 } \
285 } else { \
286 if (sd2[x]) { \
287 if (sd2[x] & 0x0800) { \
288 dd[x] = paldata[sd1[x] | 0x0400] + paldata[sd2[x]]; \
289 } else { \
290 dd[x] = paldata[sd2[x]]; \
291 } \
292 } else { \
293 dd[x] = paldata[sd1[x]]; \
294 } \
295 }
296
297 end = dd + sw;
298 while (dd <= end - 8)
299 {
300 BLENDPIXEL(0);
301 BLENDPIXEL(1);
302 BLENDPIXEL(2);
303 BLENDPIXEL(3);
304 BLENDPIXEL(4);
305 BLENDPIXEL(5);
306 BLENDPIXEL(6);
307 BLENDPIXEL(7);
308 dd += 8;
309 sd1 += 8;
310 sd2 += 8;
311 sd3 += 8;
312 }
313 while (dd < end)
314 {
315 BLENDPIXEL(0);
316 dd++;
317 sd1++;
318 sd2++;
319 sd3++;
320 }
321 dd += dm;
322 sd1 += sm;
323 sd2 += sm;
324 sd3 += sm;
325 sh--;
326
327 #undef BLENDPIXEL
328
329 }
330 }
331 }
332
333 /* sprite format:
334 *
335 * word bit usage
336 * --------+-fedcba9876543210-+----------------
337 * 0 | ---------------x | flip x
338 * | --------------x- | flip y
339 * | -------------x-- | enable
340 * | ----------x----- | blend
341 * | --------xx------ | sprite-tile priority
342 * 1 | xxxxxxxxxxxxxxxx | number
343 * 2 | --------xxxx---- | palette
344 * | --------------xx | size: 8x8, 16x16, 32x32, 64x64
345 * 3 | xxxxxxxxxxxxxxxx | y position
346 * 4 | xxxxxxxxxxxxxxxx | x position
347 * 5,6,7| | unused
348 */
349
350 #define NUM_SPRITES 256
351
draw_sprites(struct mame_bitmap * bitmap_bg,struct mame_bitmap * bitmap_fg,struct mame_bitmap * bitmap_sp,const struct rectangle * cliprect)352 static void draw_sprites(struct mame_bitmap *bitmap_bg, struct mame_bitmap *bitmap_fg, struct mame_bitmap *bitmap_sp, const struct rectangle *cliprect)
353 {
354 const UINT8 layout[8][8] =
355 {
356 { 0, 1, 4, 5,16,17,20,21},
357 { 2, 3, 6, 7,18,19,22,23},
358 { 8, 9,12,13,24,25,28,29},
359 {10,11,14,15,26,27,30,31},
360 {32,33,36,37,48,49,52,53},
361 {34,35,38,39,50,51,54,55},
362 {40,41,44,45,56,57,60,61},
363 {42,43,46,47,58,59,62,63}
364 };
365
366 const struct GfxElement *gfx = Machine->gfx[3];
367 struct mame_bitmap *bitmap = bitmap_bg;
368 const UINT16 *source = (NUM_SPRITES - 1) * 8 + spriteram16;
369 const UINT8 blend_support = (bitmap_fg && bitmap_sp);
370 int count = NUM_SPRITES;
371
372 /* draw all sprites from front to back */
373 while (count--)
374 {
375 UINT32 attributes = source[0];
376 UINT32 priority_mask;
377 int col,row;
378
379 if (attributes & 0x04)
380 {
381 UINT32 priority = (attributes >> 6) & 3;
382 UINT32 flipx = (attributes & 1);
383 UINT32 flipy = (attributes & 2);
384
385 UINT32 color = source[2];
386 UINT32 sizex = 1 << ((color >> 0) & 3); /* 1,2,4,8 */
387 UINT32 sizey = 1 << ((color >> gaiden_sprite_sizey) & 3); /* 1,2,4,8 */
388
389 /* raiga needs something like this */
390 UINT32 number = (source[1] & (sizex > 2 ? 0x7ff8 : 0x7ffc));
391
392 int ypos = source[3] & 0x01ff;
393 int xpos = source[4] & 0x01ff;
394
395 if (!blend_support && (attributes & 0x20) && (cpu_getcurrentframe() & 1))
396 goto skip_sprite;
397
398 color = (color >> 4) & 0x0f;
399
400 /* wraparound */
401 if (xpos >= 256)
402 xpos -= 512;
403 if (ypos >= 256)
404 ypos -= 512;
405
406 if (flip_screen)
407 {
408 flipx = !flipx;
409 flipy = !flipy;
410
411 xpos = 256 - (8 * sizex) - xpos;
412 ypos = 256 - (8 * sizey) - ypos;
413
414 if (xpos <= -256)
415 xpos += 512;
416 if (ypos <= -256)
417 ypos += 512;
418 }
419
420 /* bg: 1; fg:2; text: 4 */
421 switch( priority )
422 {
423 default:
424 case 0x0: priority_mask = 0; break;
425 case 0x1: priority_mask = 0xf0; break; /* obscured by text layer */
426 case 0x2: priority_mask = 0xf0 | 0xcc; break; /* obscured by foreground */
427 case 0x3: priority_mask = 0xf0 | 0xcc | 0xaa; break; /* obscured by bg and fg */
428 }
429
430 /* blending */
431 if (blend_support && (attributes & 0x20))
432 {
433 color |= 0x80;
434
435 for (row = 0; row < sizey; row++)
436 {
437 for (col = 0; col < sizex; col++)
438 {
439 int sx = xpos + 8 * (flipx ? (sizex - 1 - col) : col);
440 int sy = ypos + 8 * (flipy ? (sizey - 1 - row) : row);
441
442 pdrawgfx(bitmap_sp, gfx,
443 number + layout[row][col],
444 color,
445 flipx, flipy,
446 sx, sy,
447 cliprect, TRANSPARENCY_PEN, 0,
448 priority_mask);
449 }
450 }
451 }
452 else
453 {
454 if (blend_support)
455 bitmap = (priority >= 2) ? bitmap_bg : bitmap_fg;
456
457 for (row = 0; row < sizey; row++)
458 {
459 for (col = 0; col < sizex; col++)
460 {
461 int sx = xpos + 8 * (flipx ? (sizex - 1 - col) : col);
462 int sy = ypos + 8 * (flipy ? (sizey - 1 - row) : row);
463
464 pdrawgfx(bitmap, gfx,
465 number + layout[row][col],
466 color,
467 flipx, flipy,
468 sx, sy,
469 cliprect, TRANSPARENCY_PEN, 0,
470 priority_mask);
471 }
472 }
473 }
474 }
475 skip_sprite:
476 source -= 8;
477 }
478 }
479
VIDEO_UPDATE(gaiden)480 VIDEO_UPDATE( gaiden )
481 {
482 fillbitmap(priority_bitmap, 0, cliprect);
483 fillbitmap(bitmap, Machine->pens[0x200], cliprect);
484
485 tilemap_draw(bitmap, cliprect, background, 0, 1);
486 tilemap_draw(bitmap, cliprect, foreground, 0, 2);
487 tilemap_draw(bitmap, cliprect, text_layer, 0, 4);
488
489 draw_sprites(bitmap, NULL, NULL, cliprect);
490 }
491
VIDEO_UPDATE(raiga)492 VIDEO_UPDATE( raiga )
493 {
494 fillbitmap(priority_bitmap, 0, cliprect);
495
496 fillbitmap(tile_bitmap_bg, 0x200, cliprect);
497 fillbitmap(tile_bitmap_fg, 0, cliprect);
498 fillbitmap(sprite_bitmap, 0, cliprect);
499
500 /* draw tilemaps into a 16-bit bitmap */
501 tilemap_draw(tile_bitmap_bg, cliprect,background, 0, 1);
502 tilemap_draw(tile_bitmap_fg, cliprect,foreground, 0, 2);
503 /* draw the blended tiles at a lower priority
504 so sprites covered by them will still be drawn */
505 tilemap_draw(tile_bitmap_fg, cliprect,foreground, 1, 0);
506 tilemap_draw(tile_bitmap_fg, cliprect,text_layer, 0, 4);
507
508 /* draw sprites into a 16-bit bitmap */
509 draw_sprites(tile_bitmap_bg, tile_bitmap_fg, sprite_bitmap, cliprect);
510
511 /* mix & blend the tilemaps and sprites into a 32-bit bitmap */
512 blendbitmaps(bitmap, tile_bitmap_bg, tile_bitmap_fg, sprite_bitmap, 0, 0, cliprect);
513 }
514