mkds.nkm module

class mkds.nkm.Section(data, size)[source]

Bases: object

Base class for sections in an NKM file.

Overview

Most NKM sections (all except STAG) begin with an 8-byte section header:
  • 0x00 (4 bytes): Section magic (ASCII, e.g., “OBJI”).

  • 0x04 (4 bytes): Number of entries in the section (UInt32).

Immediately after the header the section contains entry_count entries, each with a fixed stride (size) which is specified by the concrete Section subclass.

This base class encapsulates:
  • raw data for the whole section (header + entries)

  • stride (size in bytes of a single entry)

  • entry_count parsed from the header

  • an iterator over each fixed-size entry slice

Notes / Caveats

  • This class assumes the data passed includes the section header.

  • If a section contains variable-length entries (rare in NKM), a custom parser should be used instead of relying on a fixed stride.

  • Many sections have fields where 0xFFFF or 0xFF indicates “unused” or “none” — callers should treat those sentinel values accordingly.

class mkds.nkm.OBJI(data)[source]

Bases: Section

OBJI — Object Instances section.

Stride: 0x3C bytes per entry.

Purpose

Describes every object placed in the track: visual decorations, interactive objects, obstacle instances, item boxes, etc. These objects are instantiated by the game engine and can be linked to PATH routes.

OBJI Entry Structure

Offset

Type

Name

Description

0x00

VecFx32

pos

3D position vector (FX32).

0x0C

VecFx32

rot

3D rotation vector.

0x18

VecFx32

scale

3D scale vector.

0x24

u16

object_id

Object ID (model/behavior).

0x26

u16

route_id

Route ID (0xFFFF = none).

0x28

u32

setting0

Object-specific setting 0.

0x2C

u32

setting1

Object-specific setting 1.

0x30

u32

setting2

Object-specific setting 2.

0x34

u32

setting3

Object-specific setting 3.

0x38

u32

show_tt

Visible in Time Trials (1=yes,0=no).

Gameplay Context

  • The object ID decides both model and in some cases runtime logic (collision, activatable behaviors).

  • The route_id links the object to a PATH. If present, the object will be moved/animated by the PATH’s POIT points at runtime (e.g., moving platforms, cameras).

  • The object settings are used by many object types to control behavior: rotation speed, spawn flags, timers, random seeds, or other per-object parameters. Different object IDs require different decoding logic.

Reverse-Engineering Notes / Tips

  • The four 32-bit settings differ radically between object types — community wikis often contain per-object decode rules (use object ID to branch).

  • The presence of a non-0 or non-0xFFFFFFFF route_id often means the object will be animated along that route; route indices are bytes in PATH entries but stored here as a 16-bit value (keep an eye on sign/width).

  • Show-in-time-trials: historically some editors used 0/1 inverse; verify against known tracks when in doubt.

Parsing Caveat

We read object_id as read_u16 and route_id as read_u16. Consumers of this class should treat 0xFFFF in route_id as “no route”.

class mkds.nkm.PATH(data)[source]

Bases: Section

PATH — Path metadata.

Stride: 0x04 bytes per entry.

Purpose

Describes metadata for routes used by objects and cameras. Each PATH entry points to a sequence of POIT entries (control points) that define the route.

PATH Entry Structure

Offset

Type

Name

Description

0x00

u8

route_id

Route identifier.

0x01

u8

loop

1 if route loops, else 0.

0x02

u16

point_ct

Number of POIT points.

Gameplay Context

  • Objects or cameras that reference a route will move along the POIT points in order; if the loop flag is set, the route repeats.

  • Route ID is commonly a small integer; the PATH list enumerates all routes in use on the track.

Reverse-Engineering Notes / Caveats

  • The canonical spec states: 0x01 == 1 if the route loops, 0 otherwise. In the code you originally used read_u8(d, 0x01) != 1 (which inverts the meaning). I have NOT altered your logic — but be aware of the discrepancy: callers should expect True when the route loops. Consider changing to read_u8(… ) == 1 for clarity.

  • point_count enumerates POIT entries but the mapping from global POIT index to route is (index offset + length) — consumers should reconstruct the actual POIT index ranges using CPAT/EPAT/IPAT/MEPA grouping sections when applicable (these groupings partition points).

