mirror of
https://github.com/EmulatorJS/EmulatorJS.git
synced 2024-09-20 02:46:23 +00:00
the game loads, no controls are available yet
This commit is contained in:
parent
f2bf2e9c30
commit
27f6802d0b
4 changed files with 145 additions and 18 deletions
|
@ -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>
|
||||
|
|
|
@ -52,3 +52,8 @@
|
|||
font-size: 12px;
|
||||
color: #bcbcbc;
|
||||
}
|
||||
|
||||
.ejs_canvas {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
|
|
153
src/emulator.js
153
src/emulator.js
|
@ -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();
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
Loading…
Reference in a new issue