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'>
|
<script type='text/javascript'>
|
||||||
EJS_player = '#game';
|
EJS_player = '#game';
|
||||||
EJS_core = 'nes';
|
EJS_core = 'nes';
|
||||||
EJS_gameUrl = '';
|
EJS_gameUrl = 'mega_mountain.nes';
|
||||||
EJS_pathtodata = 'data/';
|
EJS_pathtodata = 'data/';
|
||||||
EJS_DEBUG_XX = true;
|
EJS_DEBUG_XX = true;
|
||||||
</script>
|
</script>
|
||||||
|
|
|
@ -52,3 +52,8 @@
|
||||||
font-size: 12px;
|
font-size: 12px;
|
||||||
color: #bcbcbc;
|
color: #bcbcbc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.ejs_canvas {
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
|
153
src/emulator.js
153
src/emulator.js
|
@ -2,11 +2,12 @@ class EmulatorJS {
|
||||||
createElement(type) {
|
createElement(type) {
|
||||||
return document.createElement(type);
|
return document.createElement(type);
|
||||||
}
|
}
|
||||||
downloadFile(path, cb, progressCB) {
|
downloadFile(path, cb, progressCB, notWithPath) {
|
||||||
//todo. Progress callback
|
//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();
|
const ab = await res.arrayBuffer();
|
||||||
cb(ab);
|
cb(new Uint8Array(ab));
|
||||||
});
|
});
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -14,6 +15,8 @@ class EmulatorJS {
|
||||||
this.setElements(element);
|
this.setElements(element);
|
||||||
this.listeners = [];
|
this.listeners = [];
|
||||||
this.config = config;
|
this.config = config;
|
||||||
|
this.canvas = this.createElement('canvas');
|
||||||
|
this.canvas.classList.add('ejs_canvas');
|
||||||
|
|
||||||
|
|
||||||
this.game.classList.add("ejs_game");
|
this.game.classList.add("ejs_game");
|
||||||
|
@ -46,20 +49,20 @@ class EmulatorJS {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
e.target.remove();
|
e.target.remove();
|
||||||
this.createText();
|
this.createText();
|
||||||
this.downloadRom();
|
this.downloadGameCore();
|
||||||
}
|
}
|
||||||
// End start button
|
// End start button
|
||||||
createText() {
|
createText() {
|
||||||
const text = this.createElement("div");
|
this.textElem = this.createElement("div");
|
||||||
text.classList.add("ejs_loading_text");
|
this.textElem.classList.add("ejs_loading_text");
|
||||||
text.innerText = this.localization("Loading...");
|
this.textElem.innerText = this.localization("Loading...");
|
||||||
this.elements.parent.appendChild(text);
|
this.elements.parent.appendChild(this.textElem);
|
||||||
}
|
}
|
||||||
localization(text) {
|
localization(text) {
|
||||||
//todo
|
//todo
|
||||||
return text;
|
return text;
|
||||||
}
|
}
|
||||||
checkCompression(e) {
|
checkCompression(data) {
|
||||||
function isCompressed(data) { //https://www.garykessler.net/library/file_sigs.html
|
function isCompressed(data) { //https://www.garykessler.net/library/file_sigs.html
|
||||||
//todo. Use hex instead of numbers
|
//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))) {
|
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';
|
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() {
|
async function decompressRar() {
|
||||||
|
|
||||||
}
|
}
|
||||||
const compression = isCompressed(e);
|
const compression = isCompressed(data.slice(0, 10));
|
||||||
if (compression) {
|
if (compression) {
|
||||||
console.log(compression); //where I left off
|
//Need to do zip and rar still
|
||||||
|
return decompress7z(data);
|
||||||
} else {
|
} 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() {
|
downloadRom() {
|
||||||
this.downloadFile(this.config.gameUrl, (e) => {
|
this.downloadFile(this.config.gameUrl, (e) => {
|
||||||
this.checkCompression(e).then((data) => {
|
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 = {};
|
const config = {};
|
||||||
config.gameUrl = EJS_gameUrl;
|
config.gameUrl = EJS_gameUrl;
|
||||||
config.dataPath = scriptPath;
|
config.dataPath = scriptPath;
|
||||||
|
'undefined' != typeof EJS_core && (config.system = EJS_core);
|
||||||
|
|
||||||
new EmulatorJS(EJS_player, config);
|
new EmulatorJS(EJS_player, config);
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue