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); |