HZC (File Format): Difference between revisions
No edit summary |
(Completed documentation for the rest of the found versions) |
||
| (4 intermediate revisions by the same user not shown) | |||
| Line 1: | Line 1: | ||
'''HZC''' is a collision format used in some games developed by ''[https://en.wikipedia.org/wiki/Firebrand_Games Firebrand Games]'' such as ''[https://en.wikipedia.org/wiki/Cartoon_Network_Racing Cartoon Network Racing DS]'' and ''[https://en.wikipedia.org/wiki/Race_Driver:_Create_%26_Race Race Driver: Create & Race]''. | '''HZC''' is a collision format used in some [[Nintendo DS]] and [[Nintendo 3DS]] games developed by ''[https://en.wikipedia.org/wiki/Firebrand_Games Firebrand Games]'' such as ''[https://en.wikipedia.org/wiki/Cartoon_Network_Racing Cartoon Network Racing DS]'' and ''[https://en.wikipedia.org/wiki/Race_Driver:_Create_%26_Race Race Driver: Create & Race]''. | ||
= File Format = | = File Format = | ||
| Line 10: | Line 10: | ||
! Offset !! Type !! Description | ! Offset !! Type !! Description | ||
|- | |- | ||
| 0x00 || UInt16 || '''[[#Version List|Version number]]'''. | | 0x00 || UInt16 || '''[[#Version List|Version number]]'''. The low byte is the minor version, and the high byte is the major version (always 1). | ||
|- | |- | ||
| 0x02 || UInt16 || '''Number of vertices''' ('''V'''). | | 0x02 || UInt16 || '''Number of vertices''' ('''V'''). | ||
| Line 17: | Line 17: | ||
|- | |- | ||
| 0x06 || UInt16 || '''Number of custom attributes''' ('''A'''). | | 0x06 || UInt16 || '''Number of custom attributes''' ('''A'''). | ||
|- bgcolor="#AAFFAA" | |||
| colspan="3" align="center" | '''If [[#Version List|version]] ≥ 1.18''' | |||
|- bgcolor="#DDFFDD" | |||
| 0x08 || UInt16 || {{Unknown-left|'''Vertex extra count''' ('''VE'''), unknown exact meaning. Usually equal to '''V''' or 0.}} | |||
|- bgcolor="#FFAAAA" | |||
| colspan="3" align="center" | '''If version ≥ 1.23''' | |||
|- bgcolor="#FFDDDD" | |||
| 0x0A || Byte[10] || {{Unknown-left|'''Unknown'''.}} | |||
|} | |} | ||
== Vertex Data == | == Vertex Data == | ||
Followed by the header, there's plain vertex position data stored as a sequence of groups of 3 | Followed by the header, there's plain vertex position data stored as a sequence of groups of 3 values (one per axis). On the DS versions, the values are integers and need to be divided by 4096. | ||
{| class="wikitable" | {| class="wikitable" | ||
! Offset !! Type !! Description | ! Offset !! Type !! Description | ||
|- | |- bgcolor="#AAFFAA" | ||
| colspan="3" align="center" | '''If [[#Version List|version]] ≥ 1.18''' | |||
|- bgcolor="#DDFFDD" | |||
| 0x00 || Float32[3]['''V'''] || '''Vertex XYZ coordinates'''. | |||
|- bgcolor="#FFAAAA" | |||
| colspan="3" align="center" | '''Else''' | |||
|- bgcolor="#FFDDDD" | |||
| 0x00 || Int32[3]['''V'''] || '''Vertex XYZ coordinates'''. | | 0x00 || Int32[3]['''V'''] || '''Vertex XYZ coordinates'''. | ||
|} | |} | ||
| Line 38: | Line 52: | ||
== Triangle Normal Data == | == Triangle Normal Data == | ||
Directly after the triangle indices there are the triangle's face normals, consisting of 3 Int32s per triangle. They seem to match the cross product of the triangle's first two edges with a magnitude of 4096. | '''Versions 1.3 and 1.5 only'''. Directly after the triangle indices there are the triangle's face normals, consisting of 3 Int32s per triangle that divide by 4096. They seem to match the cross product of the triangle's first two edges with a magnitude of 4096. | ||
{| class="wikitable" | {| class="wikitable" | ||
! Offset !! Type !! Description | ! Offset !! Type !! Description | ||
|- | |- bgcolor="#AAFFAA" | ||
| colspan="3" align="center" | '''If [[#Version List|version]] == 1.3 OR 1.5''' | |||
|- bgcolor="#DDFFDD" | |||
| 0x00 || Int32[3]['''T'''] || '''Triangle XYZ normals'''. | | 0x00 || Int32[3]['''T'''] || '''Triangle XYZ normals'''. | ||
|} | |||
== Triangle Adjacency Data == | |||
'''Version 1.5 only'''. Directly after the triangle normals there is an additional set of 3 UInt16s per triangle. The values appear to be the indices of the three neighboring triangles, with 0xFFFF for open edges. | |||
{| class="wikitable" | |||
! Offset !! Type !! Description | |||
|- bgcolor="#AAFFAA" | |||
| colspan="3" align="center" | '''If [[#Version List|version]] == 1.5''' | |||
|- bgcolor="#DDFFDD" | |||
| 0x00 || UInt16[3]['''T'''] || '''Neighbor triangle indices'''. | |||
|} | |||
== Vertex Extra Data == | |||
'''Versions 1.18 and up only'''. After the triangle data there is a block of '''VE''' x 4 bytes. The purpose is not fully known, but the values are commonly <code>01 01 01 01</code> per entry. This block is absent when '''VE''' is 0. | |||
{| class="wikitable" | |||
! Offset !! Type !! Description | |||
|- bgcolor="#AAFFAA" | |||
| colspan="3" align="center" | '''If [[#Version List|version]] ≥ 1.18''' | |||
|- bgcolor="#DDFFDD" | |||
| 0x00 || UInt32['''VE'''] || {{Unknown-left|'''Unknown'''.}} | |||
|} | |} | ||
== Grid == | == Grid == | ||
A spatial grid of 3D cells is used for faster collision detection. Each cell holds an index into the [[#Linked List Array|Linked List Array]], or 0xFFFF when the cell is empty. The grid is made of three blocks: the cell array, the [[#Grid Info|Grid Info]], and the [[#Linked List Array|Linked List Array]]. On versions 1.22 and up the order is reversed (the Linked List Array comes first, then the Grid Info, and then the cell array). | |||
{| class="wikitable" | {| class="wikitable" | ||
| Line 54: | Line 92: | ||
| 0x00 || Int32 || '''Number of cells''' ('''C'''). | | 0x00 || Int32 || '''Number of cells''' ('''C'''). | ||
|- | |- | ||
| 0x04 || UInt16['''C'''] || '''Cell indices'''. 0xFFFF if empty. | | 0x04 || UInt16['''C'''] || '''Cell indices'''. Each index is the head index of that cell's chain in the [[#Linked List Array|Linked List Array]]. 0xFFFF if the cell is empty. | ||
|} | |} | ||
| Line 62: | Line 100: | ||
|- | |- | ||
| 0x00 || Int32[3] || '''Number of cells in the grid's XYZ dimensions'''. | | 0x00 || Int32[3] || '''Number of cells in the grid's XYZ dimensions'''. | ||
|- | |- bgcolor="#AAFFAA" | ||
| 0x0C || Int32[3] || '''Grid bounding box minimum XYZ position'''. | | colspan="3" align="center" | '''If [[#Version List|version]] ≥ 1.18''' | ||
|- | |- bgcolor="#DDFFDD" | ||
| 0x18 || Int32[3] || '''Grid bounding box maximum XYZ position'''. | | 0x0C || Float32[3] || '''Grid bounding box minimum XYZ position'''. | ||
|- | |- bgcolor="#DDFFDD" | ||
| 0x24 || Int32 || {{Unknown-left|'''Unknown'''. Always 0 | | 0x18 || Float32[3] || '''Grid bounding box maximum XYZ position'''. | ||
|- bgcolor="#FFAAAA" | |||
| colspan="3" align="center" | '''Else''' | |||
|- bgcolor="#FFDDDD" | |||
| 0x0C || Int32[3] || '''Grid bounding box minimum XYZ position'''. Divide by 4096. | |||
|- bgcolor="#FFDDDD" | |||
| 0x18 || Int32[3] || '''Grid bounding box maximum XYZ position'''. Divide by 4096. | |||
|- bgcolor="#AAFFAA" | |||
| colspan="3" align="center" | '''If [[#Version List|version]] == 1.3''' (Cartoon Network Racing only) | |||
|- bgcolor="#DDFFDD" | |||
| 0x24 || Int32 || {{Unknown-left|'''Unknown'''. Always 0.}} | |||
|} | |} | ||
== Linked List Array == | == Linked List Array == | ||
After the grid data there's an array of triangle/cell links. | After the grid data there's an array of triangle/cell links. Each cell stores the index of the first entry of its chain, and each entry names a triangle and the index of the next entry in the same chain, ending at 0xFFFF. A triangle is added to every cell it overlaps. | ||
{| class="wikitable" | {| class="wikitable" | ||
! Offset !! Type !! Description | ! Offset !! Type !! Description | ||
|- | |- bgcolor="#AAFFAA" | ||
| colspan="3" align="center" | '''If [[#Version List|version]] == 1.18 OR 1.19''' | |||
|- bgcolor="#DDFFDD" | |||
| 0x00 || UInt16 || '''Number of links''' ('''L'''). | |||
|- bgcolor="#DDFFDD" | |||
| 0x02 || UInt16[2]['''L'''] || '''Triangle index'''/'''next index'''. The next index is 0xFFFF at the end of a cell's chain, otherwise another index into this same array. | |||
|- bgcolor="#FFAAAA" | |||
| colspan="3" align="center" | '''Else''' | |||
|- bgcolor="#FFDDDD" | |||
| 0x00 || Int32 || '''Number of links''' ('''L'''). | | 0x00 || Int32 || '''Number of links''' ('''L'''). | ||
|- | |- bgcolor="#FFDDDD" | ||
| 0x04 || UInt16[2]['''L'''] || '''Triangle index''' | | 0x04 || UInt16[2]['''L'''] || '''Triangle index'''/'''next index'''. The next index is 0xFFFF at the end of a cell's chain, otherwise another index into this same array. | ||
|} | |} | ||
== Custom Attribute Table == | == Custom Attribute Table == | ||
This section is only present if '''A''' > 0. | This section is only present if '''A''' > 0. Version 1.14 stores a single surface type byte per triangle and has no string table. Not all attributes may be used, as some files have been seen with unused attribute strings. | ||
{| class="wikitable" | {| class="wikitable" | ||
! Offset !! Type !! Description | ! Offset !! Type !! Description | ||
|- | |- bgcolor="#AAFFAA" | ||
| colspan="3" align="center" | '''If [[#Version List|version]] == 1.14''' | |||
|- bgcolor="#DDFFDD" | |||
| 0x00 || Byte['''T'''] || '''Surface type'''. | |||
|- bgcolor="#FFAAAA" | |||
| colspan="3" align="center" | '''Else''' | |||
|- bgcolor="#FFDDDD" | |||
| 0x00 || UInt16['''T'''] || '''Attribute IDs'''. 0xFFFF if none. | | 0x00 || UInt16['''T'''] || '''Attribute IDs'''. 0xFFFF if none. | ||
|} | |} | ||
=== String Table === | === String Table === | ||
'''Not present in version 1.14.''' | |||
{| class="wikitable" | {| class="wikitable" | ||
! Offset !! Type !! Description | ! Offset !! Type !! Description | ||
|- | |- | ||
| 0x00 || [[#Key-Value | | 0x00 || [[#Key-Value Attribute|Key-Value Attribute]]['''A'''] || '''Key-value attribute strings'''. | ||
|} | |} | ||
==== Key-Value | ==== Key-Value Attribute ==== | ||
{| class="wikitable" | {| class="wikitable" | ||
! Offset !! Type !! Description | ! Offset !! Type !! Description | ||
|- | |- | ||
| 0x00 || UInt16 || '''Key string length''' (''' | | 0x00 || UInt16 || '''Key string length''' ('''AK'''). | ||
|- | |- | ||
| 0x02 || String (Char[''' | | 0x02 || String (Char['''AK''']) || '''Attribute key'''. | ||
|- | |- | ||
| 0x02 + ''' | | 0x02 + '''AK''' || UInt16 || '''Value string length''' ('''AV'''). | ||
|- | |- | ||
| 0x04 + ''' | | 0x04 + '''AK''' || String (Char['''AV''']) || '''Attribute value'''. Seen as ''float(SurfaceType)='''X'''.000000'' in Cartoon Network Racing DS. | ||
|} | |} | ||
| Line 187: | Line 251: | ||
|- | |- | ||
| 1.3 | | 1.3 | ||
| [https://en.wikipedia.org/wiki/Cartoon_Network_Racing Cartoon Network Racing DS] | | | ||
* [https://en.wikipedia.org/wiki/Cartoon_Network_Racing Cartoon Network Racing DS] | |||
* [https://en.wikipedia.org/wiki/Ferrari_Challenge:_Trofeo_Pirelli Ferrari Challenge: Trofeo Pirelli DS] | |||
|- | |- | ||
| 1.4 | | 1.4 | ||
| Line 195: | Line 261: | ||
| | | | ||
* [https://en.wikipedia.org/wiki/Cars_2:_The_Video_Game Cars 2: The Video Game DS] | * [https://en.wikipedia.org/wiki/Cars_2:_The_Video_Game Cars 2: The Video Game DS] | ||
* [https://en.wikipedia.org/wiki/Colin_McRae:_Dirt_2 Colin McRae: Dirt 2 DS] | |||
* [https://en.wikipedia.org/wiki/Hot_Wheels:_Track_Attack Hot Wheels: Track Attack DS] | * [https://en.wikipedia.org/wiki/Hot_Wheels:_Track_Attack Hot Wheels: Track Attack DS] | ||
* [https://en.wikipedia.org/wiki/Need_for_Speed:_Nitro Need for Speed: Nitro DS] | |||
* [[Need for Speed: Nitro-X]] | |||
* [https://en.wikipedia.org/wiki/Need_for_Speed:_Undercover Need for Speed: Undercover DS] | |||
* [https://en.wikipedia.org/wiki/Race_Driver:_Grid Race Driver: Grid DS] | |||
* [https://en.wikipedia.org/wiki/SpongeBob's_Boating_Bash SpongeBob's Boating Bash] | |||
|- | |||
| 1.12 | |||
| | |||
* [[Planet 51: The Game DS]] | |||
* [https://en.wikipedia.org/wiki/TrackMania_DS TrackMania DS] | |||
|- | |||
| 1.14 | |||
| [https://en.wikipedia.org/wiki/TrackMania_Turbo_(2010_video_game) TrackMania Turbo (2010)] | |||
|- | |||
| 1.18 | |||
| | |||
* [https://en.wikipedia.org/wiki/Cars_2:_The_Video_Game Cars 2: The Video Game 3DS] | |||
* [https://en.wikipedia.org/wiki/NASCAR_Unleashed NASCAR Unleashed] | |||
|- | |||
| 1.19 | |||
| [https://en.wikipedia.org/wiki/Need_for_Speed:_The_Run Need for Speed: The Run 3DS] | |||
|- | |||
| 1.22 | |||
| [https://en.wikipedia.org/wiki/Fast_&_Furious:_Showdown Fast & Furious: Showdown 3DS] | |||
|- | |||
| 1.23 | |||
| | |||
* [https://en.wikipedia.org/wiki/Hot_Wheels:_World's_Best_Driver Hot Wheels: World's Best Driver 3DS] | |||
* [https://en.wikipedia.org/wiki/WRC_FIA_World_Rally_Championship WRC FIA World Rally Championship 3DS] | |||
|} | |} | ||
= Tools = | = Tools = | ||
Latest revision as of 12:30, 11 October 2026
HZC is a collision format used in some Nintendo DS and Nintendo 3DS games developed by Firebrand Games such as Cartoon Network Racing DS and Race Driver: Create & Race.
File Format
The file byte order is always little endian.
Header
The file starts with the following header:
| Offset | Type | Description |
|---|---|---|
| 0x00 | UInt16 | Version number. The low byte is the minor version, and the high byte is the major version (always 1). |
| 0x02 | UInt16 | Number of vertices (V). |
| 0x04 | UInt16 | Number of triangles (T). |
| 0x06 | UInt16 | Number of custom attributes (A). |
| If version ≥ 1.18 | ||
| 0x08 | UInt16 | Vertex extra count (VE), unknown exact meaning. Usually equal to V or 0. |
| If version ≥ 1.23 | ||
| 0x0A | Byte[10] | Unknown. |
Vertex Data
Followed by the header, there's plain vertex position data stored as a sequence of groups of 3 values (one per axis). On the DS versions, the values are integers and need to be divided by 4096.
| Offset | Type | Description |
|---|---|---|
| If version ≥ 1.18 | ||
| 0x00 | Float32[3][V] | Vertex XYZ coordinates. |
| Else | ||
| 0x00 | Int32[3][V] | Vertex XYZ coordinates. |
Triangle Index Data
After the vertex data, there's a list of T * 3 UInt16s that correspond to the indices of each triangle.
| Offset | Type | Description |
|---|---|---|
| 0x00 | UInt16[3][T] | Triangle indices. |
Triangle Normal Data
Versions 1.3 and 1.5 only. Directly after the triangle indices there are the triangle's face normals, consisting of 3 Int32s per triangle that divide by 4096. They seem to match the cross product of the triangle's first two edges with a magnitude of 4096.
| Offset | Type | Description |
|---|---|---|
| If version == 1.3 OR 1.5 | ||
| 0x00 | Int32[3][T] | Triangle XYZ normals. |
Triangle Adjacency Data
Version 1.5 only. Directly after the triangle normals there is an additional set of 3 UInt16s per triangle. The values appear to be the indices of the three neighboring triangles, with 0xFFFF for open edges.
| Offset | Type | Description |
|---|---|---|
| If version == 1.5 | ||
| 0x00 | UInt16[3][T] | Neighbor triangle indices. |
Vertex Extra Data
Versions 1.18 and up only. After the triangle data there is a block of VE x 4 bytes. The purpose is not fully known, but the values are commonly 01 01 01 01 per entry. This block is absent when VE is 0.
| Offset | Type | Description |
|---|---|---|
| If version ≥ 1.18 | ||
| 0x00 | UInt32[VE] | Unknown. |
Grid
A spatial grid of 3D cells is used for faster collision detection. Each cell holds an index into the Linked List Array, or 0xFFFF when the cell is empty. The grid is made of three blocks: the cell array, the Grid Info, and the Linked List Array. On versions 1.22 and up the order is reversed (the Linked List Array comes first, then the Grid Info, and then the cell array).
| Offset | Type | Description |
|---|---|---|
| 0x00 | Int32 | Number of cells (C). |
| 0x04 | UInt16[C] | Cell indices. Each index is the head index of that cell's chain in the Linked List Array. 0xFFFF if the cell is empty. |
Grid Info
| Offset | Type | Description |
|---|---|---|
| 0x00 | Int32[3] | Number of cells in the grid's XYZ dimensions. |
| If version ≥ 1.18 | ||
| 0x0C | Float32[3] | Grid bounding box minimum XYZ position. |
| 0x18 | Float32[3] | Grid bounding box maximum XYZ position. |
| Else | ||
| 0x0C | Int32[3] | Grid bounding box minimum XYZ position. Divide by 4096. |
| 0x18 | Int32[3] | Grid bounding box maximum XYZ position. Divide by 4096. |
| If version == 1.3 (Cartoon Network Racing only) | ||
| 0x24 | Int32 | Unknown. Always 0. |
Linked List Array
After the grid data there's an array of triangle/cell links. Each cell stores the index of the first entry of its chain, and each entry names a triangle and the index of the next entry in the same chain, ending at 0xFFFF. A triangle is added to every cell it overlaps.
| Offset | Type | Description |
|---|---|---|
| If version == 1.18 OR 1.19 | ||
| 0x00 | UInt16 | Number of links (L). |
| 0x02 | UInt16[2][L] | Triangle index/next index. The next index is 0xFFFF at the end of a cell's chain, otherwise another index into this same array. |
| Else | ||
| 0x00 | Int32 | Number of links (L). |
| 0x04 | UInt16[2][L] | Triangle index/next index. The next index is 0xFFFF at the end of a cell's chain, otherwise another index into this same array. |
Custom Attribute Table
This section is only present if A > 0. Version 1.14 stores a single surface type byte per triangle and has no string table. Not all attributes may be used, as some files have been seen with unused attribute strings.
| Offset | Type | Description |
|---|---|---|
| If version == 1.14 | ||
| 0x00 | Byte[T] | Surface type. |
| Else | ||
| 0x00 | UInt16[T] | Attribute IDs. 0xFFFF if none. |
String Table
Not present in version 1.14.
| Offset | Type | Description |
|---|---|---|
| 0x00 | Key-Value Attribute[A] | Key-value attribute strings. |
Key-Value Attribute
| Offset | Type | Description |
|---|---|---|
| 0x00 | UInt16 | Key string length (AK). |
| 0x02 | String (Char[AK]) | Attribute key. |
| 0x02 + AK | UInt16 | Value string length (AV). |
| 0x04 + AK | String (Char[AV]) | Attribute value. Seen as float(SurfaceType)=X.000000 in Cartoon Network Racing DS. |
| Key | Value | Found in |
|---|---|---|
| COL_grass | float(SurfaceType)=1.000000 |
|
| grass | float(SurfaceType)=1.000000 | Townsville.hzc |
| Grass | float(SurfaceType)=1.000000 |
|
| heavyTerrain | float(SurfaceType)=2.000000 |
|
| HeavyTerrain | float(SurfaceType)=3.000000 |
|
| MudPuddle | float(SurfaceType)=5.000000 | IslandDash.hzc |
| not_track |
|
|
| raceTrackFloor | — | DextersLab.hzc |
| raceTrackWalls | — | DextersLab.hzc |
| RoughGround |
|
|
| terrainLight | float(SurfaceType)=0.000000 |
|
Version List
| Version | Found in |
|---|---|
| 1.3 | |
| 1.4 | Race Driver: Create & Race |
| 1.5 | |
| 1.12 | |
| 1.14 | TrackMania Turbo (2010) |
| 1.18 | |
| 1.19 | Need for Speed: The Run 3DS |
| 1.22 | Fast & Furious: Showdown 3DS |
| 1.23 |
Tools
The following tools can handle HZC files:
- (none)