Modularize EmulatorJS

This commit is contained in:
Ethan O'Brien 2024-08-03 20:54:05 -05:00
parent 10e5320261
commit 41c7850dfa
2 changed files with 52 additions and 48 deletions

View file

@ -39,8 +39,8 @@ class EJS_GameManager {
this.writeFile("/home/web_user/retroarch/userdata/retroarch.cfg", this.getRetroArchCfg()); this.writeFile("/home/web_user/retroarch/userdata/retroarch.cfg", this.getRetroArchCfg());
this.FS.mount(IDBFS, {}, '/data/saves'); this.FS.mount(this.FS.filesystems.IDBFS, {autoPersist: true}, '/data/saves');
this.FS.syncfs(true, () => {}); //this.FS.syncfs(true, () => {});
this.initShaders(); this.initShaders();
@ -48,10 +48,8 @@ class EJS_GameManager {
this.toggleMainLoop(0); this.toggleMainLoop(0);
this.functions.saveSaveFiles(); this.functions.saveSaveFiles();
setTimeout(() => { setTimeout(() => {
this.FS.syncfs(() => {
try {window.abort()} catch(e){}; try {window.abort()} catch(e){};
}); }, 1000);
}, 500);
}) })
} }
loadExternalFiles() { loadExternalFiles() {
@ -164,7 +162,7 @@ class EJS_GameManager {
return new Promise(async resolve => { return new Promise(async resolve => {
while (1) { while (1) {
try { try {
FS.stat("/screenshot.png"); this.FS.stat("/screenshot.png");
return resolve(this.FS.readFile("/screenshot.png")); return resolve(this.FS.readFile("/screenshot.png"));
} catch(e) {} } catch(e) {}
@ -273,14 +271,14 @@ class EJS_GameManager {
} }
for (let i=0; i<fileNames.length; i++) { for (let i=0; i<fileNames.length; i++) {
const contents = " FILE \""+fileNames[i]+"\" BINARY\n TRACK 01 MODE1/2352\n INDEX 01 00:00:00"; const contents = " FILE \""+fileNames[i]+"\" BINARY\n TRACK 01 MODE1/2352\n INDEX 01 00:00:00";
FS.writeFile("/"+baseFileName+"-"+i+".cue", contents); this.FS.writeFile("/"+baseFileName+"-"+i+".cue", contents);
} }
if (fileNames.length > 1) { if (fileNames.length > 1) {
let contents = ""; let contents = "";
for (let i=0; i<fileNames.length; i++) { for (let i=0; i<fileNames.length; i++) {
contents += "/"+baseFileName+"-"+i+".cue\n"; contents += "/"+baseFileName+"-"+i+".cue\n";
} }
FS.writeFile("/"+baseFileName+".m3u", contents); this.FS.writeFile("/"+baseFileName+".m3u", contents);
} }
return (fileNames.length === 1) ? baseFileName+"-0.cue" : baseFileName+".m3u"; return (fileNames.length === 1) ? baseFileName+"-0.cue" : baseFileName+".m3u";
} }
@ -304,7 +302,7 @@ class EJS_GameManager {
if (paths[i] === "") continue; if (paths[i] === "") continue;
cp += "/"+paths[i]; cp += "/"+paths[i];
if (!FS.analyzePath(cp).exists) { if (!FS.analyzePath(cp).exists) {
FS.mkdir(cp); this.FS.mkdir(cp);
} }
} }
this.FS.writeFile(path, data); this.FS.writeFile(path, data);
@ -349,15 +347,15 @@ class EJS_GameManager {
} }
saveSaveFiles() { saveSaveFiles() {
this.functions.saveSaveFiles(); this.functions.saveSaveFiles();
this.FS.syncfs(false, () => {}); //this.FS.syncfs(false, () => {});
} }
supportsStates() { supportsStates() {
return !!this.functions.supportsStates(); return !!this.functions.supportsStates();
} }
getSaveFile() { getSaveFile() {
this.saveSaveFiles(); this.saveSaveFiles();
const exists = FS.analyzePath(this.getSaveFilePath()).exists; const exists = this.FS.analyzePath(this.getSaveFilePath()).exists;
return (exists ? FS.readFile(this.getSaveFilePath()) : null); return (exists ? this.FS.readFile(this.getSaveFilePath()) : null);
} }
loadSaveFiles() { loadSaveFiles() {
this.clearEJSResetTimer(); this.clearEJSResetTimer();

View file

@ -702,9 +702,11 @@ class EmulatorJS {
}, null, false, {responseType: "text", method: "GET"}); }, null, false, {responseType: "text", method: "GET"});
} }
initGameCore(js, wasm, thread) { initGameCore(js, wasm, thread) {
this.initModule(wasm, thread);
let script = this.createElement("script"); let script = this.createElement("script");
script.src = URL.createObjectURL(new Blob([js], {type: "application/javascript"})); script.src = URL.createObjectURL(new Blob([js], {type: "application/javascript"}));
script.addEventListener("load", () => {
this.initModule(wasm, thread);
});
document.body.appendChild(script); document.body.appendChild(script);
} }
getBaseFileName(force) { getBaseFileName(force) {
@ -773,11 +775,11 @@ class EmulatorJS {
this.checkCompression(new Uint8Array(data), this.localization("Decompress Game Patch")).then((data) => { this.checkCompression(new Uint8Array(data), this.localization("Decompress Game Patch")).then((data) => {
for (const k in data) { for (const k in data) {
if (k === "!!notCompressedData") { if (k === "!!notCompressedData") {
FS.writeFile(this.config.gamePatchUrl.split('/').pop().split("#")[0].split("?")[0], data[k]); this.gameManager.FS.writeFile(this.config.gamePatchUrl.split('/').pop().split("#")[0].split("?")[0], data[k]);
break; break;
} }
if (k.endsWith('/')) continue; if (k.endsWith('/')) continue;
FS.writeFile("/" + k.split('/').pop(), data[k]); this.gameManager.FS.writeFile("/" + k.split('/').pop(), data[k]);
} }
resolve(); resolve();
}) })
@ -823,11 +825,11 @@ class EmulatorJS {
this.checkCompression(new Uint8Array(data), this.localization("Decompress Game Parent")).then((data) => { this.checkCompression(new Uint8Array(data), this.localization("Decompress Game Parent")).then((data) => {
for (const k in data) { for (const k in data) {
if (k === "!!notCompressedData") { if (k === "!!notCompressedData") {
FS.writeFile(this.config.gameParentUrl.split('/').pop().split("#")[0].split("?")[0], data[k]); this.gameManager.FS.writeFile(this.config.gameParentUrl.split('/').pop().split("#")[0].split("?")[0], data[k]);
break; break;
} }
if (k.endsWith('/')) continue; if (k.endsWith('/')) continue;
FS.writeFile("/" + k.split('/').pop(), data[k]); this.gameManager.FS.writeFile("/" + k.split('/').pop(), data[k]);
} }
resolve(); resolve();
}) })
@ -873,11 +875,11 @@ class EmulatorJS {
this.checkCompression(new Uint8Array(data), this.localization("Decompress Game BIOS")).then((data) => { this.checkCompression(new Uint8Array(data), this.localization("Decompress Game BIOS")).then((data) => {
for (const k in data) { for (const k in data) {
if (k === "!!notCompressedData") { if (k === "!!notCompressedData") {
FS.writeFile(this.config.biosUrl.split('/').pop().split("#")[0].split("?")[0], data[k]); this.gameManager.FS.writeFile(this.config.biosUrl.split('/').pop().split("#")[0].split("?")[0], data[k]);
break; break;
} }
if (k.endsWith('/')) continue; if (k.endsWith('/')) continue;
FS.writeFile("/" + k.split('/').pop(), data[k]); this.gameManager.FS.writeFile("/" + k.split('/').pop(), data[k]);
} }
resolve(); resolve();
}) })
@ -928,7 +930,7 @@ class EmulatorJS {
const gotGameData = (data) => { const gotGameData = (data) => {
if (['arcade', 'mame'].includes(this.getCore(true))) { if (['arcade', 'mame'].includes(this.getCore(true))) {
this.fileName = this.getBaseFileName(true); this.fileName = this.getBaseFileName(true);
FS.writeFile(this.fileName, new Uint8Array(data)); this.gameManager.FS.writeFile(this.fileName, new Uint8Array(data));
resolve(); resolve();
return; return;
} }
@ -950,20 +952,20 @@ class EmulatorJS {
for (let i=0; i<paths.length-1; i++) { for (let i=0; i<paths.length-1; i++) {
if (paths[i] === "") continue; if (paths[i] === "") continue;
cp += `/${paths[i]}`; cp += `/${paths[i]}`;
if (!FS.analyzePath(cp).exists) { if (!this.gameManager.FS.analyzePath(cp).exists) {
FS.mkdir(cp); this.gameManager.FS.mkdir(cp);
} }
} }
} }
if (fileName.endsWith('/')) { if (fileName.endsWith('/')) {
FS.mkdir(fileName); this.gameManager.FS.mkdir(fileName);
return; return;
} }
if (fileName === "!!notCompressedData") { if (fileName === "!!notCompressedData") {
FS.writeFile(altName, fileData); this.gameManager.FS.writeFile(altName, fileData);
fileNames.push(altName); fileNames.push(altName);
} else { } else {
FS.writeFile(`/${fileName}`, fileData); this.gameManager.FS.writeFile(`/${fileName}`, fileData);
fileNames.push(fileName); fileNames.push(fileName);
} }
}).then(() => { }).then(() => {
@ -1067,26 +1069,28 @@ class EmulatorJS {
})(); })();
} }
initModule(wasmData, threadData) { initModule(wasmData, threadData) {
window.Module = { window.EJS_Runtime({
'noInitialRun': true, noInitialRun: true,
'onRuntimeInitialized': this.downloadFiles.bind(this), onRuntimeInitialized: null,
'arguments': [], arguments: [],
'preRun': [], preRun: [],
'postRun': [], postRun: [],
'canvas': this.canvas, canvas: this.canvas,
'print': (msg) => { print: (msg) => {
if (this.debug) { if (this.debug) {
console.log(msg); console.log(msg);
} }
}, },
'printErr': (msg) => { printErr: (msg) => {
if (this.debug) { if (this.debug) {
console.log(msg); console.log(msg);
} }
}, },
'totalDependencies': 0, totalDependencies: 0,
'monitorRunDependencies': () => {}, monitorRunDependencies: () => {},
'locateFile': function(fileName) { locateFile: function(fileName) {
if (this.debug) console.log(fileName); if (this.debug) console.log(fileName);
if (fileName.endsWith(".wasm")) { if (fileName.endsWith(".wasm")) {
return URL.createObjectURL(new Blob([wasmData], {type: "application/wasm"})); return URL.createObjectURL(new Blob([wasmData], {type: "application/wasm"}));
@ -1094,8 +1098,10 @@ class EmulatorJS {
return URL.createObjectURL(new Blob([threadData], {type: "application/javascript"})); return URL.createObjectURL(new Blob([threadData], {type: "application/javascript"}));
} }
} }
}; }).then(module => {
this.Module = window.Module; this.Module = module;
this.downloadFiles();
});
} }
startGame() { startGame() {
try { try {
@ -1815,10 +1821,10 @@ class EmulatorJS {
for (let i=0; i<paths.length-1; i++) { for (let i=0; i<paths.length-1; i++) {
if (paths[i] === "") continue; if (paths[i] === "") continue;
cp += "/"+paths[i]; cp += "/"+paths[i];
if (!FS.analyzePath(cp).exists) FS.mkdir(cp); if (!this.gameManager.FS.analyzePath(cp).exists) this.gameManager.FS.mkdir(cp);
} }
if (FS.analyzePath(path).exists) FS.unlink(path); if (this.gameManager.FS.analyzePath(path).exists) this.gameManager.FS.unlink(path);
FS.writeFile(path, sav); this.gameManager.FS.writeFile(path, sav);
this.gameManager.loadSaveFiles(); this.gameManager.loadSaveFiles();
}); });
const netplay = addButton("Netplay", '<svg viewBox="0 0 512 512"><path fill="currentColor" d="M364.215 192h131.43c5.439 20.419 8.354 41.868 8.354 64s-2.915 43.581-8.354 64h-131.43c5.154-43.049 4.939-86.746 0-128zM185.214 352c10.678 53.68 33.173 112.514 70.125 151.992.221.001.44.008.661.008s.44-.008.661-.008c37.012-39.543 59.467-98.414 70.125-151.992H185.214zm174.13-192h125.385C452.802 84.024 384.128 27.305 300.95 12.075c30.238 43.12 48.821 96.332 58.394 147.925zm-27.35 32H180.006c-5.339 41.914-5.345 86.037 0 128h151.989c5.339-41.915 5.345-86.037-.001-128zM152.656 352H27.271c31.926 75.976 100.6 132.695 183.778 147.925-30.246-43.136-48.823-96.35-58.393-147.925zm206.688 0c-9.575 51.605-28.163 104.814-58.394 147.925 83.178-15.23 151.852-71.949 183.778-147.925H359.344zm-32.558-192c-10.678-53.68-33.174-112.514-70.125-151.992-.221 0-.44-.008-.661-.008s-.44.008-.661.008C218.327 47.551 195.872 106.422 185.214 160h141.572zM16.355 192C10.915 212.419 8 233.868 8 256s2.915 43.581 8.355 64h131.43c-4.939-41.254-5.154-84.951 0-128H16.355zm136.301-32c9.575-51.602 28.161-104.81 58.394-147.925C127.872 27.305 59.198 84.024 27.271 160h125.385z"/></svg>', async () => { const netplay = addButton("Netplay", '<svg viewBox="0 0 512 512"><path fill="currentColor" d="M364.215 192h131.43c5.439 20.419 8.354 41.868 8.354 64s-2.915 43.581-8.354 64h-131.43c5.154-43.049 4.939-86.746 0-128zM185.214 352c10.678 53.68 33.173 112.514 70.125 151.992.221.001.44.008.661.008s.44-.008.661-.008c37.012-39.543 59.467-98.414 70.125-151.992H185.214zm174.13-192h125.385C452.802 84.024 384.128 27.305 300.95 12.075c30.238 43.12 48.821 96.332 58.394 147.925zm-27.35 32H180.006c-5.339 41.914-5.345 86.037 0 128h151.989c5.339-41.915 5.345-86.037-.001-128zM152.656 352H27.271c31.926 75.976 100.6 132.695 183.778 147.925-30.246-43.136-48.823-96.35-58.393-147.925zm206.688 0c-9.575 51.605-28.163 104.814-58.394 147.925 83.178-15.23 151.852-71.949 183.778-147.925H359.344zm-32.558-192c-10.678-53.68-33.174-112.514-70.125-151.992-.221 0-.44-.008-.661-.008s-.44.008-.661.008C218.327 47.551 195.872 106.422 185.214 160h141.572zM16.355 192C10.915 212.419 8 233.868 8 256s2.915 43.581 8.355 64h131.43c-4.939-41.254-5.154-84.951 0-128H16.355zm136.301-32c9.575-51.602 28.161-104.81 58.394-147.925C127.872 27.305 59.198 84.024 27.271 160h125.385z"/></svg>', async () => {