NKM Files

From CW-Games Wiki
Jump to: navigation, search

Original text by mkdasher

Contents

NKM Data Structure

Header: Based on checksums. It shows the number of parts and the structure of the .nkm file.

Object Positions (OBJI): Contains the Object Position Data and Object settings (if that object can have some variations). The Object Positions Data starts with "OBJI". They are linked with Routes if those objects has routes to follow.

Routes (PATH/POIT): Routes can be used for more than one thing, mainly Object Routes and Camera Routes. Routes are divided in Sections, "PATH" will determine those Sections and "POIT" will determine the Routes Positions.

"STAG": I don't really know too much about it. I think it has to do with start gate info. I can just say that it determines the number of laps, and I think the alignment of the racers can be changed here but I don't know how.

Start Position (KTPS): The position where you start the race.

Respawn Positions (KTPJ): Determines the respawn positions in the track after falling down.

"KTP2": The position you have to pass to finish a lap.

Cannon Position (KTPC): Determines the Cannon exit (when the cannon stops being effective). Only used in Waluigi Pinball, Airship Fortress and Pipe Plaza battle arena. The beginning of the cannon can't be modified here since its data is contained in the .kcl file.

"KTPM": Finish of mission.

Checkpoints (CPOI/CPAT): line segments bounded by two end points. Lap count will happen if the kart has passed between those end points (I believe you can just skip one in a row). "CPOI" will determine those end points and they are linked with the Respawn Positions. "CPAT" will determine the Checkpoint Sections.

Item Routes (IPOI/IPAT): Determines the item routes. These routes are made with points. "IPOI" determines those points and "IPAT" determines the Item Routes Sections.

Enemy Routes (EPOI/EPAT): Determines the routes that the CPU karts will follow. These routes are made with points. "EPOI" determines those points and "EPAT" determines the Enemy Routes Sections.

AREA: I can't completely explain how AREA works, but in most of the cases it's related to cameras. It is also made with points, and when a kart gets near an AREA point in replay mode, it calls upon the camera that is assigned to that AREA point., but this just happens with some of the AREA points, there are some other points that have different purposes I don't know.

CAME: Camera position. There are three kind of cameras, the ones in the track intro, the ones in the replay and the one after you finish the 3 laps that looks at your character. They are linked with the Routes. Routes would be the camera itself and "CAME" would be where the camera is looking.

