wasmcart 0.2.0 → 0.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.
Files changed (2) hide show
  1. package/package.json +1 -1
  2. package/src/CartHost.js +33 -4
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "wasmcart",
3
- "version": "0.2.0",
3
+ "version": "0.3.0",
4
4
  "description": "WASM cartridge host - load and run sandboxed .wasm and .wasc game carts",
5
5
  "type": "module",
6
6
  "main": "index.js",
package/src/CartHost.js CHANGED
@@ -214,6 +214,12 @@ export class CartHost {
214
214
  this.lastFrameTime = 0;
215
215
  this.audioReadCursor = 0;
216
216
 
217
+ // Deterministic-clock mode (opt-in via setFixedStep). 0 = use wall-clock
218
+ // (performance.now) as normal. > 0 = each runFrame advances this many virtual
219
+ // ms, so frame N always reports timeMs = N * step regardless of real elapsed
220
+ // time. Lets a host step frames reproducibly (screenshot testing, harnesses).
221
+ this._fixedStepMs = 0;
222
+
217
223
  // Views into cart memory (set after init)
218
224
  this._u8 = null;
219
225
  this._u16 = null;
@@ -629,10 +635,21 @@ export class CartHost {
629
635
  * @returns {{ framebuffer: Uint8Array, width: number, height: number, audio: Int16Array|Float32Array|null }}
630
636
  */
631
637
  runFrame(pads) {
632
- const now = performance.now();
633
- const deltaMs = now - this.lastFrameTime;
634
- const timeMs = now - this.startTime;
635
- this.lastFrameTime = now;
638
+ let timeMs, deltaMs;
639
+ if (this._fixedStepMs > 0) {
640
+ // Deterministic clock: a host (e.g. an automated harness) drives frames
641
+ // and wants frame N to always report the same time, independent of how
642
+ // long the frame actually took. Each runFrame advances a fixed virtual
643
+ // step. Opt-in via setFixedStep(); wall-clock is the default (below).
644
+ deltaMs = this._fixedStepMs;
645
+ timeMs = this.frameCount * this._fixedStepMs;
646
+ this.lastFrameTime = this.startTime + timeMs;
647
+ } else {
648
+ const now = performance.now();
649
+ deltaMs = now - this.lastFrameTime;
650
+ timeMs = now - this.startTime;
651
+ this.lastFrameTime = now;
652
+ }
636
653
 
637
654
  this._updateViews(); // in case memory grew
638
655
 
@@ -679,6 +696,18 @@ export class CartHost {
679
696
  };
680
697
  }
681
698
 
699
+ /**
700
+ * Enable (or disable) the deterministic fixed-step clock. When set to a
701
+ * positive value, each runFrame() advances exactly that many virtual ms and
702
+ * reports timeMs = frameCount * stepMs — so a host driving frames gets
703
+ * reproducible timing independent of real elapsed time. Pass 0 (or nothing) to
704
+ * return to wall-clock timing. Optional; standalone hosts never call this.
705
+ * @param {number} [stepMs=1000/60] virtual ms per frame (default ~16.667 for 60fps)
706
+ */
707
+ setFixedStep(stepMs = 1000 / 60) {
708
+ this._fixedStepMs = stepMs > 0 ? stepMs : 0;
709
+ }
710
+
682
711
  /**
683
712
  * Get the current save data.
684
713
  * @returns {Uint8Array|null}