code wiki / _hdl_build / nx_adnet_banner_gen.nx
nx_adnet_banner_gen.nx source
↩ module page · 170 lines · 7112 B
1// nx_adnet_banner_gen.nx -- GENERATOR: sovereign 728x90 house-ad PNG creatives for the adnet slot
2// (build generators, not hand-authored artifacts). Pure pixels: vertical gradient + accent frame +
3// centered scaled 8x8 sovereign font text -> nx_png_write_rgb. Self-verifying: each emitted file is
4// read back and must carry the PNG magic + plausible size, else exit 1 (no fabricated greens).
5// Output: knowledge/staging/adnet/adnet_ha_{torrent,library,video,world}.png
6// expect_exit: 0 license_tier: ORIGINAL
7import "nx_syscalls.nx"
8import "nx_png_write.nx"
9import "nx_png.nx"
10import "nx_font8x8.nx"
11const ABG_MAGIC_65536: i64 = 65536
12
13const ABG_W: i64 = 728
14const ABG_H: i64 = 90
15
16func abg_px(buf: *u8, x: i64, y: i64, r: i64, g: i64, b: i64) -> i64 {
17 if x < 0 { return 0 }
18 if y < 0 { return 0 }
19 if x >= ABG_W { return 0 }
20 if y >= ABG_H { return 0 }
21 let off: i64 = (y * ABG_W + x) * 3
22 buf[off] = r as u8
23 buf[off + 1] = g as u8
24 buf[off + 2] = b as u8
25 return 0
26}
27
28// vertical gradient background: top color -> ~55 percent at bottom, plus a 3px accent frame.
29func abg_bg(buf: *u8, r: i64, g: i64, b: i64, ar: i64, ag: i64, ab: i64) -> i64 {
30 var y: i64 = 0
31 while y < ABG_H {
32 let kr: i64 = r - (((r * 45) / 100) * y) / ABG_H
33 let kg: i64 = g - (((g * 45) / 100) * y) / ABG_H
34 let kb: i64 = b - (((b * 45) / 100) * y) / ABG_H
35 var x: i64 = 0
36 while x < ABG_W {
37 abg_px(buf, x, y, kr, kg, kb)
38 x = x + 1
39 }
40 y = y + 1
41 }
42 var i: i64 = 0
43 while i < 3 {
44 var x2: i64 = 0
45 while x2 < ABG_W {
46 abg_px(buf, x2, i, ar, ag, ab)
47 abg_px(buf, x2, ABG_H - 1 - i, ar, ag, ab)
48 x2 = x2 + 1
49 }
50 var y2: i64 = 0
51 while y2 < ABG_H {
52 abg_px(buf, i, y2, ar, ag, ab)
53 abg_px(buf, ABG_W - 1 - i, y2, ar, ag, ab)
54 y2 = y2 + 1
55 }
56 i = i + 1
57 }
58 return 0
59}
60
61// draw text at scale s, top-left (ox,oy), color (r,g,b). 8x8 glyphs, LSB = leftmost column.
62func abg_text(buf: *u8, t: *u8, text: *u8, ox: i64, oy: i64, s: i64, r: i64, g: i64, b: i64) -> i64 {
63 var i: i64 = 0
64 var cx: i64 = ox
65 while text[i] != (0 as u8) {
66 let ch: i64 = text[i] as i64
67 if ch >= 32 {
68 if ch <= 126 {
69 let gi: i64 = (ch - 32) * 8
70 var row: i64 = 0
71 while row < 8 {
72 let gb: i64 = t[gi + row] as i64
73 var col: i64 = 0
74 while col < 8 {
75 let bit: i64 = (gb >> col) & 1
76 if bit == 1 {
77 var sy: i64 = 0
78 while sy < s {
79 var sx: i64 = 0
80 let py: i64 = oy + row * s + sy
81 while sx < s {
82 let px2: i64 = cx + col * s + sx
83 abg_px(buf, px2, py, r, g, b)
84 sx = sx + 1
85 }
86 sy = sy + 1
87 }
88 }
89 col = col + 1
90 }
91 row = row + 1
92 }
93 }
94 }
95 cx = cx + 8 * s
96 i = i + 1
97 }
98 return 0
99}
100
101func abg_tlen(s: *u8) -> i64 { var n: i64 = 0; while s[n] != (0 as u8) { n = n + 1 } return n }
102
103// compose + write one banner; verify PNG magic on read-back. 1 = verified on disk.
104func abg_emit(path: *u8, title: *u8, sub: *u8, r: i64, g: i64, b: i64, ar: i64, ag: i64, ab: i64) -> i64 {
105 let buf: *u8 = sys_mmap(ABG_W * ABG_H * 3)
106 abg_bg(buf, r, g, b, ar, ag, ab)
107 let t: *u8 = font8x8_table()
108 let tl: i64 = abg_tlen(title)
109 let tw: i64 = tl * 8 * 3
110 var tox: i64 = (ABG_W - tw) / 2
111 if tox < 8 { tox = 8 }
112 abg_text(buf, t, title, tox, 14, 3, 255, 255, 255)
113 let sl: i64 = abg_tlen(sub)
114 let sw: i64 = sl * 8 * 2
115 var sox: i64 = (ABG_W - sw) / 2
116 if sox < 8 { sox = 8 }
117 abg_text(buf, t, sub, sox, 52, 2, 235, 235, 235)
118 // ROOT FIX (2026-07-31): this generator imported nx_png_write.nx, whose OWN HEADER says it emits
119 // "zlib STORED blocks (no compression -- a real DEFLATE pass is a perf rung)". That is why all four
120 // banners were EXACTLY 196733 bytes regardless of artwork: content-independent size is the signature
121 // of no compression. nx_png.nx gained REAL DEFLATE (LZ77 + fixed Huffman) on 2026-07-04 -- TWO PNG
122 // WRITERS EXIST AND ONLY ONE WAS UPGRADED, and this generator was importing the other one.
123 // Repacking to nx_png's framebuffer contract (R + G*256 + B*65536) costs one pass over 65,520 pixels
124 // and cuts the wire weight of a creative that ships on EVERY served page.
125 // NOT FORKED SILENTLY: the chokepoint fix -- giving nx_png_write.nx the same DEFLATE pass so its
126 // OTHER callers stop shipping uncompressed images -- is filed as debt for that lib's owner.
127 let fb: *i64 = (sys_mmap(ABG_W * ABG_H * 8)) as *i64
128 var py: i64 = 0
129 while py < ABG_H {
130 var px: i64 = 0
131 while px < ABG_W {
132 let o3: i64 = (py * ABG_W + px) * 3
133 fb[py * ABG_W + px] = (buf[o3] as i64) + ((buf[o3 + 1] as i64) * 256) + ((buf[o3 + 2] as i64) * ABG_MAGIC_65536)
134 px = px + 1
135 }
136 py = py + 1
137 }
138 let wr: i64 = write_png(fb, ABG_W, ABG_H, path)
139 if wr != 0 { return 0 }
140 let box: *i64 = (sys_mmap(8)) as *i64
141 box[0] = 0
142 let back: *u8 = sys_read_file(path, box)
143 if (back as i64) == 0 { return 0 }
144 if box[0] < 1000 { return 0 }
145 if (back[0] as i64) != 137 { return 0 }
146 if (back[1] as i64) != 80 { return 0 }
147 if (back[2] as i64) != 78 { return 0 }
148 if (back[3] as i64) != 71 { return 0 }
149 return 1
150}
151
152func abg_puts(s: *u8) -> i64 { var n: i64 = 0; while s[n] != (0 as u8) { n = n + 1 } sys_write(1, s, n); return 0 }
153
154func main() -> i64 {
155 sys_mkdir("knowledge/staging/adnet" as *u8, 0x1ED)
156 var ok: i64 = 0
157 ok = ok + abg_emit("knowledge/staging/adnet/adnet_ha_torrent.png" as *u8, "NISHI TORRENT" as *u8, "SHARE THE FAMILY SWARM" as *u8, 26, 54, 118, 90, 150, 235)
158 ok = ok + abg_emit("knowledge/staging/adnet/adnet_ha_library.png" as *u8, "NISHI LIBRARY" as *u8, "SHARED FAMILY READING" as *u8, 116, 70, 22, 230, 175, 85)
159 ok = ok + abg_emit("knowledge/staging/adnet/adnet_ha_video.png" as *u8, "NISHI VIDEO" as *u8, "FAMILY FILMS AND CIRCLES" as *u8, 108, 26, 38, 230, 120, 130)
160 ok = ok + abg_emit("knowledge/staging/adnet/adnet_ha_world.png" as *u8, "NISHI WORLD" as *u8, "A LIVING GENERATED WORLD" as *u8, 24, 88, 52, 110, 210, 150)
161 abg_puts("banners emitted+verified: " as *u8)
162 let d: *u8 = sys_mmap(8)
163 d[0] = (48 + ok) as u8
164 sys_write(1, d, 1)
165 abg_puts(" / 4\n" as *u8)
166 if ok == 4 { abg_puts("ADNET-BANNER-GEN verdict=GREEN\n" as *u8); sys_exit(0); return 0 }
167 abg_puts("ADNET-BANNER-GEN verdict=RED\n" as *u8)
168 sys_exit(1)
169 return 1
170}