code wiki / _hdl_build / nx_nishios_browser.nx

nx_nishios_browser.nx source

↩ module page · 351 lines · 21901 B

1// nx_nishios_browser.nx -- BROWSER-ON-ALL-OS arc, rung N1: the Nishi browser renders ON NishiOS. 2// 3// Operator (2026-07-02): "finish getting our nishi browser to s class exceed on all OSs including our 4// future nishi os." The browser already runs on Linux (nx_browser, X11/WSLg) and native Windows 5// (nishi.exe PE). This rung puts the SAME OS-agnostic render core (nx_browser_render: br_layout -> 6// CSS cascade -> box layout -> br_draw_fb paint) onto NISHIOS: it boots the persisted NishiOS image on 7// the sovereign x86 emu (same unified boot-disk emu proven in nx_nishi_usb_longmode/_desktop), and ONLY 8// because the disk-loaded kernel reached LONG mode does the browser render a real HTML page and 9// composite it into the NishiOS desktop framebuffer (nx_fb). Export = knowledge/status/ 10// nishios_browser.bmp + .html = one picture of "boot NishiOS -> open the Nishi browser". 11// 12// KAT: T1 booted off the persisted image (INT 13h: 0x8000 0->0xBE); T2 disk-loaded kernel reached LONG 13// mode (mode==2); T3 UART banner == 'NishiOS'; T4 REAL layout (page.ok, box count, page height); 14// T5 h1 background bar pixels present in the composited desktop; T6 link-blue pixels present; 15// T7 body-text pixels present; T8 BMP exported at the exact expected size. NEG/liar-kill: 16// T9 a 0-sector-load sibling image never reaches long mode -> the browser gate never fires (window 17// region of a fresh desktop stays zero); T10 a tampered EMPTY page collapses the box count below the 18// T4 threshold (the layout evidence is content-sensitive, not a constant). 19// 20// HONEST SEAM (no overclaim, same as every nx_nishi_usb_* rung): the emu EXECUTES the MBR loader + 21// real->protected->long CR0/EFER transition as real x86 off the on-disk bytes; the browser render then 22// runs in NishiLang (the same sovereign language the kernel compiles from) as the OS's app layer, 23// painting the nx_fb framebuffer. Running the render loop itself as x86-on-emu, NishiOS-native 24// networking (fetch on-OS), and live input are the next rungs (N2/N3) -- named, not claimed. 25// NEVER-BRICK (Rule 26): writes FILE artifacts only (.img/.bmp/.html); models INT 13h *reads*; no /dev. 26// expect_exit: 0 license_tier: ORIGINAL 27import "nx_browser_render.nx" 28import "nx_itoa_lib.nx" // shared MSB-first emitter (zero-alloc) 29import "nx_fb.nx" 30const NB_MAGIC_200000: i64 = 200000 31const NB_MAGIC_32767: i64 = 32767 32const NB_MAGIC_65536: i64 = 65536 33const NB_MAGIC_202124: i64 = 202124 34 35func nb_puts(s: *u8) -> i64 { var n: i64=0; while s[n]!=(0 as u8){n=n+1} sys_write(1,s,n); return 0 } 36// MIGRATED to the shared emitter (debt 1785563586). The old body mmapped a scratch buffer 37// per call and never freed it. At PAGE granularity that is 4096B leaked PER CALL -- the 38// defect that took 28.5GB of a 36GB host in nx_ts_lumadiff (2MB input, ~3.66M calls). 39// nxi_* is MSB-first, allocates NOTHING, and emits identical bytes including the sign. 40func nb_num(v: i64) -> i64 { nxi_out(v); return 0 } 41func nb_slen(s: *u8) -> i64 { var n: i64=0; while s[n]!=(0 as u8){n=n+1} return n } 42func nb_contains(hay: *u8, hn: i64, ndl: *u8, nn: i64) -> i64 { 43 if nn==0 { return 1 } 44 var i: i64 = 0 45 while i + nn <= hn { var j: i64 = 0; var ok: i64 = 1; while j < nn { if hay[i+j]!=ndl[j] { ok=0; j=nn } else { j=j+1 } } if ok==1 { return 1 } i=i+1 } 46 return 0 47} 48func nb_mode(cr0: i64, efer: i64) -> i64 { let pe: i64=cr0&1; let pg: i64=(cr0>>31)&1; let lme: i64=(efer>>8)&1; if pe==0 { return 0 } if pg==1 { if lme==1 { return 2 } } return 1 } 49 50// UNIFIED boot-disk emu (proven in nx_nishi_usb_longmode/_desktop): 16-bit real-mode + INT 13h/INT 10h 51// PLUS 64-bit mov + CR0/EFER mode transition. st[0]=final cr0, st[1]=final mode. 52func nb_emu_boot_disk(mem: *u8, disk: *u8, entry: i64, console: *u8, clen: *i64, st: *i64) -> i64 { 53 var ip: i64=entry 54 var ax: i64=0 55 var bx: i64=0 56 var cx: i64=0 57 var dx: i64=0 58 var si: i64=0 59 var zf: i64=0 60 var rax: i64=0 61 var cr0: i64=0 62 var efer: i64=0 63 var guard: i64=0 64 st[0]=0; st[1]=0 65 while guard < NB_MAGIC_200000 { 66 guard = guard + 1 67 let op: i64 = mem[ip] as i64 68 if op == 0xF4 { st[0]=cr0; st[1]=nb_mode(cr0,efer); return 0 } 69 var h: i64 = 0 70 if h==0 { if op==0x48 { 71 if mem[ip+1]==(0xC7 as u8) { 72 let modrm: i64 = mem[ip+2] as i64 73 let imm: i64 = (mem[ip+3] as i64) | ((mem[ip+4] as i64)<<8) | ((mem[ip+5] as i64)<<16) | ((mem[ip+6] as i64)<<24) 74 if modrm==0xC0 { rax = imm } 75 ip=ip+7; h=1 76 } 77 } } 78 if h==0 { if op==0x0F { 79 let b1: i64 = mem[ip+1] as i64 80 if b1==0x22 { let m: i64=mem[ip+2] as i64; if ((m>>3)&7)==0 { cr0=rax }; ip=ip+3; h=1 } 81 if h==0 { if b1==0x30 { efer=rax; ip=ip+2; h=1 } } 82 if h==0 { if b1==0x05 { st[0]=cr0; st[1]=nb_mode(cr0,efer); return rax & 0xff } } 83 if h==0 { return 0 - 1 } 84 } } 85 if h==0 { if op==0xBE { si = (mem[ip+1] as i64) | ((mem[ip+2] as i64)<<8); ip=ip+3; h=1 } } 86 if h==0 { if op==0xB8 { ax = (mem[ip+1] as i64) | ((mem[ip+2] as i64)<<8); ip=ip+3; h=1 } } 87 if h==0 { if op==0xBB { bx = (mem[ip+1] as i64) | ((mem[ip+2] as i64)<<8); ip=ip+3; h=1 } } 88 if h==0 { if op==0xB9 { cx = (mem[ip+1] as i64) | ((mem[ip+2] as i64)<<8); ip=ip+3; h=1 } } 89 if h==0 { if op==0xBA { dx = (mem[ip+1] as i64) | ((mem[ip+2] as i64)<<8); ip=ip+3; h=1 } } 90 if h==0 { if op==0xAC { let al: i64 = mem[si] as i64; ax = (ax & 0xFF00) | al; si=si+1; ip=ip+1; h=1 } } 91 if h==0 { if op==0x08 { let al2: i64 = ax & 0xFF; if al2==0 { zf=1 } else { zf=0 } ip=ip+2; h=1 } } 92 if h==0 { if op==0x74 { var r: i64 = mem[ip+1] as i64; if r>127 { r=r-256 } if zf==1 { ip=ip+2+r } else { ip=ip+2 } h=1 } } 93 if h==0 { if op==0xB4 { ax = (ax & 0xFF) | ((mem[ip+1] as i64)<<8); ip=ip+2; h=1 } } 94 if h==0 { if op==0xEB { var r2: i64 = mem[ip+1] as i64; if r2>127 { r2=r2-256 } ip=ip+2+r2; h=1 } } 95 if h==0 { if op==0xE9 { var r3: i64 = (mem[ip+1] as i64) | ((mem[ip+2] as i64)<<8); if r3>NB_MAGIC_32767 { r3=r3-NB_MAGIC_65536 } ip=ip+3+r3; h=1 } } 96 if h==0 { if op==0xCD { 97 let vec: i64 = mem[ip+1] as i64 98 let ah: i64 = (ax >> 8) & 0xFF 99 if vec==0x10 { if ah==0x0E { console[clen[0]]=(ax & 0xFF) as u8; clen[0]=clen[0]+1 } } 100 if vec==0x13 { if ah==0x02 { 101 let count: i64 = ax & 0xFF 102 let sector: i64 = cx & 0xFF 103 let lba: i64 = sector - 1 104 var s: i64 = 0 105 while s < count*512 { mem[bx + s] = disk[lba*512 + s]; s=s+1 } 106 ax = ax & 0xFF 107 } } 108 ip=ip+2; h=1 109 } } 110 if h==0 { return 0 - 1 } 111 } 112 return 0 - 2 113} 114 115const NB_IMG_SZ: i64 = 1024 116 117func nb_movrax(img: *u8, base: i64, o: i64, b0: i64, b1: i64, b2: i64, b3: i64) -> i64 { 118 img[base+o]=0x48 as u8; img[base+o+1]=0xC7 as u8; img[base+o+2]=0xC0 as u8 119 img[base+o+3]=(b0&0xff) as u8; img[base+o+4]=(b1&0xff) as u8; img[base+o+5]=(b2&0xff) as u8; img[base+o+6]=(b3&0xff) as u8 120 return o+7 121} 122 123// author the 2-sector image: MBR loads the long-mode kernel off sector 1 and jumps to it (the proven 124// nx_nishi_usb_desktop layout: banner over INT 10h, then CR0.PE -> EFER.LME -> CR0.PG|PE -> LONG -> HLT). 125func nb_build_image(img: *u8) -> i64 { 126 var z: i64=0 127 while z<NB_IMG_SZ { img[z]=0 as u8; z=z+1 } 128 img[0]=0xB8 as u8; img[1]=0x01 as u8; img[2]=0x02 as u8 129 img[3]=0xBB as u8; img[4]=0x00 as u8; img[5]=0x80 as u8 130 img[6]=0xB9 as u8; img[7]=0x02 as u8; img[8]=0x00 as u8 131 img[9]=0xBA as u8; img[10]=0x80 as u8; img[11]=0x00 as u8 132 img[12]=0xCD as u8; img[13]=0x13 as u8 133 let rel16: i64 = 0x8000 - (0x7C00 + 14 + 3) 134 img[14]=0xE9 as u8; img[15]=(rel16 & 0xFF) as u8; img[16]=((rel16>>8) & 0xFF) as u8 135 img[510]=0x55 as u8; img[511]=0xAA as u8 136 var r: i64 = 0 137 img[512+r]=0xBE as u8; let si_r: i64 = r+1; r=r+3 138 let loop_r: i64 = r 139 img[512+r]=0xAC as u8; r=r+1 140 img[512+r]=0x08 as u8; img[512+r+1]=0xC0 as u8; r=r+2 141 img[512+r]=0x74 as u8; let jz_r: i64 = r+1; r=r+2 142 img[512+r]=0xB4 as u8; img[512+r+1]=0x0E as u8; r=r+2 143 img[512+r]=0xCD as u8; img[512+r+1]=0x10 as u8; r=r+2 144 img[512+r]=0xEB as u8; img[512+r+1]=((loop_r-(r+2)) & 0xFF) as u8; r=r+2 145 let after_r: i64 = r 146 r = nb_movrax(img, 512, r, 1, 0, 0, 0) 147 img[512+r]=0x0F as u8; img[512+r+1]=0x22 as u8; img[512+r+2]=0xC0 as u8; r=r+3 148 r = nb_movrax(img, 512, r, 0x00, 0x01, 0, 0) 149 img[512+r]=0x0F as u8; img[512+r+1]=0x30 as u8; r=r+2 150 r = nb_movrax(img, 512, r, 0x01, 0x00, 0x00, 0x80) 151 img[512+r]=0x0F as u8; img[512+r+1]=0x22 as u8; img[512+r+2]=0xC0 as u8; r=r+3 152 img[512+r]=0xF4 as u8; r=r+1 153 let msg_r: i64 = r 154 let msg: *u8 = "NishiOS\x0D\x0A\x00" 155 var mi: i64=0 156 while msg[mi]!=(0 as u8) { img[512+r]=msg[mi]; r=r+1; mi=mi+1 } 157 img[512+r]=0 as u8; r=r+1 158 img[512+jz_r] = ((after_r - (jz_r+1)) & 0xFF) as u8 159 let si_abs: i64 = 0x8000 + msg_r 160 img[512+si_r] = (si_abs & 0xFF) as u8 161 img[512+si_r+1] = ((si_abs>>8) & 0xFF) as u8 162 return 0 163} 164 165func nb_boot_image(img: *u8, console: *u8, clen: *i64, st: *i64, loaded: *i64) -> i64 { 166 let mem: *u8 = sys_mmap(NB_MAGIC_65536) 167 var k: i64=0 168 while k<NB_MAGIC_65536 { mem[k]=0 as u8; k=k+1 } 169 var j: i64=0 170 while j<512 { mem[0x7C00+j]=img[j]; j=j+1 } 171 loaded[0] = mem[0x8000] as i64 172 clen[0]=0 173 let rc: i64 = nb_emu_boot_disk(mem, img, 0x7C00, console, clen, st) 174 loaded[1] = mem[0x8000] as i64 175 return rc 176} 177 178// render s at (x,y) glyph-by-glyph via the full 8x8 ASCII font (bit0 = LEFTMOST column, top->bottom rows). 179func nb_str(fb: *u8, W: i64, H: i64, x: i64, y: i64, s: *u8, r: i64, g: i64, b: i64) -> i64 { 180 let table: *u8 = font8x8_table() 181 var i: i64=0 182 while s[i]!=(0 as u8) { 183 let cc: i64 = s[i] as i64 184 if cc>=0x20 { if cc<=0x7E { 185 let gi: i64=(cc-0x20)*8 186 var rr: i64=0 187 while rr<8 { let bits: i64=table[gi+rr] as i64; var co: i64=0; while co<8 { if ((bits>>co)&1)==1 { fb_setpx(fb,W,H, x+i*8+co, y+rr, r,g,b) } co=co+1 } rr=rr+1 } 188 } } 189 i=i+1 190 } 191 return 0 192} 193 194func nb_write_file(path: *u8, data: *u8, n: i64) -> i64 { 195 let fd: i64 = sys_openat_wr(path, 0x1a4) 196 if fd<=0 { return 0 - 1 } 197 sys_write(fd, data, n) 198 sys_close(fd) 199 return n 200} 201 202// desktop geometry (W*3 divisible by 4 so the BMP needs no row padding) 203const NB_W: i64 = 640 204const NB_H: i64 = 480 205const NB_BW: i64 = 620 // browser page framebuffer width (blit interior of the OS window) 206const NB_BH: i64 = 426 // browser page framebuffer height 207const NB_OX: i64 = 10 // blit origin in the desktop 208const NB_OY: i64 = 38 209 210// count exact-RGB pixels inside the blitted browser region of the desktop 211func nb_count_rgb(desk: *u8, r: i64, g: i64, b: i64) -> i64 { 212 var cnt: i64 = 0 213 var y: i64 = 0 214 while y < NB_BH { 215 var x: i64 = 0 216 while x < NB_BW { 217 let d: i64 = ((NB_OY+y)*NB_W + (NB_OX+x))*3 218 if (desk[d] as i64)==r { if (desk[d+1] as i64)==g { if (desk[d+2] as i64)==b { cnt=cnt+1 } } } 219 x = x + 1 220 } 221 y = y + 1 222 } 223 return cnt 224} 225 226func main() -> i64 { 227 nb_puts("BROWSER-ON-ALL-OS N1: boot the persisted NishiOS image to LONG mode -> the Nishi browser renders a page into the NishiOS desktop\n" as *u8) 228 229 // ---- 1. author + persist the bootable NishiOS image, read the ON-DISK bytes back 230 let img: *u8 = sys_mmap(NB_IMG_SZ + 16) 231 nb_build_image(img) 232 if nb_write_file("knowledge/status/nishios_browser.img\x00" as *u8, img, NB_IMG_SZ) <= 0 { nb_puts("NISHIOS-BROWSER RED: cannot write image\n" as *u8); sys_exit(1); return 1 } 233 let ilp: *i64 = sys_mmap(16) as *i64 234 let rd: *u8 = sys_read_file("knowledge/status/nishios_browser.img\x00" as *u8, ilp) 235 if ilp[0] != NB_IMG_SZ { nb_puts("NISHIOS-BROWSER RED: image readback size\n" as *u8); sys_exit(1); return 1 } 236 237 // ---- 2. boot the on-disk image on the sovereign emu 238 let con: *u8 = sys_mmap(256) 239 let clen: *i64 = sys_mmap(8) as *i64 240 let st: *i64 = sys_mmap(64) as *i64 241 let ld: *i64 = sys_mmap(64) as *i64 242 let brc: i64 = nb_boot_image(rd, con, clen, st, ld) 243 nb_puts(" boot: 0x8000 " as *u8); nb_num(ld[0]); nb_puts("->" as *u8); nb_num(ld[1]); nb_puts(" mode=" as *u8); nb_num(st[1]); nb_puts(" (2=long) banner='" as *u8); sys_write(1, con, clen[0]); nb_puts("' rc=" as *u8); nb_num(brc); nb_puts("\n" as *u8) 244 245 // ---- 3. persist the REAL start page, read the on-disk bytes back, lay it out with the browser core 246 let phtml: *u8 = "<html><head><title>Nishi Browser on NishiOS</title></head><body><h1>Nishi</h1><p><b>Links:</b> <a href='https://nishifamily.com/'>nishifamily.com</a> and the <a href='/wiki/'>NishiOS wiki</a>.</p><p>The sovereign browser on the sovereign NishiOS: own HTML tokenizer, own CSS cascade, own layout, own paint &amp; fonts.</p><h2>The stack under this page</h2><ul><li>boot: MBR loader, INT 13h, real to protected to LONG mode</li><li>render: the same br_layout core as Linux + Windows</li><li>paint: nx_fb, the NishiOS framebuffer driver</li></ul><h2>Status</h2><p>Rendered by the Nishi browser core, composited into the NishiOS desktop.</p></body></html>\x00" 247 nb_write_file("knowledge/status/nishios_browser_page.html\x00" as *u8, phtml, nb_slen(phtml)) 248 let plp: *i64 = sys_mmap(16) as *i64 249 let praw: *u8 = sys_read_file("knowledge/status/nishios_browser_page.html\x00" as *u8, plp) 250 let page: *Page = sys_mmap(NX_PAGE_BYTES) as *Page 251 page.raw = praw 252 page.raw_len = plp[0] 253 br_layout(page, NB_BW/2) // LEGIBILITY (OCR-judge-driven): lay out at half width... 254 page.vec_headings = 2 // modern stroke-vector font for headings 255 nb_puts(" layout: ok=" as *u8); nb_num(page.ok); nb_puts(" boxes=" as *u8); nb_num(page.tree.count); nb_puts(" page_h=" as *u8); nb_num(page.page_h); nb_puts("\n" as *u8) 256 257 // ---- 4. the browser paints ONLY because the disk-loaded kernel reached long mode 258 let desk: *u8 = sys_mmap(NB_W*NB_H*3 + 16) 259 let font: *u8 = sys_mmap(64) 260 let idx: *u8 = sys_mmap(8) 261 var bmpsz: i64 = 0 262 if st[1]==2 { if page.ok==1 { 263 fb_nishi_font(font, idx) 264 var wy: i64=0 265 while wy<NB_H { let wr: i64=10-(8*wy)/NB_H; let wg: i64=30+(40*wy)/NB_H; let wb: i64=50+(30*wy)/NB_H; fb_rect(desk,NB_W,NB_H, 0,wy, NB_W,1, wr,wg,wb); wy=wy+1 } 266 fb_rect(desk,NB_W,NB_H, 0,0, NB_W,16, 28,28,110) // OS top bar 267 fb_text(desk,NB_W,NB_H, font, idx, 7, 6,4, 1, 255,255,255) // NISHIOS logo 268 fb_window(desk,NB_W,NB_H, font,idx, 8,22, 624,444, 50,80,180, 210,210,225) // the browser window 269 nb_str(desk,NB_W,NB_H, 8+3+66, 22+3, "- NISHI BROWSER\x00" as *u8, 240,240,250) // window title suffix 270 // render the page with the OS-agnostic browser core into an RGBA framebuffer 271 let bfb: *Framebuffer = sys_mmap(NX_FRAMEBUFFER_BYTES) as *Framebuffer 272 let bpx: *u8 = sys_mmap(NB_BW*NB_BH*4 + 64) 273 nx_framebuffer_init(bfb, bpx, NB_BW, NB_BH) 274 br_draw_fb(bfb, page, NB_BW/2, "nishios://start\x00" as *u8, 15, 2) // ...and paint at 2x = 16px body text (876 vs 153 permille OCR recall) 275 // composite RGBA -> the NishiOS RGB desktop at the window interior 276 var by: i64 = 0 277 while by < NB_BH { 278 var bx: i64 = 0 279 while bx < NB_BW { 280 let so: i64 = (by*NB_BW + bx)*4 281 let dof: i64 = ((NB_OY+by)*NB_W + (NB_OX+bx))*3 282 desk[dof] = bpx[so] 283 desk[dof+1] = bpx[so+1] 284 desk[dof+2] = bpx[so+2] 285 bx = bx + 1 286 } 287 by = by + 1 288 } 289 fb_rect(desk,NB_W,NB_H, 0,466, NB_W,14, 20,20,40) // taskbar 290 fb_rect(desk,NB_W,NB_H, 4,469, 36,8, 80,200,80) // start button 291 nb_str(desk,NB_W,NB_H, 46,469, "browser\x00" as *u8, 200,210,230) // running-app label 292 fb_cursor(desk,NB_W,NB_H, 330,240) 293 bmpsz = fb_bmp_save(desk, NB_W, NB_H, "knowledge/status/nishios_browser.bmp\x00" as *u8) 294 let html: *u8 = "<!doctype html><html><body style=\x27margin:0;background:#0a0a12;display:flex;align-items:center;justify-content:center;height:100vh\x27><div><img src=\x27nishios_browser.bmp\x27 style=\x27image-rendering:pixelated;width:960px;border:1px solid #333\x27><div style=\x27color:#8af;font-family:monospace;text-align:center;margin-top:8px\x27>NishiOS boots (MBR -&gt; LONG mode, executed on the sovereign emu) -&gt; the Nishi browser (br_layout + br_draw_fb, the same core as Linux/Windows) renders nishios_browser_page.html into the NishiOS desktop</div></div></body></html>\x00" 295 nb_write_file("knowledge/status/nishios_browser.html\x00" as *u8, html, nb_slen(html)) 296 nb_puts(" browser composited -> knowledge/status/nishios_browser.bmp (" as *u8); nb_num(bmpsz); nb_puts(" bytes) + .html\n" as *u8) 297 } } 298 299 // ---- 5. NEG 1: a 0-sector-load sibling image never reaches long mode -> browser gate never fires 300 let bad: *u8 = sys_mmap(NB_IMG_SZ + 16) 301 var c: i64=0 302 while c<NB_IMG_SZ { bad[c]=rd[c]; c=c+1 } 303 bad[1]=0x00 as u8 304 let con2: *u8 = sys_mmap(256) 305 let clen2: *i64 = sys_mmap(8) as *i64 306 let st2: *i64 = sys_mmap(64) as *i64 307 let ld2: *i64 = sys_mmap(64) as *i64 308 nb_boot_image(bad, con2, clen2, st2, ld2) 309 let desk2: *u8 = sys_mmap(NB_W*NB_H*3 + 16) 310 var neg_drawn: i64 = 0 311 if st2[1]==2 { // (never taken -- mirrors the live gate) 312 fb_rect(desk2,NB_W,NB_H, NB_OX,NB_OY, NB_BW,NB_BH, 255,255,255) 313 neg_drawn = 1 314 } 315 let negpx: i64 = desk2[((NB_OY+50)*NB_W + (NB_OX+50))*3] as i64 316 nb_puts(" NEG boot: mode=" as *u8); nb_num(st2[1]); nb_puts(" drawn=" as *u8); nb_num(neg_drawn); nb_puts(" probe_px=" as *u8); nb_num(negpx); nb_puts("\n" as *u8) 317 318 // ---- 6. NEG 2: a tampered EMPTY page collapses the box count (layout evidence is content-sensitive) 319 let thtml: *u8 = "<html><body></body></html>\x00" 320 let page2: *Page = sys_mmap(NX_PAGE_BYTES) as *Page 321 page2.raw = thtml 322 page2.raw_len = nb_slen(thtml) 323 br_layout(page2, NB_BW) 324 nb_puts(" NEG layout: tampered boxes=" as *u8); nb_num(page2.tree.count); nb_puts("\n" as *u8) 325 326 // ---- KATs 327 // RE-PINNED 2026-07-09 (render-core CSS rung): UA headings/p/li no longer carry own colors -- text 328 // INHERITS body ink #2a2a33 via br_comp_color_inh; the old #14142b heading ink and col=0 black fallback 329 // no longer exist. Pins track the deliberately-changed core, measured from the actual BMP. 330 let cnt_h1: i64 = nb_count_rgb(desk, 42, 42, 51) // #2a2a33 page text ink (UA body, INHERITED) 331 let cnt_lnk: i64 = nb_count_rgb(desk, 37, 99, 235) // #2563eb link text + underline (modern blue) 332 let cnt_txt: i64 = nb_count_rgb(desk, 32, 33, 36) // #NB_MAGIC_202124 browser chrome ink (buttons + URL) 333 nb_puts(" pixels: h1bar=" as *u8); nb_num(cnt_h1); nb_puts(" link=" as *u8); nb_num(cnt_lnk); nb_puts(" text=" as *u8); nb_num(cnt_txt); nb_puts("\n" as *u8) 334 let banner: *u8 = "NishiOS" as *u8 335 var pass: i64=0 336 var ttl: i64=0 337 ttl=ttl+1; nb_puts(" T1 booted off the persisted image (0x8000: 0->0xBE): " as *u8); if ld[0]==0 { if ld[1]==0xBE { pass=pass+1; nb_puts("PASS\n" as *u8) } else { nb_puts("FAIL\n" as *u8) } } else { nb_puts("FAIL\n" as *u8) } 338 ttl=ttl+1; nb_puts(" T2 disk-loaded kernel reached LONG mode (mode==2): " as *u8); if st[1]==2 { pass=pass+1; nb_puts("PASS\n" as *u8) } else { nb_puts("FAIL\n" as *u8) } 339 ttl=ttl+1; nb_puts(" T3 UART banner == 'NishiOS': " as *u8); if nb_contains(con, clen[0], banner, 7)==1 { pass=pass+1; nb_puts("PASS\n" as *u8) } else { nb_puts("FAIL\n" as *u8) } 340 ttl=ttl+1; nb_puts(" T4 REAL layout (ok, boxes>=15, page_h>=100): " as *u8); if page.ok==1 { if page.tree.count>=15 { if page.page_h>=100 { pass=pass+1; nb_puts("PASS\n" as *u8) } else { nb_puts("FAIL\n" as *u8) } } else { nb_puts("FAIL\n" as *u8) } } else { nb_puts("FAIL\n" as *u8) } 341 ttl=ttl+1; nb_puts(" T5 page text ink composited (UA body #2a2a33, inherited; >100 px): " as *u8); if cnt_h1>100 { pass=pass+1; nb_puts("PASS\n" as *u8) } else { nb_puts("FAIL\n" as *u8) } 342 ttl=ttl+1; nb_puts(" T6 link-blue pixels composited (>20 px): " as *u8); if cnt_lnk>20 { pass=pass+1; nb_puts("PASS\n" as *u8) } else { nb_puts("FAIL\n" as *u8) } 343 ttl=ttl+1; nb_puts(" T7 browser chrome ink composited (#202124, >100 px): " as *u8); if cnt_txt>100 { pass=pass+1; nb_puts("PASS\n" as *u8) } else { nb_puts("FAIL\n" as *u8) } 344 ttl=ttl+1; nb_puts(" T8 BMP exported at the exact expected size: " as *u8); if bmpsz==(54 + NB_W*NB_H*3) { pass=pass+1; nb_puts("PASS\n" as *u8) } else { nb_puts("FAIL\n" as *u8) } 345 ttl=ttl+1; nb_puts(" T9 NEG: 0-sector load never reaches long mode, browser never fires: " as *u8); if st2[1]!=2 { if neg_drawn==0 { if negpx==0 { pass=pass+1; nb_puts("PASS\n" as *u8) } else { nb_puts("FAIL\n" as *u8) } } else { nb_puts("FAIL\n" as *u8) } } else { nb_puts("FAIL\n" as *u8) } 346 ttl=ttl+1; nb_puts(" T10 NEG: tampered empty page collapses below the T4 box threshold: " as *u8); if page2.tree.count<15 { pass=pass+1; nb_puts("PASS\n" as *u8) } else { nb_puts("FAIL\n" as *u8) } 347 348 nb_puts("NISHIOS-BROWSER-GATE passed " as *u8); nb_num(pass); nb_puts("/" as *u8); nb_num(ttl) 349 if pass==ttl { nb_puts(" verdict=GREEN (boot NishiOS -> the Nishi browser renders; open knowledge/status/nishios_browser.html)\n" as *u8); sys_exit(0); return 0 } 350 nb_puts(" verdict=RED\n" as *u8); sys_exit(1); return 1 351}