trunk/src/mame/video/twin16.c
r241616 | r241617 | |
19 | 19 | |
20 | 20 | enum |
21 | 21 | { |
22 | | TWIN16_SCREEN_FLIPY = 0x01, |
23 | | TWIN16_SCREEN_FLIPX = 0x02, // confirmed: Hard Puncher Intro |
24 | | TWIN16_UNKNOWN_PRI0 = 0x04, // ? Hard Puncher uses this |
25 | | TWIN16_PLANE_ORDER = 0x08, // confirmed: Devil Worlds |
26 | | TWIN16_UNKNOWN_PRI2 = 0x10, // unused? |
27 | | TWIN16_TILE_FLIPY = 0x20 // confirmed: Vulcan Venture |
| 22 | TWIN16_SCREEN_FLIPY = 0x01, |
| 23 | TWIN16_SCREEN_FLIPX = 0x02, // confirmed: Hard Puncher Intro |
| 24 | TWIN16_PRI0 = 0x04, // PRI0 input into 007789 PAL |
| 25 | TWIN16_PRI1 = 0x08, // PRI1 input into 007789 PAL |
| 26 | TWIN16_PRI2_UNUSED = 0x10, // schematic shows as PRI2 input, but unused |
| 27 | TWIN16_TILE_FLIPY = 0x20 // confirmed: Vulcan Venture |
28 | 28 | }; |
29 | 29 | |
30 | 30 | enum |
31 | 31 | { |
32 | 32 | // user-defined priorities |
33 | | TWIN16_BG_LAYER1 = 0x01, |
34 | | TWIN16_SPRITE_PRI_L1 = 0x02, |
35 | | TWIN16_BG_LAYER2 = 0x04, |
36 | | TWIN16_SPRITE_PRI_L2 = 0x08, |
37 | | TWIN16_SPRITE_OCCUPIED = 0x10, // sprite on screen pixel |
38 | | TWIN16_SPRITE_CAST_SHADOW = 0x20 |
| 33 | TWIN16_BG_OVER_SPRITES = 0x01, // BG pixel has priority over opaque sprite pixels |
| 34 | TWIN16_BG_NO_SHADOW = 0x02, // BG pixel has priority over shadow sprite pixels |
| 35 | TWIN16_SPRITE_OCCUPIED = 0x04 |
39 | 36 | }; |
40 | 37 | |
41 | 38 | |
r241616 | r241617 | |
177 | 174 | * 2 | -------xxxxxxxxx | xpos |
178 | 175 | * -----+------------------+ |
179 | 176 | * 3 | x--------------- | enable |
180 | | * 3 | -x-------------- | priority ? |
181 | | * 3 | -----x---------- | no shadow ? |
| 177 | * 3 | -xxxxx---------- | ? |
182 | 178 | * 3 | ------x--------- | yflip ? |
183 | 179 | * 3 | -------x-------- | xflip |
184 | 180 | * 3 | --------xx------ | height |
r241616 | r241617 | |
230 | 226 | UINT32 xpos = (0x10000*source[4])|source[5]; |
231 | 227 | UINT32 ypos = (0x10000*source[6])|source[7]; |
232 | 228 | |
233 | | /* notes on uncertain attributes: |
234 | | shadows: pen $F only (like other Konami hw), used in devilw, fround, |
235 | | miaj? (shadows are solid in tmnt hw version), |
236 | | gradius2? (ship exhaust) |
| 229 | /* notes on sprite attributes: |
237 | 230 | |
238 | | sprite-background priority: in devilw, most sprites look best at high priority, |
239 | | in gradius2, most sprites look best at low priority. exceptions: |
240 | | - devilw prologue: sprites behind crowd (maybe more, haven't completed the game) |
241 | | - gradius2 intro showing earlier games: sprites above layers |
| 231 | The only inputs from the sprite hardware into the mixer PAL are four bits of |
| 232 | pixel data, with 0000 being transparent, 1111 being shadow, and anything else |
| 233 | opaque. Sprite to background priority, and whether shadows are visible, depends |
| 234 | entirely on the priority mode bits in m_video_register and on the underlying |
| 235 | background pixel, and not on any of the sprite attribute bits. |
242 | 236 | |
243 | | currently using (priority&0x200), broken: |
244 | | - devilw prologue: sprites should be behind crowd |
245 | | - gradius2 level 7: bosses should be behind portal (ok except brain boss and mouth boss) |
246 | | - gradius2 ending: sun should be behind planet |
| 237 | Shadows in the devilw lava stages look a bit strange; the shadows "punch holes" |
| 238 | in the platforms and reveal the lava underneath. As far as I can tell from the |
| 239 | schematics this has to be correct; unlike later Konami hardware there seems to |
| 240 | be no way for a sprite to cast a shadow onto another sprite. |
247 | 241 | |
248 | | does TWIN16_PLANE_ORDER affect it? |
249 | | |
250 | | more? |
251 | | devilw monster dens exploding monochrome, players fading to white in prologue, and trees in |
252 | | the 1st level shrinking with a solid green color look odd, maybe alpha blended? |
253 | | |
254 | | fround, hpuncher, miaj, cuebrickj, don't use the preprocessor. all sprites are expected |
255 | | to be high priority, and shadows are enabled |
| 242 | fround, hpuncher, miaj, cuebrickj, don't use the preprocessor. |
256 | 243 | */ |
257 | | UINT16 attributes = 0x8000| // enabled |
258 | | (source[2]&0x03ff)| // scale,size,color |
259 | | (source[2]&0x4000)>>4| // no-shadow? (gradius2 level 7 boss sets this bit and appears to expect pen $F to be solid) |
260 | | (priority&0x200)<<5; // sprite-background priority? |
| 244 | UINT16 attributes = 0x8000 | (source[2]&0x03ff); // scale,size,color |
261 | 245 | |
262 | 246 | dest[0] = source[3]; /* gfx data */ |
263 | 247 | dest[1] = ((xpos>>8) - dx)&0xffff; |
r241616 | r241617 | |
291 | 275 | const UINT16 *pen_data = 0; |
292 | 276 | int flipy = attributes&0x0200; |
293 | 277 | int flipx = attributes&0x0100; |
294 | | int priority = (attributes&0x4000)?TWIN16_SPRITE_PRI_L1:TWIN16_SPRITE_PRI_L2; |
295 | 278 | |
296 | 279 | if( m_is_fround ) { |
297 | 280 | /* fround board */ |
r241616 | r241617 | |
360 | 343 | { |
361 | 344 | UINT16 pen = pen_data[x>>2]>>((~x&3)<<2)&0xf; |
362 | 345 | |
363 | | if( pen ) |
| 346 | if( pen && !(pdest[sx] & TWIN16_SPRITE_OCCUPIED)) |
364 | 347 | { |
365 | | int shadow = (pen==0xf) & ((attributes&0x400)==0); |
| 348 | pdest[sx] |= TWIN16_SPRITE_OCCUPIED; |
366 | 349 | |
367 | | if (pdest[sx]<priority) { |
368 | | if (shadow) { |
| 350 | if (pen==0xf) // shadow |
| 351 | { |
| 352 | if (!(pdest[sx] & TWIN16_BG_NO_SHADOW)) |
369 | 353 | dest[sx] = m_palette->shadow_table()[dest[sx]]; |
370 | | pdest[sx]|=TWIN16_SPRITE_CAST_SHADOW; |
371 | | } |
372 | | else { |
| 354 | } |
| 355 | else // opaque pixel |
| 356 | { |
| 357 | if (!(pdest[sx] & TWIN16_BG_OVER_SPRITES)) |
373 | 358 | dest[sx] = pal_base + pen; |
374 | | } |
375 | 359 | } |
376 | | else if (!shadow && pdest[sx]&TWIN16_SPRITE_CAST_SHADOW && (pdest[sx]&0xf)<priority) { |
377 | | // shadow cast onto sprite below, evident in devilw lava level |
378 | | dest[sx] = m_palette->shadow_table()[pal_base + pen]; |
379 | | pdest[sx]^=TWIN16_SPRITE_CAST_SHADOW; |
380 | | } |
381 | | |
382 | | pdest[sx]|=TWIN16_SPRITE_OCCUPIED; |
383 | 360 | } |
384 | 361 | } |
385 | 362 | } |
r241616 | r241617 | |
412 | 389 | void twin16_state::tile_get_info(tile_data &tileinfo, UINT16 data, int color_base) |
413 | 390 | { |
414 | 391 | /* fedcba9876543210 |
415 | | xxx------------- color |
| 392 | xxx------------- color; high bit is also priority over sprites |
416 | 393 | ---xxxxxxxxxxxxx tile number |
417 | 394 | */ |
418 | 395 | int code = (data & 0x1fff); |
r241616 | r241617 | |
420 | 397 | int flags = 0; |
421 | 398 | if (m_video_register & TWIN16_TILE_FLIPY) flags |= TILE_FLIPY; |
422 | 399 | SET_TILE_INFO_MEMBER(1, code, color, flags); |
| 400 | tileinfo.category = BIT(data, 15); |
423 | 401 | } |
424 | 402 | |
425 | 403 | void fround_state::tile_get_info(tile_data &tileinfo, UINT16 data, int color_base) |
426 | 404 | { |
427 | 405 | /* fedcba9876543210 |
428 | | xxx------------- color |
| 406 | xxx------------- color; high bit is also priority over sprites |
429 | 407 | ---xx----------- tile bank |
430 | 408 | -----xxxxxxxxxxx tile number |
431 | 409 | */ |
r241616 | r241617 | |
435 | 413 | int flags = 0; |
436 | 414 | if (m_video_register & TWIN16_TILE_FLIPY) flags |= TILE_FLIPY; |
437 | 415 | SET_TILE_INFO_MEMBER(1, code, color, flags); |
| 416 | tileinfo.category = BIT(data, 15); |
438 | 417 | } |
439 | 418 | |
440 | 419 | TILE_GET_INFO_MEMBER(twin16_state::layer0_tile_info) |
r241616 | r241617 | |
483 | 462 | |
484 | 463 | UINT32 twin16_state::screen_update_twin16(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect) |
485 | 464 | { |
486 | | int layer = m_video_register & TWIN16_PLANE_ORDER ? 0 : 1; |
| 465 | /* |
| 466 | PAL equations (007789 @ 11J): |
487 | 467 | |
488 | | m_scroll_tmap[layer]->draw(screen, bitmap, cliprect, TILEMAP_DRAW_OPAQUE, TWIN16_BG_LAYER1, 0); |
489 | | m_scroll_tmap[layer^1]->draw(screen, bitmap, cliprect, 0, TWIN16_BG_LAYER2); |
| 468 | /SHAD = /FIX * /PRI1 * OCO0 * OCO1 * OCO2 * OCO3 |
| 469 | + /FIX * /PRI0 * OCO0 * OCO1 * OCO2 * OCO3 * /V1C0 |
| 470 | + /FIX * PRI0 * OCO0 * OCO1 * OCO2 * OCO3 * /V2C6 |
| 471 | + /FIX * PRI0 * /V2C0 * /V2C3 * OCO0 * /V2C2 * OCO1 * /V2C1 * OCO2 * OCO3 |
490 | 472 | |
| 473 | /SELB = /FIX * OCO0 * OCO1 * OCO2 * OCO3 |
| 474 | + /FIX * /OCO0 * /OCO1 * /OCO2 * /OCO3 |
| 475 | + /FIX * PRI0 * /PRI1 * V1C0 |
| 476 | + /FIX * PRI0 * PRI1 * V2C0 * V2C6 |
| 477 | + /FIX * PRI0 * PRI1 * V2C1 * V2C6 |
| 478 | + /FIX * PRI0 * PRI1 * V2C2 * V2C6 |
| 479 | + /FIX * PRI0 * PRI1 * V2C3 * V2C6 |
| 480 | |
| 481 | SELA = FIX |
| 482 | + PRI0 * /PRI1 * V1C0 |
| 483 | + /PRI1 * OCO0 * OCO1 * OCO2 * OCO3 * V1C0 |
| 484 | + /PRI1 * /OCO0 * /OCO1 * /OCO2 * /OCO3 * V1C0 |
| 485 | + PRI1 * /V2C0 * /V2C3 * OCO0 * /V2C2 * OCO1 * /V2C1 * OCO2 * OCO3 |
| 486 | + PRI1 * /V2C0 * /V2C3 * /OCO0 * /V2C2 * /OCO1 * /V2C1 * /OCO2 * /OCO3 |
| 487 | |
| 488 | SELB SELA Visible layer |
| 489 | 0 0 VRAM2 |
| 490 | 0 1 VRAM1 |
| 491 | 1 0 Object |
| 492 | 1 1 Fix |
| 493 | */ |
| 494 | screen.priority().fill(0, cliprect); |
| 495 | |
| 496 | switch ((m_video_register >> 2) & 0x3) |
| 497 | { |
| 498 | case 0: // PRI1 = 0, PRI0 = 0 |
| 499 | m_scroll_tmap[1]->draw(screen, bitmap, cliprect, TILEMAP_DRAW_ALL_CATEGORIES | TILEMAP_DRAW_OPAQUE); |
| 500 | m_scroll_tmap[0]->draw(screen, bitmap, cliprect, TILEMAP_DRAW_ALL_CATEGORIES); |
| 501 | break; |
| 502 | case 1: // PRI1 = 0, PRI0 = 1 |
| 503 | m_scroll_tmap[1]->draw(screen, bitmap, cliprect, TILEMAP_DRAW_ALL_CATEGORIES | TILEMAP_DRAW_OPAQUE); |
| 504 | m_scroll_tmap[0]->draw(screen, bitmap, cliprect, TILEMAP_DRAW_ALL_CATEGORIES, TWIN16_BG_OVER_SPRITES); |
| 505 | break; |
| 506 | case 2: // PRI1 = 1, PRI0 = 0 |
| 507 | m_scroll_tmap[0]->draw(screen, bitmap, cliprect, TILEMAP_DRAW_ALL_CATEGORIES | TILEMAP_DRAW_OPAQUE); |
| 508 | m_scroll_tmap[0]->draw(screen, bitmap, cliprect, TILEMAP_DRAW_ALL_CATEGORIES, TWIN16_BG_NO_SHADOW); |
| 509 | m_scroll_tmap[1]->draw(screen, bitmap, cliprect, TILEMAP_DRAW_ALL_CATEGORIES); |
| 510 | break; |
| 511 | case 3: // PRI1 = 1, PRI0 = 1 |
| 512 | m_scroll_tmap[0]->draw(screen, bitmap, cliprect, TILEMAP_DRAW_ALL_CATEGORIES | TILEMAP_DRAW_OPAQUE); |
| 513 | m_scroll_tmap[1]->draw(screen, bitmap, cliprect, 0); |
| 514 | m_scroll_tmap[1]->draw(screen, bitmap, cliprect, 1, TWIN16_BG_OVER_SPRITES | TWIN16_BG_NO_SHADOW); |
| 515 | break; |
| 516 | } |
| 517 | |
491 | 518 | draw_sprites( screen, bitmap ); |
492 | 519 | |
493 | 520 | m_fixed_tmap->draw(screen, bitmap, cliprect, 0); |