The new hng64 rasterizing code is better than the old, so I can remove a hack

or two.  Also learned that a good deal of my floor code was already known, so I
converted my latest floor findings to that. (nw)
This commit is contained in:
Andrew Gardner 2015-10-08 12:10:20 +02:00
parent 63c636ccb2
commit 50b48189f7
2 changed files with 326 additions and 361 deletions

View File

@ -8,143 +8,6 @@
#define HNG64_VIDEO_DEBUG 0 #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 ) void hng64_state::hng64_mark_all_tiles_dirty( int tilemap )
{ {
m_tilemap[tilemap].m_tilemap_8x8->mark_all_dirty(); 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); hng64_mark_tile_dirty(3, offset&0x3fff);
} }
// Offsets 0x40000 - 0x58000 are for "floor" scanline control // Offsets 0x40000 - 0x58000 are for "floor" scanline control
/* 400000 - 7fffff is scroll regs etc. */ /* 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; blit_parameters blit;
/* notes: // notes:
- startx and starty MUST be UINT32 for calculations to work correctly // - 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 // - 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) //if (!tmap->enable)
// return; // 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)
const UINT32 global_tileregs = m_videoregs[0x00]; * --------------------------------------------------
const int global_dimensions = (global_tileregs & 0x03000000) >> 24; *
* 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)
{
// 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; int debug_blend_enabled = 0;
if ((m_additive_tilemap_debug&(1 << tm))) if ((m_additive_tilemap_debug&(1 << tm)))
debug_blend_enabled = 1; 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"); popmessage("unsupported global_dimensions on tilemaps");
#endif #endif
UINT32 scrollbase = 0; // Determine which tilemap registers and scroll base this tilemap uses
UINT32 tileregs = 0; UINT16 tileregs = 0;
UINT16 scrollbase = 0;
if (tm==0) if (tm==0)
{ {
scrollbase = (m_videoregs[0x04]&0x3fff0000)>>16; 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; 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; tilemap_t* tilemap = NULL;
if (global_dimensions==0) 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 tilemap = m_tilemap[tm].m_tilemap_8x8;
} }
else 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 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; int transmask = 0x00;
if (tileregs & 0x0400) if (bppBit)
transmask = 0xff; transmask = 0xff;
else else
transmask = 0xf; transmask = 0xf;
// buriki tm1 = roz if (floorModeBit == 0x0000)
// 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).
{ {
// 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); // fprintf(stderr, "Tilemap %d is a floor using :\n", tm);
const UINT32 floorAddress = 0x40000 + (scrollbase << 4);
// Floor buffer enables // TODO: The row count is correct, but how is this layer clipped? m_tcram?
// 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: 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 // 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 // DEBUG: Change this to a loop that goes over each line and draws them - it's just for visualization now
int lineCount = 0; //int lineCount = 0;
for (int ii = 0; ii < 0x2000/4; ii += 4) //for (int ii = 0; ii < 0x2000/4; ii += 4)
{ //{
const int realAddress = dataAddress/4; // const int realAddress = floorAddress/4;
if (m_videoram[realAddress+ii] == 0xffffff00 && m_videoram[realAddress+ii+1] == 0xffffff00) // if (m_videoram[realAddress+ii] == 0xffffff00 && m_videoram[realAddress+ii+1] == 0xffffff00)
continue; // continue;
if (m_videoram[realAddress+ii] == 0x00000000 && m_videoram[realAddress+ii+1] == 0x00000000) // if (m_videoram[realAddress+ii] == 0x00000000 && m_videoram[realAddress+ii+1] == 0x00000000)
continue; // continue;
//
lineCount++; // lineCount++;
} //}
//printf("lines %d\n", lineCount); //printf("lines %d\n", lineCount);
// Buriki uses a 2x mosaic effect on its floor, so its line count is half // Buriki uses a 2x mosaic effect on its floor, so its line count is half
if (m_mcu_type == BURIKI_MCU) // (but so does fatfurwa - maybe it overdraws a bunch of pixels?)
lineCount *= 2; //if (m_mcu_type == BURIKI_MCU)
// lineCount *= 2;
// DEBUG - draw a horizontal green line where the uppermost line of the floor is drawn // DEBUG - draw a horizontal green line where the uppermost line of the floor is drawn
const rectangle &visarea = screen.visible_area(); 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; // 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 // 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? // the linescroll ram fills a buffer and it's cleared automatically between frames?
for (int ii = 0; ii < 0x2000/4; ii++) for (int ii = 0; ii < 0x2000/4; ii++)
{ {
const int realAddress = dataAddress/4; const int realAddress = floorAddress/4;
m_videoram[realAddress+ii] = 0x00000000; m_videoram[realAddress+ii] = 0x00000000;
} }
//if ((tileregs&0xf000) == 0x1000)
//{
// popmessage("Floor is Active");
//}
// Floor mode - per pixel simple / complex modes? -- every other line? // 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) // (there doesn't seem to be enough data in Buriki for every line at least)
rectangle clip = visarea; 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, // Logic would dictate that this should be the 'complex' scroll register layout,
// but per-line. That doesn't work however. // 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; 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? // 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 // 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 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? // 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? */ /* complex zoom mode? */
/* with this scroll register layout rotation effects are possible /* 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]); m_videoram[(0x4001c+(scrollbase<<4))/4]);
#endif #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? /* 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 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) 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 #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 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); 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) if (m_screen_dis)
return 0; 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 animmask = m_videoregs[0x0b];
const UINT32 animbits = m_videoregs[0x0c]; 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)) if ((m_old_animmask != animmask) || (m_old_animbits != animbits))
{ {
int tile_index; int tile_index;
@ -1134,6 +977,13 @@ UINT32 hng64_state::screen_update_hng64(screen_device &screen, bitmap_rgb32 &bit
m_old_animbits = animbits; 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++) for (int i = 0; i < 4; i++)
{ {
if ((m_old_tileflags[i] & IMPORTANT_DIRTY_TILEFLAG_MASK) != (tileflags[i] & IMPORTANT_DIRTY_TILEFLAG_MASK)) 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, 3);
hng64_drawtilemap(screen,bitmap,cliprect, 2); hng64_drawtilemap(screen,bitmap,cliprect, 2);
hng64_drawtilemap(screen,bitmap,cliprect, 1); hng64_drawtilemap(screen,bitmap,cliprect, 1);
hng64_drawtilemap(screen,bitmap,cliprect, 0); 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)) if(!(m_3dregs[0] & 0x1000000))
{ {
int x, y; 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); // transition_control(bitmap, cliprect);
#if HNG64_VIDEO_DEBUG #if HNG64_VIDEO_DEBUG
if (0) if (0)
popmessage("%08x %08x %08x %08x %08x", m_spriteregs[0], m_spriteregs[1], m_spriteregs[2], m_spriteregs[3], m_spriteregs[4]); 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", 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[0x00],
m_videoregs[0x01], m_videoregs[0x01],
(m_videoregs[0x02]>>16)&0x01ff, // ---- bits we're sure about are masked out (m_videoregs[0x02]>>16)&0xffff,
(m_videoregs[0x02]>>0)&0x01ff, // ss64_2 debug mode indicates that 0x0040 is enable! (m_videoregs[0x02]>>0)&0xffff, // 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]>>16)&0xffff, // 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[0x03]>>0)&0xffff, // fatal fury doesn't (all backgrounds have it set) joy
(m_videoregs[0x04]>>16)&0xffff, (m_videoregs[0x04]>>16)&0xffff,
(m_videoregs[0x04]>>0)&0xffff, (m_videoregs[0x04]>>0)&0xffff,
(m_videoregs[0x05]>>16)&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); popmessage("blend changed %02x", m_additive_tilemap_debug);
} }
#endif #endif
return 0; return 0;
} }
@ -1264,6 +1118,138 @@ void hng64_state::screen_eof_hng64(screen_device &screen, bool state)
clear3d(); 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() void hng64_state::video_start()
{ {
m_old_animmask = -1; m_old_animmask = -1;

View File

@ -3,11 +3,11 @@
#include "includes/hng64.h" #include "includes/hng64.h"
///////////////////////////////// /////////////////////////////////
/// Hyper NeoGeo 64 - 3D bits /// /// Hyper NeoGeo 64 - 3D bits ///
///////////////////////////////// /////////////////////////////////
// Polygon rasterizer interface // Polygon rasterizer interface
hng64_poly_renderer::hng64_poly_renderer(hng64_state& state) hng64_poly_renderer::hng64_poly_renderer(hng64_state& state)
: poly_manager<float, hng64_poly_data, 7, HNG64_MAX_POLYGONS>(state.machine()) : 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) WRITE32_MEMBER(hng64_state::dl_upload_w)
{ {
// Data is: // Data is:
// 00000f00 for everything else
// 00000b50 for the sams64 games // 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 // 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. // 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. // Camera transformation.
void hng64_state::setCameraTransformation(const UINT16* packet) void hng64_state::setCameraTransformation(const UINT16* packet)
{ {
float *cameraMatrix = m_cameraMatrix;
/*////////////// /*//////////////
// PACKET FORMAT // PACKET FORMAT
// [0] - 0001 ... ID // [0] - 0001 ... ID
@ -167,33 +165,31 @@ void hng64_state::setCameraTransformation(const UINT16* packet)
// [15] - ???? ... ? Same as 13 & 14 // [15] - ???? ... ? Same as 13 & 14
////////////*/ ////////////*/
// CAMERA TRANSFORMATION MATRIX // CAMERA TRANSFORMATION MATRIX
cameraMatrix[0] = uToF(packet[1]); m_cameraMatrix[0] = uToF(packet[1]);
cameraMatrix[4] = uToF(packet[2]); m_cameraMatrix[4] = uToF(packet[2]);
cameraMatrix[8] = uToF(packet[3]); m_cameraMatrix[8] = uToF(packet[3]);
cameraMatrix[3] = 0.0f; m_cameraMatrix[3] = 0.0f;
cameraMatrix[1] = uToF(packet[4]); m_cameraMatrix[1] = uToF(packet[4]);
cameraMatrix[5] = uToF(packet[5]); m_cameraMatrix[5] = uToF(packet[5]);
cameraMatrix[9] = uToF(packet[6]); m_cameraMatrix[9] = uToF(packet[6]);
cameraMatrix[7] = 0.0f; m_cameraMatrix[7] = 0.0f;
cameraMatrix[2] = uToF(packet[7]); m_cameraMatrix[2] = uToF(packet[7]);
cameraMatrix[6] = uToF(packet[8]); m_cameraMatrix[6] = uToF(packet[8]);
cameraMatrix[10] = uToF(packet[9]); m_cameraMatrix[10] = uToF(packet[9]);
cameraMatrix[11] = 0.0f; m_cameraMatrix[11] = 0.0f;
cameraMatrix[12] = uToF(packet[10]); m_cameraMatrix[12] = uToF(packet[10]);
cameraMatrix[13] = uToF(packet[11]); m_cameraMatrix[13] = uToF(packet[11]);
cameraMatrix[14] = uToF(packet[12]); m_cameraMatrix[14] = uToF(packet[12]);
cameraMatrix[15] = 1.0f; m_cameraMatrix[15] = 1.0f;
} }
// Operation 0010 // Operation 0010
// Lighting information // Lighting information
void hng64_state::setLighting(const UINT16* packet) void hng64_state::setLighting(const UINT16* packet)
{ {
float *lightVector = m_lightVector;
/*////////////// /*//////////////
// PACKET FORMAT // PACKET FORMAT
// [0] - 0010 ... ID // [0] - 0010 ... ID
@ -205,7 +201,7 @@ void hng64_state::setLighting(const UINT16* packet)
// [6] - ???? ... ? Seems to be another light vector ? // [6] - ???? ... ? Seems to be another light vector ?
// [7] - ???? ... ? Seems to be another light vector ? // [7] - ???? ... ? Seems to be another light vector ?
// [8] - ???? ... ? 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 // [10] - ???? ... ? Used in fatfurwa
// [11] - ???? ... ? Used in fatfurwa // [11] - ???? ... ? Used in fatfurwa
// [12] - ???? ... ? 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[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"); if (packet[2] != 0x0000) printf("ZOMG! packet[2] in setLighting function is non-zero!\n");
lightVector[0] = uToF(packet[3]); m_lightVector[0] = uToF(packet[3]);
lightVector[1] = uToF(packet[4]); m_lightVector[1] = uToF(packet[4]);
lightVector[2] = uToF(packet[5]); m_lightVector[2] = uToF(packet[5]);
m_lightStrength = uToF(packet[9]); m_lightStrength = uToF(packet[9]);
} }
@ -252,65 +248,63 @@ void hng64_state::set3dFlags(const UINT16* packet)
// Projection Matrix. // Projection Matrix.
void hng64_state::setCameraProjectionMatrix(const UINT16* packet) void hng64_state::setCameraProjectionMatrix(const UINT16* packet)
{ {
float *projectionMatrix = m_projectionMatrix;
/*////////////// /*//////////////
// PACKET FORMAT // PACKET FORMAT
// [0] - 0012 ... ID // [0] - 0012 ... ID
// [1] - ???? ... ? Contains a value in buriki's 'how to play' - probably a projection window/offset. // [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. // [2] - ???? ... ? Contains a value in buriki's 'how to play' - probably a projection window/offset.
// [3] - ???? ... ? Contains a value // [3] - ???? ... ? Contains a value
// [4] - xxxx ... Camera projection near (?) // [4] - xxxx ... Camera projection near - confirmed by sams64_2
// [5] - xxxx ... Camera projection near (?) // [5] - xxxx ... Camera projection near - confirmed by sams64_2
// [6] - xxxx ... Camera projection near (?) // [6] - xxxx ... Camera projection near - confirmed by sams64_2
// [7] - xxxx ... Camera projection far (?) // [7] - xxxx ... Camera projection far (?)
// [8] - xxxx ... Camera projection far (?) // [8] - xxxx ... Camera projection far (?)
// [9] - xxxx ... Camera projection far (?) // [9] - xxxx ... Camera projection far (?)
// [10] - xxxx ... Camera projection right // [10] - xxxx ... Camera projection right - confirmed by sams64_2
// [11] - xxxx ... Camera projection left // [11] - xxxx ... Camera projection left - confirmed by sams64_2
// [12] - xxxx ... Camera projection top // [12] - xxxx ... Camera projection top - confirmed by sams64_2
// [13] - xxxx ... Camera projection bottom // [13] - xxxx ... Camera projection bottom - confirmed by sams64_2
// [14] - ???? ... ? Gets data during buriki door-run // [14] - ???? ... ? Gets data during buriki door-run
// [15] - ???? ... ? Gets data during buriki door-run // [15] - ???? ... ? Gets data during buriki door-run
////////////*/ ////////////*/
// Heisted from GLFrustum - 6 parameters... // Heisted from GLFrustum - 6 parameters...
float left, right, top, bottom, near_, far_; const float left = uToF(packet[11]);
const float right = uToF(packet[10]);
const float top = uToF(packet[12]);
const float bottom = uToF(packet[13]);
left = uToF(packet[11]); // TODO: It's unclear how the 3 values combine to make a near clipping plane
right = uToF(packet[10]); const float near_ = uToF(packet[6]) + (uToF(packet[6]) * uToF(packet[4]));
top = uToF(packet[12]); const float far_ = 0.9f; // uToF(packet[9]) + (uToF(packet[9]) * uToF(packet[7]));
bottom = uToF(packet[13]);
// Note: The near and far clipping planes are totally guesses. m_projectionMatrix[0] = (2.0f*near_)/(right-left);
near_ = uToF(packet[6]) + (uToF(packet[6]) * uToF(packet[4])); m_projectionMatrix[1] = 0.0f;
far_ = 0.9f; // uToF(packet[9]) + (uToF(packet[9]) * uToF(packet[7])); m_projectionMatrix[2] = 0.0f;
m_projectionMatrix[3] = 0.0f;
projectionMatrix[0] = (2.0f*near_)/(right-left); m_projectionMatrix[4] = 0.0f;
projectionMatrix[1] = 0.0f; m_projectionMatrix[5] = (2.0f*near_)/(top-bottom);
projectionMatrix[2] = 0.0f; m_projectionMatrix[6] = 0.0f;
projectionMatrix[3] = 0.0f; m_projectionMatrix[7] = 0.0f;
projectionMatrix[4] = 0.0f; m_projectionMatrix[8] = (right+left)/(right-left);
projectionMatrix[5] = (2.0f*near_)/(top-bottom); m_projectionMatrix[9] = (top+bottom)/(top-bottom);
projectionMatrix[6] = 0.0f; m_projectionMatrix[10] = -((far_+near_)/(far_-near_));
projectionMatrix[7] = 0.0f; m_projectionMatrix[11] = -1.0f;
projectionMatrix[8] = (right+left)/(right-left); m_projectionMatrix[12] = 0.0f;
projectionMatrix[9] = (top+bottom)/(top-bottom); m_projectionMatrix[13] = 0.0f;
projectionMatrix[10] = -((far_+near_)/(far_-near_)); m_projectionMatrix[14] = -((2.0f*far_*near_)/(far_-near_));
projectionMatrix[11] = -1.0f; m_projectionMatrix[15] = 0.0f;
projectionMatrix[12] = 0.0f;
projectionMatrix[13] = 0.0f;
projectionMatrix[14] = -((2.0f*far_*near_)/(far_-near_));
projectionMatrix[15] = 0.0f;
} }
// Operation 0100 // Operation 0100
// Polygon rasterization. // Polygon rasterization.
void hng64_state::recoverPolygonBlock(const UINT16* packet, int& numPolys) void hng64_state::recoverPolygonBlock(const UINT16* packet, int& numPolys)
{ {
//printPacket(packet, 1);
/*////////////// /*//////////////
// PACKET FORMAT // PACKET FORMAT
// [0] - 0100 ... ID // [0] - 0100 ... ID
@ -346,8 +340,6 @@ void hng64_state::recoverPolygonBlock(const UINT16* packet, int& numPolys)
// [15] - xxxx ... Transformation matrix // [15] - xxxx ... Transformation matrix
////////////*/ ////////////*/
float objectMatrix[16]; float objectMatrix[16];
setIdentity(objectMatrix); setIdentity(objectMatrix);
///////////////// /////////////////
@ -378,7 +370,6 @@ void hng64_state::recoverPolygonBlock(const UINT16* packet, int& numPolys)
UINT32 address[4]; UINT32 address[4];
UINT32 megaOffset; UINT32 megaOffset;
polygon lastPoly = { 0 }; polygon lastPoly = { 0 };
const rectangle &visarea = m_screen->visible_area();
////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////
@ -478,10 +469,6 @@ void hng64_state::recoverPolygonBlock(const UINT16* packet, int& numPolys)
UINT16* chunkOffset = &threeDRoms[address[k] * 3]; UINT16* chunkOffset = &threeDRoms[address[k] * 3];
for (int l = 0; l < size[k]; l++) for (int l = 0; l < size[k]; l++)
{ {
////////////////////////////////////////////
// GATHER A SINGLE TRIANGLE'S INFORMATION //
////////////////////////////////////////////
// SINGLE POLY CHUNK FORMAT
//////////////////////////////////////////// ////////////////////////////////////////////
// GATHER A SINGLE TRIANGLE'S INFORMATION // // GATHER A SINGLE TRIANGLE'S INFORMATION //
//////////////////////////////////////////// ////////////////////////////////////////////
@ -875,6 +862,7 @@ void hng64_state::recoverPolygonBlock(const UINT16* packet, int& numPolys)
currentPoly.vert[m].light[2] = clipVerts[m].p[4]; currentPoly.vert[m].light[2] = clipVerts[m].p[4];
} }
const rectangle& visarea = m_screen->visible_area();
for (int m = 0; m < currentPoly.n; m++) for (int m = 0; m < currentPoly.n; m++)
{ {
// Convert into normalized device coordinates... // Convert into normalized device coordinates...
@ -933,26 +921,19 @@ void hng64_state::hng64_command3d(const UINT16* packet)
break; break;
case 0x0010: // Lighting information. case 0x0010: // Lighting information.
//if (packet[9]) printPacket(packet, 1);
setLighting(packet); setLighting(packet);
break; break;
case 0x0011: // Palette / Model flags? case 0x0011: // Palette / Model flags?
//printPacket(packet, 1); printf("\n");
set3dFlags(packet); set3dFlags(packet);
break; break;
case 0x0012: // Projection Matrix case 0x0012: // Projection Matrix
//printPacket(packet, 1);
setCameraProjectionMatrix(packet); setCameraProjectionMatrix(packet);
break; break;
case 0x0100: case 0x0100:
case 0x0101: // Geometry with full transformations 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); recoverPolygonBlock(packet, numPolys);
break; break;
@ -977,7 +958,6 @@ void hng64_state::hng64_command3d(const UINT16* packet)
memset(miniPacket, 0, sizeof(UINT16)*16); 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];
for (int i = 0; i < 7; i++) miniPacket[i] = packet[i+8];
miniPacket[7] = 0x7fff; miniPacket[7] = 0x7fff;
miniPacket[11] = 0x7fff; miniPacket[11] = 0x7fff;
miniPacket[15] = 0x7fff; miniPacket[15] = 0x7fff;
@ -988,7 +968,7 @@ void hng64_state::hng64_command3d(const UINT16* packet)
//printPacket(packet, 1); printf("\n"); //printPacket(packet, 1); printf("\n");
break; 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); //printPacket(packet, 1);
break; break;
@ -1010,9 +990,8 @@ void hng64_state::hng64_command3d(const UINT16* packet)
void hng64_state::clear3d() void hng64_state::clear3d()
{ {
const rectangle &visarea = m_screen->visible_area();
// Reset the buffers... // Reset the buffers...
const rectangle& visarea = m_screen->visible_area();
for (int i = 0; i < (visarea.max_x)*(visarea.max_y); i++) for (int i = 0; i < (visarea.max_x)*(visarea.max_y); i++)
{ {
m_poly_renderer->depthBuffer3d()[i] = 100.0f; 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 * 0 | ???? ???? ???? ???? ccc? ???? ???? ???? | framebuffer color base, 0x311800 in Fatal Fury WA, 0x313800 in Buriki One
* 1 | | * 1 | |
* 2 | ???? ???? ???? ???? ???? ???? ???? ???? | camera / framebuffer global x/y? Actively used by Samurai Shodown 64 2 * 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 * 4-11 | ---- ???? ---- ???? ---- ???? ---- ???? | Table filled with 0x0? data
* *
*/ */