Katana SDK: Difference between revisions
mNo edit summary |
mNo edit summary |
||
| Line 461: | Line 461: | ||
{ 1.801057f, 18.50802f, -3.119523f }, | { 1.801057f, 18.50802f, -3.119523f }, | ||
{ -1.801059f, 18.50802f, -3.119523f }, | { -1.801059f, 18.50802f, -3.119523f }, | ||
// And so on... | // And so on... | ||
};</syntaxhighlight> | };</syntaxhighlight> | ||
| Line 628: | Line 628: | ||
| | | | ||
|} | |} | ||
The following evaluation flags can be used: | |||
{| class="wikitable" | |||
!Name | |||
!Flag bits | |||
!Description | |||
|- | |||
|NJD_EVAL_UNIT_POS | |||
|BIT_0 | |||
|Ignore the model's position. | |||
|- | |||
|NJD_EVAL_UNIT_ANG | |||
|BIT_1 | |||
|Ignore the model's rotation. | |||
|- | |||
|NJD_EVAL_UNIT_SCL | |||
|BIT_2 | |||
|Ignore the model's scale. | |||
|- | |||
|NJD_EVAL_HIDE | |||
|BIT_3 | |||
|Do not render the model. | |||
|- | |||
|NJD_EVAL_BREAK | |||
|BIT_4 | |||
|Node is the end of the hierarchy (do not check children). | |||
|- | |||
|NJD_EVAL_ZXY_ANG | |||
|BIT_5 | |||
|Inverted order of rotation. | |||
|- | |||
|NJD_EVAL_SKIP | |||
|BIT_6 | |||
|Do not animate (ignore) this node. | |||
|- | |||
|NJD_EVAL_SHAPE_SKIP | |||
|BIT_7 | |||
|Do not animate (ignore) this node in shape animations. | |||
|- | |||
|NJD_EVAL_CLIP | |||
|BIT_8 | |||
|If this node is clipped, do not clip child nodes. | |||
|- | |||
|NJD_EVAL_MODIFIER | |||
|BIT_9 | |||
|The node has a modifier volume. | |||
|} | |||
=== Ninja Chunk Model === | |||
=== Ninja Motions and Actions === | |||
== Ports of Ninja to Other Platforms == | |||
Revision as of 11:16, 7 October 2025
Dreamcast SDK
Katana SDK (Dreamcast SDK for SEGA Library) was the official SEGA development kit for the Dreamcast console that came with Dreamcast development units. The Dreamcast SDK had a number of libraries and APIs that many developers used in their games. The SDK evolved together with the console, and earlier versions of the SDK had fewer features or targeted different hardware. Updates to the SDK continued after the Dreamcast's release, and some releases were as late as 2001.
The Dreamcast SDK consisted of several subsystems:
The Shinobi library set interfaced with the CPU, cache and memory.
The Kamui API (low level) and the Ninja library (high level) provided access to graphics.
The Manatee and Audio64 subsystems interfaced with sound hardware.
Over the years there have been multiple SDK leaks, including parts of source code for older revisions. For modding purposes, we should focus on the Ninja library, which is used by the Sonic Adventure games.
Common Types
The following types are used in Shinobi and Ninja headers:
| Ninja type | C type | Size | Description |
|---|---|---|---|
| Sint8 | char | 1 | Signed 8-bit integer |
| Uint8 | unsigned char | 1 | Unsigned 8-bit integer |
| Sint16 | __int16 | 2 | Signed 16-bit integer |
| Uint16 | unsigned __int16 | 2 | Unsigned 16-bit integer |
| Sint32 | int | 4 | Signed 32-bit integer |
| Uint32 | unsigned int | 4 | Unsigned 32-bit integer |
| Bool | unsigned int | 4 | Unsigned 32-bit integer that is either TRUE (1) or FALSE (0) |
| Float and Float32 | float | 4 | 32-bit floating point |
| Float64 | double | 8 | 64-bit floating point |
| Void | void | Pointer |
Ninja Model Formats
The Ninja library can use two model formats, the Basic model and the Chunk model. Basic models were introduced early on, while Chunk models were added later as a format that is optimized for better performance on Dreamcast hardware. The Basic format is easier to read as text.
Ninja Basic Model
The Basic model consists of the following structs:
Material struct (NJS_MATERIAL) and Material Array
The material affects how the model's surface looks. It defines which texture to use, whether to use environment mapping etc.
| Field | Offset | Type | Size | Description | Notes |
|---|---|---|---|---|---|
| diffuse | 0 | NJS_COLOR | 4 | Diffuse color. | In SA1 with palette lighting, only alpha is used. |
| specular | 0x4 | NJS_COLOR | 4 | Specular color. | In SA1 with palette lighting, only alpha is used. The alpha value of 0 is treated as the "ignore specular" flag. |
| exponent | 0x8 | Float | 4 | Specular color strength. | |
| attr_texId | 0xC | Uint32 | 4 | Texture ID. | |
| attrflags | 0x10 | Uint32 | 4 | Material flags. | Bits 31-29 and 28-26 are used for source and destination alpha blending instructions respectively. |
Size: 20 bytes (0x14).
NJS_COLOR is a union that can be either NJS_BGRA, NJS_TEX or Uint32 (4 bytes).
NJS_BGRAis a 4-byte struct that consists of blue, green, red and alpha values ranging from 0 to 255. For example, the color A255 R178 G178 B178 would be 0xFFB2B2B2.
NJS_TEX (4 bytes) is a struct commonly used in UVs. It consists of two Sint16 values: one for U (horizontal) and one for V (vertical). UVs used in SA1 range from 0 to 255.
The following flags can be used in attrflags:
| Flag name | Flag bit | Description | Comments |
|---|---|---|---|
| NJD_FLAG_IGNORE_LIGHT | BIT_25 | Ignore lighting. | |
| NJD_FLAG_USE_FLAT | BIT_24 | Flat lighting. | Has no effect when palette-based lighting in SA1 is used. |
| NJD_FLAG_DOUBLE_SIDE | BIT_23 | Double-sided mesh. | May be used for collision. |
| NJD_FLAG_USE_ENV | BIT_22 | Enable environment mapping. | |
| NJD_FLAG_USE_TEXTURE | BIT_21 | Enable texture. | |
| NJD_FLAG_USE_ALPHA | BIT_20 | Enable transparency. | |
| NJD_FLAG_IGNORE_SPECULAR | BIT_19 | Disable specular lighting. | Used for specular palette selection in palette-based lighting in SA1. |
| NJD_FLAG_FLIP_U | BIT_18 | Flip Us. | |
| NJD_FLAG_FLIP_V | BIT_17 | Flip Vs. | |
| NJD_FLAG_CLAMP_U | BIT_16 | Clamp Us. | |
| NJD_FLAG_CLAMP_V | BIT_15 | Clamp Vs. | |
| NJD_FLAG_USE_ANISOTROPIC | BIT_12 | Enable anisotropic filtering, | Unused. |
| NJD_FLAG_PICK | BIT_7 | "Pick status" | Unused. |
Alpha modes can be as follows:
Source alpha
|
Destination alpha
|
|---|
Basic models' materials are stored in arrays of NJS_MATERIAL.
NJS_MATERIAL matlist_004451A8[] = {
{ { 0xFFFFFFFF }, { 0xFFFFFFFF }, 11, 14, NJD_D_100 | NJD_FILTER_BILINEAR | NJD_FLAG_CLAMP_V | NJD_FLAG_CLAMP_U | NJD_FLAG_IGNORE_SPECULAR | NJD_FLAG_USE_TEXTURE | NJD_DA_INV_SRC | NJD_SA_SRC },
{ { 0xFFB2B2B2 }, { 0xFFFFFFFF }, 11, 13, NJD_D_100 | NJD_FILTER_BILINEAR | NJD_FLAG_CLAMP_V | NJD_FLAG_CLAMP_U | NJD_FLAG_IGNORE_SPECULAR | NJD_FLAG_USE_ALPHA | NJD_FLAG_USE_TEXTURE | NJD_DA_INV_SRC | NJD_SA_SRC },
{ { 0xFFB2B2B2 }, { 0xFFFFFFFF }, 11, 15, NJD_D_100 | NJD_FILTER_BILINEAR | NJD_FLAG_CLAMP_V | NJD_FLAG_CLAMP_U | NJD_FLAG_IGNORE_SPECULAR | NJD_FLAG_USE_TEXTURE | NJD_DA_INV_SRC | NJD_SA_SRC }
};
Poly Array
The poly array in an array of Sint16 that lists the model's primitives (polygons). It is commonly formatted with the number of vertices (points) followed by vertex indices. The indices are used to pick the specific vertices from the model's vertices array.
Here is an example of a polys array. The 4 in each new line indicates the number of vertices in the surface, and the following four values are vertex indices.
Sint16 poly_0000002C[] = {
4, 13, 12, 5, 4,
4, 9, 8, 1, 0,
4, 11, 10, 3, 2,
4, 15, 14, 7, 6
};
The number of vertices can be ORd with 0x8000, which indicates a flipped surface. TODO: Confirm this.
UV Array
The UV array is an array of NJS_TEX. UVs determine how the texture is applied to the model's surface. For exampled, bigger UV values will make the texture "zoomed in", adding values to U will make the texture offset horizontally etc. UVs are per-polygon.
NJS_TEX uv_000003A4[] = {
{ 130, 145 },
{ 212, 225 },
{ 124, 230 },
// And so on...
};
Vertex Color Array
This is an array of NJS_COLOR that determines the colors of the model's vertices. Vertex colors are used per-polygon, not per-vertex.
NJS_COLOR vcolor_0000003C[] = {
{ 0xFFFFFFDF },
{ 0xFFFFFFFF },
{ 0xFFFFDFBF },
{ 0xFFFFFFFF },
{ 0xFFFFDFBF },
// And so on...
};
Polynormal Array
Normals determine the model's lighting and environment mapping distortion. Normals can be specified per-vertex or por-polygon. Almost no models in SA1 use per-poly normals (polynormals), with the exception of Tails' tails and Sonic's stretchy shoes. When polynormals are used, this is the array they are expected to be in.
Normals and polynormals are defined as arrays of NJS_VECTOR. NJS_VECTOR consists of three floats for X, Y and Z.
NJS_VECTOR polynormal_007383D8[] = {
{ 0 },
{ 0 },
{ 0 },
{ 0 },
{ 0 },
{ 0 }
};
Polygon Attribute Array
This is an array of Uint32 containing polygon-specific attributes. It is not used in Sonic Adventure games.
Meshset Struct (NJS_MESHSET) and Meshset Array
Multiple connected polygons form meshes. The NJS_MESHSET struct defines a single mesh.
| Field | Offset | Type | Size | Description | Notes |
|---|---|---|---|---|---|
| type_matId | 0 | Uint16 | 2 | Diffuse color. | Bits 0-13 are material id (0-4095) in the material array.
Bits 14-15 are meshset type bits (see below). |
| nbMesh | 0x2 | Uint16 | 2 | Number of meshes. | |
| *meshes | 0x4 | Sint16* | 4 | Pointer to the poly array. | |
| *attrs | 0x8 | Uint32* | 4 | Pointer to the poly attribute array. | Unused in SA games. |
| *normals | 0xC | NJS_VECTOR* | 4 | Pointer to the polynormal array. | Almost never used. |
| *vertcolor | 0x10 | NJS_COLOR* | 4 | Pointer to the vertex color array. | Unused in SA1 DC, used in SADX. |
| *vertuv | 0x14 | NJS_TEX* | 4 | Pointer to the UV array. | |
| buffer | 0x18 | void | 4 | Pointer to the Direct3D mesh buffer. | Always null.
SADX PC 2004, SADX X360 and SADX PS3 only. |
In the 2004 PC port of SADX this struct contains an extra field for the mesh buffer (buffer). This version of the struct is used in the PC, X360 and PS3 versions.
SA2 and Gamecube versions of SADX use the original struct without the extra field.
In SADX Mod Loader headers the original Ninja version is NJS_MESHSET, and the one with the extra field is NJS_MESHSET_SADX.
In the SADX X360 prototype with symbols, the one with the extra field is NJS_MESHSET, and the original Ninja version is NJS_MESHSET_OLD.
The size of the original NJS_MESHSET is 24 (0x18) bytes, and the size of NJS_MESHSET_SADX is 28 (0x1C) bytes.
Meshset type bits are as follows:
| Meshset type | Value | Description |
|---|---|---|
| NJD_MESHSET_3 | 0x0000 | Default mesh type (three vertices). Technically identical to NJD_MESHSET_TRIMESH.
|
| NJD_MESHSET_4 | 0x4000 | Quad (four vertices). |
| NJD_MESHSET_N | 0x8000 | N-Gon (custom number of vertices). |
| NJD_MESHSET_TRIMESH | 0xC000 | Trimesh, the most common meshset type. |
| NJS_MESHSET_MASK | 0xC000 | Meshset type mask. |
To get the material ID from the type_matId field in your code, use type_matId & ~NJD_MESHSET_MASK. To get the mesh type, use type_matId >> 0xE.
Meshes in Basic models are stored in arrays of NJS_MESHSET:
NJS_MESHSET_SADX meshlist_00000294[] = {
{ NJD_MESHSET_TRIMESH | 0, 9, poly_00000044, NULL, NULL, NULL, uv_00000128, NULL },
{ NJD_MESHSET_TRIMESH | 1, 10, poly_000000A4, NULL, NULL, NULL, uv_000001C4, NULL },
{ NJD_MESHSET_TRIMESH | 2, 3, poly_00000108, NULL, NULL, NULL, uv_00000264, NULL }
};
Vertex Array
The model's vertices are in an array of NJS_POINT3 (NJS_VECTOR in Mod Loader headers).
NJS_VECTOR vertex_00000ADC[] = {
{ 0, 26.04398f, 0 },
{ 3.602116f, 18.50802f, 0 },
{ 1.801057f, 18.50802f, -3.119523f },
{ -1.801059f, 18.50802f, -3.119523f },
// And so on...
};
Normal Array
The model's normals are in an array of NJS_VECTOR.
NJS_VECTOR normal_00000D28[] = {
{ 0, 1, 0 },
{ 0.902229f, 0.431257f, 0 },
{ 0.451115f, 0.431256f, -0.781354f },
{ -0.451115f, 0.431256f, -0.781354f },
// And so on...
}
Model Struct (NJS_MODEL)
The Model struct combines all the things mentioned above and adds model center coordinates and radius.
| Field | Offset | Type | Size | Description | Notes |
|---|---|---|---|---|---|
| *points | 0 | NJS_POINT3* | 4 | Pointer to the vertex array. | |
| *normals | 0x4 | NJS_VECTOR* | 4 | Pointer to the normal array. | |
| nbPoint | 0x8 | Sint32 | 4 | Number of vertices. | |
| *meshsets | 0xC | NJS_MESHSET* | 4 | Pointer to the meshset array. | |
| *mats | 0x10 | NJS_MATERIAL* | 4 | Pointer to the material array. | |
| nbMeshset | 0x14 | Uint16 | 2 | Number of meshsets. | |
| nbMat | 0x16 | Uint16 | 2 | Number of materials. | |
| center | 0x18 | NJS_POINT3 | 12 | Model center. | |
| r | 0x24 | Float | 4 | Model radius. | |
| *buffer | 0x28 | void | 4 | Pointer to the Direct3D mesh buffer. | Always null.
SADX PC 2004, SADX X360 and SADX PS3 only. |
In the 2004 PC port of SADX this struct contains an extra field for the mesh buffer (buffer). This version of the struct is used in the PC, X360 and PS3 versions.
SA2 and Gamecube versions of SADX use the original struct without the extra field.
In SADX Mod Loader headers the original Ninja version is NJS_MODEL, and the one with the extra field is NJS_MODEL_SADX.
In the SADX X360 prototype with symbols, the one with the extra field is NJS_MODEL, and the original Ninja version is NJS_MODEL_OLD.
The size of the original NJS_MODEL is 40 (0x28) bytes, and the size of NJS_MODEL_SADX is 44 (0x2C) bytes.
In old modding terminology, the Model struct was referred to as the "attach" struct. You can still see this label in SA Tools' C exports.
Object Struct (NJS_OBJECT)
Ninja models use a node-like hierarchy, and the Object struct represents a single node. The size of NJS_OBJECT is 52 (0x34) bytes.
| Field | Offset | Type | Size | Description | Notes |
|---|---|---|---|---|---|
| evalflags | 0 | Uint32 | 4 | Model evaluation flags (see below). | |
| *model | 0x4 | NJS_MODEL* | 4 | Pointer to the NJS_MODEL.
|
|
| pos | 0x8 | Float[3] | 12 | Model position (X, Y, Z). | |
| ang | 0x14 | Angle[3] | 12 | Model rotation (X, Y, Z). | Angle is the same as Sint32. |
| scl | 0x20 | Float[3] | 12 | Model scale (X, Y, Z). | |
| *child | 0x2C | NJS_OBJECT* | 4 | Pointer to the child model in the hierarchy. | |
| *sibling | 0x30 | NJS_OBJECT* | 4 | Pointer to the sibling model in the hierarchy. |
The following evaluation flags can be used:
| Name | Flag bits | Description |
|---|---|---|
| NJD_EVAL_UNIT_POS | BIT_0 | Ignore the model's position. |
| NJD_EVAL_UNIT_ANG | BIT_1 | Ignore the model's rotation. |
| NJD_EVAL_UNIT_SCL | BIT_2 | Ignore the model's scale. |
| NJD_EVAL_HIDE | BIT_3 | Do not render the model. |
| NJD_EVAL_BREAK | BIT_4 | Node is the end of the hierarchy (do not check children). |
| NJD_EVAL_ZXY_ANG | BIT_5 | Inverted order of rotation. |
| NJD_EVAL_SKIP | BIT_6 | Do not animate (ignore) this node. |
| NJD_EVAL_SHAPE_SKIP | BIT_7 | Do not animate (ignore) this node in shape animations. |
| NJD_EVAL_CLIP | BIT_8 | If this node is clipped, do not clip child nodes. |
| NJD_EVAL_MODIFIER | BIT_9 | The node has a modifier volume. |