code wiki / _hdl_build / nx_apng_write_gate.nx
nx_apng_write_gate.nx source
↩ module page · 144 lines · 8440 B
1// nx_apng_write_gate.nx -- gate for the sovereign APNG encoder. Writes a 4-frame moving-square clip,
2// reads the ON-DISK bytes back and verifies the structure a browser needs: PNG signature, acTL with the
3// right frame count, the fcTL/fdAT chain with the SPEC's shared sequence numbering (0,1,2,3,4,5 across
4// fcTL/IDAT/fcTL/fdAT...), CRC of the acTL chunk validates, and the frame PAYLOADS DIFFER (the square
5// really moves -- parsed out of the stored-zlib stream, not assumed). NEG: a plain nx_png_write PNG has
6// NO acTL (the animated check cannot false-fire on a still). expect_exit: 0 license_tier: ORIGINAL
7import "nx_apng_write.nx"
8import "nx_gate_verdict.nx"
9
10func ag_puts(s: *u8) -> i64 { var n: i64=0; while s[n]!=(0 as u8){n=n+1} sys_write(1,s,n); return 0 }
11func ag_num(v: i64) -> i64 { let b: *u8=sys_mmap(28); var m: i64=v; if m<0{m=0-m;sys_write(1,"-" as *u8,1)} let t: *u8=sys_mmap(28); var k: i64=0; if m==0{t[0]=48 as u8;k=1} while m>0{t[k]=(48+(m%10)) as u8;m=m/10;k=k+1} var i: i64=0; while i<k{b[i]=t[k-1-i];i=i+1} sys_write(1,b,k); return 0 }
12func ag_rd32(b: *u8, o: i64) -> i64 { return ((b[o] as i64)<<24)|((b[o+1] as i64)<<16)|((b[o+2] as i64)<<8)|(b[o+3] as i64) }
13func ag_typ(b: *u8, o: i64, t0: i64, t1: i64, t2: i64, t3: i64) -> i64 {
14 if (b[o] as i64)==t0 { if (b[o+1] as i64)==t1 { if (b[o+2] as i64)==t2 { if (b[o+3] as i64)==t3 { return 1 } } } }
15 return 0
16}
17
18func main() -> i64 {
19 ag_puts("APNG-WRITE gate: sovereign animated-PNG clips (the test-evidence video container)\n" as *u8)
20 let W: i64 = 64
21 let H: i64 = 48
22 let st: *ApngState = sys_mmap(NX_APNG_STATE_BYTES) as *ApngState
23 if apng_open(st, "knowledge/status/apng_demo.png\x00" as *u8, W, H, 4, 1, 4) < 0 { ag_puts("open fail\n" as *u8); sys_exit(1); return 1 }
24 let rgb: *u8 = sys_mmap(W*H*3 + 16)
25 var f: i64 = 0
26 while f < 4 {
27 var i: i64 = 0
28 while i < W*H { rgb[i*3]=240 as u8; rgb[i*3+1]=244 as u8; rgb[i*3+2]=248 as u8; i=i+1 }
29 var y: i64 = 12
30 while y < 36 { var x: i64 = 4 + f*14; while x < 4 + f*14 + 14 { let o: i64=(y*W+x)*3; rgb[o]=30 as u8; rgb[o+1]=90 as u8; rgb[o+2]=200 as u8; x=x+1 } y=y+1 }
31 apng_frame(st, rgb)
32 f = f + 1
33 }
34 apng_close(st)
35
36 // read back + chunk-walk
37 let lp: *i64 = sys_mmap(16) as *i64
38 lp[0] = 0 - 1
39 let b: *u8 = sys_read_file("knowledge/status/apng_demo.png\x00" as *u8, lp)
40 let n: i64 = lp[0]
41 var pass: i64=0
42 var ttl: i64=0
43 ttl=ttl+1; ag_puts(" T1 file written + PNG signature: " as *u8)
44 var sig_ok: i64=0
45 if n > 100 { if (b[0] as i64)==137 { if (b[1] as i64)==80 { sig_ok=1 } } }
46 if sig_ok==1 { pass=pass+1; ag_puts("PASS (" as *u8); ag_num(n); ag_puts("B)\n" as *u8) } else { ag_puts("FAIL\n" as *u8) }
47
48 var p: i64 = 8
49 var actl_frames: i64 = 0 - 1
50 var n_fctl: i64 = 0
51 var n_fdat: i64 = 0
52 var n_idat: i64 = 0
53 var seq_ok: i64 = 1
54 var expect_seq: i64 = 0
55 var actl_crc_ok: i64 = 0
56 var frame0_off: i64 = 0 - 1
57 var frame1_off: i64 = 0 - 1
58 while p + 12 <= n {
59 let clen: i64 = ag_rd32(b, p)
60 let to: i64 = p + 4
61 if ag_typ(b,to, 97,99,84,76)==1 { // acTL
62 actl_frames = ag_rd32(b, p+8)
63 var crc: i64 = pw_crc_block(0xFFFFFFFF, ((b as i64)+to) as *u8, 0, 4)
64 crc = pw_crc_block(crc, ((b as i64)+p+8) as *u8, 0, clen)
65 if (crc ^ 0xFFFFFFFF) == ag_rd32(b, p+8+clen) { actl_crc_ok = 1 }
66 }
67 if ag_typ(b,to, 102,99,84,76)==1 { // fcTL
68 n_fctl = n_fctl + 1
69 if ag_rd32(b, p+8) != expect_seq { seq_ok = 0 }
70 expect_seq = expect_seq + 1
71 }
72 if ag_typ(b,to, 73,68,65,84)==1 { // IDAT
73 n_idat = n_idat + 1
74 frame0_off = p + 8
75 }
76 if ag_typ(b,to, 102,100,65,84)==1 { // fdAT
77 n_fdat = n_fdat + 1
78 if ag_rd32(b, p+8) != expect_seq { seq_ok = 0 }
79 expect_seq = expect_seq + 1
80 if frame1_off < 0 { frame1_off = p + 12 } // payload after the 4-byte seq
81 }
82 p = p + 8 + clen + 4
83 }
84 ttl=ttl+1; ag_puts(" T2 acTL frames==4 + CRC validates: " as *u8)
85 if actl_frames==4 { if actl_crc_ok==1 { pass=pass+1; ag_puts("PASS\n" as *u8) } else { ag_puts("FAIL\n" as *u8) } } else { ag_puts("FAIL\n" as *u8) }
86 ttl=ttl+1; ag_puts(" T3 chunk chain: fcTL=4, IDAT=1, fdAT=3: " as *u8)
87 if n_fctl==4 { if n_idat==1 { if n_fdat==3 { pass=pass+1; ag_puts("PASS\n" as *u8) } else { ag_puts("FAIL\n" as *u8) } } else { ag_puts("FAIL\n" as *u8) } } else { ag_puts("FAIL\n" as *u8) }
88 ttl=ttl+1; ag_puts(" T4 shared fcTL/fdAT sequence numbering exact (0..6): " as *u8)
89 if seq_ok==1 { if expect_seq==7 { pass=pass+1; ag_puts("PASS\n" as *u8) } else { ag_puts("FAIL\n" as *u8) } } else { ag_puts("FAIL\n" as *u8) }
90 // frames really differ: compare the two stored-zlib payloads' data regions (skip 2B zlib hdr + 5B block hdr)
91 ttl=ttl+1; ag_puts(" T5 frame payloads DIFFER (the square moved): " as *u8)
92 var differ: i64 = 0
93 if frame0_off > 0 { if frame1_off > 0 {
94 // scan past the all-background top rows: the moving square lives at y>=12 (~byte 12*(1+W*3))
95 var k: i64 = 7
96 while k < 9000 { if b[frame0_off + k] != b[frame1_off + k] { differ = 1; k = 9000 } k = k + 1 }
97 } }
98 if differ==1 { pass=pass+1; ag_puts("PASS\n" as *u8) } else { ag_puts("FAIL\n" as *u8) }
99 // NEG: a still PNG has no acTL
100 nx_png_write_rgb("knowledge/status/apng_neg_still.png\x00" as *u8, rgb, W, H)
101 lp[0]=0-1
102 let s2: *u8 = sys_read_file("knowledge/status/apng_neg_still.png\x00" as *u8, lp)
103 let n2: i64 = lp[0]
104 var has_actl: i64 = 0
105 var q: i64 = 8
106 while q + 12 <= n2 { if ag_typ(s2,q+4, 97,99,84,76)==1 { has_actl=1 } q = q + 8 + ag_rd32(s2,q) + 4 }
107 ttl=ttl+1; ag_puts(" T6 NEG: a still PNG has NO acTL (animated check cannot false-fire): " as *u8)
108 if has_actl==0 { pass=pass+1; ag_puts("PASS\n" as *u8) } else { ag_puts("FAIL\n" as *u8) }
109
110 // ---- T7: STORED-DEFLATE LEN/NLEN COMPLEMENT (mutation-derived, debt 1785604588) ----
111 // nx_gate_mutation_probe scored this pair 3/4 with a survivor at nx_apng_write.nx:76 -- the write of
112 // the NLEN field of a zlib STORED block. In a stored deflate block the layout is
113 // [BFINAL/BTYPE:1][LEN:2 LE][NLEN:2 LE][raw LEN bytes]
114 // and the format REQUIRES NLEN == ~LEN. A real decoder rejects the stream when it does not.
115 // It survived because every existing tooth reads PNG CHUNK structure -- signature, acTL, the
116 // fcTL/fdAT chain, sequence numbers, a chunk CRC -- and then compares frame payload BYTES. All of
117 // that stays valid when NLEN is wrong: the chunks are still well-formed and the payload region is
118 // still where the gate looks. Only an actual inflate would notice.
119 // LAW: VALIDATING THE CONTAINER IS NOT VALIDATING THE STREAM INSIDE IT. A chunk-level check can be
120 // perfect while the compressed payload is undecodable, and "a browser would render this" is a claim
121 // about the STREAM, which this gate had never tested.
122 ttl=ttl+1; ag_puts(" T7 stored-deflate LEN/NLEN are one's complements (a decoder would accept): " as *u8)
123 var nlen_ok: i64 = 0
124 if frame0_off > 0 {
125 let hb: i64 = frame0_off + 2 // skip the 2-byte zlib header -> block header byte
126 if hb + 5 <= n {
127 let dlen: i64 = (b[hb+1] as i64) | ((b[hb+2] as i64) << 8)
128 let dnl: i64 = (b[hb+3] as i64) | ((b[hb+4] as i64) << 8)
129 if dnl == ((dlen ^ 0xFFFF) & 0xFFFF) { nlen_ok = 1 }
130 }
131 }
132 if nlen_ok==1 { pass=pass+1; ag_puts("PASS\n" as *u8) } else { ag_puts("FAIL\n" as *u8) }
133
134 ag_puts("APNG-WRITE-GATE passed " as *u8); ag_num(pass); ag_puts("/" as *u8); ag_num(ttl)
135 // MIGRATED onto nx_gate_verdict by nx_gate_dry_apply (D001, minimal form): every check
136 // row above is untouched, so the PASS/FAIL vector cannot change; only the hand-rolled
137 // verdict emission is replaced by the ONE shared base class. Proven by nx_gate_migrate verify.
138 let ctr__dry: *i64 = gv_ctr()
139 ctr__dry[0] = pass
140 ctr__dry[1] = ttl
141 let rc__dry: i64 = gv_verdict("APNG-WRITE-GATE" as *u8, ctr__dry, "open knowledge/status/apng_demo.png in a browser -- it MOVES)" as *u8)
142 sys_exit(rc__dry)
143 return rc__dry
144}