class mkds.nkm.POIT(data)[source]

Bases: Section

POIT — Path points (control points).

Stride: 0x14 bytes per entry.

Purpose

Stores the actual 3D points used by PATH routes. Points are grouped by route using the counts stored in PATH plus the various *PAT grouping sections.

POIT Entry Structure

Offset

Type

Name

Description

0x00

VecFx32

pos

3D position vector.

0x0C

u8

index

Point index in route.

0x0D

u8

unknown1

Unknown/padding.

0x0E

s16

duration

Point duration (optional).

0x10

u32

unknown2

Reserved/unknown.

Gameplay Context

  • Moving objects and cameras read these points sequentially to interpolate positions. The “point_index” normally indicates position in the route’s ordering (0,1,2,…).

  • Some cameras or scripted objects use point_duration to wait between points, enabling non-linear motion.

  • POIT order in the file is important: group membership is often determined by successive ranges; use PAT sections to map ranges to specific routes.

Reverse-Engineering Notes

  • The unknown fields often show consistent patterns per track editor — check community resources to decode them for special behaviors.

  • Some older track versions or beta files encode rotation differently; when in doubt, cross-check with KTPJ notes for version-dependent behavior.

class mkds.nkm.STAG(data)[source]

Bases: object

STAG — Stage (track) information.

Fixed-size: The STAG section is unique in NKM: it does NOT have a section header and is a single 0x2C-byte structure placed directly in the file (after POIT in the canonical header ordering).

Purpose

Contains global track settings: track ID, default lap count, fog settings, colors used by KCL (collision visual palettes), and other miscellaneous bytes.

STAG Entry Structure

Offset

Type

Name

Description

0x00

char[4]

magic

Always “STAG”.

0x04

u16

track_id

Track ID.

0x06

u16

laps

Lap count.

0x08

u8

unknown1

Unknown small integer.

0x09

u8

fog_enabled

1 = fog on, 0 = off.

0x0A

u8

fog_mode

Fog generation mode.

0x0B

u8

fog_slope

Fog slope.

0x0C

u8

u0

Unknown.

0x0D

u8

u1

Unknown.

0x0E

u8

u2

Unknown.

0x0F

u8

u3

Unknown.

0x10

u8

u4

Unknown.

0x11

u8

u5

Unknown.

0x12

u8

u6

Unknown.

0x13

u8

u7

Unknown.

0x14

Fx32

fog_dist

Fog distance.

0x18

GXRgb

fog_color

Fog color.

0x1A

u16

fog_alpha

Fog alpha (0–15).

0x1C

GXRgb

kcl_color1

Default KCL color 1.

0x1E

GXRgb

kcl_color2

Default KCL color 2.

0x20

GXRgb

kcl_color3

Default KCL color 3.

0x22

GXRgb

kcl_color4

Default KCL color 4.

0x24

u8

v0

Unknown.

0x25

u8

v1

Unknown.

0x26

u8

v2

Unknown.

0x27

u8

v3

Unknown.

0x28

u8

v4

Unknown.

0x29

u8

v5

Unknown.

0x2A

u8

v6

Unknown.

0x2B

u8

v7

Unknown.

Gameplay Context

  • Amount of laps controls how many laps the race uses by default for the stage; some tracks use lap_count = 0 for special cases (verify per track).

  • Fog parameters influence rendering: enabling fog can hide distant objects and alter perceived depth; fog color & distance control atmosphere.

  • KCL colors are the default palette for collision visualization (useful for editors and collision debugging).

Implementation Notes

  • This class sets placeholders for color fields (GXRgb) — you can implement GXRgb decoding (usually 2 bytes per color or platform-specific) and populate these fields for richer output.

  • The unknown arrays are repeated in code (unknown2 and unknown3) — that mirrors the spec layout but may be redundant; keep one copy or rename for clarity if desired.

class mkds.nkm.KTPS(data)[source]

Bases: Section

KTPS — Kart/Start Positions (Start points for racers).

Stride: 0x1C bytes per entry.

Purpose

Defines start positions (spawn/starting grid) for players/racers. Typically used for the main race starts; can also be used in battle or mission modes.

KTPS Entry Structure

Offset

Type

Name

Description

0x00

VecFx32

pos

3D position vector (spawn).

0x0C

