code wiki / _hdl_build / nx_frame_score.nx
nx_frame_score.nx source
↩ module page · 246 lines · 10633 B
1// nx_frame_score.nx -- score ANY captured frame with the hardened nx_game_critic, ONE ruler ONE scale.
2//
3// WHY (seq890/seq1004): the head-to-head vsbench contract says a Tier-3 EXT cell must be measured off a
4// captured artifact by OUR instrument -- but the organ that minted the first EXT cell existed in NO source
5// tree and was never registered, so the evidence path was not reproducible by any agent. This is that
6// organ rebuilt from the first byte as a REGISTERED MCP tool: OUR render and a REFERENCE render are graded
7// by the SAME deployed binary on the SAME scale, on the NAS, with the artifact on disk.
8//
9// INPUT FORMAT NXFH1 (text-hex framebuffer -- deliberately TEXT so it travels the fs-write lane safely;
10// raw binary through JSON-string tooling is the proven corruption path):
11// line 1: "NXFH1 <w> <h>\n" then w*h pixels as 6 lowercase hex chars each (rrggbb), any
12// whitespace between pixels ignored. Encoder: scratchpad/png2hex.js (same code path for BOTH sides).
13// USAGE: nx_frame_score <path.nxfh> | nx_frame_score selftest
14// Composes nx_game_critic (gc_score/gc_quality/gc_verdict) -- nothing re-implemented.
15// license_tier: ORIGINAL No hw writes (Rule 26). expect_exit: 0
16import "nx_syscalls.nx"
17import "nx_game_critic.nx"
18const FS_MAGIC_65536: i64 = 65536
19const FS_MAGIC_3600: i64 = 3600
20
21const FS_MAXW: i64 = 1024
22const FS_MAXH: i64 = 1024
23const FS_SELF_W: i64 = 400 // the canonical comparison scale (the Veloren-cell methodology)
24const FS_SELF_H: i64 = 240
25
26func ocat(o: *u8, at: i64, s: *u8) -> i64 { var i: i64=0; var a: i64=at; while s[i]!=(0 as u8){o[a]=s[i]; a=a+1; i=i+1} return a }
27func onum(o: *u8, at: i64, v: i64) -> i64 {
28 var a: i64=at; var m: i64=v
29 if m==0 { o[a]=48 as u8; return a+1 }
30 if m<0 { o[a]=45 as u8; a=a+1; m=0-m }
31 let t: *u8 = sys_mmap(32); var k: i64=0
32 while m>0 { t[k]=(48+(m%10)) as u8; m=m/10; k=k+1 }
33 var q: i64=k-1
34 while q>=0 { o[a]=t[q]; a=a+1; q=q-1 }
35 return a
36}
37func emit(o: *u8, n: i64) -> i64 { sys_write(1, o, n); return 0 }
38
39// hex nibble -> value; -1 on a non-hex byte
40func fs_nib(c: i64) -> i64 {
41 if c >= 48 { if c <= 57 { return c - 48 } }
42 if c >= 97 { if c <= 102 { return c - 87 } }
43 if c >= 65 { if c <= 70 { return c - 55 } }
44 return 0-1
45}
46func fs_isws(c: i64) -> i64 { if c==32 { return 1 } if c==10 { return 1 } if c==13 { return 1 } if c==9 { return 1 } return 0 }
47
48// parse an ascii integer at buf[p..], stop at non-digit; returns value, writes end pos to pp[0]
49func fs_int(b: *u8, p: i64, n: i64, pp: *i64) -> i64 {
50 var v: i64 = 0
51 var i: i64 = p
52 while i < n {
53 let c: i64 = b[i] as i64
54 if c < 48 { pp[0]=i; return v }
55 if c > 57 { pp[0]=i; return v }
56 v = v*10 + (c-48)
57 i = i + 1
58 }
59 pp[0]=i
60 return v
61}
62
63// Load an NXFH1 file into a freshly mmapped packed fb (r | g<<8 | b<<16, the critic's layout).
64// On success writes w,h to whp[0],whp[1] and returns the fb ptr; on any malformation returns 0 --
65// a truncated or corrupt capture must be REFUSED loudly, never scored as a dark frame.
66func fs_load(path: *u8, whp: *i64) -> *i64 {
67 let lenp: *i64 = sys_mmap(8) as *i64
68 lenp[0]=0
69 let b: *u8 = sys_read_file(path, lenp)
70 if (b as i64)==0 { return 0 as *i64 }
71 let n: i64 = lenp[0]
72 if n < 12 { return 0 as *i64 }
73 // magic "NXFH1 "
74 if b[0]!=(78 as u8) { return 0 as *i64 }
75 if b[1]!=(88 as u8) { return 0 as *i64 }
76 if b[2]!=(70 as u8) { return 0 as *i64 }
77 if b[3]!=(72 as u8) { return 0 as *i64 }
78 if b[4]!=(49 as u8) { return 0 as *i64 }
79 let pp: *i64 = sys_mmap(8) as *i64
80 var p: i64 = 5
81 while p < n { if fs_isws(b[p] as i64)==1 { p=p+1 } else { p = n + p; } }
82 p = p - n // first non-ws after magic
83 let w: i64 = fs_int(b, p, n, pp)
84 p = pp[0]
85 while p < n { if fs_isws(b[p] as i64)==1 { p=p+1 } else { p = n + p; } }
86 p = p - n
87 let h: i64 = fs_int(b, p, n, pp)
88 p = pp[0]
89 if w < 8 { return 0 as *i64 }
90 if h < 8 { return 0 as *i64 }
91 if w > FS_MAXW { return 0 as *i64 }
92 if h > FS_MAXH { return 0 as *i64 }
93 let need: i64 = w*h
94 let fb: *i64 = sys_mmap(need*8) as *i64
95 var px: i64 = 0
96 var acc: i64 = 0
97 var nyb: i64 = 0
98 while p < n {
99 let c: i64 = b[p] as i64
100 if fs_isws(c)==0 {
101 let v: i64 = fs_nib(c)
102 if v < 0 { return 0 as *i64 } // junk byte = REFUSE, not "score what parsed"
103 acc = acc*16 + v
104 nyb = nyb + 1
105 if nyb == 6 {
106 if px >= need { return 0 as *i64 } // more pixels than declared = REFUSE
107 // hex is rrggbb; critic wants r | g<<8 | b<<16
108 let r: i64 = (acc / FS_MAGIC_65536) % 256
109 let g: i64 = (acc / 256) % 256
110 let bb: i64 = acc % 256
111 fb[px] = r + g*256 + bb*FS_MAGIC_65536
112 px = px + 1
113 acc = 0
114 nyb = 0
115 }
116 }
117 p = p + 1
118 }
119 if px != need { return 0 as *i64 } // short capture = REFUSE
120 if nyb != 0 { return 0 as *i64 }
121 whp[0]=w
122 whp[1]=h
123 return fb
124}
125
126// score a packed fb and emit the JSON row
127func fs_report(fb: *i64, w: i64, h: i64, label: *u8) -> i64 {
128 let m: *i64 = sys_mmap(GC_N*8) as *i64
129 gc_score(fb, w, h, m)
130 let q: i64 = gc_quality(m)
131 let jb: *u8 = sys_mmap(GC_MAGIC_4096)
132 var j: i64 = 0
133 j = ocat(jb, j, "{\x22organ\x22:\x22nx_frame_score\x22,\x22src\x22:\x22" as *u8)
134 j = ocat(jb, j, label)
135 j = ocat(jb, j, "\x22,\x22w\x22:" as *u8); j = onum(jb, j, w)
136 j = ocat(jb, j, ",\x22h\x22:" as *u8); j = onum(jb, j, h)
137 j = ocat(jb, j, ",\x22pal\x22:" as *u8); j = onum(jb, j, m[GC_M_PAL])
138 j = ocat(jb, j, ",\x22det1\x22:" as *u8); j = onum(jb, j, m[GC_M_DET1])
139 j = ocat(jb, j, ",\x22det4\x22:" as *u8); j = onum(jb, j, m[GC_M_DET4])
140 j = ocat(jb, j, ",\x22grad\x22:" as *u8); j = onum(jb, j, m[GC_M_GRAD])
141 j = ocat(jb, j, ",\x22cov\x22:" as *u8); j = onum(jb, j, m[GC_M_COV])
142 j = ocat(jb, j, ",\x22cohere\x22:" as *u8); j = onum(jb, j, m[GC_M_COHERE])
143 j = ocat(jb, j, ",\x22quality\x22:" as *u8); j = onum(jb, j, q)
144 j = ocat(jb, j, ",\x22verdict\x22:\x22" as *u8); j = ocat(jb, j, gc_verdict(q))
145 j = ocat(jb, j, "\x22,\x22ruler\x22:\x22hardened nx_game_critic (coherence-capped, red-teamed vs noise); one code path for OURS and THEIRS\x22}" as *u8)
146 jb[j]=10 as u8
147 emit(jb, j+1)
148 return q
149}
150
151// deterministic synthetic frames for selftest -- a flat TOY scene and a gradient RICH scene.
152func fs_mk_toy(fb: *i64, w: i64, h: i64) -> i64 {
153 var i: i64 = 0
154 while i < w*h { fb[i] = 16 + 18*256 + 28*FS_MAGIC_65536; i=i+1 }
155 // three flat discs (the shipped-game failure mode the critic was hardened against)
156 var y: i64 = 0
157 while y < h {
158 var x: i64 = 0
159 while x < w {
160 var k: i64 = 0
161 while k < 3 {
162 let cx: i64 = (w/4)*(k+1)
163 let cy: i64 = h/2
164 let dx: i64 = x-cx
165 let dy: i64 = y-cy
166 if dx*dx + dy*dy < 900 { fb[y*w+x] = 90 + 60*256 + 40*FS_MAGIC_65536 }
167 k = k + 1
168 }
169 x = x + 1
170 }
171 y = y + 1
172 }
173 return 0
174}
175func fs_mk_rich(fb: *i64, w: i64, h: i64) -> i64 {
176 var y: i64 = 0
177 while y < h {
178 var x: i64 = 0
179 while x < w {
180 // smooth two-axis gradient bg (coherent by construction) + varied palette banding
181 let r: i64 = (x*255)/w
182 let g: i64 = (y*255)/h
183 let b: i64 = ((x+y)*255)/(w+h)
184 var v: i64 = r + g*256 + b*FS_MAGIC_65536
185 // structured detail: soft diagonal bands + a lit sphere
186 if ((x/24)+(y/24))%2==0 { v = (r*3/4) + (g*3/4)*256 + (b*3/4)*FS_MAGIC_65536 }
187 let dx: i64 = x - w/2
188 let dy: i64 = y - h/2
189 let d2: i64 = dx*dx + dy*dy
190 if d2 < FS_MAGIC_3600 {
191 let lum: i64 = 255 - (d2*220)/FS_MAGIC_3600
192 v = lum + ((lum*3/4))*256 + ((lum/2))*FS_MAGIC_65536
193 }
194 fb[y*w+x] = v
195 x = x + 1
196 }
197 y = y + 1
198 }
199 return 0
200}
201
202func main(argc: i64, argv: *i64) -> i64 {
203 if argc < 2 {
204 let e: *u8 = "{\x22organ\x22:\x22nx_frame_score\x22,\x22error\x22:\x22usage: nx_frame_score <path.nxfh> | selftest\x22,\x22fix\x22:\x22pass an NXFH1 text-hex frame (scratchpad/png2hex.js emits it) or run selftest\x22}\n" as *u8
205 var n: i64=0
206 while e[n]!=(0 as u8) { n=n+1 }
207 emit(e, n)
208 return 2
209 }
210 let a1: *u8 = argv[1] as *u8
211 // selftest: generate, score, and REQUIRE the toy<rich margin -- verify-by-behavior with no upload
212 if a1[0]==(115 as u8) {
213 if a1[1]==(101 as u8) {
214 let fb1: *i64 = sys_mmap(FS_SELF_W*FS_SELF_H*8) as *i64
215 let fb2: *i64 = sys_mmap(FS_SELF_W*FS_SELF_H*8) as *i64
216 fs_mk_toy(fb1, FS_SELF_W, FS_SELF_H)
217 fs_mk_rich(fb2, FS_SELF_W, FS_SELF_H)
218 let qt: i64 = fs_report(fb1, FS_SELF_W, FS_SELF_H, "selftest-toy" as *u8)
219 let qr: i64 = fs_report(fb2, FS_SELF_W, FS_SELF_H, "selftest-rich" as *u8)
220 let jb: *u8 = sys_mmap(512)
221 var j: i64 = 0
222 j = ocat(jb, j, "{\x22selftest\x22:\x22" as *u8)
223 if qr > qt { if qr - qt >= 250 { j = ocat(jb, j, "PASS" as *u8) } }
224 if qr - qt < 250 { j = ocat(jb, j, "FAIL" as *u8) }
225 j = ocat(jb, j, "\x22,\x22toy\x22:" as *u8); j = onum(jb, j, qt)
226 j = ocat(jb, j, ",\x22rich\x22:" as *u8); j = onum(jb, j, qr)
227 j = ocat(jb, j, ",\x22margin\x22:" as *u8); j = onum(jb, j, qr-qt)
228 j = ocat(jb, j, ",\x22note\x22:\x22a critic that cannot separate a flat toy from a structured scene is not a critic\x22}" as *u8)
229 jb[j]=10 as u8
230 emit(jb, j+1)
231 if qr - qt < 250 { return 1 }
232 return 0
233 }
234 }
235 let whp: *i64 = sys_mmap(16) as *i64
236 let fb: *i64 = fs_load(a1, whp)
237 if (fb as i64)==0 {
238 let e2: *u8 = "{\x22organ\x22:\x22nx_frame_score\x22,\x22error\x22:\x22REFUSED: not a well-formed NXFH1 frame (missing, bad magic, junk bytes, or pixel count != w*h)\x22,\x22fix\x22:\x22re-encode with scratchpad/png2hex.js; a truncated capture must never be scored as a dark frame\x22}\n" as *u8
239 var n2: i64=0
240 while e2[n2]!=(0 as u8) { n2=n2+1 }
241 emit(e2, n2)
242 return 3
243 }
244 fs_report(fb, whp[0], whp[1], a1)
245 return 0
246}