code wiki / _hdl_build / nx_browser_xp.nx

nx_browser_xp.nx source

↩ module page · 96 lines · 4751 B

1// nx_browser_xp.nx -- EXPERIENTIAL BROWSER TEST, reusable organ + MCP tool. Drives the REAL render core 2// (br_layout + br_draw_fb_at -- the SAME path every OS surface ships) through a human SCROLL session on any 3// staged page and RECORDS it as a browser-playable APNG MOVIE + a full-page shot. Proves render behavior the 4// way a human tester SEES it, no human needed -- the experiential-evidence capability, callable over MCP. 5// argv[1] = html file to load (default _offc/nxhtml.html) 6// argv[2] = output path prefix (default knowledge/status/xp) 7// Writes <prefix>_scroll.png (APNG, 12 frames top->bottom) + <prefix>_full.png (full-page RGB shot). 8// license_tier: ORIGINAL expect_exit: 0 9import "nx_browser_render.nx" 10import "nx_itoa_lib.nx" // shared MSB-first emitter (zero-alloc) 11import "nx_apng_write.nx" 12 13func xp_puts(s: *u8) -> i64 { var n: i64=0; while s[n]!=(0 as u8){n=n+1} sys_write(1,s,n); return 0 } 14// MIGRATED to the shared emitter (debt 1785563586). The old body mmapped a scratch buffer 15// per call and never freed it. At PAGE granularity that is 4096B leaked PER CALL -- the 16// defect that took 28.5GB of a 36GB host in nx_ts_lumadiff (2MB input, ~3.66M calls). 17// nxi_* is MSB-first, allocates NOTHING, and emits identical bytes including the sign. 18func xp_num(v: i64) -> i64 { nxi_out(v); return 0 } 19 20const XP_VW: i64 = 500 // viewport width in page px (scale 1 -> 500px-wide frames) 21const XP_VH: i64 = 400 // viewport height in page px 22const XP_NF: i64 = 12 // scroll frames top->bottom 23 24// render one scroll frame at scale 1 into rgb (XP_VW x XP_VH) 25func xp_frame(page: *Page, sy: i64, url: *u8, ulen: i64, rgb: *u8) -> i64 { 26 let fb: *Framebuffer = sys_mmap(NX_FRAMEBUFFER_BYTES) as *Framebuffer 27 let px: *u8 = sys_mmap(XP_VW*XP_VH*4 + 64) 28 nx_framebuffer_init(fb, px, XP_VW, XP_VH) 29 br_draw_fb_at(fb, page, XP_VW, url, ulen, 1, sy) 30 var p: i64 = 0 31 while p < XP_VW*XP_VH { rgb[p*3]=px[p*4]; rgb[p*3+1]=px[p*4+1]; rgb[p*3+2]=px[p*4+2]; p=p+1 } 32 return 0 33} 34// build "<prefix><suffix>" (both null-terminated) into out; returns len 35func xp_path(prefix: *u8, suffix: *u8, out: *u8) -> i64 { 36 var n: i64 = 0 37 while prefix[n]!=(0 as u8) { out[n]=prefix[n]; n=n+1 } 38 var j: i64 = 0 39 while suffix[j]!=(0 as u8) { out[n]=suffix[j]; n=n+1; j=j+1 } 40 out[n]=0 as u8 41 return n 42} 43 44func main(argc: i64, argv: *i64) -> i64 { 45 var htmlpath: *u8 = "_offc/nxhtml.html\x00" as *u8 46 if argc > 1 { htmlpath = argv[1] as *u8 } 47 var prefix: *u8 = "knowledge/status/xp\x00" as *u8 48 if argc > 2 { prefix = argv[2] as *u8 } 49 50 xp_puts("BROWSER-XP: experiential scroll session on " as *u8); xp_puts(htmlpath); xp_puts("\n" as *u8) 51 let lp: *i64 = sys_mmap(16) as *i64 52 let html: *u8 = sys_read_file(htmlpath, lp) 53 if lp[0] <= 0 { xp_puts("xp: cannot read html\n" as *u8); sys_exit(1); return 1 } 54 55 let page: *Page = sys_mmap(NX_PAGE_BYTES) as *Page 56 page.raw = html 57 page.raw_len = lp[0] 58 br_layout(page, XP_VW) 59 if page.ok != 1 { xp_puts("xp: layout failed\n" as *u8); sys_exit(2); return 2 } 60 xp_puts(" layout ok page_h=" as *u8); xp_num(page.page_h); xp_puts("\n" as *u8) 61 62 // ---- SCROLL MOVIE: XP_NF frames from top to bottom ---- 63 let sp: *u8 = sys_mmap(512) 64 xp_path(prefix, "_scroll.png\x00" as *u8, sp) 65 let rgb: *u8 = sys_mmap(XP_VW*XP_VH*3 + 64) 66 let st: *ApngState = sys_mmap(NX_APNG_STATE_BYTES) as *ApngState 67 apng_open(st, sp, XP_VW, XP_VH, XP_NF, 1, 4) 68 var maxsy: i64 = page.page_h - XP_VH 69 if maxsy < 0 { maxsy = 0 } 70 var f: i64 = 0 71 while f < XP_NF { 72 var sy: i64 = 0 73 if XP_NF > 1 { sy = (maxsy * f) / (XP_NF - 1) } 74 xp_frame(page, sy, "nishi://xp/scroll\x00" as *u8, 17, rgb) 75 apng_frame(st, rgb) 76 f = f + 1 77 } 78 apng_close(st) 79 xp_puts(" SCROLL MOVIE: " as *u8); xp_num(XP_NF); xp_puts(" frames -> " as *u8); xp_puts(sp); xp_puts("\n" as *u8) 80 81 // ---- FULL-PAGE SHOT (still) ---- 82 let fpp: *u8 = sys_mmap(512) 83 xp_path(prefix, "_full.png\x00" as *u8, fpp) 84 br_shot_png(page, "nishi://xp/full\x00" as *u8, 15, fpp) 85 xp_puts(" FULL SHOT -> " as *u8); xp_puts(fpp); xp_puts("\n" as *u8) 86 87 // ---- verify the movie landed + is animated (acTL chunk 'a''c' at bytes 37-38 after IHDR) ---- 88 let vp: *i64 = sys_mmap(16) as *i64 89 vp[0] = 0 - 1 90 let cb: *u8 = sys_read_file(sp, vp) 91 var ok: i64 = 0 92 if vp[0] > 50000 { if (cb[37] as i64)==97 { if (cb[38] as i64)==99 { ok=1 } } } 93 xp_puts("BROWSER-XP verdict=" as *u8) 94 if ok==1 { xp_puts("GREEN movie_bytes=" as *u8); xp_num(vp[0]); xp_puts("\n" as *u8); sys_exit(0); return 0 } 95 xp_puts("RED (movie missing / not animated)\n" as *u8); sys_exit(1); return 1 96}