code wiki / (root) / nx_nxa.nx

nx_nxa.nx source

↩ module page · 91 lines · 3896 B

1// nx_nxa.nx -- Provides shared identity and integrity primitives for the NXA (Nishi Animated 3D) format version 1. 2const NXA_MAGIC_1000003: i64 = 1000003 3// nx_nxa.nx -- NXA (Nishi Animated 3D) format v1: shared identity + integrity primitives. 4// The format spec lives in knowledge/nxa_format_spec.md. This organ is the ONLY place the 5// magic, tags, and checksum are defined -- writer (nx_fbx_measure) and readers (nx_mesh_view) 6// import it so they can never drift (DRY, rule-15). 7// license_tier: ORIGINAL 8 9const NXA_VER: i64 = 1 10 11// magic = the 8 ASCII bytes "NXANIM01" read as one little-endian i64 (no 64-bit hex literal risk) 12func nxa_magic() -> i64 { 13 let s: *u8 = "NXANIM01" as *u8 14 return ((s[0] & 0xff) as i64) | (((s[1] & 0xff) as i64) << 8) 15 | (((s[2] & 0xff) as i64) << 16) | (((s[3] & 0xff) as i64) << 24) 16 | (((s[4] & 0xff) as i64) << 32) | (((s[5] & 0xff) as i64) << 40) 17 | (((s[6] & 0xff) as i64) << 48) | (((s[7] & 0xff) as i64) << 56) 18} 19// 4-char section tag ("VERT", "TRIS", ...) as u32 20func nxa_tag4(s: *u8) -> i64 { 21 return ((s[0] & 0xff) as i64) | (((s[1] & 0xff) as i64) << 8) 22 | (((s[2] & 0xff) as i64) << 16) | (((s[3] & 0xff) as i64) << 24) 23} 24// order-sensitive rolling checksum over i64 words (seeded so writers can fold split buffers) 25func nxa_check2(seed: i64, w: *i64, nw: i64) -> i64 { 26 var c: i64 = seed 27 var i: i64 = 0 28 while i < nw { c = c*NXA_MAGIC_1000003 + w[i]; i = i + 1 } 29 return c 30} 31// Validate a section and return its TOC entry's word offset, preserving payload extent metadata. 32// Returns a nonnegative entry index, 33// or -1 not-found/not-NXA, -2 future-version (refuse), -3 corrupt (refuse). 34func nxa_section_entry(b: *u8, flen: i64, tag: i64) -> i64 { 35 if flen < 32 { return 0 - 1 } 36 let h: *i64 = b as *i64 37 if h[0] != nxa_magic() { return 0 - 1 } 38 if h[1] > NXA_VER { return 0 - 2 } 39 if h[1] < 1 { return 0 - 3 } 40 let ns: i64 = h[2] 41 if ns < 1 { return 0 - 3 } 42 // The available TOC bytes bound the count before multiplication; v1 declares no 64-section ceiling. 43 if ns > (flen - 32)/32 { return 0 - 3 } 44 let tb: *i64 = ((b as i64) + 32) as *i64 45 if h[3] != nxa_check2(1, tb, ns*4) { return 0 - 3 } 46 var s: i64 = 0 47 while s < ns { 48 if tb[s*4] == tag { 49 let off: i64 = tb[s*4+1] 50 let wl: i64 = tb[s*4+2] 51 if off < 32 + ns*32 { return 0 - 3 } 52 // Wire offsets are byte offsets, but callers receive an i64-word index. 53 // Validate alignment and remaining bytes before address/length arithmetic. 54 if off % 8 != 0 { return 0 - 3 } 55 if off > flen { return 0 - 3 } 56 if wl < 0 { return 0 - 3 } 57 if wl > (flen - off)/8 { return 0 - 3 } 58 let pw: *i64 = ((b as i64) + off) as *i64 59 if tb[s*4+3] != nxa_check2(1, pw, wl) { return 0 - 3 } 60 return 4+s*4 61 } 62 s = s + 1 63 } 64 return 0 - 1 65} 66 67// Compatibility entry point: payload word offset, with unchanged negative return classes. 68func nxa_find(b: *u8,flen: i64,tag: i64) -> i64 { 69 let entry: i64=nxa_section_entry(b,flen,tag) 70 if entry<0 { return entry } 71 let h: *i64=b as *i64 72 return h[entry+1]/8 73} 74 75// Fixed-stride v1 arrays carry [count][count * stride words]. 76// Check exact shape by division before multiplication or any element access. 77func nxa_counted_section(b: *u8,flen: i64,tag: i64,stride: i64) -> i64 { 78 if stride<=0 { return 0-3 } 79 let entry: i64=nxa_section_entry(b,flen,tag) 80 if entry<0 { return entry } 81 let h: *i64=b as *i64 82 let words: i64=h[entry+2] 83 if words<1 { return 0-3 } 84 let offset: i64=h[entry+1]/8 85 let count: i64=h[offset] 86 if count<0 { return 0-3 } 87 let remaining: i64=words-1 88 if remaining%stride!=0 { return 0-3 } 89 if count!=remaining/stride { return 0-3 } 90 return offset 91}