Target Titles: Ys: The Oath in Felghana, Ys VI: The Ark of Napishtim, Ys Origin
The game stores its assets in paired archive files:
data.na: Data payload container.data.ni: Encrypted index file containing file records and string table.
| Offset | Type | Field | Description |
|---|---|---|---|
0x00 |
u32 |
signature |
Magic: 0x00494E4E ("NNI\0") |
0x04 |
u32 |
entry_count |
Total number of file entries |
0x08 |
u32 |
string_table_size |
Size in bytes of decrypted filename pool |
0x0C |
u32 |
zero |
Reserved (0) |
Both the file entry table and string table are encrypted using a linear congruential cipher (LCG):
def decrypt_ni(data: bytearray) -> bytearray:
num = 0x7C53F961
for i in range(len(data)):
num = (num * 0x3D09) & 0xFFFFFFFF
data[i] = (data[i] - ((num >> 16) & 0xFF)) & 0xFF| Offset | Type | Field | Description |
|---|---|---|---|
0x00 |
u32 |
file_id |
Unique resource ID |
0x04 |
u32 |
compressed_size |
Size of payload in data.na |
0x08 |
u32 |
data_offset |
Byte offset in data.na |
0x0C |
u32 |
name_offset |
Byte offset into decrypted string table |
Files ending in .z in data.na start with an 8-byte header followed by standard raw zlib DEFLATE streams:
0x00:u32CRC32 of uncompressed data0x04:u32uncompressed size0x08..: zlib compressed stream
| Offset | Type | Field | Description |
|---|---|---|---|
0x00 |
4 bytes |
magic |
"YMO\0" |
0x04 |
u32 |
version |
Version (9) |
0x08 |
u32 |
flags_0 |
Engine flags |
0x0C |
u32 |
flags_1 |
Engine flags |
0x10 |
u32 |
flags_2 |
Engine flags |
0x14 |
u32 |
material_count |
Number of material records |
0x18 |
u32 |
motion_count |
Number of animation motion tracks |
0x1C |
u32 |
mesh_count |
Number of 3D meshes |
0x20 |
u32 |
node_count |
Number of transform/bone nodes |
0x24..0x44 |
floats |
bounds |
Bounding sphere / box coordinates |
0x78..0x168 |
3x80B |
collision_refs |
Associated .yco collision filenames (__s.yco, __w.yco, __c.yco) |
Materials start at 0x0178 (or 0x0170 + motion_count * 68 when motions > 0):
+0x00:u32flags(render blend modes, double-sided, additive)+0x04:f32alpha(opacity: 1.0 = opaque, 0.2 = glass, 0.0 = trigger)+0x8C:stringnull-terminated texture path (e.g...\common\01wall12.dds)
Nodes start immediately after the material table (mat_start + mat_count * 388, shifted -8 bytes if motions > 0):
+0x00:16 bytesNode name (e.g.f_0000)+0x10:16 bytesParent node name (or""for root)+0x20:16x f324x4 Transformation matrix
Each mesh begins at pos = node_start + node_count * 240 + 80:
+0x00:16 bytesMesh name (e.g.m_0000)+0x10: Submesh Table (32 bytes per submesh):f0:u32triangle_countf1:u32vertex_startf2:u32vertex_countf3..f5: Reserved (0)f6:u32material_indexf7:u32cumulative_verts
- Vertex Stream Descriptor:
strip_count:u32stride:u32(36 or 40 bytes)- 16 bytes alignment padding
- Vertex Buffer (
total_verts * stridebytes):stride = 36:Pos(3f), Norm(3f), Color(u32 ARGB), UV(2f)stride = 40:Pos(3f), Norm(2f/3f), Color0(u32 ARGB), Color1(u32 ARGB), UV(2f), UV2(1f/2f)
- Index Buffer Header:
pad:u32(0)total_indices:u32(count of uint16 indices)buf_type:u32(101)prim_type:u32(2 = Triangles)- 16 bytes alignment padding
- Index Buffer Data:
total_indices * 2bytes (uint16triangle list).
Falcom used two distinct collision architectures across the Napishtim Engine family:
- Dedicated Collision Format (
.YCO) — Ys: The Oath in Felghana and Ys VI: The Ark of Napishtim. - Low-Poly Companion Model Format (
Stage_.YMO) — Ys Origin.
Collision geometry in Felghana and Ys VI is authored as separate binary files alongside stage and prop models:
__s.yco: Standable / Walkable ground geometry (semi-transparent emerald green in viewer).__w.yco: Wall / Obstacle barrier geometry (semi-transparent coral orange in viewer).__c.yco: Camera bounding volume / occlusion frustum (semi-transparent cyan blue in viewer).
| Offset | Type | Field | Description |
|---|---|---|---|
0x00 |
4 bytes |
magic |
"YCO\0" (0x004F4359) |
0x04 |
u32 |
version |
Version (1) |
0x08 |
u32 |
polygon_count |
Exact count of 96-byte collision triangle records |
0x0C |
u32 |
spatial_cell_count |
Number of spatial partition index entries |
0x10 |
u32 |
spatial_grid_dim |
Spatial partition grid dimension (e.g. 10) |
0x14 |
f32 |
cell_size |
Grid cell world scale factor (e.g. 1.0f) |
0x18 |
u32 |
spatial_depth_flags |
Spatial hierarchy depth & engine flags (e.g. 8) |
| Offset | Type | Field | Description |
|---|---|---|---|
+0x00 |
3x f32 |
v0 |
Vertex 0 position (x, y, z)
|
+0x0C |
3x f32 |
v1 |
Vertex 1 position (x, y, z)
|
+0x18 |
3x f32 |
v2 |
Vertex 2 position (x, y, z)
|
+0x24 |
3x f32 |
normal |
Triangle plane unit normal (nx, ny, nz)
|
+0x30 |
f32 |
plane_d |
Plane equation constant D where |
+0x34 |
4x f32 |
bounding_box_min |
Triangle AABB (min_x, min_y, min_z, max_x)
|
+0x44 |
2x f32 |
bounding_box_max |
Triangle AABB (max_y, max_z)
|
+0x48 |
u32 |
surface_flags |
Material type (wood, stone, water, ice, metal, slippery, fall-through) |
+0x4C |
u32 |
collision_attributes |
Trigger ID, damage zone flag, sound FX ID |
Immediately following the polygon array (0x1C + polygon_count * 96):
-
6x f32: Overall collision volume AABB(min_x, min_y, min_z, max_x, max_y, max_z). - Array of
u32spatial grid indices for$O(1)$ capsule sweep and raycast broadphase queries.
In Ys Origin, Falcom deprecated the proprietary .YCO compiler and standardized collision authoring on standard low-poly companion .YMO models:
- Every stage has a visual mesh
S_XXXX.YMO(high-poly, textured) and a collision meshS_XXXX_.YMO(low-poly proxy, untextured). - Map objects follow the same convention:
MAPOBJ/DOOR_07/DOOR_07.YMOhasDOOR_07_.YMO. -
Materials: Empty texture string (
tex=''),flags=0x00000000,alpha=1.0. -
Submeshes & Normal Partitioning:
-
Wall Submeshes: Face normals are horizontal (
$|N_y| \approx 0.0$ ), defining solid boundaries and obstacles. -
Walkable Submeshes: Face normals point upward (
$|N_y| > 0.45$ ), defining standable floors, stairs, and ramps.
-
Wall Submeshes: Face normals are horizontal (
-
Viewer Integration: The viewer deduplicates
S_XXXX_.YMOfrom the map browser, links it asst.coll_mesh_path, and renders it as a toggleable collision layer in the viewport.
Stages use .SOB files to place the base map geometry along with props, doors, torches, and interactive objects into a composite world scene.
0x00:4 bytesMagic"SOB\0"0x04:u32Version0x08:u32Entry size (680bytes)0x0C:u32Object count
+0x00:stringRelative model path (e.g.data\map\mapobj\s01dor30\s01dor30.ymo)+0x104:3x f32Translation position(px, py, pz)+0x110:3x f32Euler rotation in radians(rx, ry, rz)+0x11C:3x f32Scaling factor(sx, sy, sz)