code wiki / (root) / nx_xps_lib.nx

nx_xps_lib.nx

buildroot/runtime/nx_xps_lib.nx

22607 B510 linesdepth 2pulls 2 transitivereach 2 importersview sourcekind library
docsdependenciesstructsconstsfunctions

about

nx_xps_lib.nx -- XPS / XNALara MODEL READER, both dialects (/compare/modding MD2, 2026-09-06). The reference readers were mirrored and READ before a line of this was written (knowledge/fetched/cmp_modding_xnalara_read_ascii_xps.py pin ac92fd7f, read_bin_xps.py pin 0e1dca05, bin_ops.py, xps_const.py). What they say, and this lib follows: ascii (.mesh.ascii): bone count; per bone a name line, a parent line, an xyz line; mesh count; per mesh a name line, a uv-layer count, a texture count with a name line and a uv-layer line per texture, a vertex count with position, normal, RGBA colour (four integers), one uv line per layer and -- when the model has bones -- a four-index line and a four-weight line (short lines are zero-filled), then a triangle count and three indices per face. Numeric lines may carry a trailing comment after a hash. binary (.xps): u32 magic 323232, u16 major, u16 minor, a length-prefixed string (one byte; a second byte when the first is at least 128, length = b1 % 128 + b2 * 128), u32 settings length in 32-bit words, three more strings (machine, user, files), then the settings block of exactly that many words (old format raw, new format typed items -- skipped whole, it carries render flags, never geometry); bones: u32 count, string, i16 parent, three float32; meshes: u32 count, string, u32 uv layers, u32 textures (string + u32 layer each), u32 vertices (three float32 position, three float32 normal, four colour bytes, per layer two float32 uv plus four float32 tangent when TANGENT versions apply), bone weights as i16 count on VARIABLE-WEIGHT versions else four, i16 indices then float32 weights; u32 triangles of three u32. TANGENT versions: minor <= 12 and major <= 2. VARIABLE weights: major >= 3. (bin_ops.py, read verbatim.) OUTPUT is the estate's own arrays for nx_nxa_write_lib: VERT in 0.01 mm model units at a DECLARED scale (units_per_xps, data never a guess), every mesh merged into one vertex table with per-mesh index offsets, SKEL from the bone table with the identity bind rotation the estate's rig convention declares, SKIN as four q12 weights per vertex summing to exactly 4096 (a float sum that rounds away from 4096 has the residual moved to its largest lane and the vertex COUNTED as fixed). Normals, colours, uvs and tangents are READ and COUNTED but not carried (TEXC is the texture rung, nx_nxa_texc). Every refusal is named; a truncated binary is refused at the byte it ran out on, never read as a smaller model. license_tier: ORIGINAL No hw writes (Rule 26).

dependencies 1 imports · 2 importers

nx_syscalls.nx nx_xps_lib.nx nx_xps.nx nx_xps_gate.nx

imports: nx_syscalls.nx

imported by: nx_xps.nxnx_xps_gate.nx

structs

none

consts

