the game loads, no controls are available yet

This commit is contained in:
Ethan O'Brien 2023-06-20 16:17:49 -05:00
parent f2bf2e9c30
commit 27f6802d0b
4 changed files with 145 additions and 18 deletions

View file

@ -5,7 +5,7 @@
<script type='text/javascript'>
EJS_player = '#game';
EJS_core = 'nes';
EJS_gameUrl = '';
EJS_gameUrl = 'mega_mountain.nes';
EJS_pathtodata = 'data/';
EJS_DEBUG_XX = true;
</script>

View file

@ -52,3 +52,8 @@
font-size: 12px;
color: #bcbcbc;
}
.ejs_canvas {
width: 100%;
height: 100%;
}

View file

@ -2,11 +2,12 @@ class EmulatorJS {
createElement(type) {
return document.createElement(type);
}
downloadFile(path, cb, progressCB) {
downloadFile(path, cb, progressCB, notWithPath) {
//todo. Progress callback
fetch(this.config.dataPath + path).then(async res => {
const basePath = notWithPath ? '' : this.config.dataPath;
fetch(basePath + path).then(async res => {
const ab = await res.arrayBuffer();
cb(ab);
cb(new Uint8Array(ab));
});
}
@ -14,6 +15,8 @@ class EmulatorJS {
this.setElements(element);
this.listeners = [];
this.config = config;
this.canvas = this.createElement('canvas');
this.canvas.classList.add('ejs_canvas');
this.game.classList.add("ejs_game");
@ -46,20 +49,20 @@ class EmulatorJS {
e.preventDefault();
e.target.remove();
this.createText();
this.downloadRom();
this.downloadGameCore();
}
// End start button
createText() {
const text = this.createElement("div");
text.classList.add("ejs_loading_text");
text.innerText = this.localization("Loading...");
this.elements.parent.appendChild(text);
this.textElem = this.createElement("div");
this.textElem.classList.add("ejs_loading_text");
this.textElem.innerText = this.localization("Loading...");
this.elements.parent.appendChild(this.textElem);
}
localization(text) {
//todo
return text;
}
checkCompression(e) {
checkCompression(data) {
function isCompressed(data) { //https://www.garykessler.net/library/file_sigs.html
//todo. Use hex instead of numbers
if ((data[0] === 80 && data[1] === 75) && ((data[2] === 3 && data[3] === 4) || (data[2] === 5 && data[3] === 6) || (data[2] === 7 && data[3] === 8))) {
@ -70,27 +73,145 @@ class EmulatorJS {
return 'rar';
}
}
async function decompressZip7z() {
const createWorker = (path) => {
return new Promise((resolve, reject) => {
this.downloadFile(path, (fileData) => {
const blob = new Blob([fileData], {
'type': 'application/javascript'
})
const url = window.URL.createObjectURL(blob);
resolve(new Worker(url));
});
})
}
const decompress7z = (file) => {
return new Promise((resolve, reject) => {
const files = {};
function onMessage(data) {
if (!data.data) return;
//data.data.t/ 4=progress, 2 is file, 1 is zip done
if (data.data.t === 2) {
files[data.data.file] = data.data.data;
}
if (data.data.t === 1) {
resolve(files);
}
}
createWorker('compression/extract7z.js').then((worker) => {
worker.onmessage = onMessage;
worker.postMessage(file);
//console.log(file);
})
})
}
async function decompressRar() {
}
const compression = isCompressed(e);
const compression = isCompressed(data.slice(0, 10));
if (compression) {
console.log(compression); //where I left off
//Need to do zip and rar still
return decompress7z(data);
} else {
return new Promise(resolve => resolve(e));
return new Promise(resolve => resolve(data));
}
return e;
}
downloadGameCore() {
this.downloadFile('cores/'+this.getCore()+'-wasm.data', (e) => {
this.checkCompression(e).then((data) => {
//console.log(data);
let js, wasm;
for (let k in data) {
if (k.endsWith(".wasm")) {
wasm = data[k];
} else if (k.endsWith(".js")) {
js = data[k];
}
}
this.initGameCore(js, wasm);
});
});
}
initGameCore(js, wasm) {
this.initModule(wasm);
let script = this.createElement("script");
script.src = URL.createObjectURL(new Blob([js], {type: "application/javascript"}));
script.onload = this.downloadRom.bind(this);
document.body.appendChild(script);
}
getCore() {
const core = this.config.system;
//switch case or an object holding this data
if (core === 'nes') {
return 'fceumm';
}
}
downloadRom() {
this.downloadFile(this.config.gameUrl, (e) => {
this.checkCompression(e).then((data) => {
console.log(e);
});
FS.writeFile("/game", data);
this.startGame();
});
}, null, true);
}
initModule(wasmData) {
window.Module = {
'TOTAL_MEMORY': 0x10000000,
'noInitialRun': true,
'arguments': [],
'preRun': [],
'postRun': [],
'canvas': this.canvas,
'print': function(msg) {
if (window.EJS_DEBUG_XX === true) {
console.log(msg);
}
},
'printErr': function(msg) {
if (window.EJS_DEBUG_XX === true) {
console.log(msg);
}
},
'totalDependencies': 0,
'monitorRunDependencies': () => {},
'locateFile': function(fileName) {
console.log(fileName);
if (fileName.endsWith(".wasm")) {
return URL.createObjectURL(new Blob([wasmData], {type: "application/wasm"}));
}
},
'readAsync': function(_0x20d016, _0x9d2de4, _0x1425ee) {
console.log(_0x20d016, _0x9d2de4, _0x1425ee)
}
};
}
startGame() {
this.bindListeners();
this.textElem.remove();
this.textElem = null;
this.game.classList.remove("ejs_game");
this.game.appendChild(this.canvas);
const args = [];
if (window.EJS_DEBUG_XX === true) args.push('-v');
args.push('/game');
Module.callMain(args);
Module.resumeMainLoop();
Module.setCanvasSize(800, 600);
let i=0;
// this needs to be fixed. Ugh
let j = setInterval(function() { // some cores have a messed up screen size on load (for example - gba)
if (i>20) clearInterval(j);
i++;
Module.setCanvasSize(800, 600);
}, 100)
}
bindListeners() {
//keyboard, etc...
this.addEventListener(this.game, 'contextmenu', (e) => {
e.preventDefault();
})
}

View file

@ -40,6 +40,7 @@
const config = {};
config.gameUrl = EJS_gameUrl;
config.dataPath = scriptPath;
'undefined' != typeof EJS_core && (config.system = EJS_core);
new EmulatorJS(EJS_player, config);