-
Write 8-bit code in your browser.
Ever wanted to be an old-school game programmer?
diff --git a/doc/notes.txt b/doc/notes.txt
index 70e5c04b..06dd3537 100644
--- a/doc/notes.txt
+++ b/doc/notes.txt
@@ -129,6 +129,8 @@ TODO:
- PPU/TIA register write visualization
- nes debug view toolbar
- vcs sound continues when paused
+- upload multiple files/zip file to subdirectory
+ - allow "include graphics.asm" instead of "include project/graphics.asm"
WEB WORKER FORMAT
diff --git a/embed.html b/embed.html
index 57d23b51..25e7bca4 100644
--- a/embed.html
+++ b/embed.html
@@ -9,7 +9,6 @@
top:0;
width:100%;
height:100%;
- background-color:#555;
display: flex;
align-items: center;
justify-content: center;
@@ -76,6 +75,10 @@ function require(modname) {
diff --git a/src/embedui.ts b/src/embedui.ts
index 131a7b76..b728c649 100644
--- a/src/embedui.ts
+++ b/src/embedui.ts
@@ -4,9 +4,11 @@ window['Javatari'].AUTO_START = false;
import { PLATFORMS } from "./emu";
import { Platform } from "./baseplatform";
import { stringToByteArray, getWithBinary } from "./util";
+import { StateRecorderImpl } from "./recorder";
export var platform_id : string; // platform ID string
export var platform : Platform; // platform object
+export var stateRecorder : StateRecorderImpl;
// external libs (TODO)
declare var ga, lzgmini;
@@ -77,9 +79,20 @@ function startROM(title, rom) {
platform.resume();
}
+function enableRecording() {
+ stateRecorder = new StateRecorderImpl(platform);
+ stateRecorder.reset();
+ stateRecorder.checkpointInterval = 60*5; // every 5 sec
+ stateRecorder.maxCheckpoints = 360; // 30 minutes
+ platform.setRecorder(stateRecorder);
+}
+
function startPlatform(qs) {
if (!PLATFORMS[platform_id]) throw Error("Invalid platform '" + platform_id + "'.");
platform = new PLATFORMS[platform_id]($("#emulator")[0]);
+ if (qs['rec']) {
+ enableRecording();
+ }
platform.start();
var title = qs['n'] || 'Game';
var rom : Uint8Array;
@@ -122,7 +135,42 @@ function loadScript(scriptfn, onload) {
// start
export function startEmbed() {
installErrorHandler();
- window.addEventListener("message", loadPlatform, false);
- if (_qs['p']) loadPlatform(_qs);
+ if (_qs['p']) {
+ loadPlatform(_qs);
+ }
}
+// iframe API
+
+window.addEventListener("message", receiveMessage, false);
+
+function receiveMessage(event) {
+ if (event.data) {
+ if (event.data.cmd == 'start' && !platform) {
+ loadPlatform(event);
+ }
+ else if (event.data.cmd == 'reset') {
+ platform.reset();
+ stateRecorder.reset();
+ }
+ else if (event.data.cmd == 'getReplay') {
+ var replay = {
+ frameCount: stateRecorder.frameCount,
+ checkpoints: stateRecorder.checkpoints,
+ framerecs: stateRecorder.framerecs,
+ checkpointInterval: stateRecorder.checkpointInterval,
+ maxCheckpoints: stateRecorder.maxCheckpoints,
+ }
+ event.source.postMessage({replay:replay}, event.origin);
+ }
+ else if (event.data.cmd == 'watchState') {
+ var watchfn = new Function('platform', 'state', event.data.fn);
+ stateRecorder.callbackNewCheckpoint = (state) => {
+ event.source.postMessage({state:watchfn(platform, state)}, event.origin);
+ }
+ }
+ else {
+ console.log("Unknown data.cmd: " + event.data.cmd);
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/recorder.ts b/src/recorder.ts
index 07d04d84..f6e40e46 100644
--- a/src/recorder.ts
+++ b/src/recorder.ts
@@ -7,6 +7,7 @@ type FrameRec = {controls:EmuControlsState, seed:number};
export class StateRecorderImpl implements EmuRecorder {
checkpointInterval : number = 60;
callbackStateChanged : () => void;
+ callbackNewCheckpoint : (state:EmuState) => void;
maxCheckpoints : number = 120;
platform : Platform;
@@ -60,6 +61,7 @@ export class StateRecorderImpl implements EmuRecorder {
recordFrame(state : EmuState) {
this.checkpoints.push(state);
+ if (this.callbackNewCheckpoint) this.callbackNewCheckpoint(state);
// checkpoints full?
if (this.checkpoints.length > this.maxCheckpoints) {
this.checkpoints.shift(); // remove 1st checkpoint
@@ -104,4 +106,8 @@ export class StateRecorderImpl implements EmuRecorder {
this.platform.loadControlsState(this.framerecs[frame].controls);
setNoiseSeed(this.framerecs[frame].seed);
}
+
+ getLastCheckpoint() : EmuState {
+ return this.checkpoints.length && this.checkpoints[this.checkpoints.length-1];
+ }
}