nx_xps_gate.nx source
↩ module page · 254 lines · 18525 B
1// nx_xps_gate.nx -- THE XPS READER GATE (/compare/modding MD2, 2026-09-06). One small rigged model (two bones, one mesh,
2// four vertices, two triangles, one texture) is written at runtime under /tmp/nx_xps_gate/ in THREE spellings the reference
3// readers define: the ascii dialect, the binary dialect at version 3.15 (variable weight counts, no tangents) and the binary
4// dialect at version 1.12 (fixed four weights, a tangent per uv layer). All three must read to BYTE-IDENTICAL NXANIM01 --
5// the cross-dialect identity is the tooth a reader written from memory cannot pass, because the version-gated tangent and
6// weight-count fields shift every byte after them. The container is read back through nx_nxa.nx's own nxa_find (an
7// independent reader that verifies the TOC and payload checksums), the served pose player is the second witness
8// (zero_weight_verts=0), a truncated binary is refused by name, an unnormalised weight line is fixed and counted, and the
9// declared scale is proven to move the numbers.
10// usage: nx_xps_gate (no args)
11// license_tier: ORIGINAL No hw writes (Rule 26). expect_exit: 0
12import "nx_syscalls.nx"
13import "nx_gate_verdict.nx"
14import "nx_gatekit_lib.nx"
15import "nx_nxa.nx"
16import "nx_xps_lib.nx"
17import "nx_nxa_write_lib.nx"
18
19const XG_DIR: *u8 = "/tmp/nx_xps_gate"
20const XG_A: *u8 = "/tmp/nx_xps_gate/model.mesh.ascii"
21const XG_B3: *u8 = "/tmp/nx_xps_gate/model_v315.xps"
22const XG_B1: *u8 = "/tmp/nx_xps_gate/model_v112.xps"
23const XG_BCUT: *u8 = "/tmp/nx_xps_gate/model_cut.xps"
24const XG_AW: *u8 = "/tmp/nx_xps_gate/model_badweights.mesh.ascii"
25const XG_OUT_A: *u8 = "/tmp/nx_xps_gate/from_ascii.nxa"
26const XG_OUT_B3: *u8 = "/tmp/nx_xps_gate/from_v315.nxa"
27const XG_OUT_B1: *u8 = "/tmp/nx_xps_gate/from_v112.nxa"
28const XG_OUT_S: *u8 = "/tmp/nx_xps_gate/scaled.nxa"
29const XG_OUT_W: *u8 = "/tmp/nx_xps_gate/badweights.nxa"
30const XG_PLAY: *u8 = "./nx_nxa_play.elf"
31const XG_ELF_LIVE: *u8 = "./nx_xps.elf"
32const XG_ELF_STAGE: *u8 = "./nx_xps.sov.elf.new"
33const XG_ELF_BUILD: *u8 = "buildroot/_build/nx_xps.sov.elf"
34const XG_DIR_MODE: i64 = 493
35const XG_FILE_MODE: i64 = 420
36const XG_CAP: i64 = 65536
37const XG_UNITS: i64 = 100000
38const XG_UNITS_SMALL: i64 = 1000
39const XG_CUT_BYTES: i64 = 10
40// IEEE-754 single bit patterns, written as decimals so no hex literal is needed
41const XG_F_0: i64 = 0
42const XG_F_1: i64 = 1065353216
43const XG_F_HALF: i64 = 1056964608
44const XG_F_NEGHALF: i64 = 3204448256
45const XG_F_3Q: i64 = 1061158912
46const XG_F_1Q: i64 = 1048576000
47
48func xg_len(s: *u8) -> i64 { var n: i64 = 0; while s[n] != (0 as u8) { n = n + 1 } return n }
49func xg_cat(d: *u8, o: i64, s: *u8) -> i64 { let n: i64 = xg_len(s); var i: i64 = 0; while i < n { d[o + i] = s[i]; i = i + 1 } return o + n }
50func xg_u8(d: *u8, o: i64, v: i64) -> i64 { d[o] = (v & 255) as u8; return o + 1 }
51func xg_u16(d: *u8, o: i64, v: i64) -> i64 { var x: i64 = v; if x < 0 { x = x + 65536 } d[o] = (x & 255) as u8; d[o + 1] = ((x / 256) & 255) as u8; return o + 2 }
52func xg_u32(d: *u8, o: i64, v: i64) -> i64 { d[o] = (v & 255) as u8; d[o + 1] = ((v / 256) & 255) as u8; d[o + 2] = ((v / 65536) & 255) as u8; d[o + 3] = ((v / 16777216) & 255) as u8; return o + 4 }
53func xg_str(d: *u8, o: i64, s: *u8) -> i64 { let n: i64 = xg_len(s); var q: i64 = xg_u8(d, o, n); return xg_cat(d, q, s) }
54func xg_write_file(path: *u8, b: *u8, n: i64) -> i64 {
55 let fd: i64 = sys_openat_wr(path, XG_FILE_MODE)
56 if fd < 0 { return 0 - 1 }
57 var done: i64 = 0
58 while done < n { let k: i64 = sys_write(fd, b + done, n - done); if k <= 0 { break } done = done + k }
59 sys_close(fd)
60 return done
61}
62func xg_exists(path: *u8) -> i64 { let fd: i64 = sys_openat_rd(path); if fd < 0 { return 0 } sys_close(fd); return 1 }
63func xg_same_file(a: *u8, b: *u8) -> i64 {
64 let la: *i64 = sys_mmap(16) as *i64
65 let lb: *i64 = sys_mmap(16) as *i64
66 let ba: *u8 = sys_read_file(a, la)
67 let bb: *u8 = sys_read_file(b, lb)
68 if (ba as i64) == 0 { return 0 }
69 if (bb as i64) == 0 { return 0 }
70 if la[0] != lb[0] { return 0 }
71 var i: i64 = 0
72 while i < la[0] { if ba[i] != bb[i] { return 0 } i = i + 1 }
73 return 1
74}
75// the ascii spelling; bad=1 writes vertex 2 with weights that sum to 0.9 instead of 1
76func xg_ascii(path: *u8, bad: i64) -> i64 {
77 let d: *u8 = sys_mmap(4096)
78 var o: i64 = xg_cat(d, 0, "2 # bones\nroot\n-1 # parent\n0.000000 0.000000 0.000000\nchild\n0\n0.000000 1.000000 0.000000\n1 # meshes\nbody\n1 # uv layers\n1 # textures\nskin.png\n0 # uv layer\n4 # vertices\n" as *u8)
79 o = xg_cat(d, o, "-0.500000 0.000000 0.000000\n0.000000 0.000000 1.000000\n255 255 255 255\n0.000000 0.000000\n0 0 0 0\n1.000000 0.000000 0.000000 0.000000\n" as *u8)
80 o = xg_cat(d, o, "0.500000 0.000000 0.000000\n0.000000 0.000000 1.000000\n255 255 255 255\n1.000000 0.000000\n0 0 0 0\n1.000000 0.000000 0.000000 0.000000\n" as *u8)
81 if bad == 1 { o = xg_cat(d, o, "0.500000 1.000000 0.000000\n0.000000 0.000000 1.000000\n255 255 255 255\n1.000000 1.000000\n1 0 0 0\n0.700000 0.200000 0.000000 0.000000\n" as *u8) }
82 else { o = xg_cat(d, o, "0.500000 1.000000 0.000000\n0.000000 0.000000 1.000000\n255 255 255 255\n1.000000 1.000000\n1 0 0 0\n0.750000 0.250000 0.000000 0.000000\n" as *u8) }
83 o = xg_cat(d, o, "-0.500000 1.000000 0.000000\n0.000000 0.000000 1.000000\n255 255 255 255\n0.000000 1.000000\n1 0 0 0\n0.750000 0.250000 0.000000 0.000000\n" as *u8)
84 o = xg_cat(d, o, "2 # faces\n0 1 2\n0 2 3\n" as *u8)
85 return xg_write_file(path, d, o)
86}
87// the binary spelling; v3=1 writes version 3.15 (variable weights, no tangent), else 1.12 (four weights, tangent per layer)
88func xg_bin(path: *u8, v3: i64, cut: i64) -> i64 {
89 let d: *u8 = sys_mmap(4096)
90 var o: i64 = xg_u32(d, 0, XP_MAGIC)
91 if v3 == 1 { o = xg_u16(d, o, 3); o = xg_u16(d, o, 15) } else { o = xg_u16(d, o, 1); o = xg_u16(d, o, 12) }
92 o = xg_str(d, o, "XNAaraL" as *u8)
93 o = xg_u32(d, o, 2) // settings block of two 32-bit words
94 o = xg_str(d, o, "gate" as *u8); o = xg_str(d, o, "gate" as *u8); o = xg_str(d, o, "gate" as *u8)
95 o = xg_u32(d, o, 0); o = xg_u32(d, o, 0)
96 o = xg_u32(d, o, 2) // bones
97 o = xg_str(d, o, "root" as *u8); o = xg_u16(d, o, 0 - 1); o = xg_u32(d, o, XG_F_0); o = xg_u32(d, o, XG_F_0); o = xg_u32(d, o, XG_F_0)
98 o = xg_str(d, o, "child" as *u8); o = xg_u16(d, o, 0); o = xg_u32(d, o, XG_F_0); o = xg_u32(d, o, XG_F_1); o = xg_u32(d, o, XG_F_0)
99 o = xg_u32(d, o, 1) // meshes
100 o = xg_str(d, o, "body" as *u8); o = xg_u32(d, o, 1); o = xg_u32(d, o, 1); o = xg_str(d, o, "skin.png" as *u8); o = xg_u32(d, o, 0)
101 o = xg_u32(d, o, 4) // vertices
102 let px: *i64 = sys_mmap(8 * 4) as *i64
103 let py: *i64 = sys_mmap(8 * 4) as *i64
104 px[0] = XG_F_NEGHALF; px[1] = XG_F_HALF; px[2] = XG_F_HALF; px[3] = XG_F_NEGHALF
105 py[0] = XG_F_0; py[1] = XG_F_0; py[2] = XG_F_1; py[3] = XG_F_1
106 var v: i64 = 0
107 while v < 4 {
108 o = xg_u32(d, o, px[v]); o = xg_u32(d, o, py[v]); o = xg_u32(d, o, XG_F_0) // position
109 o = xg_u32(d, o, XG_F_0); o = xg_u32(d, o, XG_F_0); o = xg_u32(d, o, XG_F_1) // normal
110 o = xg_u8(d, o, 255); o = xg_u8(d, o, 255); o = xg_u8(d, o, 255); o = xg_u8(d, o, 255)
111 o = xg_u32(d, o, px[v]); o = xg_u32(d, o, py[v]) // uv
112 if v3 == 0 { o = xg_u32(d, o, XG_F_0); o = xg_u32(d, o, XG_F_0); o = xg_u32(d, o, XG_F_0); o = xg_u32(d, o, XG_F_0) }
113 if v3 == 1 {
114 if v < 2 { o = xg_u16(d, o, 1); o = xg_u16(d, o, 0); o = xg_u32(d, o, XG_F_1) }
115 else { o = xg_u16(d, o, 2); o = xg_u16(d, o, 1); o = xg_u16(d, o, 0); o = xg_u32(d, o, XG_F_3Q); o = xg_u32(d, o, XG_F_1Q) }
116 } else {
117 if v < 2 { o = xg_u16(d, o, 0); o = xg_u16(d, o, 0); o = xg_u16(d, o, 0); o = xg_u16(d, o, 0); o = xg_u32(d, o, XG_F_1); o = xg_u32(d, o, XG_F_0); o = xg_u32(d, o, XG_F_0); o = xg_u32(d, o, XG_F_0) }
118 else { o = xg_u16(d, o, 1); o = xg_u16(d, o, 0); o = xg_u16(d, o, 0); o = xg_u16(d, o, 0); o = xg_u32(d, o, XG_F_3Q); o = xg_u32(d, o, XG_F_1Q); o = xg_u32(d, o, XG_F_0); o = xg_u32(d, o, XG_F_0) }
119 }
120 v = v + 1
121 }
122 o = xg_u32(d, o, 2) // triangles
123 o = xg_u32(d, o, 0); o = xg_u32(d, o, 1); o = xg_u32(d, o, 2)
124 o = xg_u32(d, o, 0); o = xg_u32(d, o, 2); o = xg_u32(d, o, 3)
125 if cut > 0 { o = o - cut }
126 return xg_write_file(path, d, o)
127}
128func xg_word_at(path: *u8, tag: *u8, idx: i64, box: *i64) -> i64 {
129 let lp: *i64 = sys_mmap(16) as *i64
130 let b: *u8 = sys_read_file(path, lp)
131 if (b as i64) == 0 { box[0] = 0 - 99; return 0 - 99 }
132 let off: i64 = nxa_find(b, lp[0], nxa_tag4(tag))
133 box[0] = off
134 if off < 0 { return 0 - 99 }
135 let h: *i64 = b as *i64
136 return h[off + idx]
137}
138func main(argc: i64, argv: *i64) -> i64 {
139 let ctr: *i64 = gv_ctr()
140 gv_head("nx_xps_gate -- three spellings of one rigged model read to one NXANIM01, verified by the container's own reader and the served player" as *u8)
141 sys_mkdir(XG_DIR, XG_DIR_MODE)
142 gv_check("ascii-fixture-written" as *u8, (xg_ascii(XG_A, 0) > 0) as i64, ctr)
143 gv_check("binary-v3.15-fixture-written" as *u8, (xg_bin(XG_B3, 1, 0) > 0) as i64, ctr)
144 gv_check("binary-v1.12-fixture-written" as *u8, (xg_bin(XG_B1, 0, 0) > 0) as i64, ctr)
145 gv_check("binary-truncated-fixture-written" as *u8, (xg_bin(XG_BCUT, 1, XG_CUT_BYTES) > 0) as i64, ctr)
146 gv_check("ascii-badweights-fixture-written" as *u8, (xg_ascii(XG_AW, 1) > 0) as i64, ctr)
147 let m: *i64 = sys_mmap(8 * XP_M_N) as *i64
148 let wrc: *i64 = sys_mmap(8 * NXW_R_N) as *i64
149 let lp: *i64 = sys_mmap(16) as *i64
150 // ---- ascii, in-process ----
151 let ba: *u8 = sys_read_file(XG_A, lp)
152 let rca: i64 = xp_read(ba, lp[0], XG_UNITS, m)
153 gv_check_eq("ascii-reads-clean" as *u8, rca, XP_OK, ctr)
154 gv_check_eq("ascii-dialect-detected" as *u8, m[XP_M_DIALECT], XP_DIALECT_ASCII, ctr)
155 gv_check_eq("ascii-bones=2" as *u8, m[XP_M_NJ], 2, ctr)
156 gv_check_eq("ascii-verts=4" as *u8, m[XP_M_NV], 4, ctr)
157 gv_check_eq("ascii-tris=2" as *u8, m[XP_M_NT], 2, ctr)
158 gv_check_eq("ascii-textures=1" as *u8, m[XP_M_NTEX], 1, ctr)
159 gv_check_eq("ascii-weights-fixed=0 (0.75+0.25 lands exactly on 4096)" as *u8, m[XP_M_WFIX], 0, ctr)
160 let vx: *i64 = m[XP_M_VX] as *i64
161 gv_check_eq("ascii-vertex0-x=-0.5xps at 100000 per xps" as *u8, vx[0], 0 - 50000, ctr)
162 gv_check_eq("ascii-vertex2-y=1.0xps" as *u8, vx[2 * 3 + 1], 100000, ctr)
163 let jpos: *i64 = m[XP_M_JPOS] as *i64
164 let jpar: *i64 = m[XP_M_JPAR] as *i64
165 gv_check_eq("ascii-child-bone-y=1.0xps" as *u8, jpos[3 + 1], 100000, ctr)
166 gv_check_eq("ascii-root-parent=-1" as *u8, jpar[0], 0 - 1, ctr)
167 gv_check_eq("ascii-child-parent=0" as *u8, jpar[1], 0, ctr)
168 let sw: *i64 = m[XP_M_SW] as *i64
169 let sj: *i64 = m[XP_M_SJ] as *i64
170 gv_check_eq("ascii-vertex2-weight0=3072 (0.75 q12)" as *u8, sw[2 * XP_INF], 3072, ctr)
171 gv_check_eq("ascii-vertex2-weight1=1024 (0.25 q12)" as *u8, sw[2 * XP_INF + 1], 1024, ctr)
172 gv_check_eq("ascii-vertex2-joint0=1 (the child bone)" as *u8, sj[2 * XP_INF], 1, ctr)
173 let wa: i64 = nxw_write(XG_OUT_A, vx, m[XP_M_NV], m[XP_M_TR] as *i64, m[XP_M_NT], jpar, jpos, m[XP_M_NJ], sj, sw, wrc)
174 gv_check("ascii-container-written" as *u8, (wa > 0) as i64, ctr)
175 gv_check_eq("ascii-container-sections=4" as *u8, wrc[NXW_R_SECTIONS], 4, ctr)
176 gv_check_eq("ascii-container-bytes-are-the-word-count-times-8" as *u8, wa, nxw_words(4, 2, 2) * 8, ctr)
177 gv_kv("ascii_nxa_bytes" as *u8, wa)
178 // ---- the container read back through nx_nxa.nx's own verifying finder (an independent reader) ----
179 let box: *i64 = sys_mmap(16) as *i64
180 gv_check_eq("nxa_find-VERT-count=4 (TOC and payload checksums verified by the finder)" as *u8, xg_word_at(XG_OUT_A, "VERT" as *u8, 0, box), 4, ctr)
181 gv_check_eq("nxa_find-VERT-x0=-50000" as *u8, xg_word_at(XG_OUT_A, "VERT" as *u8, 1, box), 0 - 50000, ctr)
182 gv_check_eq("nxa_find-TRIS-count=2" as *u8, xg_word_at(XG_OUT_A, "TRIS" as *u8, 0, box), 2, ctr)
183 gv_check_eq("nxa_find-TRIS-last-index=3" as *u8, xg_word_at(XG_OUT_A, "TRIS" as *u8, 6, box), 3, ctr)
184 gv_check_eq("nxa_find-SKEL-count=2" as *u8, xg_word_at(XG_OUT_A, "SKEL" as *u8, 0, box), 2, ctr)
185 gv_check_eq("nxa_find-SKEL-child-ty=100000" as *u8, xg_word_at(XG_OUT_A, "SKEL" as *u8, 1 + 8 + 2, box), 100000, ctr)
186 gv_check_eq("nxa_find-SKEL-child-qw=4096 (identity bind rotation)" as *u8, xg_word_at(XG_OUT_A, "SKEL" as *u8, 1 + 8 + 7, box), NXW_Q12, ctr)
187 gv_check_eq("nxa_find-SKIN-count=4" as *u8, xg_word_at(XG_OUT_A, "SKIN" as *u8, 0, box), 4, ctr)
188 gv_check_eq("nxa_find-SKIN-vertex2-w0=3072" as *u8, xg_word_at(XG_OUT_A, "SKIN" as *u8, 1 + 2 * 8 + 4, box), 3072, ctr)
189 // ---- the two binary spellings must read to the SAME bytes ----
190 let b3: *u8 = sys_read_file(XG_B3, lp)
191 let rc3: i64 = xp_read(b3, lp[0], XG_UNITS, m)
192 gv_check_eq("binary-v3.15-reads-clean" as *u8, rc3, XP_OK, ctr)
193 gv_check_eq("binary-v3.15-dialect-detected" as *u8, m[XP_M_DIALECT], XP_DIALECT_BIN, ctr)
194 gv_check_eq("binary-v3.15-variable-weights-recognised" as *u8, m[XP_M_VARW], 1, ctr)
195 gv_check_eq("binary-v3.15-no-tangent-recognised" as *u8, m[XP_M_TANGENT], 0, ctr)
196 let w3: i64 = nxw_write(XG_OUT_B3, m[XP_M_VX] as *i64, m[XP_M_NV], m[XP_M_TR] as *i64, m[XP_M_NT], m[XP_M_JPAR] as *i64, m[XP_M_JPOS] as *i64, m[XP_M_NJ], m[XP_M_SJ] as *i64, m[XP_M_SW] as *i64, wrc)
197 gv_check("binary-v3.15-container-written" as *u8, (w3 > 0) as i64, ctr)
198 gv_check("CROSS-DIALECT IDENTITY: binary v3.15 and ascii produce byte-identical NXANIM01" as *u8, xg_same_file(XG_OUT_A, XG_OUT_B3), ctr)
199 let b1: *u8 = sys_read_file(XG_B1, lp)
200 let rc1: i64 = xp_read(b1, lp[0], XG_UNITS, m)
201 gv_check_eq("binary-v1.12-reads-clean" as *u8, rc1, XP_OK, ctr)
202 gv_check_eq("binary-v1.12-tangent-recognised" as *u8, m[XP_M_TANGENT], 1, ctr)
203 gv_check_eq("binary-v1.12-fixed-weights-recognised" as *u8, m[XP_M_VARW], 0, ctr)
204 let w1: i64 = nxw_write(XG_OUT_B1, m[XP_M_VX] as *i64, m[XP_M_NV], m[XP_M_TR] as *i64, m[XP_M_NT], m[XP_M_JPAR] as *i64, m[XP_M_JPOS] as *i64, m[XP_M_NJ], m[XP_M_SJ] as *i64, m[XP_M_SW] as *i64, wrc)
205 gv_check("binary-v1.12-container-written" as *u8, (w1 > 0) as i64, ctr)
206 gv_check("CROSS-DIALECT IDENTITY: binary v1.12 (tangents skipped by version) and ascii produce byte-identical NXANIM01" as *u8, xg_same_file(XG_OUT_A, XG_OUT_B1), ctr)
207 // ---- refusals and fixes ----
208 let bc: *u8 = sys_read_file(XG_BCUT, lp)
209 let rcc: i64 = xp_read(bc, lp[0], XG_UNITS, m)
210 gv_bite("neg-control-truncated-binary-REFUSED-by-name (whole file reads clean)" as *u8, (rcc == XP_ERR_TRUNCATED) as i64, (rc3 == XP_ERR_TRUNCATED) as i64, ctr)
211 gv_check("truncated-binary-names-the-byte-it-ran-out-on" as *u8, (m[XP_M_ERRPOS] >= 0) as i64, ctr)
212 let bw: *u8 = sys_read_file(XG_AW, lp)
213 let rcw: i64 = xp_read(bw, lp[0], XG_UNITS, m)
214 gv_check_eq("badweights-ascii-still-reads" as *u8, rcw, XP_OK, ctr)
215 gv_check_eq("badweights-vertex-COUNTED-as-fixed" as *u8, m[XP_M_WFIX], 1, ctr)
216 let sww: *i64 = m[XP_M_SW] as *i64
217 gv_check_eq("badweights-vertex2-sums-to-4096-after-the-fix (residual to the largest lane)" as *u8, sww[2 * XP_INF] + sww[2 * XP_INF + 1] + sww[2 * XP_INF + 2] + sww[2 * XP_INF + 3], NXW_Q12, ctr)
218 let ww: i64 = nxw_write(XG_OUT_W, m[XP_M_VX] as *i64, m[XP_M_NV], m[XP_M_TR] as *i64, m[XP_M_NT], m[XP_M_JPAR] as *i64, m[XP_M_JPOS] as *i64, m[XP_M_NJ], m[XP_M_SJ] as *i64, m[XP_M_SW] as *i64, wrc)
219 gv_check("badweights-container-accepted-by-the-writer-after-the-fix" as *u8, (ww > 0) as i64, ctr)
220 // scale is data: the same ascii at 1000 per xps lands vertex0 at -500
221 let rcs: i64 = xp_read(ba, xg_len(ba), XG_UNITS_SMALL, m)
222 let vxs: *i64 = m[XP_M_VX] as *i64
223 gv_check_eq("declared-scale-moves-the-numbers (1000 per xps -> -500)" as *u8, vxs[0], 0 - 500, ctr)
224 gv_check_eq("declared-scale-announced-in-the-model" as *u8, m[XP_M_MUL], XG_UNITS_SMALL, ctr)
225 gv_kv("units_default" as *u8, XP_UNITS_PER_XPS_DEFAULT)
226 // ---- second witness: the served pose player evaluates the rigged asset ----
227 gv_need("served-player-present (./nx_nxa_play.elf)" as *u8, xg_exists(XG_PLAY), ctr)
228 if xg_exists(XG_PLAY) == 1 {
229 let out: *u8 = sys_mmap(XG_CAP)
230 let bl: *i64 = sys_mmap(16) as *i64
231 gk_run_capture(XG_PLAY, XG_OUT_A, 0 as *u8, 0 as *u8, 0 as *u8, out, XG_CAP, bl)
232 gv_check("player-read-the-container (produced output)" as *u8, (bl[0] > 0) as i64, ctr)
233 gv_check("player-zero_weight_verts=0 (every vertex is bound)" as *u8, gk_out_has(out, bl[0], "zero_weight_verts=0" as *u8), ctr)
234 }
235 // ---- the CLI as a witness on the ascii fixture ----
236 var elf: *u8 = 0 as *u8
237 if xg_exists(XG_ELF_LIVE) == 1 { elf = XG_ELF_LIVE }
238 else { if xg_exists(XG_ELF_STAGE) == 1 { elf = XG_ELF_STAGE } else { if xg_exists(XG_ELF_BUILD) == 1 { elf = XG_ELF_BUILD } } }
239 gv_need("cli-witness-present (live, staged or build fossil of nx_xps)" as *u8, ((elf as i64) != 0) as i64, ctr)
240 if (elf as i64) != 0 {
241 let out2: *u8 = sys_mmap(XG_CAP)
242 let bl2: *i64 = sys_mmap(16) as *i64
243 let rcx: i64 = gk_run_capture(elf, XG_B1, XG_OUT_S, 0 as *u8, 0 as *u8, out2, XG_CAP, bl2)
244 gv_check_eq("cli-exits-0-on-the-v1.12-binary" as *u8, rcx, 0, ctr)
245 gv_check("cli-receipt-names-the-dialect-and-version" as *u8, gk_out_has(out2, bl2[0], "dialect=binary version=1.12" as *u8), ctr)
246 gv_check("cli-receipt-announces-the-scale" as *u8, gk_out_has(out2, bl2[0], "units_per_xps=100000" as *u8), ctr)
247 gv_check("cli-wrote-a-container" as *u8, gk_out_has(out2, bl2[0], "XPS-NXA wrote=" as *u8), ctr)
248 gv_check("cli-output-byte-identical-to-the-in-process-ascii-read" as *u8, xg_same_file(XG_OUT_A, XG_OUT_S), ctr)
249 let rct: i64 = gk_run_capture(elf, XG_BCUT, XG_OUT_S, 0 as *u8, 0 as *u8, out2, XG_CAP, bl2)
250 gv_check_eq("cli-refuses-the-truncated-binary-with-exit-3" as *u8, rct, 3, ctr)
251 gv_check("cli-names-the-refusal" as *u8, gk_out_has(out2, bl2[0], "XPS-REFUSE truncated-input" as *u8), ctr)
252 }
253 return gv_verdict("NX-XPS" as *u8, ctr, "one rigged model in three XPS spellings reads to one byte-identical NXANIM01 that the container's own verifying reader and the served player accept, with truncation refused by name, weights fixed and counted, and scale carried as data" as *u8)
254}