code wiki / (root) / nx_pmx.nx

nx_pmx.nx

buildroot/runtime/nx_pmx.nx

21931 B557 linesdepth 3pulls 3 transitivereach 0 importersview sourcekind tool
docsdependenciesstructsconstsfunctions

about

nx_pmx.nx -- PMX (MikuMikuDance 2.x) MODEL READER: header, section census, and the BONE TABLE. WHY: measured 2026-08-07 from vrstormlab.com/dancexr/preparecontent -- PMX is DanceXR's primary model format. It is also where the MMD standard BONE NAMES live, and bone names are what a retarget binds to. nx_bvhfk gives us third-party motion in world space; PMX gives us the named skeleton that motion is authored against. *YOU CANNOT REACH THE BONES WITHOUT WALKING EVERYTHING, WHICH IS WHY THE WALK PROVES ITSELF. PMX vertex records are VARIABLE LENGTH -- the size depends on a per-vertex weight-deform byte (BDEF1/BDEF2/BDEF4/SDEF/QDEF) and on index widths declared in the header globals. Miscount one vertex by one byte and the bone section is garbage. There is no way to "just skip to bones". FAIL-CLOSED: every read is bounds-checked against the ACTUAL file length before it happens. A count in a header is a CLAIM, never an authority -- the same discipline as nx_vmd, and here it matters more because a lying vertex count would drive a variable-stride walk off the buffer. TEXT: PMX globals[0] declares UTF-16LE (0) or UTF-8 (1). Names are emitted as UTF-8 either way; UTF-16LE is transcoded (BMP). We do NOT guess an encoding -- the file states it. usage: nx_pmx info <file.pmx> version, encoding, index widths, per-section counts nx_pmx bones <file.pmx> bone table: index, parent, position, name nx_pmx --kat selftest: 6 teeth, 3 of them anti-vacuity exit 0 ok | 2 unreadable | 3 usage | 4 REFUSED | 1 KAT RED license_tier: ORIGINAL No hw writes (Rule 26). expect_exit: 0

dependencies 1 imports · 0 importers

nx_gate_verdict.nx nx_pmx.nx

imports: nx_gate_verdict.nx

imported by: nobody (leaf or entry point)

call flow from main pre-order; caps 40 nodes / depth 6 declared; ↻ = already shown

main gv_puts sys_write px_slen px_kat gv_ctr sys_mmap nxa_die sys_write ↻ sys_exit nxa_lock_take nxa_lock_addr sys_write ↻ nxa_lock_give nxa_lock_addr ↻ nxa_report_overrun sys_write ↻ nxa_dump_printable sys_write ↻ nxa_dump_sizes sys_write ↻ gv_head gv_puts ↻ px_fixture px_put px_slen ↻ px_p32 px_ptext px_slen ↻ px_p32 ↻ px_walk px_u32 px_u8 px_need px_u8 ↻ px_text px_need ↻ px_i32 px_u32 ↻ px_u16_to_u8

structs

none

consts

26const PX_MAGIC_2147483648: i64 = 2147483648
27const PX_MAGIC_4294967296: i64 = 4294967296
28const PX_MAGIC_32768: i64 = 32768
29const PX_MAGIC_65536: i64 = 65536
30const PX_MAGIC_2048: i64 = 2048
31const PX_MAGIC_1073741824: i64 = 1073741824
32const PX_MAGIC_1000000: i64 = 1000000
34const PX_HDRSIG: i64 = 4
35const PX_MAXBONE: i64 = 1024
36const PX_NAMEW: i64 = 128
37const PX_ENC_U16: i64 = 0
38const PX_ENC_U8: i64 = 1
39const PX_KATBUF: i64 = 8192
42const PX_G_ENC: i64 = 0
43const PX_G_ADDUV: i64 = 1
44const PX_G_VIDX: i64 = 2
45const PX_G_TIDX: i64 = 3
46const PX_G_MIDX: i64 = 4
47const PX_G_BIDX: i64 = 5
48const PX_G_MOIDX: i64 = 6
49const PX_G_RIDX: i64 = 7
52const PX_BDEF1: i64 = 0
53const PX_BDEF2: i64 = 1
54const PX_BDEF4: i64 = 2
55const PX_SDEF: i64 = 3
56const PX_QDEF: i64 = 4
59const PX_BF_TAILIDX: i64 = 1
60const PX_BF_IK: i64 = 32
61const PX_BF_INH_ROT: i64 = 256
62const PX_BF_INH_TRN: i64 = 512
63const PX_BF_FIXAXIS: i64 = 1024
64const PX_BF_LOCALAX: i64 = 2048
65const PX_BF_EXTPAR: i64 = 8192
68const PX_R_MAGIC: i64 = 0 - 1
69const PX_R_TRUNC: i64 = 0 - 2
70const PX_R_COUNT: i64 = 0 - 3
71const PX_R_CAP: i64 = 0 - 4
72const PX_R_DEFORM:i64 = 0 - 5
197const PX_H_VER: i64 = 0
198const PX_H_NVERT: i64 = 1
199const PX_H_NSURF: i64 = 2
200const PX_H_NTEX: i64 = 3
201const PX_H_NMAT: i64 = 4
202const PX_H_NBONE: i64 = 5
203const PX_H_BONEOFF: i64 = 6
204const PX_H_WORDS: i64 = 12

functions

74func px_slen(s: *u8) -> i64 { var i: i64 = 0; while s[i] != (0 as u8) { i = i + 1 } return i }
called by 3: px_putpx_ptextmain
76func px_u8(b: *u8, o: i64) -> i64 { return (b[o] & 0xff) as i64 }
77func px_u16(b: *u8, o: i64) -> i64 { return px_u8(b,o) | (px_u8(b,o+1) << 8) }
called by 2: px_idxpx_walk calls 1: px_u8
78func px_u32(b: *u8, o: i64) -> i64
called by 3: px_i32px_walkpx_kat calls 1: px_u8
81func px_i32(b: *u8, o: i64) -> i64
called by 3: px_idxpx_textpx_walk calls 1: px_u32
87func px_idx(b: *u8, o: i64, w: i64) -> i64
called by 1: px_walk calls 3: px_u8px_u16px_i32
94func px_need(C: *i64, len: i64, n: i64) -> i64
101func px_u16_to_u8(src: *u8, n: i64, dst: *u8, cap: i64) -> i64
called by 1: px_text calls 1: px_u8
130func px_text(b: *u8, C: *i64, len: i64, enc: i64, dst: *u8, cap: i64) -> i64
151func px_vertex(b: *u8, C: *i64, len: i64, G: *i64) -> i64
called by 1: px_walk calls 2: px_needpx_u8
170func px_material(b: *u8, C: *i64, len: i64, G: *i64) -> i64
called by 1: px_walk calls 3: px_textpx_needpx_u8
206func px_walk(b: *u8, len: i64, G: *i64, H: *i64, names: *u8, bparent: *i64, bpos: *i64) -> i64
350func px_refuse(c: i64) -> i64
called by 1: main calls 2: gv_putsgv_num
362func px_put(b: *u8, o: i64, s: *u8) -> i64
called by 1: px_fixture calls 1: px_slen
368func px_p32(b: *u8, o: i64, v: i64) -> i64
373func px_ptext(b: *u8, o: i64, s: *u8) -> i64
called by 1: px_fixture calls 2: px_slenpx_p32
383func px_fixture(b: *u8) -> i64
called by 1: px_kat calls 3: px_putpx_p32px_ptext
440func px_streq(a: *u8, s: *u8) -> i64
called by 1: px_kat
447func px_kat() -> i64
510func main(argc: i64, argv: *i64) -> i64