nx_nishi_usb_fbkernel.nx
buildroot/runtime/nx_nishi_usb_fbkernel.nx
about
nx_nishi_usb_fbkernel.nx -- x86 ladder R9-FBKERNEL: the disk-loaded kernel DRAWS its own framebuffer.
Closes the seam nx_nishi_usb_desktop honestly flagged: there the desktop was drawn by the NishiLang
nx_fb driver AFTER the emu returned. HERE the booted kernel's framebuffer write is REAL x86
INSTRUCTIONS executed on the emu: the kernel that the MBR loads off the persisted image, after it
reaches LONG mode, runs an authored fill loop (mov-imm / store [rax],rcx / add / cmp / jne) that writes
a computed value into every framebuffer word. Afterward we read the framebuffer straight out of the
emu's memory -- the pixels were written by x86 the booted kernel executed, not by a NishiLang call --
and encode it to BMP via nx_fb (now ONLY the encoder).
This fuses THREE proven emus into ONE: the 16-bit real-mode + INT 13h loader (nx_nishi_usb_image),
the CR0/EFER mode transition (nx_nishi_usb_longmode), and the 64-bit store/arith/loop engine
(nx_nishios_fb_x86's ek_emu). 16-bit ops use named regs; 64-bit ops use a reg[] file; the boot
phases (banner -> mode-switch -> fill) each init their own registers, so there is no aliasing.
Boot flow, executed off the PERSISTED on-disk bytes:
sector 0 (MBR) --INT 13h--> loads sector 1 (kernel) to 0x8000, jmps to it
sector 1 (kernel) prints "NishiOS" (INT 10h) -> CR0.PE/EFER.LME/CR0.PG (LONG mode) ->
x86 fill loop writes the framebuffer at 0x9000 -> HLT
KAT: (T1) booted off disk; (T2) reached LONG mode; (T3) banner; (T4) the framebuffer holds EXACTLY
what the x86 loop computed at word 1 / 200 / last (proves the booted kernel's x86 ran to completion);
(T5) BMP exported. NEG/liar-kill (T6): a 0-sector-load sibling never runs the kernel, so the
framebuffer stays ZERO and long mode is never reached -- the pixels exist ONLY because the disk-loaded
kernel executed.
HONEST SCOPE: the loop fills a computed ramp = proof of per-pixel x86 writes by the booted kernel;
richer chrome (rects/text drawn purely in x86) + a real VESA/GOP framebuffer on hardware are the
continuation. NEVER-BRICK (Rule 26): writes FILE artifacts; models INT 13h *reads* only; no /dev.
expect_exit: 0 license_tier: ORIGINAL
dependencies 2 imports · 0 importers
imports: nx_fb.nxnx_itoa_lib.nx
imported by: nobody (leaf or entry point)
call flow from main pre-order; caps 40 nodes / depth 6 declared; ↻ = already shown
structs
| none |
consts
| 33 | const IMG_MAGIC_2000000: i64 = 2000000 |
| 34 | const IMG_MAGIC_32767: i64 = 32767 |
| 35 | const IMG_MAGIC_65536: i64 = 65536 |
| 36 | const IMG_MAGIC_18432: i64 = 18432 |
| 37 | const IMG_MAGIC_2304: i64 = 2304 |
| 132 | const IMG_SZ: i64 = 1024 |
| 133 | const FB_BASE: i64 = 0x9000 // framebuffer in emu RAM, above the kernel (0x8000) -- no overlap |
| 134 | const FB_W: i64 = 96 |
| 135 | const FB_H: i64 = 64 |
functions
| 39 | func uf_puts(s: *u8) -> i64 { var n: i64=0; while s[n]!=(0 as u8){n=n+1} sys_write(1,s,n); return 0 } called by 1: main |
| 44 | func uf_num(v: i64) -> i64 { nxi_out(v); return 0 } |
| 45 | func uf_contains(hay: *u8, hn: i64, ndl: *u8, nn: i64) -> i64 called by 1: main |
| 51 | func uf_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 } called by 1: emu_x86_boot_fb |
| 52 | func uf_st64(mem: *u8, addr: i64, v: i64) -> i64 { var i: i64=0; while i<8 { mem[addr+i]=((v>>(i*8))&0xff) as u8; i=i+1 } return 0 } called by 1: emu_x86_boot_fb |
| 56 | func emu_x86_boot_fb(mem: *u8, disk: *u8, entry: i64, console: *u8, clen: *i64, st: *i64) -> i64 |
| 138 | func uf_movr(img: *u8, base: i64, o: i64, modrm: i64, imm: i64) -> i64 called by 1: build_image |
| 144 | func build_image(img: *u8, nwords: i64) -> i64 |
| 201 | func boot_image(img: *u8, console: *u8, clen: *i64, st: *i64, loaded: *i64, fbout: *i64) -> i64 |
| 215 | func uf_read(path: *u8, out: *u8, cap: i64) -> i64 |
| 224 | func main() -> i64 |