code wiki / _hdl_build / nx_gx1c_canvas_gate.nx
nx_gx1c_canvas_gate.nx source
↩ module page · 143 lines · 8855 B
1// nx_gx1c_canvas_gate.nx -- Gx-1c (seq103 EAT-BY-BUILD): <canvas> = a FIRST-CLASS sourceless render surface
2// in the LIVE Nishi-Browser + the PER-FRAME loop = the sovereign GAME SUBSTRATE. A fetched page DECLARES
3// <canvas>; br_layout gives it a real CSS-sized box in flow (page.bcanvas + br_find_canvas); the game loop
4// then drives frames: update world state (yaw) -> render the REAL nx_swgpu mesh pipeline (sg_humanoid +
5// sg_project + sg_render -- the seq103 DRY fold, NO inline rasterizer in this gate) -> point page.bimg at the
6// fresh buffer -> the browser repaints the whole page. Frame time MEASURED (mono clock, envelope declared).
7// Neg-control: a page WITHOUT <canvas> finds none. license_tier: ORIGINAL expect_exit: 0
8import "nx_browser_render.nx"
9import "nx_swgpu.nx"
10
11func gxc_puts(s: *u8) -> i64 { var n: i64=0; while s[n]!=(0 as u8){n=n+1} sys_write(1,s,n); return 0 }
12func gxc_pn(v: i64) -> i64 { let b: *u8=sys_mmap(32) as *u8; var x: i64=v; var ng: i64=0; if x<0{ng=1;x=0-x} var i: i64=31; if x==0{b[i]=48 as u8;i=i-1} while x>0{b[i]=(48+x%10) as u8;x=x/10;i=i-1} if ng==1{b[i]=45 as u8;i=i-1} sys_write(1,(b as i64+i+1) as *u8,31-i); return 0 }
13func gxc_now_ms() -> i64 { let ts: *i64=sys_mmap(16) as *i64; sys_clock_gettime_mono(ts); return ts[0]*1000 + ts[1]/1000000 }
14
15// swgpu i64 framebuffer (r + g*256 + b*65536) -> tightly packed RGB bytes
16func gxc_fb_to_rgb(base: i64, dst: *u8) -> i64 {
17 let fb: *i64 = sg_fb(base)
18 var p: i64 = 0
19 while p < ww()*hh() {
20 let v: i64 = fb[p]
21 dst[p*3] = (v % 256) as u8
22 dst[p*3+1] = ((v/256) % 256) as u8
23 dst[p*3+2] = ((v/65536) % 256) as u8
24 p = p + 1
25 }
26 return 0
27}
28
29func main() -> i64 {
30 gxc_puts("=== nx_gx1c_canvas_gate -- <canvas> surface + per-frame loop = the sovereign game substrate ===\n" as *u8)
31 var fails: i64=0
32
33 // ---- T0 NEG-CONTROL: a page with NO canvas finds none ----
34 let h0: *u8 = "<html><body><h1>plain</h1><p>no render surface on this page</p></body></html>\x00" as *u8
35 let p0: *Page = sys_mmap(NX_PAGE_BYTES) as *Page
36 p0.raw = h0; p0.raw_len = br_slen(h0); p0.dark_mode = 0
37 br_layout(p0, 1000)
38 if br_find_canvas(p0, 0) == (0-1) { gxc_puts("T0 PASS neg-control: canvas-less page finds no canvas box\n" as *u8) }
39 else { fails=fails+1; gxc_puts("T0 FAIL neg-control\n" as *u8) }
40
41 // ---- the GAME page: heading + copy + <canvas> + copy, canvas sized by author CSS ----
42 let html: *u8 = "<html><head><style>canvas{display:block;width:512px;height:384px;margin:18px 0}</style></head><body><h1>Sovereign Game Surface</h1><p>This page is fetched, parsed, and laid out by our own browser engine. The canvas below is a first-class sourceless render surface: each frame the sovereign software GPU renders the world state and the browser repaints it in place.</p><canvas></canvas><p>No WebGPU. No WebGL. No third-party. The game loop is ours from the first byte.</p></body></html>\x00" as *u8
43 let page: *Page = sys_mmap(NX_PAGE_BYTES) as *Page
44 page.raw = html; page.raw_len = br_slen(html); page.dark_mode = 0
45 br_layout(page, 1000)
46 var t1: i64=0
47 if page.ok==1 { if page.tree.count>5 { t1=1 } }
48 gxc_puts(" layout boxes="); gxc_pn(page.tree.count); gxc_puts(" page_h="); gxc_pn(page.page_h); gxc_puts("\n" as *u8)
49 if t1==1 { gxc_puts("T1 PASS the live engine laid out the game page\n" as *u8) } else { fails=fails+1; gxc_puts("T1 FAIL layout\n" as *u8) }
50
51 // ---- T2 the <canvas> element became a REAL laid-out box ----
52 let cv: i64 = br_find_canvas(page, 0)
53 var cvx: i64=0; var cvy: i64=0
54 if cv>=0 {
55 let cb: *LayoutBox = ((page.tree.boxes as i64)+cv*NX_LAYOUT_BOX_BYTES) as *LayoutBox
56 cvx=cb.x; cvy=cb.y
57 }
58 gxc_puts(" canvas box idx="); gxc_pn(cv); gxc_puts(" at x="); gxc_pn(cvx); gxc_puts(" y="); gxc_pn(cvy); gxc_puts("\n" as *u8)
59 if cv>=0 { gxc_puts("T2 PASS <canvas> is a first-class laid-out box (page.bcanvas)\n" as *u8) } else { fails=fails+1; gxc_puts("T2 FAIL no canvas box\n" as *u8) }
60
61 // ---- T3 FLOW: the canvas sits BELOW the heading (a real in-flow box, not an overlay) ----
62 var t3: i64=0
63 if cv>=0 { if cvy>40 { t3=1 } }
64 if t3==1 { gxc_puts("T3 PASS canvas is in flow below the heading (y="); gxc_pn(cvy); gxc_puts(")\n" as *u8) } else { fails=fails+1; gxc_puts("T3 FAIL canvas y="); gxc_pn(cvy); gxc_puts("\n" as *u8) }
65
66 // ---- the GAME LOOP: 4 frames, world state = yaw; render = the REAL nx_swgpu pipeline ----
67 let base: i64 = sys_mmap(swgpu_bytes()) as i64
68 let f0: *u8 = sys_mmap(ww()*hh()*3+16)
69 let fc: *u8 = sys_mmap(ww()*hh()*3+16)
70 let t_start: i64 = gxc_now_ms()
71 var f: i64=0
72 while f<4 {
73 let yaw: i64 = 500 + f*1600
74 sg_reset(base)
75 sg_humanoid(base, 14)
76 sg_project(base, yaw, 0-5)
77 sg_render(base, 240, 182, 158)
78 var dst: *u8 = fc
79 if f==0 { dst = f0 }
80 gxc_fb_to_rgb(base, dst)
81 if cv>=0 { page.bimg[cv] = dst as i64; page.bimg_w[cv] = ww(); page.bimg_h[cv] = hh() }
82 if f==0 { br_shot_png(page, "https://nishifamily.com/world/game\x00" as *u8, 34, "knowledge/nx_gx1c_f0.png\x00" as *u8) }
83 if f==1 { br_shot_png(page, "https://nishifamily.com/world/game\x00" as *u8, 34, "knowledge/nx_gx1c_f1.png\x00" as *u8) }
84 if f==2 { br_shot_png(page, "https://nishifamily.com/world/game\x00" as *u8, 34, "knowledge/nx_gx1c_f2.png\x00" as *u8) }
85 if f==3 { br_shot_png(page, "https://nishifamily.com/world/game\x00" as *u8, 34, "knowledge/nx_gx1c_f3.png\x00" as *u8) }
86 f=f+1
87 }
88 let ms_total: i64 = gxc_now_ms() - t_start
89 gxc_puts(" MEASURED: 4 frames in "); gxc_pn(ms_total); gxc_puts(" ms = "); gxc_pn(ms_total/4)
90 gxc_puts(" ms/frame (envelope: swgpu 512x384 mesh render + FULL 1000x1000 browser repaint + PNG encode per frame)\n" as *u8)
91
92 // ---- T4 the swgpu rendered a real BODY into frame 0 (pixels off the analytic background gradient) ----
93 var bodypx: i64=0
94 var pi: i64=0
95 while pi < ww()*hh() {
96 let row: i64 = pi / ww()
97 let bgr: i64 = 26 + row*36/hh()
98 let bgg: i64 = 28 + row*34/hh()
99 let bgb: i64 = 42 + row*30/hh()
100 var d1: i64 = (f0[pi*3] as i64) - bgr; if d1<0 { d1=0-d1 }
101 var d2: i64 = (f0[pi*3+1] as i64) - bgg; if d2<0 { d2=0-d2 }
102 var d3: i64 = (f0[pi*3+2] as i64) - bgb; if d3<0 { d3=0-d3 }
103 if d1+d2+d3 > 40 { bodypx=bodypx+1 }
104 pi = pi + 7
105 }
106 var t4: i64=0
107 if bodypx>1500 { t4=1 }
108 gxc_puts(" body pixels (sampled/7)="); gxc_pn(bodypx); gxc_puts("\n" as *u8)
109 if t4==1 { gxc_puts("T4 PASS nx_swgpu rendered the world into the canvas (DRY: sg_humanoid+sg_project+sg_render)\n" as *u8) } else { fails=fails+1; gxc_puts("T4 FAIL bodypx="); gxc_pn(bodypx); gxc_puts("\n" as *u8) }
110
111 // ---- T5 ANIMATION IS REAL: frame 3 differs from frame 0 (the world state advanced) ----
112 var diffpx: i64=0
113 pi=0
114 while pi < ww()*hh() {
115 var e1: i64 = (f0[pi*3] as i64) - (fc[pi*3] as i64); if e1<0 { e1=0-e1 }
116 var e2: i64 = (f0[pi*3+1] as i64) - (fc[pi*3+1] as i64); if e2<0 { e2=0-e2 }
117 var e3: i64 = (f0[pi*3+2] as i64) - (fc[pi*3+2] as i64); if e3<0 { e3=0-e3 }
118 if e1+e2+e3 > 30 { diffpx=diffpx+1 }
119 pi = pi + 7
120 }
121 var t5: i64=0
122 if diffpx>400 { t5=1 }
123 gxc_puts(" frame0 vs frame3 changed pixels (sampled/7)="); gxc_pn(diffpx); gxc_puts("\n" as *u8)
124 if t5==1 { gxc_puts("T5 PASS per-frame loop animates: the yaw state advanced and the surface changed\n" as *u8) } else { fails=fails+1; gxc_puts("T5 FAIL diffpx="); gxc_pn(diffpx); gxc_puts("\n" as *u8) }
125
126 // ---- T6 all 4 browser-painted frames are on disk ----
127 let szp: *i64 = sys_mmap(16) as *i64
128 var okpng: i64=0
129 let r0: *u8 = sys_read_file("knowledge/nx_gx1c_f0.png\x00" as *u8, szp)
130 if (r0 as i64)!=0 { if szp[0]>1000 { okpng=okpng+1 } }
131 let r1: *u8 = sys_read_file("knowledge/nx_gx1c_f1.png\x00" as *u8, szp)
132 if (r1 as i64)!=0 { if szp[0]>1000 { okpng=okpng+1 } }
133 let r2: *u8 = sys_read_file("knowledge/nx_gx1c_f2.png\x00" as *u8, szp)
134 if (r2 as i64)!=0 { if szp[0]>1000 { okpng=okpng+1 } }
135 let r3: *u8 = sys_read_file("knowledge/nx_gx1c_f3.png\x00" as *u8, szp)
136 if (r3 as i64)!=0 { if szp[0]>1000 { okpng=okpng+1 } }
137 if okpng==4 { gxc_puts("T6 PASS all 4 browser-painted frames on disk (knowledge/nx_gx1c_f0..f3.png)\n" as *u8) } else { fails=fails+1; gxc_puts("T6 FAIL frames on disk="); gxc_pn(okpng); gxc_puts("\n" as *u8) }
138
139 if fails==0 { gxc_puts("GX1C-CANVAS GREEN -- <canvas> is a first-class surface in the live browser and the per-frame sovereign game loop runs through it (zero 3rd-party)\n" as *u8); sys_exit(0); return 0 }
140 gxc_puts("GX1C-CANVAS RED fails="); gxc_pn(fails); gxc_puts("\n" as *u8)
141 sys_exit(1)
142 return 1
143}