diff options
-rw-r--r-- | src/mame/video/hng64.c | 546 | ||||
-rw-r--r-- | src/mame/video/hng64_3d.c | 155 |
2 files changed, 333 insertions, 368 deletions
diff --git a/src/mame/video/hng64.c b/src/mame/video/hng64.c index 45f4f26e7f0..fe9bfcd8d9b 100644 --- a/src/mame/video/hng64.c +++ b/src/mame/video/hng64.c @@ -8,143 +8,6 @@ #define HNG64_VIDEO_DEBUG 0 - - -/* Transition Control Video Registers - * ---------------------------------- - * - * UINT32 | Bits | Use - * | 3322 2222 2222 1111 1111 11 | - * -------+-1098-7654-3210-9876-5432-1098-7654-3210-+---------------- - * 0 | | - * 1 | xxxx xxxx xxxx xxxx yyyy yyyy yyyy yyyy | Min X / Min Y visible area rectangle values - * 2 | xxxx xxxx xxxx xxxx yyyy yyyy yyyy yyyy | Max X / Max Y visible area rectangle values (added up with the Min X / Min Y) - * 3 | | - * 4 | | - * 5 | ---- ---- ---- ---? ---- --?? ???? ???? | Global Fade In/Fade Out control - * 6 | | - * 7 | ---- ---- xxxx xxxx xxxx xxxx xxxx xxxx | Port A of RGB fade (subtraction) - * 8 | | - * 9 | ---- ---- ---- ---? ---- ---- ---- ???? | Per-layer Fade In/Fade Out control - * 10 | ---- ---- xxxx xxxx xxxx xxxx xxxx xxxx | Port B of RGB fade (additive) - * 11 | xxxx xxxx xxxx xxxx xxxx xxxx xxxx xxxx | Unknown - looks like an ARGB value - it seems to change when the scene changes - * 12 | | - * 13 | | - * 14 | | - * 15 | | - * 16 | | - * 17 | | - * 18 | xxxx xxxx xxxx xxxx xxxx xxxx xxxx xxxx | V-Blank related stuff - * 19 | | - * 20 | ---- ---- ---- ---x ---- ---- ---- ---- | Back layer control register? - * 21 | | - * 22 | | - * 23 | | - * 24 | | - * - * - * - * Various bits change depending on what is happening in the scene. - * These bits may set which 'layer' is affected by the blending. - * Or maybe they adjust the scale of the lightening and darkening... - * Or maybe it switches from fading by scaling to fading using absolute addition and subtraction... - * Or maybe they set transition type (there seems to be a cute scaling-squares transition in there somewhere)... - */ - -/* this is broken for the 'How to Play' screen in Buriki after attract, disabled for now */ -void hng64_state::transition_control( bitmap_rgb32 &bitmap, const rectangle &cliprect) -{ - int i, j; - -// float colorScaleR, colorScaleG, colorScaleB; - INT32 finR, finG, finB; - - INT32 darkR, darkG, darkB; - INT32 brigR, brigG, brigB; - - // If either of the fading memory regions is non-zero... - if (m_tcram[0x00000007] != 0x00000000 || m_tcram[0x0000000a] != 0x00000000) - { - darkR = (INT32)( m_tcram[0x00000007] & 0xff); - darkG = (INT32)((m_tcram[0x00000007] >> 8) & 0xff); - darkB = (INT32)((m_tcram[0x00000007] >> 16) & 0xff); - - brigR = (INT32)( m_tcram[0x0000000a] & 0xff); - brigG = (INT32)((m_tcram[0x0000000a] >> 8) & 0xff); - brigB = (INT32)((m_tcram[0x0000000a] >> 16) & 0xff); - - for (i = cliprect.min_x; i < cliprect.max_x; i++) - { - for (j = cliprect.min_y; j < cliprect.max_y; j++) - { - rgb_t* thePixel = reinterpret_cast<rgb_t *>(&bitmap.pix32(j, i)); - - finR = (INT32)thePixel->r(); - finG = (INT32)thePixel->g(); - finB = (INT32)thePixel->b(); - -#if 0 - // Apply the darkening pass (0x07)... - colorScaleR = 1.0f - (float)( m_tcram[0x00000007] & 0xff) / 255.0f; - colorScaleG = 1.0f - (float)((m_tcram[0x00000007] >> 8) & 0xff) / 255.0f; - colorScaleB = 1.0f - (float)((m_tcram[0x00000007] >> 16) & 0xff) / 255.0f; - - finR = ((float)thePixel->r() * colorScaleR); - finG = ((float)thePixel->g() * colorScaleG); - finB = ((float)thePixel->b() * colorScaleB); - - - // Apply the lightening pass (0x0a)... - colorScaleR = 1.0f + (float)( m_tcram[0x0000000a] & 0xff) / 255.0f; - colorScaleG = 1.0f + (float)((m_tcram[0x0000000a] >> 8) & 0xff) / 255.0f; - colorScaleB = 1.0f + (float)((m_tcram[0x0000000a] >> 16) & 0xff) / 255.0f; - - finR *= colorScaleR; - finG *= colorScaleG; - finB *= colorScaleB; - - - // Clamp - if (finR > 255.0f) finR = 255.0f; - if (finG > 255.0f) finG = 255.0f; - if (finB > 255.0f) finB = 255.0f; -#endif - - - // Subtractive fading - if (m_tcram[0x00000007] != 0x00000000) - { - finR -= darkR; - finG -= darkG; - finB -= darkB; - } - - // Additive fading - if (m_tcram[0x0000000a] != 0x00000000) - { - finR += brigR; - finG += brigG; - finB += brigB; - } - - // Clamp the high end - if (finR > 255) finR = 255; - if (finG > 255) finG = 255; - if (finB > 255) finB = 255; - - // Clamp the low end - if (finR < 0) finR = 0; - if (finG < 0) finG = 0; - if (finB < 0) finB = 0; - - *thePixel = rgb_t(255, (UINT8)finR, (UINT8)finG, (UINT8)finB); - } - } - } -} - - - void hng64_state::hng64_mark_all_tiles_dirty( int tilemap ) { m_tilemap[tilemap].m_tilemap_8x8->mark_all_dirty(); @@ -305,7 +168,6 @@ WRITE32_MEMBER(hng64_state::hng64_videoram_w) { hng64_mark_tile_dirty(3, offset&0x3fff); } - // Offsets 0x40000 - 0x58000 are for "floor" scanline control /* 400000 - 7fffff is scroll regs etc. */ @@ -573,12 +435,11 @@ void hng64_state::hng64_tilemap_draw_roz_primask(screen_device &screen, bitmap_r { blit_parameters blit; -/* notes: - - startx and starty MUST be UINT32 for calculations to work correctly - - srcbitmap->width and height are assumed to be a power of 2 to speed up wraparound - */ + // notes: + // - startx and starty MUST be UINT32 for calculations to work correctly + // - srcbitmap->width and height are assumed to be a power of 2 to speed up wraparound - /* skip if disabled */ + // skip if disabled //if (!tmap->enable) // return; @@ -604,11 +465,69 @@ inline void hng64_state::hng64_tilemap_draw_roz(screen_device &screen, bitmap_rg -void hng64_state::hng64_drawtilemap(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect, int tm ) +/* + * Video Regs Format (appear to just be tilemap regs) + * -------------------------------------------------- + * + * UINT32 | Bits | Use + * | 3322 2222 2222 1111 1111 11 | + * -------+-1098-7654-3210-9876-5432-1098-7654-3210-+---------------- + * 0 | ---- -Cdd ---- -??Z ---- ---- ---- ---- | C = global complex zoom + | 0000 0011 - road edge alt 1 | dd = global tilemap dimension selector + | 0000 0111 - road edge alt 2 | ? = Always Set? + | | Z = Global Zoom Disable? + * 1 | oooo oooo oooo oooo ---- ---- ---- ---- | unknown - 0001 is a popular value. Explore. + * 1 | ---- ---- ---- ---- oooo oooo oooo oooo | unknown - untouched in sams64 games, initialized elsewhere + * 2 | xxxx xxxx xxxx xxxx ---- ---- ---- ---- | tilemap0 per layer flags + * 2 | ---- ---- ---- ---- xxxx xxxx xxxx xxxx | tilemap1 per layer flags + * 3 | xxxx xxxx xxxx xxxx ---- ---- ---- ---- | tilemap2 per layer flags + * 3 | ---- ---- ---- ---- xxxx xxxx xxxx xxxx | tilemap3 per layer flags + * 4 | xxxx xxxx xxxx xxxx ---- ---- ---- ---- | tilemap0 scrollbase when not floor, lineram offset when floor + * 4 | ---- ---- ---- ---- xxxx xxxx xxxx xxxx | tilemap1 scrollbase when not floor, lineram offset when floor + * 5 | xxxx xxxx xxxx xxxx ---- ---- ---- ---- | tilemap3 scrollbase when not floor, lineram offset when floor + * 5 | ---- ---- ---- ---- xxxx xxxx xxxx xxxx | tilemap4 scrollbase when not floor, lineram offset when floor + * 6 | oooo oooo oooo oooo oooo oooo oooo oooo | unknown - always seems to be 000001ff (fatfurwa) + * 7 | oooo oooo oooo oooo oooo oooo oooo oooo | unknown - always seems to be 000001ff (fatfurwa) + * 8 | oooo oooo oooo oooo oooo oooo oooo oooo | unknown - always seems to be 80008000 (fatfurwa) + * 9 | oooo oooo oooo oooo oooo oooo oooo oooo | unknown - always seems to be 00000000 (fatfurwa) + * a | oooo oooo oooo oooo oooo oooo oooo oooo | unknown - always seems to be 00000000 (fatfurwa) + * b | mmmm mmmm mmmm mmmm mmmm mmmm mmmm mmmm | auto animation mask for tilemaps + * c | xxxx xxxx xxxx xxxx xxxx xxxx xxxx xxxx | auto animation bits for tilemaps + * d | oooo oooo oooo oooo oooo oooo oooo oooo | not used ?? + * e | oooo oooo oooo oooo oooo oooo oooo oooo | not used ?? + + // tilemap0 per layer flags + // 0840 - startup tests, 8x8x4 layer + // 0cc0 - beast busters 2, 8x8x8 layer + // 0860 - fatal fury wa + // 08e0 - fatal fury wa during transitions + // 0940 - samurai shodown 64 + // 0880 - buriki + + // Individual tilemap regs format + // ------------------------------ + // mmmm dbr? ??ez zzzz + // m = Tilemap mosaic level [0-15] - confirmed in sams64 demo mode + // -- they seem to enable mosaic at the same time as rowscroll in several cases (floor in buriki / ff) + // and also on the rotating logo in buriki.. does it cause some kind of aliasing side-effect, or.. ? + // d = line (floor) mode - buriki, fatafurwa, some backgrounds in ss64_2 + // b = 4bpp/8bpp (seems correct) (beast busters, samsh64, sasm64 2, xrally switch it for some screens) + // r = tile size (seems correct) + // e = tilemap enable bit according to sams64_2 + // z = z depth/priority? tilemaps might also be affected by min / max clip values somewhere? + // (debug layer on buriki has priority 0x020, which would be highest) + */ + + +void hng64_state::hng64_drawtilemap(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect, int tm) { - const UINT32 global_tileregs = m_videoregs[0x00]; + // Useful bits from the global tilemap flags + const UINT32& global_tileregs = m_videoregs[0x00]; const int global_dimensions = (global_tileregs & 0x03000000) >> 24; - + const int global_alt_scroll_register_format = global_tileregs & 0x04000000; + const int global_zoom_disable = global_tileregs & 0x00010000; + + // Debug blending on/off based on m_additive_tilemap_debug int debug_blend_enabled = 0; if ((m_additive_tilemap_debug&(1 << tm))) debug_blend_enabled = 1; @@ -618,8 +537,9 @@ void hng64_state::hng64_drawtilemap(screen_device &screen, bitmap_rgb32 &bitmap, popmessage("unsupported global_dimensions on tilemaps"); #endif - UINT32 scrollbase = 0; - UINT32 tileregs = 0; + // Determine which tilemap registers and scroll base this tilemap uses + UINT16 tileregs = 0; + UINT16 scrollbase = 0; if (tm==0) { scrollbase = (m_videoregs[0x04]&0x3fff0000)>>16; @@ -641,71 +561,68 @@ void hng64_state::hng64_drawtilemap(screen_device &screen, bitmap_rgb32 &bitmap, tileregs = (m_videoregs[0x03]&0x0000ffff)>>0; } + // Useful bits from the tilemap registers + const UINT8 mosaicValueBits = (tileregs & 0xf000) >> 12; (void)mosaicValueBits; + const UINT8 floorModeBit = (tileregs & 0x0800) >> 11; + const UINT8 bppBit = (tileregs & 0x0400) >> 10; + const UINT8 bigTilemapBit = (tileregs & 0x0200) >> 9; + const UINT8 tilemapEnableBit = (tileregs & 0x0040) >> 6; (void)tilemapEnableBit; + + // Tilemap drawing enable (sams64_2 demo mode says this is legit) + //if (!tilemapEnableBit) + //{ + // return; + //} + + // Select the proper tilemap size tilemap_t* tilemap = NULL; if (global_dimensions==0) { - if (tileregs&0x0200) tilemap = m_tilemap[tm].m_tilemap_16x16; + if (bigTilemapBit) tilemap = m_tilemap[tm].m_tilemap_16x16; else tilemap = m_tilemap[tm].m_tilemap_8x8; } else { - if (tileregs&0x0200) tilemap = m_tilemap[tm].m_tilemap_16x16_alt; + if (bigTilemapBit) tilemap = m_tilemap[tm].m_tilemap_16x16_alt; else tilemap = m_tilemap[tm].m_tilemap_8x8; // _alt } - // set the transmask so our manual copy is correct + // Set the transmask so our manual copy is correct int transmask = 0x00; - if (tileregs & 0x0400) + if (bppBit) transmask = 0xff; else transmask = 0xf; - // buriki tm1 = roz - - // my life would be easier if the roz we're talking about for complex zoom wasn't setting this as well - if ((tileregs & 0x0800)==0x0000) // floor mode -- could actually be related to ((tileregs & 0xf000) == 0x1000). + if (floorModeBit == 0x0000) { + // floor mode + // life would be easier if the roz we're talking about for complex zoom wasn't setting this as well + // fprintf(stderr, "Tilemap %d is a floor using :\n", tm); + const UINT32 floorAddress = 0x40000 + (scrollbase << 4); - // Floor buffer enables - // TODO: the upper bit(s) in here are probably useful to check as well - const int floorInner0 = (m_videoregs[0x04] & 0x00000600) >> 9; - const int floorInner1 = (m_videoregs[0x05] & 0x06000000) >> 25; (void)floorInner1; - const int floorInner2 = (m_videoregs[0x05] & 0x00000600) >> 9; - const int floorOuter0 = (m_videoregs[0x04] & 0x00001800) >> 11; - const int floorOuter1 = (m_videoregs[0x05] & 0x18000000) >> 27; (void)floorOuter1; - const int floorOuter2 = (m_videoregs[0x05] & 0x00001800) >> 11; - // fprintf(stderr, "Buffers %d-%d %d-%d %d-%d\n", floorOuter2, floorInner2, floorOuter1, floorInner1, floorOuter0, floorInner0); + // TODO: The row count is correct, but how is this layer clipped? m_tcram? - // TODO: This can likely be simplified with some &s and some <<s, but this works for now - const UINT32 address0 = 0x40000 + (floorOuter0 * 0x8000) + (floorInner0 * 0x2000); - const UINT32 address1 = 0x40000 + (floorOuter1 * 0x8000) + (floorInner1 * 0x2000); (void)address1; - const UINT32 address2 = 0x40000 + (floorOuter2 * 0x8000) + (floorInner2 * 0x2000); - - // TODO: Some bit somewhere probably specifies scissor layers, but for now we switch based on game :-( - const UINT32& dataAddress = (m_mcu_type == BURIKI_MCU) ? address0 : address2; - const UINT32& scissorAddress0 = address1; (void)scissorAddress0; - const UINT32& scissorAddress1 = (m_mcu_type == BURIKI_MCU) ? address2 : address0; (void)scissorAddress1; - //printf("dataAddress: %08x scissorAddress0: %08x scissorAddress1: %08x\n", dataAddress, scissorAddress0, scissorAddress1); - // See how many lines we have in the data region - // TODO: Change this to a loop that goes over each line and draws them - it's just for visualization now - int lineCount = 0; - for (int ii = 0; ii < 0x2000/4; ii += 4) - { - const int realAddress = dataAddress/4; - if (m_videoram[realAddress+ii] == 0xffffff00 && m_videoram[realAddress+ii+1] == 0xffffff00) - continue; - if (m_videoram[realAddress+ii] == 0x00000000 && m_videoram[realAddress+ii+1] == 0x00000000) - continue; - - lineCount++; - } + // DEBUG: Change this to a loop that goes over each line and draws them - it's just for visualization now + //int lineCount = 0; + //for (int ii = 0; ii < 0x2000/4; ii += 4) + //{ + // const int realAddress = floorAddress/4; + // if (m_videoram[realAddress+ii] == 0xffffff00 && m_videoram[realAddress+ii+1] == 0xffffff00) + // continue; + // if (m_videoram[realAddress+ii] == 0x00000000 && m_videoram[realAddress+ii+1] == 0x00000000) + // continue; + // + // lineCount++; + //} //printf("lines %d\n", lineCount); // Buriki uses a 2x mosaic effect on its floor, so its line count is half - if (m_mcu_type == BURIKI_MCU) - lineCount *= 2; + // (but so does fatfurwa - maybe it overdraws a bunch of pixels?) + //if (m_mcu_type == BURIKI_MCU) + // lineCount *= 2; // DEBUG - draw a horizontal green line where the uppermost line of the floor is drawn const rectangle &visarea = screen.visible_area(); @@ -715,26 +632,21 @@ void hng64_state::hng64_drawtilemap(screen_device &screen, bitmap_rgb32 &bitmap, // bitmap.pix32((visarea.height()-lineCount), ii) = 0xff00ff00; //} - // HACK : Clear ram - this is "needed" in fatfurwa since it doesn't clear its own ram (buriki does) + // HACK : Clear RAM - this is "needed" in fatfurwa since it doesn't clear its own ram (buriki does) // Figure out what the difference between the two programs is. It's possible writing to // the linescroll ram fills a buffer and it's cleared automatically between frames? for (int ii = 0; ii < 0x2000/4; ii++) { - const int realAddress = dataAddress/4; + const int realAddress = floorAddress/4; m_videoram[realAddress+ii] = 0x00000000; } - //if ((tileregs&0xf000) == 0x1000) - //{ - // popmessage("Floor is Active"); - //} - // Floor mode - per pixel simple / complex modes? -- every other line? // (there doesn't seem to be enough data in Buriki for every line at least) rectangle clip = visarea; - if (global_tileregs&0x04000000) // globally selects alt scroll register layout??? + if (global_alt_scroll_register_format) // globally selects alt scroll register layout??? { // Logic would dictate that this should be the 'complex' scroll register layout, // but per-line. That doesn't work however. @@ -763,7 +675,7 @@ void hng64_state::hng64_drawtilemap(screen_device &screen, bitmap_rgb32 &bitmap, { clip.min_y = clip.max_y = line; - if (m_videoregs[0x00]&0x00010000) // disable all scrolling / zoom (test screen) (maybe) + if (global_zoom_disable) // disable all scrolling / zoom (test screen) (maybe) { // If this bit is active the scroll registers don't seem valid at all? // It either disables zooming, or disables use of the scroll registers completely @@ -795,13 +707,9 @@ void hng64_state::hng64_drawtilemap(screen_device &screen, bitmap_rgb32 &bitmap, } else { -#if HNG64_VIDEO_DEBUG - if ((tileregs&0xf000)) - popmessage("Tilemap Mosaic? %02x", tileregs>>12); -#endif // 0x1000 is set up the buriki 2nd title screen with rotating logo and in fatal fury at various times? - if (global_tileregs&0x04000000) // globally selects alt scroll register layout??? + if (global_alt_scroll_register_format) // globally selects alt scroll register layout??? { /* complex zoom mode? */ /* with this scroll register layout rotation effects are possible @@ -925,7 +833,7 @@ void hng64_state::hng64_drawtilemap(screen_device &screen, bitmap_rgb32 &bitmap, m_videoram[(0x4001c+(scrollbase<<4))/4]); #endif - if (m_videoregs[0x00]&0x00010000) // disable all scrolling / zoom (test screen) (maybe) + if (global_zoom_disable) // disable all scrolling / zoom (test screen) (maybe) { /* If this bit is active the scroll registers don't seem valid at all? It either disables zooming, or disables use of the scroll registers completely @@ -1003,63 +911,6 @@ void hng64_state::hng64_drawtilemap(screen_device &screen, bitmap_rgb32 &bitmap, } - -/* - * Video Regs Format - * ------------------ - * - * UINT32 | Bits | Use - * | 3322 2222 2222 1111 1111 11 | - * -------+-1098-7654-3210-9876-5432-1098-7654-3210-+---------------- - * 0 | ---- -C-- ---- -??Z ---- ---- ---- ---- | unknown (scroll control?) C = Global Complex zoom, ? = Always Set?, Z = Global Zoom Disable? - 0000 0011 - road edge alt 1 - 0000 0111 - road edge alt 2 - * 1 | xxxx xxxx xxxx xxxx ---- ---- ---- ---- | looks like it's 0001 most (all) of the time - turns off in buriki intro - * 1 | ---- ---- ---- ---- oooo oooo oooo oooo | unknown - always seems to be 0000 (fatfurwa) - * 2 | xxxx xxxx xxxx xxxx ---- ---- ---- ---- | tilemap0 per layer flags - * 2 | ---- ---- ---- ---- xxxx xxxx xxxx xxxx | tilemap1 per layer flags - * 3 | xxxx xxxx xxxx xxxx ---- ---- ---- ---- | tilemap2 per layer flags - * 3 | ---- ---- ---- ---- xxxx xxxx xxxx xxxx | tilemap3 per layer flags - * 4 | xxxx xxxx xxxx xxxx ---- ---- ---- ---- | tilemap0 offset into tilemap RAM? - * 4 | ---- ---- ---- ---- xxxx xxxx xxxx xxxx | tilemap1 offset into tilemap RAM - * 5 | xxxx xxxx xxxx xxxx ---- ---- ---- ---- | tilemap3 offset into tilemap RAM - * 5 | ---- ---- ---- ---- xxxx xxxx xxxx xxxx | tilemap4 offset into tilemap RAM? - * 6 | oooo oooo oooo oooo oooo oooo oooo oooo | unknown - always seems to be 000001ff (fatfurwa) - * 7 | oooo oooo oooo oooo oooo oooo oooo oooo | unknown - always seems to be 000001ff (fatfurwa) - * 8 | oooo oooo oooo oooo oooo oooo oooo oooo | unknown - always seems to be 80008000 (fatfurwa) - * 9 | oooo oooo oooo oooo oooo oooo oooo oooo | unknown - always seems to be 00000000 (fatfurwa) - * a | oooo oooo oooo oooo oooo oooo oooo oooo | unknown - always seems to be 00000000 (fatfurwa) - * b | mmmm mmmm mmmm mmmm mmmm mmmm mmmm mmmm | auto animation mask for tilemaps, - use these bits from the original tile number - * c | xxxx xxxx xxxx xxxx xxxx xxxx xxxx xxxx | auto animation bits for tilemaps, - merge in these bits to auto animate the tilemap - * d | oooo oooo oooo oooo oooo oooo oooo oooo | not used ?? - * e | oooo oooo oooo oooo oooo oooo oooo oooo | not used ?? - - per tile regs (0x2/0x3) - - // tilemap0 per layer flags - // 0840 - startup tests, 8x8x4 layer - // 0cc0 - beast busters 2, 8x8x8 layer - // 0860 - fatal fury wa - // 08e0 - fatal fury wa during transitions - // 0940 - samurai shodown 64 - // 0880 - buriki - - // mmmm dbrz zzzz zzzz - // m = mosaic related? - // -- they seem to enable mosaic at the same time as rowscroll in several cases (floor in buriki / ff) - // and also on the rotating logo in buriki.. does it cause some kind of aliasing side-effect, or.. ? - // r = tile size (seems correct) - // b = 4bpp/8bpp (seems correct) (beast busters, samsh64, sasm64 2, xrally switch it for some screens) - // d = line (floor) mode - buriki, fatafurwa, some backgrounds in ss64_2 - // z = z depth? tilemaps might also be affected by min / max clip values somewhere? (debug layer on buriki has priority 0x020, which would be highest) - - - */ - - - -#define IMPORTANT_DIRTY_TILEFLAG_MASK (0x0600) - UINT32 hng64_state::screen_update_hng64(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect) { @@ -1088,25 +939,17 @@ UINT32 hng64_state::screen_update_hng64(screen_device &screen, bitmap_rgb32 &bit #endif - - - + // Initialize some buffers bitmap.fill(m_tcram[0x50/4] & 0x10000 ? m_palette->black_pen() : m_palette->pen(0), cliprect); //FIXME: Is the register correct? check with HW tests screen.priority().fill(0x00, cliprect); + // If the screen is disabled, don't draw anything (m_screen_dis is a shady variable at best) if (m_screen_dis) return 0; + // If the auto-animation mask or bits have changed search for tiles using them and mark as dirty const UINT32 animmask = m_videoregs[0x0b]; const UINT32 animbits = m_videoregs[0x0c]; - - UINT16 tileflags[4]; - tileflags[0] = m_videoregs[0x02] >> 16; - tileflags[1] = m_videoregs[0x02] & 0xffff; - tileflags[2] = m_videoregs[0x03] >> 16; - tileflags[3] = m_videoregs[0x03] & 0xffff; - - // if the auto-animation mask or bits have changed search for tiles using them and mark as dirty if ((m_old_animmask != animmask) || (m_old_animbits != animbits)) { int tile_index; @@ -1134,6 +977,13 @@ UINT32 hng64_state::screen_update_hng64(screen_device &screen, bitmap_rgb32 &bit m_old_animbits = animbits; } + // If any magic bits have been touched, mark every tilemap dirty + UINT16 tileflags[4]; + tileflags[0] = m_videoregs[0x02] >> 16; + tileflags[1] = m_videoregs[0x02] & 0xffff; + tileflags[2] = m_videoregs[0x03] >> 16; + tileflags[3] = m_videoregs[0x03] & 0xffff; + const UINT16 IMPORTANT_DIRTY_TILEFLAG_MASK = 0x0600; for (int i = 0; i < 4; i++) { if ((m_old_tileflags[i] & IMPORTANT_DIRTY_TILEFLAG_MASK) != (tileflags[i] & IMPORTANT_DIRTY_TILEFLAG_MASK)) @@ -1143,12 +993,13 @@ UINT32 hng64_state::screen_update_hng64(screen_device &screen, bitmap_rgb32 &bit } } + // Draw the four tilemaps hng64_drawtilemap(screen,bitmap,cliprect, 3); hng64_drawtilemap(screen,bitmap,cliprect, 2); hng64_drawtilemap(screen,bitmap,cliprect, 1); hng64_drawtilemap(screen,bitmap,cliprect, 0); - // 3d really shouldn't be last, but you don't see some cool stuff right now if it's put before sprites. + // 3d gets drawn next if(!(m_3dregs[0] & 0x1000000)) { int x, y; @@ -1170,10 +1021,13 @@ UINT32 hng64_state::screen_update_hng64(screen_device &screen, bitmap_rgb32 &bit } } - draw_sprites(screen, bitmap,cliprect); + // Draw the sprites on top of everything + draw_sprites(screen, bitmap, cliprect); + // Layer the global frame buffer operations on top of everything // transition_control(bitmap, cliprect); + #if HNG64_VIDEO_DEBUG if (0) popmessage("%08x %08x %08x %08x %08x", m_spriteregs[0], m_spriteregs[1], m_spriteregs[2], m_spriteregs[3], m_spriteregs[4]); @@ -1182,10 +1036,10 @@ UINT32 hng64_state::screen_update_hng64(screen_device &screen, bitmap_rgb32 &bit popmessage("%08x %08x TR(%04x %04x %04x %04x) SB(%04x %04x %04x %04x) %08x %08x %08x %08x %08x AA(%08x %08x) %08x", m_videoregs[0x00], m_videoregs[0x01], - (m_videoregs[0x02]>>16)&0x01ff, // ---- bits we're sure about are masked out - (m_videoregs[0x02]>>0)&0x01ff, // ss64_2 debug mode indicates that 0x0040 is enable! - (m_videoregs[0x03]>>16)&0x01ff, // buriki agrees (debug data on text layer) xrally agress (pink layer) - (m_videoregs[0x03]>>0)&0x01ff, // fatal fury doesn't (all backgrounds have it set) joy + (m_videoregs[0x02]>>16)&0xffff, + (m_videoregs[0x02]>>0)&0xffff, // ss64_2 debug mode indicates that 0x0040 is enable! + (m_videoregs[0x03]>>16)&0xffff, // buriki agrees (debug data on text layer) xrally agress (pink layer) + (m_videoregs[0x03]>>0)&0xffff, // fatal fury doesn't (all backgrounds have it set) joy (m_videoregs[0x04]>>16)&0xffff, (m_videoregs[0x04]>>0)&0xffff, (m_videoregs[0x05]>>16)&0xffff, @@ -1253,7 +1107,7 @@ UINT32 hng64_state::screen_update_hng64(screen_device &screen, bitmap_rgb32 &bit popmessage("blend changed %02x", m_additive_tilemap_debug); } #endif - + return 0; } @@ -1264,6 +1118,138 @@ void hng64_state::screen_eof_hng64(screen_device &screen, bool state) clear3d(); } + +/* Transition Control Video Registers + * ---------------------------------- + * + * UINT32 | Bits | Use + * | 3322 2222 2222 1111 1111 11 | + * -------+-1098-7654-3210-9876-5432-1098-7654-3210-+---------------- + * 0 | | + * 1 | xxxx xxxx xxxx xxxx yyyy yyyy yyyy yyyy | Min X / Min Y visible area rectangle values + * 2 | xxxx xxxx xxxx xxxx yyyy yyyy yyyy yyyy | Max X / Max Y visible area rectangle values (added up with the Min X / Min Y) + * 3 | | + * 4 | | + * 5 | ---- ---- ---- ---? ---- --?? ???? ???? | Global Fade In/Fade Out control + * 6 | | + * 7 | ---- ---- xxxx xxxx xxxx xxxx xxxx xxxx | Port A of RGB fade (subtraction) + * 8 | | + * 9 | ---- ---- ---- ---? ---- ---- ---- ???? | Per-layer Fade In/Fade Out control + * 10 | ---- ---- xxxx xxxx xxxx xxxx xxxx xxxx | Port B of RGB fade (additive) + * 11 | xxxx xxxx xxxx xxxx xxxx xxxx xxxx xxxx | Unknown - looks like an ARGB value - it seems to change when the scene changes + * 12 | | + * 13 | | + * 14 | | + * 15 | | + * 16 | | + * 17 | | + * 18 | xxxx xxxx xxxx xxxx xxxx xxxx xxxx xxxx | V-Blank related stuff + * 19 | | + * 20 | ---- ---- ---- ---x ---- ---- ---- ---- | Back layer control register? + * 21 | | + * 22 | | + * 23 | | + * 24 | | + * + * Various bits change depending on what is happening in the scene. + * These bits may set which 'layer' is affected by the blending. + * Or maybe they adjust the scale of the lightening and darkening... + * Or maybe it switches from fading by scaling to fading using absolute addition and subtraction... + * Or maybe they set transition type (there seems to be a cute scaling-squares transition in there somewhere)... + */ + +// Very much a work in progress - no hard testing has been done +void hng64_state::transition_control( bitmap_rgb32 &bitmap, const rectangle &cliprect) +{ + int i, j; + +// float colorScaleR, colorScaleG, colorScaleB; + INT32 finR, finG, finB; + + INT32 darkR, darkG, darkB; + INT32 brigR, brigG, brigB; + + // If either of the fading memory regions is non-zero... + if (m_tcram[0x00000007] != 0x00000000 || m_tcram[0x0000000a] != 0x00000000) + { + darkR = (INT32)( m_tcram[0x00000007] & 0xff); + darkG = (INT32)((m_tcram[0x00000007] >> 8) & 0xff); + darkB = (INT32)((m_tcram[0x00000007] >> 16) & 0xff); + + brigR = (INT32)( m_tcram[0x0000000a] & 0xff); + brigG = (INT32)((m_tcram[0x0000000a] >> 8) & 0xff); + brigB = (INT32)((m_tcram[0x0000000a] >> 16) & 0xff); + + for (i = cliprect.min_x; i < cliprect.max_x; i++) + { + for (j = cliprect.min_y; j < cliprect.max_y; j++) + { + rgb_t* thePixel = reinterpret_cast<rgb_t *>(&bitmap.pix32(j, i)); + + finR = (INT32)thePixel->r(); + finG = (INT32)thePixel->g(); + finB = (INT32)thePixel->b(); + +#if 0 + // Apply the darkening pass (0x07)... + colorScaleR = 1.0f - (float)( m_tcram[0x00000007] & 0xff) / 255.0f; + colorScaleG = 1.0f - (float)((m_tcram[0x00000007] >> 8) & 0xff) / 255.0f; + colorScaleB = 1.0f - (float)((m_tcram[0x00000007] >> 16) & 0xff) / 255.0f; + + finR = ((float)thePixel->r() * colorScaleR); + finG = ((float)thePixel->g() * colorScaleG); + finB = ((float)thePixel->b() * colorScaleB); + + + // Apply the lightening pass (0x0a)... + colorScaleR = 1.0f + (float)( m_tcram[0x0000000a] & 0xff) / 255.0f; + colorScaleG = 1.0f + (float)((m_tcram[0x0000000a] >> 8) & 0xff) / 255.0f; + colorScaleB = 1.0f + (float)((m_tcram[0x0000000a] >> 16) & 0xff) / 255.0f; + + finR *= colorScaleR; + finG *= colorScaleG; + finB *= colorScaleB; + + + // Clamp + if (finR > 255.0f) finR = 255.0f; + if (finG > 255.0f) finG = 255.0f; + if (finB > 255.0f) finB = 255.0f; +#endif + + + // Subtractive fading + if (m_tcram[0x00000007] != 0x00000000) + { + finR -= darkR; + finG -= darkG; + finB -= darkB; + } + + // Additive fading + if (m_tcram[0x0000000a] != 0x00000000) + { + finR += brigR; + finG += brigG; + finB += brigB; + } + + // Clamp the high end + if (finR > 255) finR = 255; + if (finG > 255) finG = 255; + if (finB > 255) finB = 255; + + // Clamp the low end + if (finR < 0) finR = 0; + if (finG < 0) finG = 0; + if (finB < 0) finB = 0; + + *thePixel = rgb_t(255, (UINT8)finR, (UINT8)finG, (UINT8)finB); + } + } + } +} + void hng64_state::video_start() { m_old_animmask = -1; diff --git a/src/mame/video/hng64_3d.c b/src/mame/video/hng64_3d.c index 3d430dc607a..92aad5cbc5f 100644 --- a/src/mame/video/hng64_3d.c +++ b/src/mame/video/hng64_3d.c @@ -3,11 +3,11 @@ #include "includes/hng64.h" + ///////////////////////////////// /// Hyper NeoGeo 64 - 3D bits /// ///////////////////////////////// - // Polygon rasterizer interface hng64_poly_renderer::hng64_poly_renderer(hng64_state& state) : poly_manager<float, hng64_poly_data, 7, HNG64_MAX_POLYGONS>(state.machine()) @@ -59,9 +59,9 @@ WRITE16_MEMBER(hng64_state::dl_w) WRITE32_MEMBER(hng64_state::dl_upload_w) { // Data is: - // 00000f00 for everything else // 00000b50 for the sams64 games - // TODO: different param for both Samurai games, less FIFO to process? + // 00000f00 for everything else + // TODO: different param for the two sams64 games, less FIFO to process? // This is written after the game uploads 16 packets, each 16 words long // We're assuming it to be a 'send to 3d hardware' trigger. @@ -145,8 +145,6 @@ void hng64_state::printPacket(const UINT16* packet, int hex) // Camera transformation. void hng64_state::setCameraTransformation(const UINT16* packet) { - float *cameraMatrix = m_cameraMatrix; - /*////////////// // PACKET FORMAT // [0] - 0001 ... ID @@ -167,33 +165,31 @@ void hng64_state::setCameraTransformation(const UINT16* packet) // [15] - ???? ... ? Same as 13 & 14 ////////////*/ // CAMERA TRANSFORMATION MATRIX - cameraMatrix[0] = uToF(packet[1]); - cameraMatrix[4] = uToF(packet[2]); - cameraMatrix[8] = uToF(packet[3]); - cameraMatrix[3] = 0.0f; - - cameraMatrix[1] = uToF(packet[4]); - cameraMatrix[5] = uToF(packet[5]); - cameraMatrix[9] = uToF(packet[6]); - cameraMatrix[7] = 0.0f; - - cameraMatrix[2] = uToF(packet[7]); - cameraMatrix[6] = uToF(packet[8]); - cameraMatrix[10] = uToF(packet[9]); - cameraMatrix[11] = 0.0f; - - cameraMatrix[12] = uToF(packet[10]); - cameraMatrix[13] = uToF(packet[11]); - cameraMatrix[14] = uToF(packet[12]); - cameraMatrix[15] = 1.0f; + m_cameraMatrix[0] = uToF(packet[1]); + m_cameraMatrix[4] = uToF(packet[2]); + m_cameraMatrix[8] = uToF(packet[3]); + m_cameraMatrix[3] = 0.0f; + + m_cameraMatrix[1] = uToF(packet[4]); + m_cameraMatrix[5] = uToF(packet[5]); + m_cameraMatrix[9] = uToF(packet[6]); + m_cameraMatrix[7] = 0.0f; + + m_cameraMatrix[2] = uToF(packet[7]); + m_cameraMatrix[6] = uToF(packet[8]); + m_cameraMatrix[10] = uToF(packet[9]); + m_cameraMatrix[11] = 0.0f; + + m_cameraMatrix[12] = uToF(packet[10]); + m_cameraMatrix[13] = uToF(packet[11]); + m_cameraMatrix[14] = uToF(packet[12]); + m_cameraMatrix[15] = 1.0f; } // Operation 0010 // Lighting information void hng64_state::setLighting(const UINT16* packet) { - float *lightVector = m_lightVector; - /*////////////// // PACKET FORMAT // [0] - 0010 ... ID @@ -205,7 +201,7 @@ void hng64_state::setLighting(const UINT16* packet) // [6] - ???? ... ? Seems to be another light vector ? // [7] - ???? ... ? Seems to be another light vector ? // [8] - ???? ... ? Seems to be another light vector ? - // [9] - xxxx ... Strength according to sams64_2 [0000,01ff] + // [9] - xxxx ... Strength according to sams64_2 (in combination with vector length) [0,512] // [10] - ???? ... ? Used in fatfurwa // [11] - ???? ... ? Used in fatfurwa // [12] - ???? ... ? Used in fatfurwa @@ -216,9 +212,9 @@ void hng64_state::setLighting(const UINT16* packet) if (packet[1] != 0x0000) printf("ZOMG! packet[1] in setLighting function is non-zero!\n"); if (packet[2] != 0x0000) printf("ZOMG! packet[2] in setLighting function is non-zero!\n"); - lightVector[0] = uToF(packet[3]); - lightVector[1] = uToF(packet[4]); - lightVector[2] = uToF(packet[5]); + m_lightVector[0] = uToF(packet[3]); + m_lightVector[1] = uToF(packet[4]); + m_lightVector[2] = uToF(packet[5]); m_lightStrength = uToF(packet[9]); } @@ -252,65 +248,63 @@ void hng64_state::set3dFlags(const UINT16* packet) // Projection Matrix. void hng64_state::setCameraProjectionMatrix(const UINT16* packet) { - float *projectionMatrix = m_projectionMatrix; - /*////////////// // PACKET FORMAT // [0] - 0012 ... ID // [1] - ???? ... ? Contains a value in buriki's 'how to play' - probably a projection window/offset. // [2] - ???? ... ? Contains a value in buriki's 'how to play' - probably a projection window/offset. // [3] - ???? ... ? Contains a value - // [4] - xxxx ... Camera projection near (?) - // [5] - xxxx ... Camera projection near (?) - // [6] - xxxx ... Camera projection near (?) + // [4] - xxxx ... Camera projection near - confirmed by sams64_2 + // [5] - xxxx ... Camera projection near - confirmed by sams64_2 + // [6] - xxxx ... Camera projection near - confirmed by sams64_2 // [7] - xxxx ... Camera projection far (?) // [8] - xxxx ... Camera projection far (?) // [9] - xxxx ... Camera projection far (?) - // [10] - xxxx ... Camera projection right - // [11] - xxxx ... Camera projection left - // [12] - xxxx ... Camera projection top - // [13] - xxxx ... Camera projection bottom + // [10] - xxxx ... Camera projection right - confirmed by sams64_2 + // [11] - xxxx ... Camera projection left - confirmed by sams64_2 + // [12] - xxxx ... Camera projection top - confirmed by sams64_2 + // [13] - xxxx ... Camera projection bottom - confirmed by sams64_2 // [14] - ???? ... ? Gets data during buriki door-run // [15] - ???? ... ? Gets data during buriki door-run ////////////*/ // Heisted from GLFrustum - 6 parameters... - float left, right, top, bottom, near_, far_; - - left = uToF(packet[11]); - right = uToF(packet[10]); - top = uToF(packet[12]); - bottom = uToF(packet[13]); - - // Note: The near and far clipping planes are totally guesses. - near_ = uToF(packet[6]) + (uToF(packet[6]) * uToF(packet[4])); - far_ = 0.9f; // uToF(packet[9]) + (uToF(packet[9]) * uToF(packet[7])); - - projectionMatrix[0] = (2.0f*near_)/(right-left); - projectionMatrix[1] = 0.0f; - projectionMatrix[2] = 0.0f; - projectionMatrix[3] = 0.0f; - - projectionMatrix[4] = 0.0f; - projectionMatrix[5] = (2.0f*near_)/(top-bottom); - projectionMatrix[6] = 0.0f; - projectionMatrix[7] = 0.0f; - - projectionMatrix[8] = (right+left)/(right-left); - projectionMatrix[9] = (top+bottom)/(top-bottom); - projectionMatrix[10] = -((far_+near_)/(far_-near_)); - projectionMatrix[11] = -1.0f; - - projectionMatrix[12] = 0.0f; - projectionMatrix[13] = 0.0f; - projectionMatrix[14] = -((2.0f*far_*near_)/(far_-near_)); - projectionMatrix[15] = 0.0f; + const float left = uToF(packet[11]); + const float right = uToF(packet[10]); + const float top = uToF(packet[12]); + const float bottom = uToF(packet[13]); + + // TODO: It's unclear how the 3 values combine to make a near clipping plane + const float near_ = uToF(packet[6]) + (uToF(packet[6]) * uToF(packet[4])); + const float far_ = 0.9f; // uToF(packet[9]) + (uToF(packet[9]) * uToF(packet[7])); + + m_projectionMatrix[0] = (2.0f*near_)/(right-left); + m_projectionMatrix[1] = 0.0f; + m_projectionMatrix[2] = 0.0f; + m_projectionMatrix[3] = 0.0f; + + m_projectionMatrix[4] = 0.0f; + m_projectionMatrix[5] = (2.0f*near_)/(top-bottom); + m_projectionMatrix[6] = 0.0f; + m_projectionMatrix[7] = 0.0f; + + m_projectionMatrix[8] = (right+left)/(right-left); + m_projectionMatrix[9] = (top+bottom)/(top-bottom); + m_projectionMatrix[10] = -((far_+near_)/(far_-near_)); + m_projectionMatrix[11] = -1.0f; + + m_projectionMatrix[12] = 0.0f; + m_projectionMatrix[13] = 0.0f; + m_projectionMatrix[14] = -((2.0f*far_*near_)/(far_-near_)); + m_projectionMatrix[15] = 0.0f; } // Operation 0100 // Polygon rasterization. void hng64_state::recoverPolygonBlock(const UINT16* packet, int& numPolys) { + //printPacket(packet, 1); + /*////////////// // PACKET FORMAT // [0] - 0100 ... ID @@ -346,8 +340,6 @@ void hng64_state::recoverPolygonBlock(const UINT16* packet, int& numPolys) // [15] - xxxx ... Transformation matrix ////////////*/ - - float objectMatrix[16]; setIdentity(objectMatrix); ///////////////// @@ -378,7 +370,6 @@ void hng64_state::recoverPolygonBlock(const UINT16* packet, int& numPolys) UINT32 address[4]; UINT32 megaOffset; polygon lastPoly = { 0 }; - const rectangle &visarea = m_screen->visible_area(); ////////////////////////////////////////////////////////// @@ -482,10 +473,6 @@ void hng64_state::recoverPolygonBlock(const UINT16* packet, int& numPolys) // GATHER A SINGLE TRIANGLE'S INFORMATION // //////////////////////////////////////////// // SINGLE POLY CHUNK FORMAT - //////////////////////////////////////////// - // GATHER A SINGLE TRIANGLE'S INFORMATION // - //////////////////////////////////////////// - // SINGLE POLY CHUNK FORMAT // [0] 0000 0000 cccc cccc 0 = always 0 | c = chunk type / format of data that follows (see below) // [1] u--l pppp pppp ssss u = unknown, always on for most games, on for the backgrounds only on sams64, l = low-res texture? p = palette? s = texture sheet (1024 x 1024 pages) // [2] S?XX *--- -YY# ---- S = use 4x4 sub-texture pages? ? = SNK logo roadedge / bbust2 / broken banners in xrally, XX = horizontal subtexture * = broken banners in xrally YY = vertical subtexture @ = broken banners in xrally @@ -875,6 +862,7 @@ void hng64_state::recoverPolygonBlock(const UINT16* packet, int& numPolys) currentPoly.vert[m].light[2] = clipVerts[m].p[4]; } + const rectangle& visarea = m_screen->visible_area(); for (int m = 0; m < currentPoly.n; m++) { // Convert into normalized device coordinates... @@ -933,26 +921,19 @@ void hng64_state::hng64_command3d(const UINT16* packet) break; case 0x0010: // Lighting information. - //if (packet[9]) printPacket(packet, 1); setLighting(packet); break; case 0x0011: // Palette / Model flags? - //printPacket(packet, 1); printf("\n"); set3dFlags(packet); break; case 0x0012: // Projection Matrix - //printPacket(packet, 1); setCameraProjectionMatrix(packet); break; case 0x0100: case 0x0101: // Geometry with full transformations - // HACK. Masks out a piece of geo bbust2's drawShaded() crashes on. - if (packet[2] == 0x0003 && packet[3] == 0x8f37 && m_mcu_type == SHOOT_MCU) - break; - recoverPolygonBlock(packet, numPolys); break; @@ -977,7 +958,6 @@ void hng64_state::hng64_command3d(const UINT16* packet) memset(miniPacket, 0, sizeof(UINT16)*16); for (int i = 0; i < 7; i++) miniPacket[i] = packet[i+8]; - for (int i = 0; i < 7; i++) miniPacket[i] = packet[i+8]; miniPacket[7] = 0x7fff; miniPacket[11] = 0x7fff; miniPacket[15] = 0x7fff; @@ -988,7 +968,7 @@ void hng64_state::hng64_command3d(const UINT16* packet) //printPacket(packet, 1); printf("\n"); break; - case 0x1001: // Unknown: Some sort of global flags (a group of 4, actually)? + case 0x1001: // Unknown: Some sort of global flags? Almost always comes in a group of 4 with an index [0,3]. //printPacket(packet, 1); break; @@ -1010,9 +990,8 @@ void hng64_state::hng64_command3d(const UINT16* packet) void hng64_state::clear3d() { - const rectangle &visarea = m_screen->visible_area(); - // Reset the buffers... + const rectangle& visarea = m_screen->visible_area(); for (int i = 0; i < (visarea.max_x)*(visarea.max_y); i++) { m_poly_renderer->depthBuffer3d()[i] = 100.0f; @@ -1038,7 +1017,7 @@ void hng64_state::clear3d() * 0 | ???? ???? ???? ???? ccc? ???? ???? ???? | framebuffer color base, 0x311800 in Fatal Fury WA, 0x313800 in Buriki One * 1 | | * 2 | ???? ???? ???? ???? ???? ???? ???? ???? | camera / framebuffer global x/y? Actively used by Samurai Shodown 64 2 - * 3 | ---- --?x ---- ---- ---- ---- ---- ---- | unknown, unsetted by Buriki One and setted by Fatal Fury WA, buffering mode? + * 3 | ---- --?x ---- ---- ---- ---- ---- ---- | unknown, unsetted by Buriki One and set by Fatal Fury WA, buffering mode? * 4-11 | ---- ???? ---- ???? ---- ???? ---- ???? | Table filled with 0x0? data * */ |