code wiki / (root) / nx_vmd.nx

nx_vmd.nx

buildroot/runtime/nx_vmd.nx

22549 B552 linesdepth 2pulls 2 transitivereach 0 importersview sourcekind orphan library
docsdependenciesstructsconstsfunctions

about

nx_vmd.nx -- VMD (Vocaloid Motion Data) MOTION DECODER: the MMD dance corpus, read sovereignly. WHY THIS EXISTS (measured 2026-08-07 against vrstormlab.com/dancexr/play, from their own served bytes -- not their marketing copy): the free LW build ingests PMX + XPS models and VMD + BVH motion. Our estate already owns the OTHER half of that pipeline -- nx_pose_retarget inverts the sovereign FK, nx_gltf2mesh segments a donor into 74 named parts -- and owned ZERO of their four ingest formats. A grep for "bvh" found nx_bvh and read as a match; nx_bvh is a BOUNDING VOLUME HIERARCHY for the slicer, not BioVision Hierarchy motion capture. *A NAME IS NOT A CAPABILITY. A GREP FINDS THE CLAIM; ONLY READING THE SOURCE SETTLES IT. VMD is the keystone of the four because the dance corpus is overwhelmingly VMD, and because it carries exactly what our retarget consumes: per-bone, per-frame rotations on a named skeleton. FAIL-CLOSED BY CONSTRUCTION: every field is bounds-checked against the ACTUAL file length before it is read. A count in a header is a CLAIM, never an authority. A truncated file is REFUSED, not partially parsed into a plausible-looking track -- because a plausible segmentation is the most dangerous kind, and a motion track that silently stops at frame 40 of 400 still animates. UNITS ARE DECLARED, NEVER IMPLIED (a threshold is meaningless until its unit is stated): positions = VMD/MMD model units x V_SCALE_POS (1000). NOT millimetres; MMD units are their own. rotations = quaternion components x V_SCALE_ROT (4096), each in [-4096, 4096]. morph = weight x V_SCALE_POS (1000), nominally [0, 1000]. usage: nx_vmd info <file.vmd> version, model name, per-section counts, duration in frames nx_vmd bones <file.vmd> per-bone keyframe census (raw name bytes + id) nx_vmd dump <file.vmd> [n] first n bone keyframes as rows nx_vmd --kat selftest: 7 teeth, 4 of them anti-vacuity exit 0 ok | 2 unreadable | 3 usage | 4 REFUSED (bad magic / truncated / count exceeds bytes) | 1 selftest RED license_tier: ORIGINAL No hw writes (Rule 26). expect_exit: 0

dependencies 1 imports · 0 importers

nx_syscalls.nx nx_vmd.nx

imports: nx_syscalls.nx

imported by: nobody (leaf or entry point)

structs

none

consts

32const V_MAGIC_2000: i64 = 2000
35const V_HDR_SIG: i64 = 30 // signature block, NUL/garbage padded
36const V_NAME_V2: i64 = 20 // model-name field, signature "...0002"
37const V_NAME_V1: i64 = 10 // model-name field, older signature
38const V_BONE_REC: i64 = 111 // name15 + frame4 + pos12 + quat16 + interp64
39const V_MORPH_REC: i64 = 23 // name15 + frame4 + weight4
40const V_CAM_REC: i64 = 61 // frame4 + dist4 + pos12 + rot12 + interp24 + fov4 + persp1
41const V_LIGHT_REC: i64 = 28 // frame4 + rgb12 + pos12
42const V_SHADOW_REC: i64 = 9 // frame4 + mode1 + dist4
43const V_NAME_BYTES: i64 = 15 // bone/morph name field width (Shift-JIS, NUL padded)
46const V_SCALE_POS: i64 = 1000
47const V_SCALE_ROT: i64 = 4096
50const V_M_255: i64 = 255
51const V_M_8388607: i64 = 8388607
52const V_M_8388608: i64 = 8388608
53const V_M_EXPBIAS: i64 = 127
54const V_M_MANTBIT: i64 = 23
55const V_MAX_SH: i64 = 40 // refuse absurd exponents rather than overflow the shift
56const V_MAX_RS: i64 = 62 // a shift wider than the word is undefined -- return 0, never garbage
59const V_MAX_UNIQ: i64 = 512 // unique bone names held; exceeding this REFUSES (declared cap)
60const V_DUMP_DEF: i64 = 8
63const V_L_VER: i64 = 0
64const V_L_NAMEOFF: i64 = 1
65const V_L_BONEOFF: i64 = 2
66const V_L_BONEN: i64 = 3
67const V_L_MORPHOFF:i64 = 4
68const V_L_MORPHN: i64 = 5
69const V_L_CAMOFF: i64 = 6
70const V_L_CAMN: i64 = 7
71const V_L_LIGHTOFF:i64 = 8
72const V_L_LIGHTN: i64 = 9
73const V_L_SHADOFF: i64 = 10
74const V_L_SHADN: i64 = 11
75const V_L_MAXFRAME:i64 = 12
76const V_L_IKOFF: i64 = 13
77const V_L_IKN: i64 = 14
78const V_L_END: i64 = 15
79const V_L_WORDS: i64 = 20
80const V_IK_NAME: i64 = 20 // per-IK-entry bone name field width
81const V_IK_FIXED: i64 = 9 // frame4 + show1 + ikcount4
84const V_BUF: i64 = 4096
85const V_MODE_644: i64 = 420
86const V_F32_1_0: i64 = 1065353216
87const V_F32_2_0: i64 = 1073741824
88const V_F32_0_5: i64 = 1056964608
89const V_F32_N1_0: i64 = 3212836864
90const V_KAT_FRAME: i64 = 30
91const V_KAT_MORPHFRAME: i64 = 10
92const V_KAT_LIARCOUNT: i64 = 100000

functions

95func v_slen(s: *u8) -> i64 { var i: i64 = 0; while s[i] != (0 as u8) { i = i + 1 } return i }
96func v_puts(s: *u8) -> i64 { sys_write(1, s, v_slen(s)); return 0 }
98func v_num(v: i64) -> i64
114func v_u32(b: *u8, o: i64) -> i64
122func v_f32(b: *u8, o: i64, scale: i64) -> i64
145func v_version(b: *u8, len: i64) -> i64
164func v_name_width(ver: i64) -> i64
177func v_section(buf: *u8, len: i64, off: i64, rec: i64, L: *i64, slot_off: i64, slot_n: i64) -> i64
190func v_layout(buf: *u8, len: i64, L: *i64) -> i64
255func v_refuse(code: i64) -> i64
265func v_name_eq(buf: *u8, a: i64, tbl: *u8, slot: i64) -> i64
274func v_name_put(buf: *u8, a: i64, tbl: *u8, slot: i64) -> i64
282func v_name_print(tbl: *u8, slot: i64) -> i64
293func v_info(buf: *u8, len: i64, L: *i64) -> i64
324func v_bones(buf: *u8, L: *i64) -> i64
362func v_dump(buf: *u8, L: *i64, maxn: i64) -> i64
387func v_put_u32(b: *u8, o: i64, v: i64) -> i64
395func v_put_str(b: *u8, o: i64, s: *u8) -> i64
403func v_kat_build(b: *u8) -> i64
433func v_kat() -> i64
509func main(argc: i64, argv: *i64) -> i64