VecFx32

rot

3D rotation vector.

0x18

u16

padding

Padding (0xFFFF).

0x1A

u16

index

Start index (battle/mission).

Gameplay Context

  • On race start, the game picks starting positions from this section.

  • start_position_index is relevant for battle stages or mission mode where start ordering differs from main racing.

  • The rotation vector might be stored differently in beta versions — the canonical community notes indicate the Y-rotation sometimes needs to be computed via Atan2 on rotation vector components for older versions.

Notes / Community Tips

  • Typically the number of KTPS entries equals the number of players or more (some tracks list more possible starts than vehicles).

  • If you want to reposition start locations, modify positions and write the file back in FX32 format.

class mkds.nkm.KTPJ(data)[source]

Bases: Section

KTPJ — Respawn positions (kart respawn).

Stride: 0x20 bytes per entry.

Purpose

Positions to which a kart (player) can respawn after falling off or during certain scripted events. Contains references to enemy/item points (EPOI/IPOI) to determine nearby behavior or AI context.

KTPJ Entry Structure

Offset

Type

Name

Description

0x00

VecFx32

pos

3D position vector.

0x0C

VecFx32

rot

3D rotation vector.

0x18

u16

enemy_id

Enemy position ID (EPOI).

0x1A

u16

item_id

Item position ID (IPOI).

0x1C

u32

respawn_id

Respawn identifier.

Gameplay Context

  • When a kart falls off the track or hits a severe collision, the engine picks a KTPJ respawn that matches the current lap and nearby conditions.

  • The enemy/item IDs let respawn logic pick nearby AI/item spawn points for smoother reintroduction.

Version Notes

  • For version 0x1E (older beta), the final Respawn ID (0x1C) may not exist.

  • The rotation encoding changed for early beta versions; if reading older tracks, compute Y-rotation via atan2(Rx, Rz) to convert to degrees.

Remarks for Parser

  • We read respawn_id as a 32-bit value; if parsing older tracks that omit it, ensure you guard read beyond section length.

class mkds.nkm.KTP2(data)[source]

Bases: Section

KTP2 — Lap checkpoints (points to pass to count lap progress).

Stride: 0x1C bytes per entry.

Purpose

Defines the “lap gate” points that the engine checks to determine whether a player completed a lap. Usually combined with timing/ordering checks.

KTP2 Entry Structure

Offset

Type

Name

Description

0x00

VecFx32

pos

3D position vector.

0x0C

VecFx32

rot

3D rotation vector.

0x18

u16

padding

Padding (0xFFFF).

0x1A

u16

index

Index (0xFFFF typical).

Gameplay Context

  • The race logic queries these points as canonical lap markers.

  • Often unused fields are set to 0xFFFF; do not treat them as valid indices.

Notes

  • The “Index” is usually unused (set to 0xFFFF); if present, it may participate in specialized lap logic or developer tools.

class mkds.nkm.KTPC(data)[source]

Bases: Section

KTPC — Cannon / Pipe destination points.

Stride: 0x1C bytes per entry.

Purpose

Describes destinations for cannons/pipes used in certain stages (mostly in battle stages). Cannon indices are used by specialized collision types.

KTPC Entry Structure

Offset

Type

Name

Description

0x00

VecFx32

pos

3D position (destination).

0x0C

VecFx32

rot

3D rotation vector.

0x18

u16

unknown

Unknown.

0x1A

u16

cannon_idx

Cannon index (links activator/destination).

Gameplay Context

  • Cannon/pipe logic teleports an object/player to the KTPC destination.

  • The cannon_index can be used as a link between activator and destination.

Notes

  • In many tracks this section is small or absent; treat missing sections gracefully when writing tools that modify KTPC entries.

class mkds.nkm.KTPM(data)[source]

Bases: Section

KTPM — Mission points.

Stride: 0x1C bytes per entry.

Purpose

Points used by mission objectives (mission mode). They often resemble KTPS/KTP2 entries but have mission-specific indexing.

KTPM Entry Structure

Offset

Type

Name

Description

0x00

VecFx32

pos

3D position vector.

0x0C

VecFx32

rot

3D rotation vector.

0x18

u16

padding

Padding (0xFFFF).

0x1A

u16

index

Mission index.

