code wiki / _hdl_build / nx_vnsprite_gate.nx

nx_vnsprite_gate.nx source

↩ module page · 409 lines · 18001 B

1// nx_vnsprite_gate.nx -- liar-kill gate for the VN sprite compositor (gamebench bit 13). 2// T1 Z-ORDER is real: at an overlap the higher-z layer's pixel wins; swapping z swaps the winner. 3// T2 ALPHA + KEY are exact: a 50% blend lands on the exact integer mix per channel, and a key-color 4// pixel is fully transparent (background shows through untouched). 5// T3 CLIPPING cannot write out of bounds: blits hanging off every edge leave 8 canary cells intact. 6// T4 EXPRESSION SWAP IS VISIBLE: base+smile vs base+frown differ in >=20 pixels; recomposing the 7// same expression twice differs in 0 (visible AND deterministic -- the VN beat that matters). 8// T5 SCENE STATE ROUND-TRIPS: the layer table through gs_save -> ZEROED -> gs_load -> recompose is 9// frame-checksum identical (parts doctrine: everything persists through the save part). 10// T6 DETERMINISM: the full scene composed twice is checksum-identical. 11// T7 ANTI-VACUITY: the composed scene differs from the bare background in >=500 px with >=5 12// distinct sprite colors (a compositor that draws nothing cannot pass). 13// T8 SCENE ARTIFACT: a full VN frame (gradient bg + two characters + alpha textbox + name tag) is 14// written as a sovereign PNG to knowledge/nx_vnsprite_scene.png -- the board's evidence. 15// T9 GROUP EXCLUSIVITY (the Ren'Py layeredimage bar, researched 2026-07-29): smile and frown are 16// two attributes of ONE group; a single vsp_setg call swaps them with no manual bookkeeping, 17// and exactly one is ever composed (probed at pixel level both ways). 18// T10 DISSOLVE EXACT: the core VN transition -- t=0 equals frame A, t=256 equals frame B (full-frame 19// checksums), and the t=128 midpoint is the exact integer channel mix at a probed pixel. 20// license_tier: ORIGINAL expect_exit: 0 21import "nx_syscalls.nx" 22import "nx_estate_path.nx" // ep_anchor: the CWD must not decide this organ's verdict 23import "nx_vnsprite.nx" 24import "nx_gamesave.nx" 25import "nx_png.nx" 26const VG_B: i64 = 65536 27const VG_CANARY: i64 = 12345678 28const VG_STAMP: i64 = 20260729 29const VG_SCHEMA: i64 = 78 30const VG_W: i64 = 640 31const VG_H: i64 = 360 32 33func hw3(s: *u8) -> i64 { var n: i64 = 0; while s[n] != (0 as u8) { n = n + 1 } sys_write(1, s, n); return 0 } 34func hn3(v: i64) -> i64 { 35 let t: *u8 = sys_mmap(32) 36 var m: i64 = v 37 if m == 0 { sys_write(1, "0" as *u8, 1); return 0 } 38 if m < 0 { sys_write(1, "-" as *u8, 1); m = 0 - m } 39 var k: i64 = 0 40 while m > 0 { t[k] = (48 + (m % 10)) as u8; m = m/10; k = k + 1 } 41 while k > 0 { k = k - 1; sys_write(1, (t as i64 + k) as *u8, 1) } 42 return 0 43} 44// procedural character sprite: key-filled, head circle + torso rect (art quality is NOT this axis) 45func mk_body(spr: *i64, sw: i64, sh: i64, key: i64, skin: i64, shirt: i64) -> i64 { 46 var i: i64 = 0 47 while i < sw*sh { spr[i] = key; i = i + 1 } 48 let cx: i64 = sw/2 49 let r: i64 = sw/3 50 var y: i64 = 0 51 while y < sh { 52 var x: i64 = 0 53 while x < sw { 54 let dy: i64 = y - r 55 let dx: i64 = x - cx 56 if dx*dx + dy*dy <= r*r { spr[y*sw + x] = skin } 57 if y > 2*r { if x > sw/5 { if x < sw - sw/5 { spr[y*sw + x] = shirt } } } 58 x = x + 1 59 } 60 y = y + 1 61 } 62 return 0 63} 64// expression sprite: mode 0 = smile (corners up), mode 1 = frown (corners down) 65func mk_expr(spr: *i64, sw: i64, sh: i64, key: i64, ink: i64, mode: i64) -> i64 { 66 var i: i64 = 0 67 while i < sw*sh { spr[i] = key; i = i + 1 } 68 var x: i64 = 1 69 while x < sw - 1 { 70 var y: i64 = sh/2 71 let edge: i64 = sw/4 72 var off: i64 = 0 73 if x < edge { off = 1 } 74 if x >= sw - edge { off = 1 } 75 if mode == 0 { y = y - off + 1 } 76 if mode == 1 { y = y + off - 1 } 77 if y >= 0 { if y < sh { spr[y*sw + x] = ink } } 78 x = x + 1 79 } 80 return 0 81} 82func fill_rect(fb: *i64, W: i64, H: i64, x0: i64, y0: i64, x1: i64, y1: i64, c: i64) -> i64 { 83 var y: i64 = y0 84 if y < 0 { y = 0 } 85 while y < y1 { 86 if y >= H { y = y1 } else { 87 var x: i64 = x0 88 if x < 0 { x = 0 } 89 while x < x1 { 90 if x >= W { x = x1 } else { fb[y*W + x] = c; x = x + 1 } 91 } 92 y = y + 1 93 } 94 } 95 return 0 96} 97// scene layer table, Ren'Py-shaped: 5 rows x 7 fields [spr,x,y,alpha,z,vis,group]. 98// rows 2+3 = smile+frown, BOTH declared, in exclusive group 1 (attributes, not separate scenes); 99// selection happens via vsp_setg -- never by editing the table by hand. 100func fs_layers(lay: *i64) -> i64 { 101 lay[0]=0; lay[1]=140; lay[2]=140; lay[3]=256; lay[4]=10; lay[5]=1; lay[6]=0 102 lay[7]=1; lay[8]=430; lay[9]=150; lay[10]=256; lay[11]=11; lay[12]=1; lay[13]=0 103 lay[14]=2; lay[15]=160; lay[16]=175; lay[17]=256; lay[18]=20; lay[19]=1; lay[20]=1 104 lay[21]=3; lay[22]=160; lay[23]=175; lay[24]=256; lay[25]=20; lay[26]=0; lay[27]=1 105 lay[28]=6; lay[29]=20; lay[30]=282; lay[31]=210; lay[32]=30; lay[33]=1; lay[34]=0 106 return 0 107} 108// bare background: vertical dusk gradient (shared by the scene and the T7 baseline) 109func fs_bg(fb: *i64) -> i64 { 110 var y: i64 = 0 111 while y < VG_H { 112 var x: i64 = 0 113 let rr: i64 = 24 + 40*(VG_H - y)/VG_H 114 let gg: i64 = 26 + 52*(VG_H - y)/VG_H 115 let bb: i64 = 40 + 90*(VG_H - y)/VG_H 116 let c: i64 = rr + gg*256 + bb*VG_B 117 while x < VG_W { fb[y*VG_W + x] = c; x = x + 1 } 118 y = y + 1 119 } 120 return 0 121} 122// full scene: gradient bg, the composed layer table, then a name tag block 123func fs_scene(fb: *i64, sprites: *i64, sprw: *i64, sprh: *i64, lay: *i64, key: i64) -> i64 { 124 fs_bg(fb) 125 vsp_compose(fb, VG_W, VG_H, sprites, sprw, sprh, lay, 5, key) 126 fill_rect(fb, VG_W, VG_H, 24, 262, 140, 284, 70 + 50*256 + 110*VG_B) 127 return 0 128} 129 130func main() -> i64 { 131 // ANCHOR FIRST (2026-08-04, nx_cwdguard finding): this organ reads a RELATIVE 132 // knowledge/ path, so its answer depended on where it was launched. No-op when 133 // already at the estate root, so the cron/MCP context is unchanged. 134 ep_anchor() 135 hw3("=== nx_vnsprite_gate: VN sprite compositing -- real, or a rubber stamp? ===\n\n" as *u8) 136 var pass: i64 = 0 137 var checks: i64 = 0 138 let key: i64 = 255 + 0*256 + 255*VG_B // magenta key 139 let npx: i64 = VG_W*VG_H 140 let fb: *i64 = sys_mmap((npx + 8)*8) as *i64 141 let fb2: *i64 = sys_mmap((npx + 8)*8) as *i64 142 143 // sprite tables: 0 bodyA 1 bodyB 2 smile 3 frown 4 red patch 5 blue patch 6 textbox 144 let sprites: *i64 = sys_mmap(8*8) as *i64 145 let sprw: *i64 = sys_mmap(8*8) as *i64 146 let sprh: *i64 = sys_mmap(8*8) as *i64 147 let bodyA: *i64 = sys_mmap(60*140*8) as *i64 148 mk_body(bodyA, 60, 140, key, 244 + 214*256 + 196*VG_B, 60 + 90*256 + 170*VG_B) 149 sprites[0] = bodyA as i64; sprw[0] = 60; sprh[0] = 140 150 let bodyB: *i64 = sys_mmap(60*140*8) as *i64 151 mk_body(bodyB, 60, 140, key, 232 + 190*256 + 170*VG_B, 160 + 60*256 + 80*VG_B) 152 sprites[1] = bodyB as i64; sprw[1] = 60; sprh[1] = 140 153 let sm: *i64 = sys_mmap(20*10*8) as *i64 154 mk_expr(sm, 20, 10, key, 120 + 30*256 + 30*VG_B, 0) 155 sprites[2] = sm as i64; sprw[2] = 20; sprh[2] = 10 156 let fr: *i64 = sys_mmap(20*10*8) as *i64 157 mk_expr(fr, 20, 10, key, 120 + 30*256 + 30*VG_B, 1) 158 sprites[3] = fr as i64; sprw[3] = 20; sprh[3] = 10 159 let redp: *i64 = sys_mmap(30*30*8) as *i64 160 var i: i64 = 0 161 while i < 900 { redp[i] = 200 + 60*256 + 60*VG_B; i = i + 1 } 162 sprites[4] = redp as i64; sprw[4] = 30; sprh[4] = 30 163 let blup: *i64 = sys_mmap(30*30*8) as *i64 164 i = 0 165 while i < 900 { blup[i] = 20 + 40*256 + 80*VG_B; i = i + 1 } 166 sprites[5] = blup as i64; sprw[5] = 30; sprh[5] = 30 167 let tbox: *i64 = sys_mmap(600*70*8) as *i64 168 i = 0 169 while i < 600*70 { tbox[i] = 18 + 22*256 + 40*VG_B; i = i + 1 } 170 sprites[6] = tbox as i64; sprw[6] = 600; sprh[6] = 70 171 172 // ---------- T1 z-order ---------- 173 checks = checks + 1 174 let bgc: i64 = 30 + 34*256 + 44*VG_B 175 let lay: *i64 = sys_mmap(16*VSP_LROW*8) as *i64 176 vsp_clear(fb, VG_W, VG_H, bgc) 177 lay[0]=4; lay[1]=100; lay[2]=100; lay[3]=256; lay[4]=1; lay[5]=1; lay[6]=0 178 lay[7]=5; lay[8]=110; lay[9]=100; lay[10]=256; lay[11]=2; lay[12]=1; lay[13]=0 179 vsp_compose(fb, VG_W, VG_H, sprites, sprw, sprh, lay, 2, key) 180 let pA: i64 = fb[105*VG_W + 115] 181 lay[4]=2; lay[11]=1 182 vsp_clear(fb, VG_W, VG_H, bgc) 183 vsp_compose(fb, VG_W, VG_H, sprites, sprw, sprh, lay, 2, key) 184 let pB: i64 = fb[105*VG_W + 115] 185 var t1ok: i64 = 0 186 if pA == 20 + 40*256 + 80*VG_B { if pB == 200 + 60*256 + 60*VG_B { t1ok = 1 } } 187 if t1ok == 1 { 188 hw3("T1 GREEN z-order real: overlap pixel = top layer both ways (blue on top, then red after the z swap)\n" as *u8) 189 pass = pass + 1 190 } else { 191 hw3("T1 RED z-order broken: got " as *u8); hn3(pA); hw3(" then " as *u8); hn3(pB); hw3("\n" as *u8) 192 } 193 194 // ---------- T2 alpha exact + key transparent ---------- 195 checks = checks + 1 196 vsp_clear(fb, VG_W, VG_H, 20 + 40*256 + 80*VG_B) 197 vsp_blit(fb, VG_W, VG_H, redp, 30, 30, 50, 50, key, 128) 198 let pm: i64 = fb[65*VG_W + 65] 199 let expct: i64 = 110 + 50*256 + 70*VG_B 200 vsp_blit(fb, VG_W, VG_H, sm, 20, 10, 300, 50, key, 256) 201 let pk: i64 = fb[51*VG_W + 305] 202 var t2ok: i64 = 0 203 if pm == expct { if pk == 20 + 40*256 + 80*VG_B { t2ok = 1 } } 204 if t2ok == 1 { 205 hw3("T2 GREEN alpha exact ((200,60,60) at 128 over (20,40,80) = (110,50,70)) and key pixels fully transparent\n" as *u8) 206 pass = pass + 1 207 } else { 208 hw3("T2 RED blend/key broken: mix=" as *u8); hn3(pm); hw3(" want " as *u8); hn3(expct) 209 hw3(" keyprobe=" as *u8); hn3(pk); hw3("\n" as *u8) 210 } 211 212 // ---------- T3 clip canaries ---------- 213 checks = checks + 1 214 i = 0 215 while i < 8 { fb[npx + i] = VG_CANARY; i = i + 1 } 216 vsp_blit(fb, VG_W, VG_H, tbox, 600, 70, VG_W - 20, VG_H - 20, key, 256) 217 vsp_blit(fb, VG_W, VG_H, tbox, 600, 70, 0 - 500, 0 - 30, key, 256) 218 vsp_blit(fb, VG_W, VG_H, redp, 30, 30, VG_W + 5, 10, key, 256) 219 var canok: i64 = 1 220 i = 0 221 while i < 8 { if fb[npx + i] != VG_CANARY { canok = 0 } i = i + 1 } 222 if canok == 1 { 223 hw3("T3 GREEN clipped blits: off-edge sprites on all sides, 8 canary cells intact\n" as *u8) 224 pass = pass + 1 225 } else { 226 hw3("T3 RED OUT-OF-BOUNDS WRITE past the framebuffer\n" as *u8) 227 } 228 229 // ---------- T4 expression swap visible (via the GROUP call, never hand-editing the table) ---------- 230 checks = checks + 1 231 fs_layers(lay) 232 vsp_setg(lay, 5, 1, 2) 233 fs_scene(fb, sprites, sprw, sprh, lay, key) 234 vsp_setg(lay, 5, 1, 3) 235 fs_scene(fb2, sprites, sprw, sprh, lay, key) 236 var diff: i64 = 0 237 i = 0 238 while i < npx { if fb[i] != fb2[i] { diff = diff + 1 } i = i + 1 } 239 vsp_setg(lay, 5, 1, 3) 240 fs_scene(fb, sprites, sprw, sprh, lay, key) 241 var same: i64 = 0 242 i = 0 243 while i < npx { if fb[i] != fb2[i] { same = same + 1 } i = i + 1 } 244 var t4ok: i64 = 0 245 if diff >= 20 { if same == 0 { t4ok = 1 } } 246 if t4ok == 1 { 247 hw3("T4 GREEN expression swap visible: smile vs frown differ in " as *u8); hn3(diff) 248 hw3(" px; same expression twice differs in 0\n" as *u8) 249 pass = pass + 1 250 } else { 251 hw3("T4 RED expression change invisible or nondeterministic: diff=" as *u8); hn3(diff) 252 hw3(" same=" as *u8); hn3(same); hw3("\n" as *u8) 253 } 254 255 // ---------- T5 scene state round-trip through gs_save ---------- 256 checks = checks + 1 257 fs_layers(lay) 258 vsp_setg(lay, 5, 1, 2) 259 fs_scene(fb, sprites, sprw, sprh, lay, key) 260 let ck0: i64 = vsp_fbck(fb, VG_W, VG_H) 261 let sret: i64 = gs_save("knowledge/nx_vnsprite_scene.sav" as *u8, VG_SCHEMA, lay, 35, VG_STAMP) 262 i = 0 263 while i < 35 { lay[i] = 0; i = i + 1 } 264 let atp: *i64 = sys_mmap(32) as *i64 265 let lret: i64 = gs_load("knowledge/nx_vnsprite_scene.sav" as *u8, lay, 35, atp) 266 fs_scene(fb2, sprites, sprw, sprh, lay, key) 267 let ck1: i64 = vsp_fbck(fb2, VG_W, VG_H) 268 var t5ok: i64 = 0 269 if sret > 0 { if lret >= 35 { if ck0 == ck1 { t5ok = 1 } } } 270 if t5ok == 1 { 271 hw3("T5 GREEN scene state round-trips: gs_save -> ZEROED -> gs_load -> recompose, frame ck " as *u8) 272 hn3(ck1); hw3(" identical\n" as *u8) 273 pass = pass + 1 274 } else { 275 hw3("T5 RED save round-trip broke the scene: ck " as *u8); hn3(ck0); hw3(" vs " as *u8); hn3(ck1) 276 hw3(" (save rc=" as *u8); hn3(sret); hw3(" load rc=" as *u8); hn3(lret); hw3(")\n" as *u8) 277 } 278 279 // ---------- T6 determinism ---------- 280 checks = checks + 1 281 fs_scene(fb, sprites, sprw, sprh, lay, key) 282 fs_scene(fb2, sprites, sprw, sprh, lay, key) 283 let ckd1: i64 = vsp_fbck(fb, VG_W, VG_H) 284 let ckd2: i64 = vsp_fbck(fb2, VG_W, VG_H) 285 if ckd1 == ckd2 { 286 hw3("T6 GREEN deterministic: full scene composed twice, identical ck " as *u8); hn3(ckd1); hw3("\n" as *u8) 287 pass = pass + 1 288 } else { 289 hw3("T6 RED nondeterministic composition\n" as *u8) 290 } 291 292 // ---------- T7 anti-vacuity: scene vs bare background ---------- 293 checks = checks + 1 294 fs_bg(fb2) 295 var ink: i64 = 0 296 var c1: i64 = 0 - 1 297 var c2: i64 = 0 - 1 298 var c3: i64 = 0 - 1 299 var c4: i64 = 0 - 1 300 var c5: i64 = 0 - 1 301 var ncol: i64 = 0 302 i = 0 303 while i < npx { 304 if fb[i] != fb2[i] { 305 ink = ink + 1 306 let v: i64 = fb[i] 307 var seen: i64 = 0 308 if v == c1 { seen = 1 } 309 if v == c2 { seen = 1 } 310 if v == c3 { seen = 1 } 311 if v == c4 { seen = 1 } 312 if v == c5 { seen = 1 } 313 if seen == 0 { if ncol < 5 { 314 if ncol == 0 { c1 = v } 315 if ncol == 1 { c2 = v } 316 if ncol == 2 { c3 = v } 317 if ncol == 3 { c4 = v } 318 if ncol == 4 { c5 = v } 319 ncol = ncol + 1 320 } } 321 } 322 i = i + 1 323 } 324 var t7ok: i64 = 0 325 if ink >= 500 { if ncol >= 5 { t7ok = 1 } } 326 if t7ok == 1 { 327 hw3("T7 GREEN anti-vacuity: scene differs from bare bg in " as *u8); hn3(ink) 328 hw3(" px with >=5 distinct sprite colors\n" as *u8) 329 pass = pass + 1 330 } else { 331 hw3("T7 RED vacuous scene: ink=" as *u8); hn3(ink); hw3(" colors=" as *u8); hn3(ncol); hw3("\n" as *u8) 332 } 333 334 // ---------- T8 scene artifact ---------- 335 checks = checks + 1 336 write_png(fb, VG_W, VG_H, "knowledge/nx_vnsprite_scene.png" as *u8) 337 let lenp: *i64 = sys_mmap(8) as *i64 338 lenp[0] = 0 339 let pb: *u8 = sys_read_file("knowledge/nx_vnsprite_scene.png" as *u8, lenp) 340 var t8ok: i64 = 0 341 if (pb as i64) != 0 { if lenp[0] > 2000 { t8ok = 1 } } 342 if t8ok == 1 { 343 hw3("T8 GREEN scene artifact written: knowledge/nx_vnsprite_scene.png " as *u8); hn3(lenp[0]) 344 hw3(" bytes (gradient bg + 2 characters + alpha textbox + name tag)\n" as *u8) 345 pass = pass + 1 346 } else { 347 hw3("T8 RED scene artifact missing or trivial: bytes=" as *u8); hn3(lenp[0]); hw3("\n" as *u8) 348 } 349 350 // ---------- T9 group exclusivity (the layeredimage bar) ---------- 351 checks = checks + 1 352 // smile's middle-row ink sits at scene y=175+6, frown's at y=175+4 (mk_expr geometry), x=170 353 let inkc: i64 = 120 + 30*256 + 30*VG_B 354 fs_layers(lay) 355 let sh1: i64 = vsp_setg(lay, 5, 1, 2) 356 fs_scene(fb, sprites, sprw, sprh, lay, key) 357 let sA: i64 = fb[181*VG_W + 170] 358 let sB: i64 = fb[179*VG_W + 170] 359 let sh2: i64 = vsp_setg(lay, 5, 1, 3) 360 fs_scene(fb2, sprites, sprw, sprh, lay, key) 361 let fA: i64 = fb2[181*VG_W + 170] 362 let fB: i64 = fb2[179*VG_W + 170] 363 var t9ok: i64 = 0 364 if sh1 == 1 { if sh2 == 1 { if sA == inkc { if sB != inkc { if fB == inkc { if fA != inkc { t9ok = 1 } } } } } } 365 if t9ok == 1 { 366 hw3("T9 GREEN group-exclusive attributes: ONE vsp_setg call swaps smile<->frown; exactly one\n" as *u8) 367 hw3(" attribute of the group composes each time (pixel-probed both ways)\n" as *u8) 368 pass = pass + 1 369 } else { 370 hw3("T9 RED attribute group broken: shown=" as *u8); hn3(sh1); hn3(sh2) 371 hw3(" probes " as *u8); hn3(sA); hw3(" " as *u8); hn3(sB); hw3(" " as *u8); hn3(fA) 372 hw3(" " as *u8); hn3(fB); hw3("\n" as *u8) 373 } 374 375 // ---------- T10 dissolve exact ---------- 376 checks = checks + 1 377 let fbd: *i64 = sys_mmap(npx*8) as *i64 378 vsp_dissolve(fb, fb2, fbd, npx, 0) 379 let ckda: i64 = vsp_fbck(fbd, VG_W, VG_H) 380 let ckfa: i64 = vsp_fbck(fb, VG_W, VG_H) 381 vsp_dissolve(fb, fb2, fbd, npx, 256) 382 let ckdb: i64 = vsp_fbck(fbd, VG_W, VG_H) 383 let ckfb: i64 = vsp_fbck(fb2, VG_W, VG_H) 384 vsp_dissolve(fb, fb2, fbd, npx, 128) 385 // probe the smile-ink pixel: A=ink(120,30,30) B=underlying skin/shirt -- expect the exact 50/50 mix 386 let a1: i64 = fb[181*VG_W + 170] 387 let b1: i64 = fb2[181*VG_W + 170] 388 let mr: i64 = ((a1 % 256) + (b1 % 256))/2 389 let mg: i64 = (((a1/256) % 256) + ((b1/256) % 256))/2 390 let mb2: i64 = (((a1/VG_B) % 256) + ((b1/VG_B) % 256))/2 391 let want: i64 = mr + mg*256 + mb2*VG_B 392 let got: i64 = fbd[181*VG_W + 170] 393 var t10ok: i64 = 0 394 if ckda == ckfa { if ckdb == ckfb { if got == want { t10ok = 1 } } } 395 if t10ok == 1 { 396 hw3("T10 GREEN dissolve exact: t=0 == frame A, t=256 == frame B (full-frame cks), t=128 = exact\n" as *u8) 397 hw3(" integer channel mix at the probed pixel\n" as *u8) 398 pass = pass + 1 399 } else { 400 hw3("T10 RED dissolve broken: endpoints " as *u8); hn3(ckda); hw3("/" as *u8); hn3(ckfa) 401 hw3(" " as *u8); hn3(ckdb); hw3("/" as *u8); hn3(ckfb) 402 hw3(" mid got " as *u8); hn3(got); hw3(" want " as *u8); hn3(want); hw3("\n" as *u8) 403 } 404 405 hw3("\n=== nx_vnsprite_gate " as *u8); hn3(pass); hw3("/" as *u8); hn3(checks) 406 if pass == checks { hw3(" verdict=GREEN ===\n" as *u8); return 0 } 407 hw3(" RED ===\n" as *u8) 408 return 1 409}