snk/hng64_v.cpp: Improved rendering: (#10891)

* Filter out most (but not all) the bad polygons in roadedge/xrally by handling display list more correctly.
* Fixed 4bpp texture handling (used extensively for background details on sams64/sams64_2).
* Added 4bpp texture decode for easy viewing of the 4bpp texture pages.
* Fixed some texture palette issues connected to the 4bpp textures and incorrect enable bits being used (wheels and windscreen palette in racing games for example).
* Found a flag that seems to enable backface culling, improves bbust2 school bus without breaking roadedge.
* Cleaned up logging.
This commit is contained in:
David Haywood 2023-02-14 18:04:05 +00:00 committed by GitHub
parent 2b9da4a413
commit 17d3ebd429
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 223 additions and 163 deletions

View File

@ -219,7 +219,9 @@ uint16_t l7a1045_sound_device::l7a1045_sound_r(offs_t offset, uint16_t mem_mask)
//logerror("%s: read at %x (mask %04x)\n", tag(), offset, mem_mask); //logerror("%s: read at %x (mask %04x)\n", tag(), offset, mem_mask);
if (offset == 0) if (offset == 0)
printf("sound_select_r?\n"); {
//logerror("sound_select_r?\n");
}
else else
return sound_data_r(offset -1); return sound_data_r(offset -1);
@ -255,7 +257,7 @@ void l7a1045_sound_device::sound_data_w(offs_t offset, uint16_t data)
l7a1045_voice *vptr = &m_voice[m_audiochannel]; l7a1045_voice *vptr = &m_voice[m_audiochannel];
//if(m_audioregister != 0 && m_audioregister != 1 && m_audioregister != 7) //if(m_audioregister != 0 && m_audioregister != 1 && m_audioregister != 7)
// printf("%04x %04x (%04x %04x)\n",offset,data,m_audioregister,m_audiochannel); // logerror("%04x %04x (%04x %04x)\n",offset,data,m_audioregister,m_audiochannel);
m_audiodat[m_audioregister][m_audiochannel].dat[offset] = data; m_audiodat[m_audioregister][m_audiochannel].dat[offset] = data;
@ -281,9 +283,9 @@ void l7a1045_sound_device::sound_data_w(offs_t offset, uint16_t data)
break; break;
case 0x01: case 0x01:
// relative to start // relative to start
//printf("%04x\n",m_audiodat[m_audioregister][m_audiochannel].dat[0]); //logerror("%04x\n",m_audiodat[m_audioregister][m_audiochannel].dat[0]);
//printf("%04x\n",m_audiodat[m_audioregister][m_audiochannel].dat[1]); //logerror("%04x\n",m_audiodat[m_audioregister][m_audiochannel].dat[1]);
//printf("%04x\n",m_audiodat[m_audioregister][m_audiochannel].dat[2]); //logerror("%04x\n",m_audiodat[m_audioregister][m_audiochannel].dat[2]);
if(m_audiodat[m_audioregister][m_audiochannel].dat[2] & 0x100) if(m_audiodat[m_audioregister][m_audiochannel].dat[2] & 0x100)
{ {
@ -312,7 +314,7 @@ void l7a1045_sound_device::sound_data_w(offs_t offset, uint16_t data)
vptr->r_volume = (vptr->r_volume) | (vptr->r_volume << 8); vptr->r_volume = (vptr->r_volume) | (vptr->r_volume << 8);
vptr->l_volume = (m_audiodat[m_audioregister][m_audiochannel].dat[0] >> 8) & 0xff; vptr->l_volume = (m_audiodat[m_audioregister][m_audiochannel].dat[0] >> 8) & 0xff;
vptr->l_volume = (vptr->l_volume) | (vptr->l_volume << 8); vptr->l_volume = (vptr->l_volume) | (vptr->l_volume << 8);
//printf("%04x %02x %02x\n",m_audiodat[m_audioregister][m_audiochannel].dat[0],vptr->l_volume,vptr->r_volume); //logerror("%04x %02x %02x\n",m_audiodat[m_audioregister][m_audiochannel].dat[0],vptr->l_volume,vptr->r_volume);
break; break;
} }
@ -321,7 +323,7 @@ void l7a1045_sound_device::sound_data_w(offs_t offset, uint16_t data)
uint16_t l7a1045_sound_device::sound_data_r(offs_t offset) uint16_t l7a1045_sound_device::sound_data_r(offs_t offset)
{ {
//printf("%04x (%04x %04x)\n",offset,m_audioregister,m_audiochannel); //logerror("%04x (%04x %04x)\n",offset,m_audioregister,m_audiochannel);
//machine().debug_break(); //machine().debug_break();
l7a1045_voice *vptr = &m_voice[m_audiochannel]; l7a1045_voice *vptr = &m_voice[m_audiochannel];
@ -356,11 +358,11 @@ void l7a1045_sound_device::sound_status_w(uint16_t data)
#if 0 #if 0
if(vptr->start != 0) if(vptr->start != 0)
{ {
printf("%08x START\n",vptr->start); logerror("%08x START\n",vptr->start);
printf("%08x END\n",vptr->end); logerror("%08x END\n",vptr->end);
for(int i=0;i<0x10;i++) for(int i=0;i<0x10;i++)
printf("%02x (%02x) = %04x%04x%04x\n",m_audiochannel,i,m_audiodat[i][m_audiochannel].dat[2],m_audiodat[i][m_audiochannel].dat[1],m_audiodat[i][m_audiochannel].dat[0]); logerror("%02x (%02x) = %04x%04x%04x\n",m_audiochannel,i,m_audiodat[i][m_audiochannel].dat[2],m_audiodat[i][m_audiochannel].dat[1],m_audiodat[i][m_audiochannel].dat[0]);
} }
#endif #endif

View File

@ -990,7 +990,7 @@ void hng64_state::hng64_sysregs_w(offs_t offset, uint32_t data, uint32_t mem_mas
#if 0 #if 0
if(((offset*4) & 0xff00) == 0x1100) if(((offset*4) & 0xff00) == 0x1100)
printf("HNG64 writing to SYSTEM Registers 0x%08x == 0x%08x. (PC=%08x)\n", offset*4, m_sysregs[offset], m_maincpu->pc()); logerror("HNG64 writing to SYSTEM Registers 0x%08x == 0x%08x. (PC=%08x)\n", offset*4, m_sysregs[offset], m_maincpu->pc());
#endif #endif
switch(offset*4) switch(offset*4)
@ -1720,20 +1720,47 @@ static const gfx_layout hng64_16x16x8_spritelayout =
}; };
static const uint32_t texlayout_xoffset[1024] = { STEP1024(0,8) }; static const uint32_t texlayout_xoffset[1024] = { STEP1024(0,8) };
static const uint32_t texlayout_yoffset[512] = { STEP512(0,8192) }; static const uint32_t texlayout_yoffset[1024] = { STEP1024(0,8192) };
static const gfx_layout hng64_texlayout =
static uint32_t texlayout_xoffset_4[1024];
static const uint32_t texlayout_yoffset_4[1024] = { STEP1024(0,4096) };
void hng64_state::texlayout_xoffset_4_create()
{ {
1024, 512, for (int i = 0; i < 1024; i++)
{
texlayout_xoffset_4[i] = (i * 4) ^ 4;
}
}
static const gfx_layout hng64_1024x1024x8_texlayout =
{
1024, 1024,
RGN_FRAC(1,1), RGN_FRAC(1,1),
8, 8,
{ 0,1,2,3,4,5,6,7 }, { 0,1,2,3,4,5,6,7 },
EXTENDED_XOFFS, EXTENDED_XOFFS,
EXTENDED_YOFFS, EXTENDED_YOFFS,
1024*512*8, 1024*1024*8,
texlayout_xoffset, texlayout_xoffset,
texlayout_yoffset texlayout_yoffset
}; };
static const gfx_layout hng64_1024x1024x4_texlayout =
{
1024, 1024,
RGN_FRAC(1,1),
4,
{ 0,1,2,3 },
EXTENDED_XOFFS,
EXTENDED_YOFFS,
1024*1024*4,
texlayout_xoffset_4,
texlayout_yoffset_4
};
static GFXDECODE_START( gfx_hng64 ) static GFXDECODE_START( gfx_hng64 )
/* tilemap tiles */ /* tilemap tiles */
GFXDECODE_ENTRY( "scrtile", 0, hng64_8x8x4_tilelayout, 0x0, 0x100 ) GFXDECODE_ENTRY( "scrtile", 0, hng64_8x8x4_tilelayout, 0x0, 0x100 )
@ -1745,7 +1772,10 @@ static GFXDECODE_START( gfx_hng64 )
GFXDECODE_ENTRY( "sprtile", 0, hng64_16x16x4_spritelayout, 0x0, 0x100 ) GFXDECODE_ENTRY( "sprtile", 0, hng64_16x16x4_spritelayout, 0x0, 0x100 )
GFXDECODE_ENTRY( "sprtile", 0, hng64_16x16x8_spritelayout, 0x0, 0x10 ) GFXDECODE_ENTRY( "sprtile", 0, hng64_16x16x8_spritelayout, 0x0, 0x10 )
GFXDECODE_ENTRY( "textures", 0, hng64_texlayout, 0x0, 0x10 ) /* textures */ /* texture pages (not used by rendering code) */
GFXDECODE_ENTRY( "textures", 0, hng64_1024x1024x4_texlayout, 0x0, 0x100 )
GFXDECODE_ENTRY( "textures", 0, hng64_1024x1024x8_texlayout, 0x0, 0x10 )
GFXDECODE_END GFXDECODE_END
static void hng64_reorder( uint8_t* gfxregion, size_t gfxregionsize) static void hng64_reorder( uint8_t* gfxregion, size_t gfxregionsize)
@ -2110,7 +2140,10 @@ TIMER_CALLBACK_MEMBER(hng64_state::comhack_callback)
{ {
LOG("comhack_callback %04x\n\n", m_comhack[0]); LOG("comhack_callback %04x\n\n", m_comhack[0]);
m_comhack[0] = m_comhack[0] | 0x0002; // different network IDs give different default colours for the cars in roadedge
uint8_t network_id = 0x01;
m_comhack[0] = m_comhack[0] | network_id;
} }
@ -2975,7 +3008,7 @@ GAME( 1997, hng64, 0, hng64_default, hng64, hng64_state, init_hn
GAME( 1997, roadedge, hng64, hng64_drive, hng64_drive, hng64_state, init_roadedge, ROT0, "SNK", "Roads Edge / Round Trip RV (rev.B)", MACHINE_NOT_WORKING|MACHINE_IMPERFECT_SOUND ) /* 001 */ GAME( 1997, roadedge, hng64, hng64_drive, hng64_drive, hng64_state, init_roadedge, ROT0, "SNK", "Roads Edge / Round Trip RV (rev.B)", MACHINE_NOT_WORKING|MACHINE_IMPERFECT_SOUND ) /* 001 */
GAME( 1998, sams64, hng64, hng64_fight, hng64_fight, hng64_state, init_ss64, ROT0, "SNK", "Samurai Shodown 64 / Samurai Spirits 64", MACHINE_NOT_WORKING|MACHINE_IMPERFECT_SOUND ) /* 002 */ GAME( 1998, sams64, hng64, hng64_fight, hng64_fight, hng64_state, init_ss64, ROT0, "SNK", "Samurai Shodown 64 / Samurai Spirits 64", MACHINE_NOT_WORKING|MACHINE_IMPERFECT_SOUND ) /* 002 */
GAME( 1998, xrally, hng64, hng64_drive, hng64_drive, hng64_state, init_hng64_drive, ROT0, "SNK", "Xtreme Rally / Off Beat Racer!", MACHINE_NOT_WORKING|MACHINE_IMPERFECT_SOUND ) /* 003 */ GAME( 1998, xrally, hng64, hng64_drive, hng64_drive, hng64_state, init_hng64_drive, ROT0, "SNK", "Xtreme Rally / Off Beat Racer!", MACHINE_NOT_WORKING|MACHINE_IMPERFECT_SOUND ) /* 003 */
GAME( 1998, bbust2, hng64, hng64_shoot, hng64_shoot, hng64_state, init_hng64_shoot, ROT0, "SNK", "Beast Busters: Second Nightmare", MACHINE_NOT_WORKING|MACHINE_IMPERFECT_SOUND ) /* 004 */ GAME( 1998, bbust2, hng64, hng64_shoot, hng64_shoot, hng64_state, init_hng64_shoot, ROT0, "SNK / ADK", "Beast Busters: Second Nightmare", MACHINE_NOT_WORKING|MACHINE_IMPERFECT_SOUND ) /* 004 */ // ADK credited in the ending sequence
GAME( 1998, sams64_2, hng64, hng64_fight, hng64_fight, hng64_state, init_ss64, ROT0, "SNK", "Samurai Shodown 64: Warriors Rage / Samurai Spirits 2: Asura Zanmaden", MACHINE_NOT_WORKING|MACHINE_IMPERFECT_SOUND ) /* 005 */ GAME( 1998, sams64_2, hng64, hng64_fight, hng64_fight, hng64_state, init_ss64, ROT0, "SNK", "Samurai Shodown 64: Warriors Rage / Samurai Spirits 2: Asura Zanmaden", MACHINE_NOT_WORKING|MACHINE_IMPERFECT_SOUND ) /* 005 */
GAME( 1998, fatfurwa, hng64, hng64_fight, hng64_fight, hng64_state, init_hng64_fght, ROT0, "SNK", "Fatal Fury: Wild Ambition / Garou Densetsu: Wild Ambition (rev.A)", MACHINE_NOT_WORKING|MACHINE_IMPERFECT_SOUND ) /* 006 */ GAME( 1998, fatfurwa, hng64, hng64_fight, hng64_fight, hng64_state, init_hng64_fght, ROT0, "SNK", "Fatal Fury: Wild Ambition / Garou Densetsu: Wild Ambition (rev.A)", MACHINE_NOT_WORKING|MACHINE_IMPERFECT_SOUND ) /* 006 */
GAME( 1999, buriki, hng64, hng64_fight, hng64_fight, hng64_state, init_hng64_fght, ROT0, "SNK", "Buriki One: World Grapple Tournament '99 in Tokyo (rev.B)", MACHINE_NOT_WORKING|MACHINE_IMPERFECT_SOUND ) /* 007 */ GAME( 1999, buriki, hng64, hng64_fight, hng64_fight, hng64_state, init_hng64_fght, ROT0, "SNK", "Buriki One: World Grapple Tournament '99 in Tokyo (rev.B)", MACHINE_NOT_WORKING|MACHINE_IMPERFECT_SOUND ) /* 007 */

View File

@ -27,7 +27,7 @@ struct polyVert
{ {
float worldCoords[4]{}; // World space coordinates (X Y Z 1.0) float worldCoords[4]{}; // World space coordinates (X Y Z 1.0)
float texCoords[4]{}; // Texture coordinates (U V 0 1.0) -> OpenGL style... float texCoords[2]{}; // Texture coordinates (U V 0 1.0) -> OpenGL style...
float normal[4]{}; // Normal (X Y Z 1.0) float normal[4]{}; // Normal (X Y Z 1.0)
float clipCoords[4]{}; // Homogeneous screen space coordinates (X Y Z W) float clipCoords[4]{}; // Homogeneous screen space coordinates (X Y Z W)
@ -47,13 +47,12 @@ struct polygon
bool flatShade = false; // Flat shaded polygon, no texture, no lighting bool flatShade = false; // Flat shaded polygon, no texture, no lighting
uint8_t texIndex = 0; // Which texture to draw from (0x00-0x0f) uint8_t texIndex = 0; // Which texture to draw from (0x00-0x0f)
uint8_t texType = 0; // How to index into the texture uint8_t tex4bpp = 0; // How to index into the texture
uint8_t texPageSmall = 0; // Does this polygon use 'small' texture pages? uint8_t texPageSmall = 0; // Does this polygon use 'small' texture pages?
uint8_t texPageHorizOffset = 0; // If it does use small texture pages, how far is this page horizontally offset? uint8_t texPageHorizOffset = 0; // If it does use small texture pages, how far is this page horizontally offset?
uint8_t texPageVertOffset = 0; // If it does use small texture pages, how far is this page vertically offset? uint8_t texPageVertOffset = 0; // If it does use small texture pages, how far is this page vertically offset?
uint32_t palOffset = 0; // The base offset where this object's palette starts. uint32_t palOffset = 0; // The base offset where this object's palette starts.
uint32_t palPageSize = 0; // The size of the palette page that is being pointed to.
uint32_t debugColor = 0; // Will go away someday. Used to explicitly color polygons for debugging. uint32_t debugColor = 0; // Will go away someday. Used to explicitly color polygons for debugging.
}; };
@ -82,13 +81,12 @@ typedef frustum_clip_vertex<float, 5> hng64_clip_vertex;
struct hng64_poly_data struct hng64_poly_data
{ {
uint8_t texType = 0; uint8_t tex4bpp = 0;
uint8_t texIndex = 0; uint8_t texIndex = 0;
uint8_t texPageSmall = 0; uint8_t texPageSmall = 0;
uint8_t texPageHorizOffset = 0; uint8_t texPageHorizOffset = 0;
uint8_t texPageVertOffset = 0; uint8_t texPageVertOffset = 0;
int palOffset = 0; int palOffset = 0;
int palPageSize = 0;
int debugColor = 0; int debugColor = 0;
}; };
@ -167,7 +165,9 @@ public:
m_in(*this, "IN%u", 0U), m_in(*this, "IN%u", 0U),
m_samsho64_3d_hack(0), m_samsho64_3d_hack(0),
m_roadedge_3d_hack(0) m_roadedge_3d_hack(0)
{ } {
texlayout_xoffset_4_create();
}
void hng64(machine_config &config); void hng64(machine_config &config);
void hng64_default(machine_config &config); void hng64_default(machine_config &config);
@ -182,6 +182,8 @@ public:
void init_ss64(); void init_ss64();
void init_hng64_fght(); void init_hng64_fght();
static void texlayout_xoffset_4_create();
uint8_t *m_texturerom = nullptr; uint8_t *m_texturerom = nullptr;
required_device<screen_device> m_screen; required_device<screen_device> m_screen;
required_device<palette_device> m_palette; required_device<palette_device> m_palette;
@ -457,7 +459,7 @@ private:
std::vector<polygon> m_polys; // HNG64_MAX_POLYGONS std::vector<polygon> m_polys; // HNG64_MAX_POLYGONS
void clear3d(); void clear3d();
void hng64_command3d(const uint16_t* packet); bool hng64_command3d(const uint16_t* packet);
void draw_sprites(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect); void draw_sprites(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect);
void transition_control(bitmap_rgb32 &bitmap, const rectangle &cliprect); void transition_control(bitmap_rgb32 &bitmap, const rectangle &cliprect);
void setCameraTransformation(const uint16_t* packet); void setCameraTransformation(const uint16_t* packet);

View File

@ -63,6 +63,8 @@ void hng64_state::dl_unk_w(offs_t offset, uint32_t data, uint32_t mem_mask)
void hng64_state::dl_upload_w(uint32_t data) void hng64_state::dl_upload_w(uint32_t data)
{ {
//m_paletteState3d = 0; // no, breaks fatfurwa characters
// Data is: // Data is:
// 00000b50 for the sams64 games // 00000b50 for the sams64 games
// 00000f00 for everything else // 00000f00 for everything else
@ -75,7 +77,8 @@ g_profiler.start(PROFILER_USER1);
for(int packetStart = 0; packetStart < 0x100; packetStart += 16) for(int packetStart = 0; packetStart < 0x100; packetStart += 16)
{ {
// Send it off to the 3d subsystem. // Send it off to the 3d subsystem.
hng64_command3d(&m_dl[packetStart]); if (!hng64_command3d(&m_dl[packetStart]))
break;
} }
// Schedule a small amount of time to let the 3d hardware rasterize the display buffer // Schedule a small amount of time to let the 3d hardware rasterize the display buffer
@ -106,7 +109,7 @@ void hng64_state::dl_control_w(uint32_t data)
*/ */
/* /*
printf("dl_control_w %08x %08x\n", data, mem_mask); logerror("dl_control_w %08x %08x\n", data, mem_mask);
if(data & 2) // swap buffers if(data & 2) // swap buffers
{ {
@ -136,7 +139,7 @@ void hng64_state::printPacket(const uint16_t* packet, int hex)
{ {
if (hex) if (hex)
{ {
printf("Packet : %04x %04x 2:%04x %04x 4:%04x %04x 6:%04x %04x 8:%04x %04x 10:%04x %04x 12:%04x %04x 14:%04x %04x\n", logerror("Packet : %04x %04x 2:%04x %04x 4:%04x %04x 6:%04x %04x 8:%04x %04x 10:%04x %04x 12:%04x %04x 14:%04x %04x\n",
packet[0], packet[1], packet[0], packet[1],
packet[2], packet[3], packet[2], packet[3],
packet[4], packet[5], packet[4], packet[5],
@ -148,7 +151,7 @@ void hng64_state::printPacket(const uint16_t* packet, int hex)
} }
else else
{ {
printf("Packet : %04x %3.4f 2:%3.4f %3.4f 4:%3.4f %3.4f 6:%3.4f %3.4f 8:%3.4f %3.4f 10:%3.4f %3.4f 12:%3.4f %3.4f 14:%3.4f %3.4f\n", logerror("Packet : %04x %3.4f 2:%3.4f %3.4f 4:%3.4f %3.4f 6:%3.4f %3.4f 8:%3.4f %3.4f 10:%3.4f %3.4f 12:%3.4f %3.4f 14:%3.4f %3.4f\n",
packet[0], uToF(packet[1] )*128, packet[0], uToF(packet[1] )*128,
uToF(packet[2] )*128, uToF(packet[3] )*128, uToF(packet[2] )*128, uToF(packet[3] )*128,
uToF(packet[4] )*128, uToF(packet[5] )*128, uToF(packet[4] )*128, uToF(packet[5] )*128,
@ -228,8 +231,8 @@ void hng64_state::setLighting(const uint16_t* packet)
// [14] - ???? ... ? Used in fatfurwa // [14] - ???? ... ? Used in fatfurwa
// [15] - ???? ... ? Used in fatfurwa // [15] - ???? ... ? Used in fatfurwa
////////////*/ ////////////*/
if (packet[1] != 0x0000) printf("ZOMG! packet[1] in setLighting function is non-zero!\n"); if (packet[1] != 0x0000) logerror("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) logerror("packet[2] in setLighting function is non-zero!\n");
m_lightVector[0] = uToF(packet[3]); m_lightVector[0] = uToF(packet[3]);
m_lightVector[1] = uToF(packet[4]); m_lightVector[1] = uToF(packet[4]);
@ -331,22 +334,14 @@ void hng64_state::recoverPolygonBlock(const uint16_t* packet, int& numPolys)
/*////////////// /*//////////////
// PACKET FORMAT // PACKET FORMAT
// [0] - 0100 ... ID // [0] - 0100 ... ID
// [1] - ?--- ... Flags [?000 = ??? // [1] - --c- ---p ---b l---
// 0?00 = ??? // l = use lighting
// 00?0 = ??? // p = use dynamic palette (maybe not just this, wrong for roadedge car select where it isn't set but needs to be)
// 000? = ???] // b = backface culling?
// [1] - -?-- ... Flags [?000 = ??? // c = set on objects a certain distance away (maybe optimization to disable clipping against camera?)
// 0?00 = ??? // none of these bits appear to be connected to texture size to solve the road/banner problem in xrally/roadedge
// 00?0 = ??? //
// 000x = Dynamic palette bit] //
// [1] - --?- ... Flags [?000 = ???
// 0?00 = ???
// 00?0 = ???
// 000? = ???]
// [1] - ---? ... Flags [x000 = Apply lighting bit
// 0?00 = ???
// 00?0 = ???
// 000? = ???]
// [2] - xxxx ... offset into ROM // [2] - xxxx ... offset into ROM
// [3] - xxxx ... offset into ROM // [3] - xxxx ... offset into ROM
// [4] - xxxx ... Transformation matrix // [4] - xxxx ... Transformation matrix
@ -430,7 +425,11 @@ void hng64_state::recoverPolygonBlock(const uint16_t* packet, int& numPolys)
if (threeDOffset >= m_vertsrom_size) if (threeDOffset >= m_vertsrom_size)
{ {
printf("Strange geometry packet: (ignoring)\n"); // bbust2 quite often spams this invalid pointer
if ((packet[2] == 0x2347) && (packet[3] == 0x5056))
return;
logerror("Strange geometry packet: (ignoring)\n");
printPacket(packet, 1); printPacket(packet, 1);
return; return;
} }
@ -453,11 +452,11 @@ void hng64_state::recoverPolygonBlock(const uint16_t* packet, int& numPolys)
address[2] = threeDPointer[3]; address[2] = threeDPointer[3];
address[3] = threeDPointer[4]; address[3] = threeDPointer[4];
if (threeDPointer[5] != 0x0000) printf("ZOMG! 3dPointer[5] is non-zero!\n"); if (threeDPointer[5] != 0x0000) logerror("3dPointer[5] is non-zero!\n");
size[0] = threeDPointer[6]; size[0] = threeDPointer[6];
size[1] = threeDPointer[7]; size[1] = threeDPointer[7];
if (threeDPointer[8] != 0x0000) printf("ZOMG! 3dPointer[8] is non-zero!\n"); if (threeDPointer[8] != 0x0000) logerror("3dPointer[8] is non-zero!\n");
size[2] = threeDPointer[9]; size[2] = threeDPointer[9];
size[3] = threeDPointer[10]; size[3] = threeDPointer[10];
@ -466,13 +465,13 @@ void hng64_state::recoverPolygonBlock(const uint16_t* packet, int& numPolys)
// ???? [13]; Used. // ???? [13]; Used.
// ???? [14]; Used. // ???? [14]; Used.
if (threeDPointer[15] != 0x0000) printf("ZOMG! 3dPointer[15] is non-zero!\n"); if (threeDPointer[15] != 0x0000) logerror("3dPointer[15] is non-zero!\n");
if (threeDPointer[16] != 0x0000) printf("ZOMG! 3dPointer[16] is non-zero!\n"); if (threeDPointer[16] != 0x0000) logerror("3dPointer[16] is non-zero!\n");
if (threeDPointer[17] != 0x0000) printf("ZOMG! 3dPointer[17] is non-zero!\n"); if (threeDPointer[17] != 0x0000) logerror("3dPointer[17] is non-zero!\n");
if (threeDPointer[18] != 0x0000) printf("ZOMG! 3dPointer[18] is non-zero!\n"); if (threeDPointer[18] != 0x0000) logerror("3dPointer[18] is non-zero!\n");
if (threeDPointer[19] != 0x0000) printf("ZOMG! 3dPointer[19] is non-zero!\n"); if (threeDPointer[19] != 0x0000) logerror("3dPointer[19] is non-zero!\n");
if (threeDPointer[20] != 0x0000) printf("ZOMG! 3dPointer[20] is non-zero!\n"); if (threeDPointer[20] != 0x0000) logerror("3dPointer[20] is non-zero!\n");
// Concatenate the megaOffset with the addresses // Concatenate the megaOffset with the addresses
address[0] |= (megaOffset << 16); address[0] |= (megaOffset << 16);
@ -497,10 +496,17 @@ void hng64_state::recoverPolygonBlock(const uint16_t* packet, int& numPolys)
//////////////////////////////////////////// ////////////////////////////////////////////
// SINGLE POLY CHUNK FORMAT // SINGLE POLY CHUNK FORMAT
// [0] 0000 0000 cccc cccc 0 = always 0 | c = chunk type / format of data that follows (see below) // [0] 0000 0000 cccc cccc 0 = always 0 | c = chunk type / format of data that follows (see below)
// [1] t--l pppp pppp ssss t = texture, always on for most games, on for the backgrounds only on sams64 // [1] tu-4 pppp pppp ssss t = texture, always on for most games, on for the backgrounds only on sams64
// if not set, u,v fields of vertices are direct palette indices, used on roadedge hng64 logo animation shadows // if not set, u,v fields of vertices are direct palette indices, used on roadedge hng64 logo animation shadows
// l = low-res texture? p = palette? s = texture sheet (1024 x 1024 pages) // u = unknown, set on sams64 / buriki at times, never on racing games
// [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 // 4 = 4bpp texture p = palette? s = texture sheet (1024 x 1024 pages)
// [2] S?XX *uuu -YY# uuu- S = use 4x4 sub-texture pages?
// ? = SNK logo roadedge / bbust2 / broken banners in xrally
// X = horizontal subtexture
// * = broken banners in xrally
// Y = vertical subtexture
// # = broken banners in xrally
// u = unknown, set late on 2nd race+3rd race in xrally
// we currently use one of the palette bits to enable a different palette mode.. seems hacky... // we currently use one of the palette bits to enable a different palette mode.. seems hacky...
// looks like vertical / horizontal sub-pages might be 3 bits, not 2, ? could be enable bit for that.. // looks like vertical / horizontal sub-pages might be 3 bits, not 2, ? could be enable bit for that..
@ -508,13 +514,12 @@ void hng64_state::recoverPolygonBlock(const uint16_t* packet, int& numPolys)
// 'Welcome to South Africa' roadside banner on xrally | 000e 8c0d d870 or 0096 8c0d d870 (8c0d, d870 seems key 1000 1100 0000 1101 // 'Welcome to South Africa' roadside banner on xrally | 000e 8c0d d870 or 0096 8c0d d870 (8c0d, d870 seems key 1000 1100 0000 1101
// 1101 1000 0111 0000 ) // 1101 1000 0111 0000 )
uint8_t chunkType = chunkOffset[0] & 0x00ff; uint8_t chunkType = chunkOffset[0] & 0x00ff;
// Debug - ajg // Debug - ajg
if (chunkOffset[0] & 0xff00) if (chunkOffset[0] & 0xff00)
{ {
printf("Weird! The top byte of the chunkType has a value %04x!\n", chunkOffset[0]); logerror("Weird! The top byte of the chunkType has a value %04x!\n", chunkOffset[0]);
continue; continue;
} }
@ -526,13 +531,11 @@ void hng64_state::recoverPolygonBlock(const uint16_t* packet, int& numPolys)
//currentPoly.debugColor = tdColor; //currentPoly.debugColor = tdColor;
// Debug - ajg // Debug - ajg
//printf("%d (%08x) : %04x %04x %04x\n", k, address[k]*3*2, chunkOffset[0], chunkOffset[1], chunkOffset[2]); //logerror("%d (%08x) : %04x %04x %04x\n", k, address[k]*3*2, chunkOffset[0], chunkOffset[1], chunkOffset[2]);
//break; //break;
// TEXTURE if (chunkOffset[1] & 0x1000) currentPoly.tex4bpp = 0x1;
// There may be more than just high & low res texture types, so I'm keeping texType as a uint8_t. */ else currentPoly.tex4bpp = 0x0;
if (chunkOffset[1] & 0x1000) currentPoly.texType = 0x1;
else currentPoly.texType = 0x0;
currentPoly.texPageSmall = (chunkOffset[2] & 0xc000)>>14; // Just a guess. currentPoly.texPageSmall = (chunkOffset[2] & 0xc000)>>14; // Just a guess.
currentPoly.texPageHorizOffset = (chunkOffset[2] & 0x3800) >> 11; currentPoly.texPageHorizOffset = (chunkOffset[2] & 0x3800) >> 11;
@ -548,7 +551,6 @@ void hng64_state::recoverPolygonBlock(const uint16_t* packet, int& numPolys)
// PALETTE // PALETTE
currentPoly.palOffset = 0; currentPoly.palOffset = 0;
currentPoly.palPageSize = 0x100;
// FIXME: This isn't correct. // FIXME: This isn't correct.
// Buriki & Xrally need this line. Roads Edge needs it removed. // Buriki & Xrally need this line. Roads Edge needs it removed.
@ -560,20 +562,27 @@ void hng64_state::recoverPolygonBlock(const uint16_t* packet, int& numPolys)
} }
//uint16_t explicitPaletteValue0 = ((chunkOffset[?] & 0x????) >> ?) * 0x800; //uint16_t explicitPaletteValue0 = ((chunkOffset[?] & 0x????) >> ?) * 0x800;
uint16_t explicitPaletteValue1 = ((chunkOffset[1] & 0x0f00) >> 8) * 0x080; uint16_t explicitPaletteValue = ((chunkOffset[1] & 0x0ff0) >> 4);
uint16_t explicitPaletteValue2 = ((chunkOffset[1] & 0x00f0) >> 4) * 0x008; explicitPaletteValue = explicitPaletteValue << 3;
// The presence of 0x00f0 *probably* sets 0x10-sized palette addressing.
if (explicitPaletteValue2) currentPoly.palPageSize = 0x10;
// HACK: this is not the enable, the cars in roadedge rely on this to switch palettes
// on the select screen, where this bit is not enabled.
// (to see the cars on the select screen disable sprite rendering, as there are
// currently priority issues)
//
// however for sams64 this is enabled on the 2nd character, but not the 1st character
// and the additional palette offset definitely only applies to the 2nd
//
// Apply the dynamic palette offset if its flag is set, otherwise stick with the fixed one // Apply the dynamic palette offset if its flag is set, otherwise stick with the fixed one
if ((packet[1] & 0x0100)) if ((packet[1] & 0x0100))
{ {
explicitPaletteValue1 = m_paletteState3d * 0x80; // bbust2 has m_paletteState3d & 0x40 set, which takes the palette out of range
explicitPaletteValue2 = 0; // This is probably hiding somewhere in operation 0011 // used for 2nd car on roadedge, used for 2nd player on buriki
// used for buildings in fatfurwa intro and characters
explicitPaletteValue |= (m_paletteState3d & 0x3f) * 0x80;
} }
currentPoly.palOffset += (explicitPaletteValue1 + explicitPaletteValue2); currentPoly.palOffset += explicitPaletteValue;
#if 0 #if 0
if (((chunkOffset[2] & 0xc000) == 0x4000) && (m_screen->frame_number() & 1)) if (((chunkOffset[2] & 0xc000) == 0x4000) && (m_screen->frame_number() & 1))
@ -581,7 +590,7 @@ void hng64_state::recoverPolygonBlock(const uint16_t* packet, int& numPolys)
// if (chunkOffset[2] == 0xd870) // if (chunkOffset[2] == 0xd870)
{ {
currentPoly.debugColor = 0xffff0000; currentPoly.debugColor = 0xffff0000;
printf("%d (%08x) : %04x %04x %04x\n", k, address[k] * 3 * 2, chunkOffset[0], chunkOffset[1], chunkOffset[2]); logerror("%d (%08x) : %04x %04x %04x\n", k, address[k] * 3 * 2, chunkOffset[0], chunkOffset[1], chunkOffset[2]);
} }
} }
#endif #endif
@ -599,6 +608,9 @@ void hng64_state::recoverPolygonBlock(const uint16_t* packet, int& numPolys)
// ---- -x-- - 1 = Has per-vert UVs // ---- -x-- - 1 = Has per-vert UVs
// ---- --x- - // ---- --x- -
// ---- ---x - 1 = Has per-vert normals // ---- ---x - 1 = Has per-vert normals
//
// none of these seem directly connected to texture size to solve texturing problem in the racing games
// maybe some of the actual packet data is being used incorrectly?
/////////////////////////*/ /////////////////////////*/
// 33 word chunk, 3 vertices, per-vertex UVs & normals, per-face normal // 33 word chunk, 3 vertices, per-vertex UVs & normals, per-face normal
@ -615,8 +627,6 @@ void hng64_state::recoverPolygonBlock(const uint16_t* packet, int& numPolys)
// chunkOffset[6 + (9*m)] is almost always 0080, but it's 0070 for the translucent globe in fatfurwa player select // chunkOffset[6 + (9*m)] is almost always 0080, but it's 0070 for the translucent globe in fatfurwa player select
currentPoly.vert[m].texCoords[0] = uToF(chunkOffset[7 + (9*m)]); currentPoly.vert[m].texCoords[0] = uToF(chunkOffset[7 + (9*m)]);
currentPoly.vert[m].texCoords[1] = uToF(chunkOffset[8 + (9*m)]); currentPoly.vert[m].texCoords[1] = uToF(chunkOffset[8 + (9*m)]);
currentPoly.vert[m].texCoords[2] = 0.0f;
currentPoly.vert[m].texCoords[3] = 1.0f;
currentPoly.vert[m].normal[0] = uToF(chunkOffset[9 + (9*m)]); currentPoly.vert[m].normal[0] = uToF(chunkOffset[9 + (9*m)]);
currentPoly.vert[m].normal[1] = uToF(chunkOffset[10 + (9*m)]); currentPoly.vert[m].normal[1] = uToF(chunkOffset[10 + (9*m)]);
@ -653,8 +663,6 @@ void hng64_state::recoverPolygonBlock(const uint16_t* packet, int& numPolys)
// chunkOffset[6 + (6*m)] is almost always 0080, but it's 0070 for the translucent globe in fatfurwa player select // chunkOffset[6 + (6*m)] is almost always 0080, but it's 0070 for the translucent globe in fatfurwa player select
currentPoly.vert[m].texCoords[0] = uToF(chunkOffset[7 + (6*m)]); currentPoly.vert[m].texCoords[0] = uToF(chunkOffset[7 + (6*m)]);
currentPoly.vert[m].texCoords[1] = uToF(chunkOffset[8 + (6*m)]); currentPoly.vert[m].texCoords[1] = uToF(chunkOffset[8 + (6*m)]);
currentPoly.vert[m].texCoords[2] = 0.0f;
currentPoly.vert[m].texCoords[3] = 1.0f;
if (currentPoly.flatShade) if (currentPoly.flatShade)
currentPoly.vert[m].colorIndex = chunkOffset[7 + (6*m)] >> 5; currentPoly.vert[m].colorIndex = chunkOffset[7 + (6*m)] >> 5;
@ -694,8 +702,6 @@ void hng64_state::recoverPolygonBlock(const uint16_t* packet, int& numPolys)
// chunkOffset[6] is almost always 0080, but it's 0070 for the translucent globe in fatfurwa player select // chunkOffset[6] is almost always 0080, but it's 0070 for the translucent globe in fatfurwa player select
currentPoly.vert[0].texCoords[0] = uToF(chunkOffset[7]); currentPoly.vert[0].texCoords[0] = uToF(chunkOffset[7]);
currentPoly.vert[0].texCoords[1] = uToF(chunkOffset[8]); currentPoly.vert[0].texCoords[1] = uToF(chunkOffset[8]);
currentPoly.vert[0].texCoords[2] = 0.0f;
currentPoly.vert[0].texCoords[3] = 1.0f;
if (currentPoly.flatShade) if (currentPoly.flatShade)
currentPoly.vert[0].colorIndex = chunkOffset[7] >> 5; currentPoly.vert[0].colorIndex = chunkOffset[7] >> 5;
@ -733,8 +739,6 @@ void hng64_state::recoverPolygonBlock(const uint16_t* packet, int& numPolys)
// chunkOffset[6] is almost always 0080, but it's 0070 for the translucent globe in fatfurwa player select // chunkOffset[6] is almost always 0080, but it's 0070 for the translucent globe in fatfurwa player select
currentPoly.vert[0].texCoords[0] = uToF(chunkOffset[7]); currentPoly.vert[0].texCoords[0] = uToF(chunkOffset[7]);
currentPoly.vert[0].texCoords[1] = uToF(chunkOffset[8]); currentPoly.vert[0].texCoords[1] = uToF(chunkOffset[8]);
currentPoly.vert[0].texCoords[2] = 0.0f;
currentPoly.vert[0].texCoords[3] = 1.0f;
if (currentPoly.flatShade) if (currentPoly.flatShade)
currentPoly.vert[0].colorIndex = chunkOffset[7] >> 5; currentPoly.vert[0].colorIndex = chunkOffset[7] >> 5;
@ -754,21 +758,21 @@ void hng64_state::recoverPolygonBlock(const uint16_t* packet, int& numPolys)
#if 0 #if 0
// DEBUG // DEBUG
printf("0x?6 : %08x (%d/%d)\n", address[k]*3*2, l, size[k]-1); logerror("0x?6 : %08x (%d/%d)\n", address[k]*3*2, l, size[k]-1);
for (int m = 0; m < 13; m++) for (int m = 0; m < 13; m++)
printf("%04x ", chunkOffset[m]); logerror("%04x ", chunkOffset[m]);
printf("\n"); logerror("\n");
for (int m = 0; m < 13; m++) for (int m = 0; m < 13; m++)
printf("%3.4f ", uToF(chunkOffset[m])); logerror("%3.4f ", uToF(chunkOffset[m]));
printf("\n\n"); logerror("\n\n");
#endif #endif
chunkLength = 12; chunkLength = 12;
break; break;
default: default:
printf("UNKNOWN geometry CHUNK TYPE : %02x\n", chunkType); logerror("UNKNOWN geometry CHUNK TYPE : %02x\n", chunkType);
chunkLength = 0; chunkLength = 0;
break; break;
} }
@ -829,8 +833,7 @@ void hng64_state::recoverPolygonBlock(const uint16_t* packet, int& numPolys)
} }
} }
// BACKFACE CULL
// roadedge has various one-way barriers that you can drive through, but need to be invisible from behind, so needs this culling
float cullRay[4]; float cullRay[4];
float cullNorm[4]; float cullNorm[4];
@ -841,11 +844,18 @@ void hng64_state::recoverPolygonBlock(const uint16_t* packet, int& numPolys)
// Dot product that with the normal to see if you're negative... // Dot product that with the normal to see if you're negative...
vecmatmul4(cullNorm, m_modelViewMatrix, currentPoly.faceNormal); vecmatmul4(cullNorm, m_modelViewMatrix, currentPoly.faceNormal);
// BACKFACE CULL
// roadedge has various one-way barriers that you can drive through, but need to be invisible from behind, so needs this culling
// this bit IS set on the objects that roadedge needs to vanish if viewed from behind, but it is NOT set on the bbust2 school bus
// which needs to be visible with backfacing polys. further test cases need to be found.
if (packet[1] & 0x0010)
{
const float backfaceCullResult = vecDotProduct(cullRay, cullNorm); const float backfaceCullResult = vecDotProduct(cullRay, cullNorm);
if (backfaceCullResult < 0.0f) if (backfaceCullResult < 0.0f)
currentPoly.visible = true; currentPoly.visible = true;
else else
currentPoly.visible = false; currentPoly.visible = false;
}
// BEHIND-THE-CAMERA CULL // // BEHIND-THE-CAMERA CULL //
vecmatmul4(cullRay, m_modelViewMatrix, currentPoly.vert[0].worldCoords); vecmatmul4(cullRay, m_modelViewMatrix, currentPoly.vert[0].worldCoords);
@ -934,25 +944,17 @@ void hng64_state::recoverPolygonBlock(const uint16_t* packet, int& numPolys)
} }
} }
// note 0x0102 packets are only 8 words, it appears they can be in either the upper or lower half of the 16 word packet.
// We currently only draw 0x0102 packets where both halves contain 0x0102 (2 calls), but this causes graphics to vanish in
// xrally because in some cases the 0x0102 packet only exists in the upper or lower half with another value (often 0x0000 - NOP) in the other.
// If we also treat (0x0000 - NOP) as 8 word instead of 16 so that we can access a 0x0102 in the 2nd half of the 16 word packet
// then we end up with other invalid packets in the 2nd half which should be ignored.
// This would suggest our processing if flawed in other ways, or there is something else to indicate packet length.
void hng64_state::hng64_command3d(const uint16_t* packet) bool hng64_state::hng64_command3d(const uint16_t* packet)
{ {
int numPolys = 0; int numPolys = 0;
//printf("packet type : %04x %04x|%04x %04x|%04x %04x|%04x %04x | %04x %04x %04x %04x %04x %04x %04x %04x\n", packet[0],packet[1],packet[2],packet[3],packet[4],packet[5],packet[6],packet[7], packet[8], packet[9], packet[10], packet[11], packet[12], packet[13], packet[14], packet[15]); //logerror("packet type : %04x %04x|%04x %04x|%04x %04x|%04x %04x | %04x %04x %04x %04x %04x %04x %04x %04x\n", packet[0],packet[1],packet[2],packet[3],packet[4],packet[5],packet[6],packet[7], packet[8], packet[9], packet[10], packet[11], packet[12], packet[13], packet[14], packet[15]);
switch (packet[0]) switch (packet[0])
{ {
case 0x0000: // NOP? case 0x0000: // NOP? / End current list (doesn't stop additional lists being sent this frame)
/* Appears to be a NOP (or 'end of list for this frame, ignore everything after' doesn't stop stray 3d objects in game for xrally/roadedge return false;
although does stop a partial hng64 logo being displayed assuming that's meant to be kept onscreen by some other means without valid data) */
break;
case 0x0001: // Camera transformation. case 0x0001: // Camera transformation.
setCameraTransformation(packet); setCameraTransformation(packet);
@ -970,12 +972,18 @@ void hng64_state::hng64_command3d(const uint16_t* packet)
setCameraProjectionMatrix(packet); setCameraProjectionMatrix(packet);
break; break;
case 0x0100: case 0x0100: // Geometry with full transformations
case 0x0101: // Geometry with full transformations // xrally/roadedge cars (not track, that uses 102), buriki, fatfurwa
recoverPolygonBlock(packet, numPolys);
break;
case 0x0101: // Geometry with full transformations (same as 0x100?)
// sams64, sams64_2, bbust2
recoverPolygonBlock(packet, numPolys); recoverPolygonBlock(packet, numPolys);
break; break;
case 0x0102: // Geometry with only translation case 0x0102: // Geometry with only translation
// 'world' in roadedge/xrally (track, trackside objects etc.)
// Split the packet and call recoverPolygonBlock on each half. // Split the packet and call recoverPolygonBlock on each half.
uint16_t miniPacket[16]; uint16_t miniPacket[16];
memset(miniPacket, 0, sizeof(uint16_t)*16); memset(miniPacket, 0, sizeof(uint16_t)*16);
@ -985,7 +993,8 @@ void hng64_state::hng64_command3d(const uint16_t* packet)
miniPacket[15] = 0x7fff; miniPacket[15] = 0x7fff;
recoverPolygonBlock(miniPacket, numPolys); recoverPolygonBlock(miniPacket, numPolys);
if (packet[7] == 1)
{
if (packet[8] == 0x0102) if (packet[8] == 0x0102)
{ {
memset(miniPacket, 0, sizeof(uint16_t) * 16); memset(miniPacket, 0, sizeof(uint16_t) * 16);
@ -994,6 +1003,8 @@ void hng64_state::hng64_command3d(const uint16_t* packet)
miniPacket[11] = 0x7fff; miniPacket[11] = 0x7fff;
miniPacket[15] = 0x7fff; miniPacket[15] = 0x7fff;
recoverPolygonBlock(miniPacket, numPolys); recoverPolygonBlock(miniPacket, numPolys);
// packet[15] is always 1?
} }
else else
{ {
@ -1001,11 +1012,12 @@ void hng64_state::hng64_command3d(const uint16_t* packet)
it could just be that the display list is corrupt at this point tho, see note above it could just be that the display list is corrupt at this point tho, see note above
*/ */
} }
}
break; break;
case 0x1000: // Unknown: Some sort of global flags? case 0x1000: // Unknown: Some sort of global flags?
//printPacket(packet, 1); printf("\n"); //printPacket(packet, 1); logerror("\n");
break; break;
case 0x1001: // Unknown: Some sort of global flags? Almost always comes in a group of 4 with an index [0,3]. case 0x1001: // Unknown: Some sort of global flags? Almost always comes in a group of 4 with an index [0,3].
@ -1013,7 +1025,7 @@ void hng64_state::hng64_command3d(const uint16_t* packet)
break; break;
default: default:
printf("HNG64: Unknown 3d command %04x.\n", packet[0]); logerror("HNG64: Unknown 3d command %04x.\n", packet[0]);
break; break;
} }
@ -1026,6 +1038,7 @@ void hng64_state::hng64_command3d(const uint16_t* packet)
} }
} }
m_poly_renderer->wait(); m_poly_renderer->wait();
return true;
} }
void hng64_state::clear3d() void hng64_state::clear3d()
@ -1040,6 +1053,8 @@ void hng64_state::clear3d()
// Clear the 3d rasterizer buffer // Clear the 3d rasterizer buffer
m_poly_renderer->colorBuffer3d().fill(0x00000000, m_screen->visible_area()); m_poly_renderer->colorBuffer3d().fill(0x00000000, m_screen->visible_area());
m_paletteState3d = 0;
// Set some matrices to the identity... // Set some matrices to the identity...
setIdentity(m_projectionMatrix); setIdentity(m_projectionMatrix);
setIdentity(m_modelViewMatrix); setIdentity(m_modelViewMatrix);
@ -1265,18 +1280,11 @@ void hng64_poly_renderer::render_texture_scanline(int32_t scanline, const extent
float textureS = 0.0f; float textureS = 0.0f;
float textureT = 0.0f; float textureT = 0.0f;
// Standard & Half-Res textures // sCorrect and tCorrect have range 0.0f - 1.0f, multiply by 1024 to get texture offset
if (renderData.texType == 0x0)
{
textureS = sCorrect * 1024.0f; textureS = sCorrect * 1024.0f;
textureT = tCorrect * 1024.0f; textureT = tCorrect * 1024.0f;
}
else if (renderData.texType == 0x1)
{
textureS = sCorrect * 512.0f;
textureT = tCorrect * 512.0f;
}
#if 1
// Small-Page textures // Small-Page textures
if (renderData.texPageSmall == 2) if (renderData.texPageSmall == 2)
{ {
@ -1288,21 +1296,37 @@ void hng64_poly_renderer::render_texture_scanline(int32_t scanline, const extent
} }
else if (renderData.texPageSmall == 3) else if (renderData.texPageSmall == 3)
{ {
// this can't be 128x128 textures, it is needed for the road etc. in xrally which is 256 wide,
// but also overhead objects which are 128 (eg lamps, near top left hand side on 8bpp texture page 8)
textureT = fmod(textureT, 128.0f); textureT = fmod(textureT, 128.0f);
textureS = fmod(textureS, 128.0f); textureS = fmod(textureS, 128.0f);
textureT += (128.0f * (renderData.texPageHorizOffset >> 0)); textureT += (128.0f * (renderData.texPageHorizOffset >> 0));
textureS += (128.0f * (renderData.texPageVertOffset >> 0)); textureS += (128.0f * (renderData.texPageVertOffset >> 0));
} }
#endif
uint8_t paletteEntry = textureOffset[((int)textureS)*1024 + (int)textureT]; uint8_t paletteEntry;
int t = (int)textureT;
if (renderData.tex4bpp)
{
paletteEntry = textureOffset[((int)textureS) * 512 + (t >> 1)];
if (t & 1)
paletteEntry = (paletteEntry >> 4) & 0x0f;
else
paletteEntry &= 0x0f;
}
else
{
paletteEntry = textureOffset[((int)textureS) * 1024 + t];
}
// Naive Alpha Implementation (?) - don't draw if you're at texture index 0... // Naive Alpha Implementation (?) - don't draw if you're at texture index 0...
if (paletteEntry != 0) if (paletteEntry != 0)
{ {
// The color out of the texture // The color out of the texture
paletteEntry %= renderData.palPageSize; rgb_t color = m_state.m_palette->pen((renderData.palOffset + paletteEntry) & 0xfff);
rgb_t color = m_state.m_palette->pen(renderData.palOffset + paletteEntry);
// Apply the lighting // Apply the lighting
float rIntensity = rCorrect / 255.0f; float rIntensity = rCorrect / 255.0f;
@ -1390,10 +1414,9 @@ void hng64_poly_renderer::drawShaded(polygon *p)
{ {
// Polygon information for the rasterizer // Polygon information for the rasterizer
hng64_poly_data rOptions; hng64_poly_data rOptions;
rOptions.texType = p->texType; rOptions.tex4bpp = p->tex4bpp;
rOptions.texIndex = p->texIndex; rOptions.texIndex = p->texIndex;
rOptions.palOffset = p->palOffset; rOptions.palOffset = p->palOffset;
rOptions.palPageSize = p->palPageSize;
rOptions.debugColor = p->debugColor; rOptions.debugColor = p->debugColor;
rOptions.texPageSmall = p->texPageSmall; rOptions.texPageSmall = p->texPageSmall;
rOptions.texPageHorizOffset = p->texPageHorizOffset; rOptions.texPageHorizOffset = p->texPageHorizOffset;

View File

@ -281,11 +281,11 @@ void hng64_state::sound_comms_w(offs_t offset, uint16_t data, uint16_t mem_mask)
/* correct? */ /* correct? */
m_audiocpu->set_input_line(5, CLEAR_LINE); m_audiocpu->set_input_line(5, CLEAR_LINE);
//if(data) //if(data)
// printf("IRQ ACK %02x?\n",data); // logerror("IRQ ACK %02x?\n",data);
return; return;
} }
//printf("SOUND W %02x %04x\n",offset*2,data); //logerror("SOUND W %02x %04x\n",offset*2,data);
} }
uint16_t hng64_state::sound_comms_r(offs_t offset) uint16_t hng64_state::sound_comms_r(offs_t offset)
@ -297,7 +297,7 @@ uint16_t hng64_state::sound_comms_r(offs_t offset)
case 0x06: case 0x06:
return main_latch[1]; return main_latch[1];
} }
//printf("SOUND R %02x\n",offset*2); //logerror("SOUND R %02x\n",offset*2);
return 0; return 0;
} }
@ -375,7 +375,7 @@ WRITE_LINE_MEMBER(hng64_state::tcu_tm2_cb)
if(i > 7) if(i > 7)
i = 7; i = 7;
//printf("trigger %02x %d\n",i,state); //logerror("trigger %02x %d\n",i,state);
//if(machine().input().code_pressed_once(KEYCODE_C)) //if(machine().input().code_pressed_once(KEYCODE_C))
{ {

View File

@ -569,7 +569,7 @@ void hng64_state::hng64_drawtilemap(screen_device &screen, bitmap_rgb32 &bitmap,
// floor mode // floor mode
// life would be easier if the roz we're talking about for complex zoom wasn't setting this as well // 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); // logerror(stderr, "Tilemap %d is a floor using :\n", tm);
// const uint32_t floorAddress = 0x40000 + (scrollbase << 4); // const uint32_t floorAddress = 0x40000 + (scrollbase << 4);
// TODO: The row count is correct, but how is this layer clipped? m_tcram? // TODO: The row count is correct, but how is this layer clipped? m_tcram?
@ -587,7 +587,7 @@ void hng64_state::hng64_drawtilemap(screen_device &screen, bitmap_rgb32 &bitmap,
// //
// lineCount++; // lineCount++;
//} //}
//printf("lines %d\n", lineCount); //logerror("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
// (but so does fatfurwa - maybe it overdraws a bunch of pixels?) // (but so does fatfurwa - maybe it overdraws a bunch of pixels?)
@ -734,7 +734,7 @@ void hng64_state::hng64_drawtilemap(screen_device &screen, bitmap_rgb32 &bitmap,
const int bmwidth = bm.width(); const int bmwidth = bm.width();
pen_t const *const paldata = m_palette->pens(); pen_t const *const paldata = m_palette->pens();
//printf("start %08x end %08x start %08x end %08x\n", xtopleft, xmiddle, ytopleft, ymiddle); //logerror("start %08x end %08x start %08x end %08x\n", xtopleft, xmiddle, ytopleft, ymiddle);
for (int yy=0; yy<448; yy++) for (int yy=0; yy<448; yy++)
{ {
@ -826,7 +826,7 @@ void hng64_state::hng64_drawtilemap(screen_device &screen, bitmap_rgb32 &bitmap,
int tmp = xtopleft; int tmp = xtopleft;
//printf("start %08x end %08x start %08x end %08x\n", xtopleft, xmiddle, ytopleft, ymiddle); //logerror("start %08x end %08x start %08x end %08x\n", xtopleft, xmiddle, ytopleft, ymiddle);
for (int yy=0; yy<448; yy++) for (int yy=0; yy<448; yy++)
{ {