26const XP_MAGIC: i64 = 323232
27const XP_STR_LIMIT: i64 = 128
28const XP_TANGENT_MAJOR_MAX: i64 = 2
29const XP_TANGENT_MINOR_MAX: i64 = 12
30const XP_VARW_MAJOR_MIN: i64 = 3
31const XP_INF: i64 = 4
32const XP_Q12: i64 = 4096
33const XP_UNITS_PER_XPS_DEFAULT: i64 = 100000 // 1 XPS unit read as 1 metre = 100000 units of 0.01 mm; DECLARED, overridable
34const XP_F32_SIGN: i64 = 2147483648
35const XP_F32_EXP_DIV: i64 = 8388608
36const XP_F32_MAN_MASK: i64 = 8388607
37const XP_F32_HIDDEN: i64 = 8388608
38const XP_F32_BIAS_MAN: i64 = 150
39const XP_F32_SHIFT_CAP: i64 = 20
40const XP_FRAC_DIGITS_MAX: i64 = 9
41const XP_VERT_MIN_BYTES: i64 = 16 // the smallest vertex either dialect can spell; caps are DERIVED from the input size
42const XP_TRI_MIN_BYTES: i64 = 6
43const XP_DIALECT_ASCII: i64 = 1
44const XP_DIALECT_BIN: i64 = 2
46const XP_M_NV: i64 = 0
47const XP_M_NT: i64 = 1
48const XP_M_NJ: i64 = 2
49const XP_M_NMESH: i64 = 3
50const XP_M_VX: i64 = 4
51const XP_M_TR: i64 = 5
52const XP_M_JPAR: i64 = 6
53const XP_M_JPOS: i64 = 7
54const XP_M_SJ: i64 = 8
55const XP_M_SW: i64 = 9
56const XP_M_HASBONES: i64 = 10
57const XP_M_DIALECT: i64 = 11
58const XP_M_VMAJ: i64 = 12
59const XP_M_VMIN: i64 = 13
60const XP_M_TANGENT: i64 = 14
61const XP_M_VARW: i64 = 15
62const XP_M_CAPV: i64 = 16
63const XP_M_CAPT: i64 = 17
64const XP_M_NTEX: i64 = 18
65const XP_M_WFIX: i64 = 19
66const XP_M_UVMAX: i64 = 20
67const XP_M_MUL: i64 = 21
68const XP_M_ERRPOS: i64 = 22
69const XP_M_BADJOINT: i64 = 23
70const XP_M_WTRUNC: i64 = 24
71const XP_M_N: i64 = 32
73const XP_OK: i64 = 0
74const XP_ERR_TRUNCATED: i64 = 0 - 1
75const XP_ERR_CAP_VERTS: i64 = 0 - 2
76const XP_ERR_CAP_TRIS: i64 = 0 - 3
77const XP_ERR_MAGIC: i64 = 0 - 4
78const XP_ERR_BAD_JOINT: i64 = 0 - 5
79const XP_ERR_BAD_TRI: i64 = 0 - 6
80const XP_ERR_EMPTY: i64 = 0 - 7
81const XP_ERR_BAD_NUMBER: i64 = 0 - 8

functions

83func xp_err_name(e: i64) -> *u8
94func xp_pow2(k: i64) -> i64 { var v: i64 = 1; var i: i64 = 0; while i < k { v = v * 2; i = i + 1 } return v }
96func xp_f32fx(bits: i64, mul: i64) -> i64
117func xp_bu8(b: *u8, n: i64, p: *i64, m: *i64) -> i64
123func xp_bu16(b: *u8, n: i64, p: *i64, m: *i64) -> i64
129func xp_bi16(b: *u8, n: i64, p: *i64, m: *i64) -> i64 { let v: i64 = xp_bu16(b, n, p, m); if v >= 32768 { return v - 65536 } return v }
130func xp_bu32(b: *u8, n: i64, p: *i64, m: *i64) -> i64
137func xp_bf32(b: *u8, n: i64, p: *i64, m: *i64, mul: i64) -> i64 { let bits: i64 = xp_bu32(b, n, p, m); return xp_f32fx(bits, mul) }
139func xp_bstr_skip(b: *u8, n: i64, p: *i64, m: *i64) -> i64
149func xp_is_ws(c: i64) -> i64 { if c == 32 { return 1 } if c == 9 { return 1 } if c == 13 { return 1 } return 0 }
150func xp_is_digit(c: i64) -> i64 { if c >= 48 { if c <= 57 { return 1 } } return 0 }
152func xp_next_line(b: *u8, n: i64, p: *i64) -> i64
159func xp_skip_ws(b: *u8, n: i64, p: *i64) -> i64
167func xp_afx(b: *u8, n: i64, p: *i64, mul: i64, ok: *i64) -> i64
202func xp_aint(b: *u8, n: i64, p: *i64, m: *i64) -> i64
211func xp_aline(b: *u8, n: i64, p: *i64, m: *i64, k: i64, mul: i64, out: *i64) -> i64
226func xp_aline_skip(b: *u8, n: i64, p: *i64, m: *i64) -> i64 { if p[0] >= n { m[XP_M_ERRPOS] = p[0]; return 0 } xp_next_line(b, n, p); return 1 }
229func xp_fix_weights(sw: *i64, base: i64, m: *i64) -> i64
245func xp_alloc(m: *i64, n: i64) -> i64
257func xp_dialect(b: *u8, n: i64) -> i64
266func xp_read_ascii(b: *u8, n: i64, m: *i64) -> i64
368func xp_read_bin(b: *u8, n: i64, m: *i64) -> i64
500func xp_read(b: *u8, n: i64, units_per_xps: i64, m: *i64) -> i64