code wiki / _hdl_build / nx_room_protocol_gate.nx
nx_room_protocol_gate.nx source
↩ module page · 188 lines · 8414 B
1import "nx_gate_base.nx"
2// nx_room_protocol_gate.nx -- the room wire/memory CONTRACT as a Nishi-owned SSOT (api-first).
3// The video room's protocol constants (linear-memory region map + lane/codec params) were hand-duplicated
4// across app.v2.js AND nishi-video.component.js AND the wasm core -- three hand-maintained copies of one
5// contract (violates rule #11 no-magic-numbers + rule #15 DRY). This organ makes NishiLang the SINGLE
6// source of truth: it (1) EMITS the documented contract web_assets/nishi_room_protocol.txt and (2) VALIDATES
7// that BOTH shipped JS clients conform to it. Any client that drifts a constant -> RED. A mobile-native
8// client consumes the SAME contract with ZERO JS. This is the "lean into nishi lang / api-first" rung.
9// expect_exit: 0 license_tier: ORIGINAL
10import "nx_syscalls.nx"
11
12func grow(name: *u8, ok: i64) -> i64 { if ok==1 { gw(" PASS " as *u8) } else { gw(" FAIL " as *u8) } gw(name); gw("
13" as *u8); return ok }
14func gn(v: i64) -> i64 {
15 let b: *u8=sys_mmap(28); var m: i64=v; if m<0{sys_write(1,"-" as *u8,1);m=0-m}
16 let t: *u8=sys_mmap(28); var k: i64=0; if m==0{t[0]=48 as u8;k=1} while m>0{t[k]=(48+(m%10)) as u8;m=m/10;k=k+1}
17 var i: i64=0; while i<k{b[i]=t[k-1-i];i=i+1} sys_write(1,b,k); return 0 }
18
19// ---- the SSOT contract table (the ONE authoritative definition) ----
20func rp_count() -> i64 { return 23 }
21func rp_name(i: i64) -> *u8 {
22 if i==0 { return "R_ID" as *u8 }
23 if i==1 { return "R_PAY" as *u8 }
24 if i==2 { return "R_WOUT" as *u8 }
25 if i==3 { return "R_WIN" as *u8 }
26 if i==4 { return "R_INFO" as *u8 }
27 if i==5 { return "R_F32" as *u8 }
28 if i==6 { return "R_FOUT" as *u8 }
29 if i==7 { return "R_PCM" as *u8 }
30 if i==8 { return "R_SCR" as *u8 }
31 if i==9 { return "R_STAGE" as *u8 }
32 if i==10 { return "R_STAGE2" as *u8 }
33 if i==11 { return "R_FTBL" as *u8 }
34 if i==12 { return "R_FSD" as *u8 }
35 if i==13 { return "R_FSS" as *u8 }
36 if i==14 { return "R_FOUT2" as *u8 }
37 if i==15 { return "R_FSCRA" as *u8 }
38 if i==16 { return "R_FSCRSH" as *u8 }
39 if i==17 { return "R_FDEC" as *u8 }
40 if i==18 { return "R_CHAT" as *u8 }
41 if i==19 { return "R_FST" as *u8 }
42 if i==20 { return "LANES" as *u8 }
43 if i==21 { return "AUDIO_CHUNK" as *u8 }
44 if i==22 { return "R_PLAN" as *u8 }
45 return "" as *u8 }
46func rp_val(i: i64) -> i64 {
47 if i==0 { return 0x200000 }
48 if i==1 { return 0x200100 }
49 if i==2 { return 0x220000 }
50 if i==3 { return 0x240000 }
51 if i==4 { return 0x260000 }
52 if i==5 { return 0x270000 }
53 if i==6 { return 0x280000 }
54 if i==7 { return 0x290000 }
55 if i==8 { return 0x2A0000 }
56 if i==9 { return 0x300000 }
57 if i==10 { return 0x400000 }
58 if i==11 { return 0x3000000 }
59 if i==12 { return 0x3010000 }
60 if i==13 { return 0x3020000 }
61 if i==14 { return 0x3030000 }
62 if i==15 { return 0x3040000 }
63 if i==16 { return 0x3050000 }
64 if i==17 { return 0x3060000 }
65 if i==18 { return 0x3080000 }
66 if i==19 { return 0x3100000 }
67 if i==20 { return 3 }
68 if i==21 { return 1024 }
69 if i==22 { return 0x2B0000 } // mb_plan output region (9 i64) -- the resource-intelligence API
70 return 0 }
71
72func is_ic(c: i64) -> i64 {
73 if c>=48 { if c<=57 { return 1 } }
74 if c>=65 { if c<=90 { return 1 } }
75 if c>=97 { if c<=122 { return 1 } }
76 if c==95 { return 1 }
77 return 0 }
78
79// parse an integer literal at hay[p0..] -- supports 0x hex and decimal
80func parse_int_at(hay: *u8, n: i64, p0: i64) -> i64 {
81 var p: i64 = p0
82 var base: i64 = 10
83 if p+1<n { if (hay[p] as i64)==48 { if (hay[p+1] as i64)==120 { base=16; p=p+2 } } }
84 var v: i64 = 0
85 var g: i64 = 1
86 while g==1 {
87 if p<n {
88 let c: i64 = hay[p] as i64
89 var d: i64 = 0-1
90 if c>=48 { if c<=57 { d=c-48 } }
91 if base==16 { if c>=97 { if c<=102 { d=c-97+10 } } }
92 if base==16 { if c>=65 { if c<=70 { d=c-65+10 } } }
93 if d<0 { g=0 } else { v=v*base+d; p=p+1 }
94 } else { g=0 }
95 }
96 return v }
97
98// find whole-word `name` FOLLOWED BY `= <int>` (a definition, not a usage); return value or -1
99func find_word_int(hay: *u8, n: i64, name: *u8) -> i64 {
100 var nl: i64=0; while name[nl]!=(0 as u8){nl=nl+1}
101 var i: i64=0
102 while i+nl<=n {
103 var j: i64=0; var ok: i64=1
104 while j<nl { if hay[i+j]!=name[j]{ok=0;j=nl} else {j=j+1} }
105 if ok==1 {
106 var bound: i64=1
107 if i>0 { if is_ic(hay[i-1] as i64)==1 { bound=0 } }
108 if i+nl<n { if is_ic(hay[i+nl] as i64)==1 { bound=0 } }
109 if bound==1 {
110 var p: i64=i+nl
111 var g: i64=1
112 while g==1 { if p<n { if (hay[p] as i64)==32 { p=p+1 } else { g=0 } } else { g=0 } }
113 if p<n { if (hay[p] as i64)==61 {
114 p=p+1
115 var g3: i64=1
116 while g3==1 { if p<n { if (hay[p] as i64)==32 { p=p+1 } else { g3=0 } } else { g3=0 } }
117 if p<n { if (hay[p] as i64)>=48 { if (hay[p] as i64)<=57 { return parse_int_at(hay,n,p) } } }
118 } }
119 }
120 }
121 i=i+1
122 }
123 return 0 - 1 }
124
125func fw(fd: i64, s: *u8) -> i64 { var n: i64=0; while s[n]!=(0 as u8){n=n+1} sys_write(fd,s,n); return 0 }
126func fhex(fd: i64, v: i64) -> i64 {
127 sys_write(fd, "0x" as *u8, 2)
128 let t: *u8 = sys_mmap(24); var m: i64=v; var k: i64=0
129 if m==0 { t[0]=48 as u8; k=1 }
130 while m>0 { let d: i64=m%16; if d<10 { t[k]=(48+d) as u8 } else { t[k]=(97+d-10) as u8 } m=m/16; k=k+1 }
131 let b: *u8 = sys_mmap(24); var i: i64=0
132 while i<k { b[i]=t[k-1-i]; i=i+1 }
133 sys_write(fd, b, k); return 0 }
134func fdec(fd: i64, v: i64) -> i64 {
135 let t: *u8 = sys_mmap(24); var m: i64=v; var k: i64=0
136 if m==0 { t[0]=48 as u8; k=1 }
137 while m>0 { t[k]=(48+(m%10)) as u8; m=m/10; k=k+1 }
138 let b: *u8 = sys_mmap(24); var i: i64=0
139 while i<k { b[i]=t[k-1-i]; i=i+1 }
140 sys_write(fd, b, k); return 0 }
141
142func main() -> i64 {
143 gw("=== nx_room_protocol_gate: Nishi-owned room contract SSOT + client conformance ===\n" as *u8)
144 // read both shipped JS clients
145 let abox: *i64 = sys_mmap(16) as *i64; abox[0]=0
146 let app: *u8 = sys_read_file("sites/nishifamily/video/app.v2.js" as *u8, abox)
147 if (app as i64)==0 { gw("no app.v2.js\n" as *u8); return 1 }
148 let an: i64 = abox[0]
149 let cbox: *i64 = sys_mmap(16) as *i64; cbox[0]=0
150 let comp: *u8 = sys_read_file("sites/nishifamily/video/nishi-video.component.js" as *u8, cbox)
151 if (comp as i64)==0 { gw("no nishi-video.component.js\n" as *u8); return 1 }
152 let cn: i64 = cbox[0]
153
154 // 1. EMIT the documented contract (the SSOT artifact any client -- web OR mobile-native -- consumes)
155 let fd: i64 = sys_openat_wr("web_assets/nishi_room_protocol.txt" as *u8, 0x1a4)
156 if fd < 0 { gw("cannot write nishi_room_protocol.txt\n" as *u8); return 1 }
157 fw(fd, "# Nishi Room Protocol -- SSOT (emitted by nx_room_protocol_gate). Clients CONSUME; never hand-copy.\n" as *u8)
158 fw(fd, "# wasm linear-memory region map + lane/codec params. A mobile-native client uses these with ZERO JS.\n" as *u8)
159 var t: i64 = 0
160 while t < rp_count() {
161 fw(fd, rp_name(t)); fw(fd, "=" as *u8); fhex(fd, rp_val(t)); fw(fd, " (" as *u8); fdec(fd, rp_val(t)); fw(fd, ")\n" as *u8)
162 t = t + 1
163 }
164 sys_close(fd)
165 gw(" emitted web_assets/nishi_room_protocol.txt (" as *u8); gn(rp_count()); gw(" contract constants)\n" as *u8)
166
167 // 2. VALIDATE both clients conform to the SSOT
168 var green: i64 = 1
169 var i: i64 = 0
170 while i < rp_count() {
171 let want: i64 = rp_val(i)
172 let av: i64 = find_word_int(app, an, rp_name(i))
173 let cv: i64 = find_word_int(comp, cn, rp_name(i))
174 var okrow: i64 = 1
175 if av != want { okrow = 0 }
176 if cv != want { okrow = 0 }
177 gw(" " as *u8); gw(rp_name(i))
178 gw(" want=" as *u8); gn(want); gw(" app.v2=" as *u8); gn(av); gw(" component=" as *u8); gn(cv)
179 if okrow==1 { gw(" OK\n" as *u8) } else { gw(" !!! DRIFT\n" as *u8); green=0 }
180 i = i + 1
181 }
182 if green==1 {
183 gw("ROOM-PROTOCOL-GATE verdict=GREEN -- both JS clients conform to the Nishi-owned contract SSOT\n" as *u8)
184 return 0
185 }
186 gw("ROOM-PROTOCOL-GATE verdict=RED -- a client drifted from the SSOT (fix the client, not the contract)\n" as *u8)
187 return 1
188}