Gameplay Context

  • Missions may use these points to define target positions or spawns.

  • index can be used in mission scripts to select a specific point out of the KTPM array.

Notes

  • If the track is not a mission type, these often default to 0xFFFF.

class mkds.nkm.CPOI(data)[source]

Bases: Section

CPOI — Checkpoints (2D oriented).

Stride: 0x24 bytes per entry.

Purpose

Defines checkpoint segments used for lap counting, key handling, and respawn logic. CPOI includes two 2D positions and precomputed trig/distance values used by the engine to determine crossing and checkpoint ordering.

CPOI Entry Structure

Offset

Type

Name

Description

0x00

VecFx32 (2D)

pos1

2D position 1.

0x08

VecFx32 (2D)

pos2

2D position 2 (other edge).

0x10

Fx32

sin

Precomputed sine.

0x14

Fx32

cos

Precomputed cosine.

0x18

Fx32

distance

Distance between pos1/pos2.

0x1C

s16

section1

Section data 1 (unknown).

0x1E

s16

section2

Section data 2 (unknown).

0x20

u16

key_id

0x0000=lap, 0xFFFF=none.

0x22

u8

respawn_id

Respawn ID.

0x23

u8

unknown

Unknown/padding.

Gameplay Context

  • CPOIs are the canonical gate the engine checks for lap progress.

  • The Key ID allows some checkpoints to behave as keys (for gates, or race logic). If Key ID == 0x0000 the point counts as the lap marker.

  • The precomputed sinus/cosinus/distance allow the engine to quickly test whether a player crossed the checkpoint along the correct orientation.

Reverse-Engineering Notes

  • Community docs note the section_data fields are partially decoded for special track logic. If you need precise behavior, compare original tracks and observe in-engine behavior.

class mkds.nkm.CPAT(data)[source]

Bases: Section

CPAT — CPOI grouping (checkpoint groups).

Stride: 0x0C bytes per entry.

Purpose

Groups CPOI entries into logical sequences (routes/sections). Each CPAT entry points to a contiguous block of CPOI points and describes adjacency (previous/next groups) and section order.

CPAT Entry Structure

Offset

Type

Name

Description

0x00

u16

point_start

Start index into CPOI array.

0x02

u16

point_len

Number of points.

0x04

u8

next0

Next group index 0.

0x05

u8

next1

Next group index 1.

0x06

u8

next2

Next group index 2.

0x07

u8

prev0

Previous group index 0.

0x08

u8

prev1

Previous group index 1.

0x09

u8

prev2

Previous group index 2.

0x0A

s16

section_order

Section ordering index.

Gameplay Context

  • CPAT allows complex checkpoint graphs (non-linear courses) by connecting multiple CPOI groups.

  • Useful when a single lap uses multiple discontiguous checkpoint regions.

Implementation Notes

  • The next_group and prev_group arrays use 0xFF as “unused”; treat sentinel values accordingly.

class mkds.nkm.IPOI(data)[source]

Bases: Section

IPOI — Item spawn points.

Stride: 0x14 bytes per entry.

Purpose

Describes where items (like red shells, bananas) may spawn or where items follow a path along a route. IPOI entries are often referenced by KTPJ (respawn) or object logic.

IPOI Entry Structure

Offset

Type

Name

Description

0x00

VecFx32

pos

3D position vector.

0x0C

Fx32

scale

Point scale (size/weight).

0x10

u32

unknown

Reserved field.

Gameplay Context

  • Items may spawn at IPOI locations or be used for scripted item routes.

  • point_scale may modify spawn probability or area radius.

Notes

  • The unknown 32-bit value is often zero; it may contain bitflags in certain custom tracks.

class mkds.nkm.IPAT(data)[source]

Bases: Section

IPAT — IPOI grouping.

Stride: 0x0C bytes per entry.

Purpose

Group IPOI entries into contiguous point ranges and define adjacency, much like CPAT but for item points.

IPAT Entry Structure

Offset

Type

Name

Description

0x00

u16

point_start

Start index into IPOI array.

0x02

u16

point_len

Number of points.

0x04

u8

next0

Next group index 0.

0x05

u8

next1

Next group index 1.

0x06

u8

next2

Next group index 2.

0x07

u8

prev0

Previous group index 0.

0x08

u8

prev1

