code wiki / (root) / nx_kkfacts.nx

nx_kkfacts.nx source

↩ module page · 95 lines · 4314 B

1// nx_kkfacts.nx -- CLI: Koikatsu card structural facts. nx_kkfacts probe <card.png> 2// Reads up to 64MB (cards are full files, payload census needs the whole artifact). Facts only: 3// structure + sizes + block census; slider values / names / creative content stay unread. 4// license_tier: ORIGINAL No hw writes (Rule 26). expect_exit: 0 5import "nx_syscalls.nx" 6import "nx_kkfacts_lib.nx" 7 8const KKC_CAP: i64 = 67108864 9const KKD_MAX_VALS: i64 = 256 // slider arrays measure ~52 (face) / ~44 (body); 256 is the refuse-beyond bound, overflow visible via parsed vs declared 10 11func kc_slen(s: *u8) -> i64 { var n: i64 = 0; while s[n] != (0 as u8) { n = n + 1 } return n } 12func kc_w(s: *u8) -> i64 { sys_write(1, s, kc_slen(s)); return 0 } 13func kc_e(s: *u8) -> i64 { sys_write(2, s, kc_slen(s)); return 0 } 14func kc_num(v: i64) -> i64 { 15 if v == 0 { sys_write(1, "0" as *u8, 1); return 0 } 16 var m: i64 = v 17 if m < 0 { sys_write(1, "-" as *u8, 1); m = 0 - m } 18 let t: *u8 = sys_mmap(32) 19 var k: i64 = 0 20 while m > 0 { t[k] = (48 + (m % 10)) as u8; m = m / 10; k = k + 1 } 21 let o: *u8 = sys_mmap(32) 22 var i: i64 = 0 23 while i < k { o[i] = t[k - 1 - i]; i = i + 1 } 24 sys_write(1, o, k) 25 return 0 26} 27 28func kc_eq(a: *u8, b: *u8) -> i64 { var i: i64 = 0; while a[i] != (0 as u8) { if a[i] != b[i] { return 0 } i = i + 1 } if b[i] != (0 as u8) { return 0 } return 1 } 29 30func main(argc: i64, argv: *i64) -> i64 { 31 if argc < 3 { kc_e("usage: nx_kkfacts probe|decode <card.png>\n" as *u8); sys_exit(2); return 2 } 32 let buf: *u8 = sys_mmap(KKC_CAP) 33 let fd: i64 = sys_openat_rd(argv[2] as *u8) 34 if fd < 0 { kc_e("ERROR: cannot open file\n" as *u8); sys_exit(1); return 1 } 35 let size: i64 = sys_lseek(fd, 0, 2) 36 sys_lseek(fd, 0, 0) 37 var want: i64 = size 38 if want > KKC_CAP { want = KKC_CAP } 39 var got: i64 = 0 40 var stop: i64 = 0 41 while stop == 0 { 42 if got >= want { stop = 1 } else { 43 let k: i64 = sys_read(fd, ((buf as i64) + got) as *u8, want - got) 44 if k <= 0 { stop = 1 } else { got = got + k } 45 } 46 } 47 sys_close(fd) 48 let facts: *i64 = sys_mmap(KK_N_SLOTS * 8) as *i64 49 // DIALECT AUTO-DETECT (2026-08-18): KK first (the incumbent contract), then AI Shoujo/HS2. 50 // dialect= is APPENDED LAST so every existing consumer of the KK line shape reads unchanged. 51 kk_probe(buf, got, size, facts) 52 var dialect: *u8 = "KK" as *u8 53 if facts[0] == 0 { 54 kk_probe_aishoujo(buf, got, size, facts) 55 if facts[0] == 1 { dialect = "AIS" as *u8 } 56 } 57 kc_w("KKFACT is_card=" as *u8); kc_num(facts[0]) 58 if facts[0] == 1 { 59 kc_w(" portrait_bytes=" as *u8); kc_num(facts[1]) 60 kc_w(" portrait_px=" as *u8); kc_num(facts[2]); kc_w("x" as *u8); kc_num(facts[3]) 61 kc_w(" payload_bytes=" as *u8); kc_num(facts[4]) 62 if facts[5] >= 0 { 63 kc_w(" custom=" as *u8); kc_num(facts[5]) 64 kc_w(" coordinate=" as *u8); kc_num(facts[6]) 65 kc_w(" parameter=" as *u8); kc_num(facts[7]) 66 kc_w(" status=" as *u8); kc_num(facts[8]) 67 kc_w(" kkex=" as *u8); kc_num(facts[9]) 68 } 69 kc_w(" dialect=" as *u8); kc_w(dialect) 70 } 71 kc_w("\n" as *u8) 72 if facts[0] == 0 { sys_exit(4); return 4 } 73 // decode verb: the kk_decode_sliders contract. Values go to the CALLER's stdout only -- 74 // per-card creative content never enters a published plane (the k-wall in the lib header). 75 if kc_eq(argv[1] as *u8, "decode" as *u8) == 1 { 76 let vals: *i64 = sys_mmap(KKD_MAX_VALS * 8) as *i64 77 let meta: *i64 = sys_mmap(16) as *i64 78 var ki: i64 = 0 79 while ki < 2 { 80 var key: *u8 = "shapeValueFace" as *u8 81 if ki == 1 { key = "shapeValueBody" as *u8 } 82 let parsed: i64 = kk_decode_sliders(buf, facts[1], got, key, vals, KKD_MAX_VALS, meta) 83 kc_w("KKDECODE key=" as *u8); kc_w(key) 84 kc_w(" declared=" as *u8); kc_num(meta[0]) 85 kc_w(" parsed=" as *u8); kc_num(parsed) 86 kc_w(" permil:" as *u8) 87 var vi: i64 = 0 88 while vi < parsed { if vi < KKD_MAX_VALS { kc_w(" " as *u8); kc_num(vals[vi]) } vi = vi + 1 } 89 kc_w("\n" as *u8) 90 ki = ki + 1 91 } 92 } 93 sys_exit(0) 94 return 0 95}