mirror of
https://github.com/sehugg/8bitworkshop.git
synced 2025-01-11 08:30:02 +00:00
embed.html can record video, ack messages
This commit is contained in:
parent
77123211cf
commit
9fe8f5d1a0
@ -46,7 +46,8 @@ if (window.location.host.endsWith('8bitworkshop.com')) {
|
|||||||
<script src="javatari.js/release/javatari/javatari.js"></script>
|
<script src="javatari.js/release/javatari/javatari.js"></script>
|
||||||
<script src="src/cpu/z80fast.js"></script>
|
<script src="src/cpu/z80fast.js"></script>
|
||||||
<script src="jsnes/dist/jsnes.min.js"></script>
|
<script src="jsnes/dist/jsnes.min.js"></script>
|
||||||
<!--<script src="src/cpu/6809.js"></script>-->
|
<script src="src/cpu/6809.js"></script>
|
||||||
|
<script src="FileSaver.js/FileSaver.min.js"></script>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
var exports = {};
|
var exports = {};
|
||||||
|
@ -11,7 +11,7 @@ export var platform : Platform; // platform object
|
|||||||
export var stateRecorder : StateRecorderImpl;
|
export var stateRecorder : StateRecorderImpl;
|
||||||
|
|
||||||
// external libs (TODO)
|
// external libs (TODO)
|
||||||
declare var ga, lzgmini;
|
declare var ga, lzgmini, GIF, saveAs;
|
||||||
|
|
||||||
var _qs = (function (a) {
|
var _qs = (function (a) {
|
||||||
if (!a || a.length == 0)
|
if (!a || a.length == 0)
|
||||||
@ -46,7 +46,7 @@ function uninstallErrorHandler() {
|
|||||||
|
|
||||||
function addPageFocusHandlers() {
|
function addPageFocusHandlers() {
|
||||||
var hidden = false;
|
var hidden = false;
|
||||||
document.addEventListener("visibilitychange", function() {
|
document.addEventListener("visibilitychange", function(e) {
|
||||||
if (document.visibilityState == 'hidden' && platform.isRunning()) {
|
if (document.visibilityState == 'hidden' && platform.isRunning()) {
|
||||||
platform.pause();
|
platform.pause();
|
||||||
hidden = true;
|
hidden = true;
|
||||||
@ -85,15 +85,65 @@ function enableRecording() {
|
|||||||
stateRecorder.checkpointInterval = 60*5; // every 5 sec
|
stateRecorder.checkpointInterval = 60*5; // every 5 sec
|
||||||
stateRecorder.maxCheckpoints = 360; // 30 minutes
|
stateRecorder.maxCheckpoints = 360; // 30 minutes
|
||||||
platform.setRecorder(stateRecorder);
|
platform.setRecorder(stateRecorder);
|
||||||
|
console.log('start recording');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function findPrimaryCanvas() {
|
||||||
|
return $("#emulator").find('canvas');
|
||||||
|
}
|
||||||
|
|
||||||
|
function recordVideo(intervalMsec, maxFrames, callback) {
|
||||||
|
loadScript("gif.js/dist/gif.js", () => {
|
||||||
|
var canvas = findPrimaryCanvas()[0] as HTMLCanvasElement;
|
||||||
|
if (!canvas) {
|
||||||
|
alert("Could not find canvas element to record video!");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
var rotate = 0;
|
||||||
|
if (canvas.style && canvas.style.transform) {
|
||||||
|
if (canvas.style.transform.indexOf("rotate(-90deg)") >= 0)
|
||||||
|
rotate = -1;
|
||||||
|
else if (canvas.style.transform.indexOf("rotate(90deg)") >= 0)
|
||||||
|
rotate = 1;
|
||||||
|
}
|
||||||
|
var gif = new GIF({
|
||||||
|
workerScript: 'gif.js/dist/gif.worker.js',
|
||||||
|
workers: 4,
|
||||||
|
quality: 10,
|
||||||
|
rotate: rotate
|
||||||
|
});
|
||||||
|
gif.on('finished', function(blob) {
|
||||||
|
console.log('finished encoding GIF');
|
||||||
|
callback(blob);
|
||||||
|
});
|
||||||
|
intervalMsec = intervalMsec || 100;
|
||||||
|
maxFrames = maxFrames || 100;
|
||||||
|
var nframes = 0;
|
||||||
|
console.log("Recording video", canvas);
|
||||||
|
var f = () => {
|
||||||
|
if (nframes++ > maxFrames) {
|
||||||
|
console.log("Rendering video");
|
||||||
|
gif.render();
|
||||||
|
} else {
|
||||||
|
gif.addFrame(canvas, {delay: intervalMsec, copy: true});
|
||||||
|
setTimeout(f, intervalMsec);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
f();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
function startPlatform(qs) {
|
function startPlatform(qs) {
|
||||||
if (!PLATFORMS[platform_id]) throw Error("Invalid platform '" + platform_id + "'.");
|
if (!PLATFORMS[platform_id]) throw Error("Invalid platform '" + platform_id + "'.");
|
||||||
platform = new PLATFORMS[platform_id]($("#emulator")[0]);
|
platform = new PLATFORMS[platform_id]($("#emulator")[0]);
|
||||||
if (qs['rec']) {
|
|
||||||
enableRecording();
|
|
||||||
}
|
|
||||||
platform.start();
|
platform.start();
|
||||||
|
// start recorder when click on canvas (TODO?)
|
||||||
|
if (qs['rec']) {
|
||||||
|
findPrimaryCanvas().on('focus', () => {
|
||||||
|
if (!stateRecorder) { enableRecording(); }
|
||||||
|
});
|
||||||
|
}
|
||||||
var title = qs['n'] || 'Game';
|
var title = qs['n'] || 'Game';
|
||||||
var rom : Uint8Array;
|
var rom : Uint8Array;
|
||||||
var romurl = qs['url'];
|
var romurl = qs['url'];
|
||||||
@ -110,6 +160,7 @@ function startPlatform(qs) {
|
|||||||
var lzgrom = stringToByteArray(atob(lzgvar));
|
var lzgrom = stringToByteArray(atob(lzgvar));
|
||||||
rom = new lzgmini().decode(lzgrom);
|
rom = new lzgmini().decode(lzgrom);
|
||||||
}
|
}
|
||||||
|
addPageFocusHandlers();
|
||||||
startROM(title, rom);
|
startROM(title, rom);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -146,14 +197,15 @@ window.addEventListener("message", receiveMessage, false);
|
|||||||
|
|
||||||
function receiveMessage(event) {
|
function receiveMessage(event) {
|
||||||
if (event.data) {
|
if (event.data) {
|
||||||
if (event.data.cmd == 'start' && !platform) {
|
var cmd = event.data.cmd;
|
||||||
|
if (cmd == 'start' && !platform) {
|
||||||
loadPlatform(event);
|
loadPlatform(event);
|
||||||
}
|
}
|
||||||
else if (event.data.cmd == 'reset') {
|
else if (cmd == 'reset') {
|
||||||
platform.reset();
|
platform.reset();
|
||||||
stateRecorder.reset();
|
stateRecorder.reset();
|
||||||
}
|
}
|
||||||
else if (event.data.cmd == 'getReplay') {
|
else if (cmd == 'getReplay') {
|
||||||
var replay = {
|
var replay = {
|
||||||
frameCount: stateRecorder.frameCount,
|
frameCount: stateRecorder.frameCount,
|
||||||
checkpoints: stateRecorder.checkpoints,
|
checkpoints: stateRecorder.checkpoints,
|
||||||
@ -161,16 +213,24 @@ function receiveMessage(event) {
|
|||||||
checkpointInterval: stateRecorder.checkpointInterval,
|
checkpointInterval: stateRecorder.checkpointInterval,
|
||||||
maxCheckpoints: stateRecorder.maxCheckpoints,
|
maxCheckpoints: stateRecorder.maxCheckpoints,
|
||||||
}
|
}
|
||||||
event.source.postMessage({replay:replay}, event.origin);
|
event.source.postMessage({ack:cmd, replay:replay}, event.origin);
|
||||||
}
|
}
|
||||||
else if (event.data.cmd == 'watchState') {
|
else if (cmd == 'watchState') {
|
||||||
var watchfn = new Function('platform', 'state', event.data.fn);
|
var watchfn = new Function('platform', 'state', event.data.fn);
|
||||||
stateRecorder.callbackNewCheckpoint = (state) => {
|
stateRecorder.callbackNewCheckpoint = (state) => {
|
||||||
event.source.postMessage({state:watchfn(platform, state)}, event.origin);
|
event.source.postMessage({ack:cmd, state:watchfn(platform, state)}, event.origin);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else if (cmd == 'recordVideo') {
|
||||||
|
recordVideo(event.data.intervalMsec, event.data.maxFrames, function(blob) {
|
||||||
|
if (event.data.filename) {
|
||||||
|
saveAs(blob, event.data.filename);
|
||||||
|
}
|
||||||
|
event.source.postMessage({ack:cmd, gif:blob}, event.origin);
|
||||||
|
});
|
||||||
|
}
|
||||||
else {
|
else {
|
||||||
console.log("Unknown data.cmd: " + event.data.cmd);
|
console.log("Unknown data.cmd: " + cmd);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -46,7 +46,7 @@ const VCS_PRESETS = [
|
|||||||
{id:'bb/sample.bas', name:'Sprite Test (batariBASIC)'},
|
{id:'bb/sample.bas', name:'Sprite Test (batariBASIC)'},
|
||||||
{id:'bb/FIFA1977.bas', name:'2P Soccer Game (batariBASIC)'},
|
{id:'bb/FIFA1977.bas', name:'2P Soccer Game (batariBASIC)'},
|
||||||
{id:'bb/duck_chase.bas', name:'Duck Chase (batariBASIC)'},
|
{id:'bb/duck_chase.bas', name:'Duck Chase (batariBASIC)'},
|
||||||
{id:'bb/rblast106.bas', name:'Road Blasters (batariBASIC)'},
|
// {id:'bb/rblast106.bas', name:'Road Blasters (batariBASIC)'},
|
||||||
];
|
];
|
||||||
|
|
||||||
Javatari.AUTO_START = false;
|
Javatari.AUTO_START = false;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user