@tishlang/tish-format 3.2.2 → 3.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -101,21 +101,41 @@ type BgAsset = (
101
101
  &'static agb::display::tile_data::TileData,
102
102
  );
103
103
 
104
- static ASSET_BGS: SingleCore<RefCell<Vec<BgAsset>>> = SingleCore::new(RefCell::new(Vec::new()));
104
+ /// ⚠️ A FIXED TABLE, not a `Vec`, because every entry is `&'static` cartridge data and the registry
105
+ /// never needed to own one.
106
+ ///
107
+ /// As a `Vec` it did: registering N backgrounds ran N pushes with log2(N) reallocs, all during
108
+ /// module init before the program body, and the freed buffers left the heap too fragmented for the
109
+ /// one big contiguous block a GBA UI canvas wants. A game with a handful of backgrounds booted; a
110
+ /// game with 162 died in the allocator with plenty of total heap free.
111
+ ///
112
+ /// This costs `MAX_BGS * size_of::<Option<BgAsset>>()` of STATIC memory and allocates nothing.
113
+ /// ⚠️ Not a `Vec` with `reserve` — that charges every small game for the largest one.
114
+ const MAX_BGS: usize = 256;
115
+ static ASSET_BGS: SingleCore<RefCell<[Option<BgAsset>; MAX_BGS]>> =
116
+ SingleCore::new(RefCell::new([None; MAX_BGS]));
117
+ static ASSET_BGS_N: SingleCore<RefCell<usize>> = SingleCore::new(RefCell::new(0));
105
118
 
106
119
  /// Register a background (palettes + tile data), returning its i32 handle.
107
120
  pub fn __asset_register_bg(bg: BgAsset) -> i32 {
108
- ASSET_BGS.with(|c| {
109
- let mut v = c.borrow_mut();
110
- let idx = v.len() as i32;
111
- v.push(bg);
121
+ ASSET_BGS_N.with(|n| {
122
+ let mut n = n.borrow_mut();
123
+ if *n >= MAX_BGS {
124
+ return -1;
125
+ }
126
+ let idx = *n as i32;
127
+ ASSET_BGS.with(|c| c.borrow_mut()[*n] = Some(bg));
128
+ *n += 1;
112
129
  idx
113
130
  })
114
131
  }
115
132
 
116
133
  /// Look up a registered background by handle. `None` if out of range.
117
134
  pub fn asset_bg(handle: i32) -> Option<BgAsset> {
118
- ASSET_BGS.with(|c| c.borrow().get(handle as usize).copied())
135
+ if handle < 0 || handle as usize >= MAX_BGS {
136
+ return None;
137
+ }
138
+ ASSET_BGS.with(|c| c.borrow()[handle as usize])
119
139
  }
120
140
 
121
141
  /// Registered fonts (`font<N>:` imports) — a compile-time-baked `Font`. All `font<N>:` schemes share
@@ -283,6 +283,35 @@ pub fn str_index(s: &str, idx: &Value) -> Value {
283
283
  }
284
284
  }
285
285
 
286
+ /// `&str` charCodeAt — the code unit at `idx`, NaN when out of range. Mirrors
287
+ /// `tish_runtime::str_char_code_at`, and missing here for the same reason `str_index` was: codegen
288
+ /// emits it whenever the receiver is statically a `&str`, so `"abc".charCodeAt(i)` was a hard E0425
289
+ /// on the GBA target only while compiling everywhere else. Found by a ROM that hashes its own trace.
290
+ #[inline]
291
+ pub fn str_char_code_at(s: &str, idx: &Value) -> Value {
292
+ let i = match idx {
293
+ Value::Number(n) if *n >= 0.0 && n.fract() == 0.0 => *n as usize,
294
+ _ => return Value::Number(f64::NAN),
295
+ };
296
+ match s.chars().nth(i) {
297
+ Some(c) => Value::Number(c as u32 as f64),
298
+ None => Value::Number(f64::NAN),
299
+ }
300
+ }
301
+
302
+ /// `&str` charAt — the 1-character string at `idx`, `""` out of range. Same reason as above.
303
+ #[inline]
304
+ pub fn str_char_at(s: &str, idx: &Value) -> Value {
305
+ let i = match idx {
306
+ Value::Number(n) if *n >= 0.0 && n.fract() == 0.0 => *n as usize,
307
+ _ => return Value::String("".into()),
308
+ };
309
+ match s.chars().nth(i) {
310
+ Some(c) => Value::String(c.to_string().into()),
311
+ None => Value::String("".into()),
312
+ }
313
+ }
314
+
286
315
  pub fn delete_property(obj: &Value, key: &Value) -> Value {
287
316
  match obj {
288
317
  Value::Object(m) => {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tishlang/tish-format",
3
- "version": "3.2.2",
3
+ "version": "3.3.0",
4
4
  "description": "Tish code formatter",
5
5
  "license": "PIF",
6
6
  "repository": {
Binary file
Binary file
Binary file
Binary file
Binary file