(Note: Final tracks has this structure inside the .nkm file. However, Beta tracks doesn't use all of them).

File format / Endianness

It's important to understand how the data is stored in the .nkm file.

Endianness is the ordering of individually addressable sub-units (words, bytes, or even bits) within a longer data word stored in external memory. The .nkm file uses the little endian, which means that The least significant byte is at the lowest address and the other bytes follow in increasing order of significance, in other words, you need to read each 4 bytes from right to left.

Endian.png

How to transform byte data into values

This transformation will be used mainly to know the coordinates of one point, angles or some extra information that can be understood in the Decimal system:

To explain the transformation, I'll use the Sky Garden .nkm file as an example (old_sky_agb).

First of all, each data is stored in 4 bytes, so when we're applying the transformation we will need to take 4 bytes. I'll use two examples:

Hex1.png

(We'll transform 00 A0 41 00 into a Decimal value)

1.First of all, we need to analyse the 4-byte, and we can find 2 possibilities:

The last byte is "00" or "01". This means that the value will be positive.

The last byte is "FF" or "FE". This means that the value will be negative.

In this case we have a positive value, so we don't need to change anything.

2.As I said before, the .nkm file has a little endian format, so we will need to read the 4-byte from right to left.

(We should read it like this: (00 41 A0 00)).

3.After that, convert it from hexadecimal to decimal:

(00 41 A0 00)  4300800

4.Then, divide the value (4300800) by 4096

4300800 / 4096 = 1050

The real value for 00 A0 41 00 is 1050.


Now we'll see an example if the value is negative. I'll use this 4-byte as an example:

Hex2.png

(We'll transform 00 B0 96 FF into a Decimal value)


1.Check the last byte and we notice it's "FF", that means it'll be negative.

2.Read the 4-byte from right to left (FF 96 B0 00).

3.This is a negative value. Every time there is a negative value we may do this:

100000000 - value = result (Hexadecimal subtraction) In this case we will do:

(100000000 - FF96B000 = 695000)


4.Convert the result into Decimal: 695000  6901760

5.Divide by 4096, then add a minus sign since the value needs to be negative.

6901760 / 4096 = 1685  -1685

The real value for 00 B0 96 FF is -1685.

Header

One of the most important things to understand about the .nkm file is the Header. The header is based on checksums, so it must be written correctly to make the file work. This is the Header Structure (again I'll use Sky garden as an example):

Hex3.png

The file always starts with "NKMD" (4E 4B 4D 44).

Then, from 0x04 to 0x07 we will always find 25 00 xx 00, where xx is where the Object Position Data starts. (In other words, where the word "OBJI" is situated. We can see that here it's situated in 0x4c and that's why it's 0x06 is "4C".

Actually, every final track will be 25 00 4C 00 since they all have the same header, but it may change in some beta files.

After that, each 4-byte data will indicate where each Section beggining (OBJI, PATH, POIT, etc):

Hex4.png

How to calculate the beginning of a section Data:

For this, I'll use the "PATH beginning" (C4 07 00 00) as an example.

Read the 4-bytes from right to left (like this: 000007c4).

Now you need to add to this value the Header length (in this case, 4c)

07c4 + 4c = 0810

In this case, PATH will start in 0x810:

Hex5.png

When a .nkm file is modified, it's always necessary to change this values in the Header to make the file work. "OBJI beginning" will always be 00 00 00 00 since it's always directly after the Header.

Coordinates and common settings

• Block size / amount: It always appear at the beginning of a block (OBJI, PATH, POIT, etc.). Its size is 4 byte, 1st byte is always the Amount of objects / points the block has (written in hexadecimal). Then it is usually followed by "000000".

Example: If a file has 14 objects, it will be (0E000000).

• Coordinates: since Mario Kart DS is a 3d game, it uses 3 coordinates. I will follow the .nkm file order so first we have the X coordinate, then Y coordinate (which will be the heigh of the course), and then the Z coordinate. The way to calculate its value is the one mentioned previously.

• Coordinate angle: it determines the angle of the coordinate. The most useful angle is the Y angle, since it's the one that will be able to make you turn around the horizontal plane. By increasing the angle value, the kart will turn counter-clockwise. The way to calculate its value is the one mentioned previously.

• Coordinate scale: it can make an object bigger or smaller depending on its value. The way to calculate its value is the one mentioned previously. If its value is 1, it will use the standard size, if its value of 2 (in x angle, y angle and z angle), then the size will be duplicated.

Object Positions (OBJI)

Object Position has the following structure:

Objistructure.png

• Object ID: Determines the object. Check the Object ID List.

• Object Route ID: Determines the object route.

None: FFFF 1st route: 0100 2nd route: 0200 3rd route: 0300 …

• Settings: Additional information to the objects, not really known at the moment. Setting 5 is 01000000 if the object appears in Time Trial Mode and 00000000 is the object doesn't (for example, itemboxes).


This would be GBA Sky Garden's OBJI Block:

OBJIPos.png

Respawn Positions (KTPJ)

Respawn Position has the following structure:

KTPJstructure.png

- Those settings are unknown at the moment. The respawn ID is just the number of the respawn.

The Respawn ID is missing in the beta courses that freeze, so adding these will make them stop freezing. After that you will have to change the Y angle value (unless you're fixing it in the demo version, where they use X and Z values) since they are all 00000000 in the beta courses. And as mentioned before, always remember to edit the header.


Sky Garden "KTPJ" section:

Ktpjpos.png

Example

Routes (PATH/POIT)

Each object in the OBJI section has an ID and a Route ID. If the Route ID is FFFF then there is no route assigned to the object, but if it's something else then there is a route assigned to the object. The route data is found in this section.

Routes are found in the PATH and POIT sections. The actual points of the route are found in the POIT section, while the route IDs and number of points in the routes are found in the PATH section. POIT has this structure:

  • First 4 bytes: POIT
  • Second 4 bytes: Number of routes.
  • Route 1 first point: X, Y (height), Z, 00000000, 00000000.
  • Route 1 second point: X, Y, Z, 01000000, 00000000.
  • Route 1 third point...
  • Route 2 points...

Routes do not have angle values or scale values, since the data is just points which are the places where a route changes direction. The 0000000 and 01000000 variable is the position ID in the route, so 00 is the first position in the route, 01 is the second position, 02 is the third etc. After the route position ID it always has 00000000. To know the number of points that make up a route, check PATH. This section has this structure:

  • First 4 bytes: PATH
  • Second 4 bytes: Number of route IDs.
  • Route ID 1: xxyyzzzz
  • Route ID 2: xxyyzzzz
  • Route ID 3...

The xx is the ID of the route. So if it's the first route then xx will be 00, if it's the second route xx will be 01.

The yy can be 00 or 01:

  • 01: Only used for objects,the object Route is a loop (e.g. Balloon, car, moving chomp, etc).
  • 00: The Route is used for a camera or for another kind of object. (e.g: goomba, crab, fireball, etc.). If the route has 2 points or less it will always be 00 even they loop.

The zzzz is the number of points in the route. Since it's little endian, if the route has 2 points in it, zzzz will be 0200, if it has 5 points in it, zzzz will be 0500, if it has 300 points in it, zzzz will be 2C01.

Example

Beach coursePATHPOIT.png

  • The black highlighted areas is the first 4 bytes of PATH, the second 4 bytes of PATH and the data of the first 2 route IDs of beach_course.
  • The red highlighted areas are the first 4 bytes of POIT, the second 4 bytes of POIT and the data of the first route of beach_course.
  • The green highlighted areas are the data of the second route of beach_course.

Beach courseOBJI.png

This is part of the OBJI section of beach_course. As you can see, the blue highlighted areas are the object ID of a crab, 01AC (AC01 because of little endian), with routes 7, 8, 9, and 10 assigned to them. Even thought is says 0600, 0700, 0800 and 0900, the route 1 is 0000, so that's why the numbers are one below what you would expect. So basically the routes which are assigned in the OBJI section are controlled in the PATH and POIT sections.

If you modify routes, always edit the header. Always edit the header anyway. And if you add a route, remember to edit the second 4 bytes to the number of routes there now are in hex.

NEW (WIP)

NKM is a file format that describes objects, routes, cameras and other information about a course. If a value is Single, divide it by 4096 to get the right value. The file is little endian.

Header

Offset Size Type Description
0x00 0x4 String File Magic in ASCII (NKMD)
0x04 0x2 UInt16 Version Number. Final tracks are always 3.7 (0x25 = 37). Beta tracks are 3.0 (0x1E = 30), 3.2 (0x20 = 32) or 3.4 (0x22 = 34)
0x06 0x2 UInt16 Header Length
0x08 Header Length - 8 UInt32s Section Offsets. Not always the same amount, because not used sections may be ommited. Beta tracks do that for example.

Section

All sections except of STAG are like this:

Offset Size Type Description
0x00 0x4 String Section Magic in ASCII
0x04 0x4 UInt32 Nr of Entries in section

After this, the first entry starts.

OBJI (Object Information)

One OBJI entry is like this:

Offset Size Type Description
0x00 0x4 Single X Position
0x04 0x4 Single Y Position
0x08 0x4 Single Z Position
0x0C 0x4 Single X Angle
0x10 0x4 Single Y Angle
0x14 0x4 Single Z Angle
0x18 0x4 Single X Scale
0x1C 0x4 Single Y Scale
0x20 0x4 Single Z Scale
0x24 0x2 UInt16 Object ID
0x26 0x2 UInt16 Route ID
0x28 0x4 UInt32 Object Setting 1. Object specific. For some objects know. If you can click on a object in the object list, you will get some information about it.
0x2C 0x4 UInt32 Object Setting 2. Object specific. For some objects know. If you can click on a object in the object list, you will get some information about it.
0x30 0x4 UInt32 Object Setting 3. Object specific. For some objects know. If you can click on a object in the object list, you will get some information about it.
0x34 0x4 UInt32 Object Setting 4. Object specific. For some objects know. If you can click on a object in the object list, you will get some information about it.
0x38 0x4 UInt32 Show in Time Trails. 1 If shown, 0 otherwise.

PATH (Path)

One PATH entry is like this:

Offset Size Type Description
0x00 0x1 Byte Route Index
0x01 0x1 Byte 1 If the route loops, 0 otherwise.
0x02 0x2 UInt16 Nr points. The points are in the POIT section.

POIT (Point)

One POIT entry is like this:

Offset Size Type Description
0x00 0x4 Single X Position
0x04 0x4 Single Y Position
0x08 0x4 Single Z Position
0x0C 0x2 Int16 Point Index in the Route
0x0E 0x2 Int16 Point Duration. Not always used.
0x10 0x4 UInt32 Unknown

STAG (Stage)

One of the most unknown sections. Some things are known. STAG is like this:

Offset Size Type Description
0x00 0x4 String Section Magic in ASCII (STAG)
0x04 0x2 UInt16 Unknown 1
0x06 0x2 UInt16 Nr Laps
0x08 0xC Bytes Unknown 2
0x14 0x4 UInt32 Fog Distance
0x18 0x2 UInt16 Fog Color
0x1A 0x2 UInt16 Fog Alpha (0-15)
0x1C 0x2 UInt16 KCL Color 1, the default color.
0x1E 0x2 UInt16 KCL Color 2
0x20 0x2 UInt16 KCL Color 3
0x22 0x2 UInt16 KCL Color 4
0x24 0x8 Bytes Unknown 4

KTPS (Kart Position Start)

KTPJ (Kart Position Jugemu)

KTP2 (Kart Position 2nd)

KTPC (Kart Position Cannon)

KTPM (Kart Position Mission)

CPOI (Checkpoint)

CPAT (Checkpoint Path)

IPOI (Item Point)

IPAT (Item Path)

EPOI (Enemey Point)

EPAT (Enemey Path)

AREA(Area)

CAME (Camera)

Structure

One CAME entry is like this:

Offset Size Type Description
0x00 0x4 Single X Position 1
0x04 0x4 Single Y Position 1
0x08 0x4 Single Z Position 1
0x0C 0x4 Single X Angle
0x10 0x4 Single Y Angle
0x14 0x4 Single Z Angle
0x18 0x4 Single X Position 2
0x1C 0x4 Single Y Position 2
0x20 0x4 Single Z Position 2
0x24 0x4 Single X Position 3
0x28 0x4 Single Y Position 3
0x2C 0x4 Single Z Position 3
0x30 0x4 UInt32 Unknown
0x34 0x4 UInt32 Unknown
0x38 0x4 UInt32 Unknown
0x3C 0x2 Int16 Camera Zoom
0x3E 0x2 Int16 Camera Type
Value Description
0x0 ?
0x1 ?
0x2 ?
0x3 Intro Camera (Top Screen)
0x4 Intro Camera (Bottom Screen)
0x5 ?
0x6 ?
0x7 Battle Mode Camera
0x8 Mission Finish Camera
0x40 0x2 Int16 Linked Route (-1 if none)
0x42 0x2 Int16 Route Speed
0x44 0x2 Int16 Point Speed
0x46 0x2 Int16 Camera Duration in 1/60 second units. (Divide by 60 to get seconds)
0x48 0x2 Int16 Next Camera (-1 if this is the last one)
0x4A 0x1 Byte Intro Pan First Camera Indicator (0x0 = None, 0x1 = Top Screen, 0x2 = Bottom Screen)
0x4B 0x1 Byte Unknown

How it works

The camera works like this:

  • The linked route is the camera itself. The camera moves on the route with the Route Speed.
  • The 3 points are the points the camera looks at. The camera looks at point 1 first, and then rotates with the Point Speed from point 1 through point 2 to point 3.
  • While rotating and moving, the camera zooms the Camera Zoom. (There could be a zoom speed)
  • When the Camera Duration expires, the camera automatically moves on to the next camera (if available)
Personal tools
Namespaces
Variants
Actions
Navigation
Toolbox
Courses
Documentation
Files
Full Hacks
Model Hacks
Texture Hacks
Misc Hacks
Applications
Theory
Tutorials
Video