nx_garment_gen.nx source
↩ module page · 80 lines · 3898 B
1// nx_garment_gen.nx -- THE GARMENT MESH GENERATOR (2026-08-30): grows conforming garment shells for every
2// id of the engine's garment table from the NPC asset's own body surface and appends them as one GARM
3// section (see nx_garment_gen_lib.nx for the geometry, the units and the fabric-table sources).
4//
5// nx_garment_gen <in.nxa> <out.nxa> [thick_permil]
6// thick_permil scales fabric thickness (1000 = as derived). 0 is the neg-control: REFUSED by name.
7//
8// EXIT: 0 written . 2 usage . 4 REFUSED (zero thickness) . 5 bad nxa . 6 REFUSED (an id selected no
9// triangle) . 7 REFUSED (a buffer cap -- named, never silently truncated) . 9 io
10// Prints one GARM line per kind (the receipt) and the section's word count; the gate re-derives the same
11// numbers IN-PROCESS from the lib, so no parser of this output exists anywhere.
12// license_tier: ORIGINAL. No hw writes (Rule 26).
13import "nx_syscalls.nx"
14import "nx_nxa.nx"
15import "nx_garment_gen_lib.nx"
16
17const GGP_EXIT_OK: i64 = 0
18const GGP_EXIT_USAGE: i64 = 2
19const GGP_EXIT_REFUSED: i64 = 4
20const GGP_EXIT_BADNXA: i64 = 5
21const GGP_EXIT_EMPTY: i64 = 6
22const GGP_EXIT_CAP: i64 = 7
23const GGP_EXIT_IO: i64 = 9
24
25func ggp_atoi(s: *u8) -> i64 {
26 var v: i64 = 0
27 var i: i64 = 0
28 var neg: i64 = 0
29 if s[0] == (45 as u8) { neg = 1; i = 1 }
30 while s[i] != (0 as u8) {
31 let c: i64 = s[i] as i64
32 if c < 48 { return 0 - 1 }
33 if c > 57 { return 0 - 1 }
34 v = v * 10 + (c - 48)
35 i = i + 1
36 }
37 if neg == 1 { return 0 - v }
38 return v
39}
40
41func main(argc: i64, argv: *i64) -> i64 {
42 if argc < 3 { gmg_puts("usage: nx_garment_gen <in.nxa> <out.nxa> [thick_permil]\n" as *u8); return GGP_EXIT_USAGE }
43 var pm: i64 = 1000
44 if argc >= 4 { pm = ggp_atoi(argv[3] as *u8) }
45 if pm < 0 { gmg_puts("usage: thick_permil must be a non-negative integer\n" as *u8); return GGP_EXIT_USAGE }
46 let lp: *i64 = sys_mmap(16) as *i64
47 let b: *u8 = sys_map_file(argv[1] as *u8, lp)
48 let flen: i64 = lp[0]
49 if (b as i64) == 0 { gmg_puts("GMG-REFUSED cannot map input\n" as *u8); return GGP_EXIT_BADNXA }
50 let G: *i64 = gmg_load(b, flen)
51 if (G as i64) == 0 { return GGP_EXIT_BADNXA }
52 G[GMG_C_THICK_PERMIL] = pm
53 gmg_puts("GMG body nv=" as *u8); gmg_pn(G[GMG_C_NV])
54 gmg_puts(" nt=" as *u8); gmg_pn(G[GMG_C_NT])
55 gmg_puts(" H=" as *u8); gmg_pn(G[GMG_C_H])
56 gmg_puts(" nip_dm=" as *u8); gmg_pn(G[GMG_C_NIP])
57 gmg_puts(" dyna=" as *u8); gmg_pn(G[GMG_C_ND])
58 gmg_puts(" skirt_top_dm=" as *u8); gmg_pn(G[GMG_C_GTH])
59 gmg_puts(" skirt_gap_units=" as *u8); gmg_pn(G[GMG_C_GAP])
60 gmg_puts(" units_per_mm_x1000=" as *u8); gmg_pn(G[GMG_C_UPMK])
61 gmg_puts(" thick_permil=" as *u8); gmg_pn(pm)
62 gmg_puts("\n" as *u8)
63 let sec: *i64 = sys_mmap(GMG_SEC_CAP * 8 + 64) as *i64
64 let stats: *i64 = sys_mmap(GMG_KINDS * GMG_STAT_N * 8 + 64) as *i64
65 let nw: i64 = gmg_gen_all(G, sec, stats)
66 if nw == GMG_ERR_REFUSED_THICK { gmg_puts("verdict=REFUSED zero-thickness\n" as *u8); return GGP_EXIT_REFUSED }
67 if nw == GMG_ERR_EMPTY { gmg_puts("verdict=REFUSED empty-kind\n" as *u8); return GGP_EXIT_EMPTY }
68 if nw == GMG_ERR_CAP { gmg_puts("verdict=REFUSED buffer-cap\n" as *u8); return GGP_EXIT_CAP }
69 if nw < 0 { gmg_puts("verdict=REFUSED\n" as *u8); return GGP_EXIT_BADNXA }
70 var k: i64 = 0
71 while k < GMG_KINDS { gmg_print_stat(((stats as i64) + k * GMG_STAT_N * 8) as *i64); k = k + 1 }
72 let rc: i64 = gmg_write_nxa(b, flen, sec, nw, argv[2] as *u8)
73 if rc < 0 { gmg_puts("GMG-REFUSED cannot open output for write\n" as *u8); return GGP_EXIT_IO }
74 gmg_puts("GARM section_words=" as *u8); gmg_pn(nw)
75 gmg_puts(" bytes=" as *u8); gmg_pn(nw * 8)
76 gmg_puts(" checksum=" as *u8); gmg_pn(nxa_check2(1, sec, nw))
77 gmg_puts(" out=" as *u8); gmg_puts(argv[2] as *u8)
78 gmg_puts(" verdict=WRITTEN\n" as *u8)
79 return GGP_EXIT_OK
80}