Previous group index 1.

0x09

u8

prev2

Previous group index 2.

0x0A

s16

section_order

Section ordering index.

Gameplay Context

  • Used by item routing and by respawn selection to find nearby item points.

class mkds.nkm.EPOI(data)[source]

Bases: Section

EPOI — Enemy/CPU path points.

Stride: 0x18 bytes per entry.

Purpose

Defines points that the CPU opponents use for their routing (AI paths). These influence how CPUs drive the course (lines, drifting behavior, etc).

EPOI Entry Structure

Offset

Type

Name

Description

0x00

VecFx32

pos

3D position vector.

0x0C

Fx32

scale

Point scale (radius/weight).

0x10

s16

drift

Drifting parameter.

0x12

u16

unknown1

Unknown flag.

0x14

u32

unknown2

Engine metadata.

Gameplay Context

  • CPU behavior heavily depends on EPOI positions and the drifting parameter — altering these can change how tight/loose CPUs corner.

  • EPOI groups are linked via EPAT entries (below).

Notes

  • The meaning of the 0x14 32-bit word is partially unknown in community docs; experiments suggest it can contain flags for AI behavior.

class mkds.nkm.EPAT(data)[source]

Bases: Section

EPAT — EPOI grouping.

Stride: 0x0C bytes per entry.

Purpose

Groups EPOI points into contiguous blocks and defines adjacency (next/prev groups) and section ordering. Used by CPU pathing code to navigate routes.

EPAT Entry Structure

Offset

Type

Name

Description

0x00

u16

point_start

Start index into EPOI array.

0x02

u16

point_len

Number of points.

0x04

u8

next0

Next group index 0.

0x05

u8

next1

Next group index 1.

0x06

u8

next2

Next group index 2.

0x07

u8

prev0

Previous group index 0.

0x08

u8

prev1

Previous group index 1.

0x09

u8

prev2

Previous group index 2.

0x0A

s16

section_order

Section ordering index.

Gameplay Context

  • EPAT partitions EPOI arrays into logical AI routes; enabling multiple CPU strategies per segment.

class mkds.nkm.MEPO(data)[source]

Bases: Section

MEPO — Mini-game enemy points.

Stride: 0x18 bytes per entry.

Purpose

Similar to EPOI but used by specific mini-games; describes where minigame entities spawn/move.

MEPO Entry Structure

Offset

Type

Name

Description

0x00

VecFx32

pos

3D position vector.

0x0C

Fx32

scale

Point scale.

0x10

s32

drifting

Drifting parameter (32-bit).

0x14

u32

unknown

Unknown/reserved.

Gameplay Context

  • MEPO entries are used only in special mini-game contexts and may allow more variety (hence Int32 for drifting).

class mkds.nkm.MEPA(data)[source]

Bases: Section

MEPA — MEPO grouping (for mini-games).

Stride: 0x14 bytes per entry.

Purpose

Groups MEPO points into sequences. MEPA entries support up to 8 next and 8 previous groups (Byte[8]) because mini-games may have richer topology.

Gameplay Context

  • Use MEPA to create complex mini-game movement graphs (multiple branching).

class mkds.nkm.AREA(data)[source]

Bases: Section

AREA — Camera/zone areas.

Stride: 0x48 bytes per entry.

Purpose

Defines 3D regions used by the engine for camera selection and environmental triggers (sounds like waterfalls). Each area contains a center position, axes/length vectors (defining an oriented bounding box), and metadata such as area type and camera ID.

AREA Entry Structure

Offset

Type

Name

Description

0x00

VecFx32

pos

Center position vector.

0x0C

VecFx32

length_vec

Length vector.

0x18

VecFx32

x_vec

X-axis vector.

0x24

VecFx32

y_vec

Y-axis vector.

0x30

VecFx32

z_vec

Z-axis vector.

0x3C

s16

u0

Unknown.

0x3E

s16

u1

Unknown.

0x40

s16

u2

Unknown.

0x42

u8

u3

Unknown.

0x43

u8

camera_id

Camera index (CAME ref).

0x44

u8

area_type

Area type (0x01=camera, etc.).

0x45

s16

u4

Unknown.

0x47

u8

u5

Unknown.

