nx_wasm_arcade.nx source
↩ module page · 120 lines · 5219 B
1// nx_wasm_arcade.nx -- the CORRECTED sovereign browser game: BASE-RELATIVE integer arcade. The SAME code
2// runs native (base = a real mmap -> render a frame to PNG for eyeball verify) AND in the browser (base = 0
3// = our own sovereign WASM linear memory). NO float, NO JS logic, NO 3rd-party canvas drawing. Game logic
4// (move/collect) + integer rasterizer write a packed-RGB framebuffer at a FIXED linear-mem offset; the blit
5// shim only copies that framebuffer to the screen + forwards keys. nx_wasm.nx auto-exports every func +
6// the linear memory, so init()/tick(dir)/render()/ww()/hh()/fb_off() become the wasm interface. The HUD
7// score is drawn into our OWN framebuffer by the sovereign Nishi font (no JS/canvas draws text). license_tier: ORIGINAL
8import "nx_nishi_font_core.nx"
9const W: i64 = 240
10const H: i64 = 192
11const CELL: i64 = 24
12const GW: i64 = 10
13const GH: i64 = 8
14const O_FB: i64 = 0 // framebuffer: W*H i64 (packed RGB), at linear-mem offset 0
15const O_GX: i64 = 368640 // W*H*8
16const O_GY: i64 = 368768
17const O_HX: i64 = 368896
18const O_HY: i64 = 369024
19const O_ST: i64 = 369152 // scalars: [0]=px [1]=py [2]=score [3]=ng [4]=nh
20const O_MSK: i64 = 376832 // HUD glyph scratch mask (base-relative; no sys_mmap -> works in wasm)
21const O_STR: i64 = 385024 // HUD score string scratch (decimal digits + reversal temp)
22
23func rgb(r: i64, g: i64, b: i64) -> i64 { return (r & 255) | ((g & 255) << 8) | ((b & 255) << 16) }
24
25func fillr(base: i64, x0: i64, y0: i64, x1: i64, y1: i64, c: i64) -> i64 {
26 let fb: *i64 = (base + O_FB) as *i64
27 var yy: i64 = y0; if yy < 0 { yy = 0 }
28 var ye: i64 = y1; if ye > H { ye = H }
29 while yy < ye {
30 var xx: i64 = x0; if xx < 0 { xx = 0 }
31 var xe: i64 = x1; if xe > W { xe = W }
32 while xx < xe { fb[yy*W + xx] = c; xx = xx + 1 }
33 yy = yy + 1
34 }
35 return 0
36}
37
38func init_impl(base: i64) -> i64 {
39 let st: *i64 = (base + O_ST) as *i64
40 let gx: *i64 = (base + O_GX) as *i64
41 let gy: *i64 = (base + O_GY) as *i64
42 let hx: *i64 = (base + O_HX) as *i64
43 let hy: *i64 = (base + O_HY) as *i64
44 st[0]=0; st[1]=0; st[2]=0; st[3]=4; st[4]=3
45 gx[0]=3; gy[0]=0; gx[1]=6; gy[1]=2; gx[2]=8; gy[2]=5; gx[3]=2; gy[3]=6
46 hx[0]=5; hy[0]=4; hx[1]=1; hy[1]=3; hx[2]=7; hy[2]=1
47 return 0
48}
49
50func tick_impl(base: i64, dir: i64) -> i64 {
51 let st: *i64 = (base + O_ST) as *i64
52 let gx: *i64 = (base + O_GX) as *i64
53 let gy: *i64 = (base + O_GY) as *i64
54 var nx: i64 = st[0]
55 var ny: i64 = st[1]
56 if dir == 0 { ny = ny - 1 }
57 if dir == 1 { ny = ny + 1 }
58 if dir == 2 { nx = nx - 1 }
59 if dir == 3 { nx = nx + 1 }
60 if nx < 0 { return 0 }
61 if ny < 0 { return 0 }
62 if nx >= GW { return 0 }
63 if ny >= GH { return 0 }
64 st[0] = nx; st[1] = ny
65 var i: i64 = 0
66 while i < st[3] {
67 if gx[i] == nx { if gy[i] == ny { gx[i] = 0 - 9; gy[i] = 0 - 9; st[2] = st[2] + 1; i = st[3] } else { i = i + 1 } } else { i = i + 1 }
68 }
69 return 0
70}
71
72func render_impl(base: i64) -> i64 {
73 let fb: *i64 = (base + O_FB) as *i64
74 let bg: i64 = rgb(16, 20, 30)
75 var p: i64 = 0
76 while p < W*H { fb[p] = bg; p = p + 1 }
77 var c: i64 = 0
78 while c <= GW { fillr(base, c*CELL, 0, c*CELL+1, GH*CELL, rgb(40,46,60)); c = c + 1 }
79 var r: i64 = 0
80 while r <= GH { fillr(base, 0, r*CELL, GW*CELL, r*CELL+1, rgb(40,46,60)); r = r + 1 }
81 let st: *i64 = (base + O_ST) as *i64
82 let gx: *i64 = (base + O_GX) as *i64
83 let gy: *i64 = (base + O_GY) as *i64
84 let hx: *i64 = (base + O_HX) as *i64
85 let hy: *i64 = (base + O_HY) as *i64
86 var i: i64 = 0
87 while i < st[3] { if gx[i] >= 0 { fillr(base, gx[i]*CELL+6, gy[i]*CELL+6, gx[i]*CELL+CELL-6, gy[i]*CELL+CELL-6, rgb(255,210,70)) } i = i + 1 }
88 var j: i64 = 0
89 while j < st[4] { fillr(base, hx[j]*CELL+4, hy[j]*CELL+4, hx[j]*CELL+CELL-4, hy[j]*CELL+CELL-4, rgb(224,80,58)) j = j + 1 }
90 fillr(base, st[0]*CELL+4, st[1]*CELL+4, st[0]*CELL+CELL-4, st[1]*CELL+CELL-4, rgb(90,210,122))
91 // --- sovereign HUD: render the score as OUR font's pixels into the framebuffer (no JS/canvas text) ---
92 let sbuf: *u8 = (base + O_STR) as *u8
93 var slen: i64 = 0
94 var sv: i64 = st[2]
95 if sv <= 0 {
96 sbuf[0] = 48 as u8 // '0'
97 slen = 1
98 } else {
99 let tmp: *u8 = (base + O_STR + 16) as *u8
100 var k: i64 = 0
101 while sv > 0 { tmp[k] = (48 + (sv % 10)) as u8; sv = sv / 10; k = k + 1 }
102 var q: i64 = 0
103 while q < k { sbuf[q] = tmp[k - 1 - q]; q = q + 1 }
104 slen = k
105 }
106 let mask: *u8 = (base + O_MSK) as *u8
107 let hud_ch: i64 = 16
108 let hud_x: i64 = W - 4 - slen * nf_adv_px(hud_ch)
109 nf_draw_text_mem(fb, W, H, mask, hud_x, 3, hud_ch, sbuf, slen, rgb(235, 240, 250))
110 return 0
111}
112
113// ---- WASM exports (base = 0 = our sovereign linear memory; auto-exported by nx_wasm.nx) ----
114func init() -> i64 { return init_impl(0) }
115func tick(dir: i64) -> i64 { return tick_impl(0, dir) }
116func render() -> i64 { return render_impl(0) }
117func score() -> i64 { let st: *i64 = (0 + O_ST) as *i64; return st[2] }
118func fb_off() -> i64 { return O_FB }
119func ww() -> i64 { return W }
120func hh() -> i64 { return H }