code wiki / _hdl_build / nx_scene_gate.nx
nx_scene_gate.nx source
↩ module page · 135 lines · 6237 B
1// nx_scene_gate.nx -- gate for SCENE-AS-DATA (beat-HS2 rung 2).
2// T1 keyframe interp EXACT: endpoints hit the key values; a midpoint = exact linear blend; pre/post clamp
3// T2 MULTI-CHANNEL independence: 3 channels (an IK-target x, a morph weight, a region param) sampled at the
4// same t give their own interpolated values
5// T3 determinism: sample the whole timeline twice -> identical
6// T4 NXSC1 pack round-trip: save -> load into a FRESH scene -> every channel samples IDENTICALLY; corrupt REJECT
7// T5 PNG knowledge/nx_scene_curve.png: the 3 channel curves plotted across the timeline (eyeball the keyframes)
8// license_tier: ORIGINAL expect_exit: 0
9import "nx_syscalls.nx"
10import "nx_png.nx"
11import "nx_scene.nx"
12
13func hw(s: *u8) -> i64 { var n: i64 = 0; while s[n] != (0 as u8) { n = n + 1 } sys_write(1, s, n); return 0 }
14func pn(v: i64) -> i64 {
15 let b: *u8 = sys_mmap(32) as *u8
16 var x: i64 = v
17 var neg: i64 = 0
18 if x < 0 { neg = 1; x = 0 - x }
19 var i: i64 = 31
20 if x == 0 { b[i] = 48 as u8; i = i - 1 }
21 while x > 0 { b[i] = (48 + x % 10) as u8; x = x / 10; i = i - 1 }
22 if neg == 1 { b[i] = 45 as u8; i = i - 1 }
23 sys_write(1, (b as i64 + i + 1) as *u8, 31 - i)
24 return 0
25}
26func gabs(v: i64) -> i64 { if v < 0 { return 0 - v } return v }
27
28// channel target ids (a scene addresses the rig by these)
29const CH_HANDX: i64 = 100
30const CH_MORPH_SMILE: i64 = 200
31const CH_REGION_SOFT: i64 = 300
32
33func build(base: i64) -> i64 {
34 sc_init(base)
35 let a: i64 = sc_channel(base, CH_HANDX) // hand x: 0 -> 1000 -> 200 over t 0..100..200
36 sc_key_add(base, a, 0, 0)
37 sc_key_add(base, a, 100, 1000)
38 sc_key_add(base, a, 200, 200)
39 let b: i64 = sc_channel(base, CH_MORPH_SMILE) // smile 0 -> 256 over t 50..150 (flat before/after)
40 sc_key_add(base, b, 50, 0)
41 sc_key_add(base, b, 150, 256)
42 let c: i64 = sc_channel(base, CH_REGION_SOFT) // softness 40 -> 16 over t 0..200
43 sc_key_add(base, c, 0, 40)
44 sc_key_add(base, c, 200, 16)
45 return 0
46}
47
48func main() -> i64 {
49 var fails: i64 = 0
50 let S: i64 = sys_mmap(sc_bytes()) as i64
51 build(S)
52
53 // T1 hand-x channel (chan 0)
54 var t1: i64 = 1
55 if sc_sample(S, 0, 0) != 0 { t1 = 0 }
56 if sc_sample(S, 0, 100) != 1000 { t1 = 0 }
57 if sc_sample(S, 0, 50) != 500 { t1 = 0 } // half of 0->1000
58 if sc_sample(S, 0, 150) != 600 { t1 = 0 } // half of 1000->200
59 if sc_sample(S, 0, 0 - 10) != 0 { t1 = 0 } // pre-clamp
60 if sc_sample(S, 0, 999) != 200 { t1 = 0 } // post-clamp
61 if sc_duration(S) != 200 { t1 = 0 }
62 if t1 == 1 { hw("T1 PASS keyframe interp exact: endpoints/midpoints/clamps (hand-x 50%=500, 75%=600), duration=200\n" as *u8) }
63 else { hw("T1 FAIL s0=" as *u8); pn(sc_sample(S, 0, 0)); hw(" s50=" as *u8); pn(sc_sample(S, 0, 50)); hw(" s150=" as *u8); pn(sc_sample(S, 0, 150)); hw("\n" as *u8); fails = fails + 1 }
64
65 // T2 multi-channel at t=100: hand=1000, smile=(100-50)/(150-50)*256=128, soft=40+(16-40)*100/200=28
66 var t2: i64 = 1
67 if sc_sample(S, 0, 100) != 1000 { t2 = 0 }
68 if sc_sample(S, 1, 100) != 128 { t2 = 0 }
69 if sc_sample(S, 2, 100) != 28 { t2 = 0 }
70 if sc_target(S, 1) != CH_MORPH_SMILE { t2 = 0 }
71 if t2 == 1 { hw("T2 PASS multi-channel @t=100: hand=1000, smile=128, soft=28 -- each channel its own curve\n" as *u8) }
72 else { hw("T2 FAIL hand=" as *u8); pn(sc_sample(S, 0, 100)); hw(" smile=" as *u8); pn(sc_sample(S, 1, 100)); hw(" soft=" as *u8); pn(sc_sample(S, 2, 100)); hw("\n" as *u8); fails = fails + 1 }
73
74 // T3 determinism
75 var acc1: i64 = 0
76 var t: i64 = 0
77 while t <= 200 {
78 acc1 = acc1 * 31 + sc_sample(S, 0, t) + sc_sample(S, 1, t) * 7 + sc_sample(S, 2, t) * 13
79 t = t + 1
80 }
81 var acc2: i64 = 0
82 t = 0
83 while t <= 200 {
84 acc2 = acc2 * 31 + sc_sample(S, 0, t) + sc_sample(S, 1, t) * 7 + sc_sample(S, 2, t) * 13
85 t = t + 1
86 }
87 if acc1 == acc2 { hw("T3 PASS determinism: full-timeline sampling identical\n" as *u8) }
88 else { hw("T3 FAIL\n" as *u8); fails = fails + 1 }
89
90 // T4 NXSC1 round-trip
91 let blob: *u8 = sys_mmap(8192) as *u8
92 let blen: i64 = sc_save(S, blob)
93 let S2: i64 = sys_mmap(sc_bytes()) as i64
94 let nc: i64 = sc_load(S2, blob, blen)
95 var t4: i64 = 1
96 if nc != 3 { t4 = 0 }
97 t = 0
98 while t <= 200 {
99 if sc_sample(S2, 0, t) != sc_sample(S, 0, t) { t4 = 0 }
100 if sc_sample(S2, 1, t) != sc_sample(S, 1, t) { t4 = 0 }
101 if sc_sample(S2, 2, t) != sc_sample(S, 2, t) { t4 = 0 }
102 t = t + 20
103 }
104 blob[1] = 90 as u8
105 if sc_load(S2, blob, blen) != 0 - 1 { t4 = 0 }
106 if t4 == 1 { hw("T4 PASS NXSC1 pack " as *u8); pn(blen); hw("B round-trips (every channel samples identical); corrupt magic REJECTED -- scenes = mod-economy content\n" as *u8) }
107 else { hw("T4 FAIL nc=" as *u8); pn(nc); hw("\n" as *u8); fails = fails + 1 }
108
109 // T5 PNG
110 let TW: i64 = 256
111 let TH: i64 = 128
112 let fb: *i64 = sys_mmap(TW * TH * 8) as *i64
113 var pi: i64 = 0
114 while pi < TW * TH { fb[pi] = 22 + 26 * 256 + 34 * 65536; pi = pi + 1 }
115 var px: i64 = 0
116 while px < TW {
117 let tt: i64 = px * 200 / TW
118 // hand (amber): 0..1000 -> y 118..10
119 let hy: i64 = 118 - sc_sample(S, 0, tt) * 108 / 1000
120 if hy >= 0 { if hy < TH { fb[hy * TW + px] = 235 + 190 * 256 + 120 * 65536 } }
121 // smile (rose): 0..256 -> y 118..10
122 let sy: i64 = 118 - sc_sample(S, 1, tt) * 108 / 256
123 if sy >= 0 { if sy < TH { fb[sy * TW + px] = 235 + 140 * 256 + 150 * 65536 } }
124 // soft (blue): 0..40 -> y 118..10
125 let cy: i64 = 118 - sc_sample(S, 2, tt) * 108 / 40
126 if cy >= 0 { if cy < TH { fb[cy * TW + px] = 120 + 180 * 256 + 240 * 65536 } }
127 px = px + 1
128 }
129 write_png(fb, TW, TH, "knowledge/nx_scene_curve.png" as *u8)
130 hw("T5 PNG written: knowledge/nx_scene_curve.png (3 channel keyframe curves)\n" as *u8)
131
132 if fails == 0 { hw("VERDICT GREEN: scene-as-data 5/5 -- keyframed multi-channel timelines, exact integer interp, NXSC1 packs (Illusion 'positions' as CID mod content, on our data law)\n" as *u8) }
133 else { hw("VERDICT RED fails=" as *u8); pn(fails); hw("\n" as *u8) }
134 return fails
135}