Gameplay Context

  • AREA sections usually determine which camera the engine should switch to when the player is inside the region.

  • Camera ID links to CAME entries; Area type allows special behavior (e.g., waterfall sound triggers).

  • Good for editors to preview camera transitions.

Notes

  • Several fields are still undocumented; their meaning varies by track.

class mkds.nkm.CAME(data)[source]

Bases: Section

CAME — Camera definitions.

Stride: 0x4C bytes per entry.

Purpose

Defines camera motions and static camera positions used in cutscenes, intros, and dynamic in-game camera triggers. Camera entries are often linked by AREA zones or object routes.

CAME Entry Structure

Offset

Type

Name

Description

0x00

VecFx32

pos1

Primary position vector.

0x0C

VecFx32

rot

Rotation vector.

0x18

VecFx32

pos2

Secondary position vector.

0x24

VecFx32

pos3

Tertiary position vector.

0x30

s16

fov_begin

Field-of-view start.

0x32

Fx16

fov_beg_sin

Precomputed sine for FOV start.

0x34

Fx16

fov_beg_cos

Precomputed cosine for FOV start.

0x36

s16

fov_end

Field-of-view end.

0x38

Fx16

fov_end_sin

Precomputed sine for FOV end.

0x3A

Fx16

fov_end_cos

Precomputed cosine for FOV end.

0x3C

u16

zoom

Camera zoom factor.

0x3E

u16

type

Camera type.

0x40

u16

linked_route

Linked PATH route index (0xFFFF = none).

0x42

u16

route_speed

Speed along linked route.

0x44

u16

point_speed

Speed between points.

0x46

u16

duration

Duration (1/60s units).

0x48

u16

next_cam

Next camera index (0xFFFF = none).

0x4A

u8

intro_pan

Intro pan indicator (0=none,1=top,2=bot).

0x4B

u8

unknown

Unknown (1 if type==5).

Camera Type (common)

Bit Offset

Description

0x00

After race camera

0x01

Unknown (with route)

0x02

Unknown

0x03

Intro camera (top screen)

0x04

Intro camera (bottom screen)

0x05

Unknown

0x06

Unknown

0x07

Battle mode camera

0x08

Mission finish camera

Gameplay Context

  • CAME entries drive cinematic camera movement during intros, cutscenes, and special camera modes.

  • Linked route + point speed define how the camera follows a PATH.

  • Camera duration uses 1/60th-second units — helpful for exact timing.

Notes & Community Tips

  • Many of these fields are precomputed (sine/cosine) for faster in-engine interpolation. Editors can either preserve or recompute them.

  • The “next camera” field allows building camera chains for sequences.

  • When building camera editors, expose both positions and FOV values to enable previewing transitions correctly.

class mkds.nkm.NKM(data)[source]

Bases: object

NKM — Mario Kart DS Course Map parser.

Purpose

Top-level container that parses the NKM file header and initializes objects representing each section (OBJI, PATH, POIT, STAG, KTPS, … , CAME).

Usage Example

>>> nkm = NKM.from_file("my_course.nkm")
>>> print(len(nkm._OBJI))         # number of object instances
>>> print(nkm._STAG.amt_of_laps)  # global lap count for the stage

Implementation Details

  • The typical header length is 0x4C and contains offsets (UInt32) to 17 canonical sections in standard order. Offsets are relative to the end of the header (H), so they are added to _header_offset to compute absolute positions inside the file.

  • This parser assumes the “typical” header layout. If an NKM contains additional special sections (like NKMI) or a different header length, additional handling will be required.

  • Parsing is defensive but assumes the file is well-formed; for robust tools consider adding bounds checks when slicing self._data[…].

Known Limitations

  • Some fields (GXRgb, camera_type, some unknown bytes) are left as None or unknown placeholders. Implementing GXRgb and Fx16/Fx32 conversions will enable richer output.

  • The code currently uses PATH.has_loop = read_u8(…) != 1 which inverts the canonical meaning (spec: 1 means loop). Consider normalizing this if you rely on literal interpretation elsewhere.

See also

The, and

classmethod from_file(path: str, **kwargs)[source]

Load an NKM file from disk and parse its sections.

Parameters:

path (str) – Path to the .nkm file. Defaults to DEFAULT_NKM_PATH.

Returns:

The parsed NKM object.

Return type:

NKM