From 2096fcfe16ae9ac00cb5e5ef2f53fa27a7f61d52 Mon Sep 17 00:00:00 2001
From: Ethan O'Brien <77750390+ethanaobrien@users.noreply.github.com>
Date: Mon, 3 Jul 2023 10:34:18 -0500
Subject: [PATCH] Save settings in browser
---
src/emulator.js | 137 +++++++++++++++++++++++++++++++++++++-----------
1 file changed, 106 insertions(+), 31 deletions(-)
diff --git a/src/emulator.js b/src/emulator.js
index d455c30..10e7ee7 100644
--- a/src/emulator.js
+++ b/src/emulator.js
@@ -618,31 +618,38 @@ class EmulatorJS {
this.Module = window.Module;
}
startGame() {
- this.textElem.remove();
- this.textElem = null;
- this.initAudio();
-
- this.game.classList.remove("ejs_game");
- this.game.appendChild(this.canvas);
- const args = [];
- if (this.debug) args.push('-v');
- args.push('/'+this.fileName);
- console.log(args);
- this.Module.callMain(args);
- this.Module.resumeMainLoop();
- this.started = true;
- this.paused = false;
- if (this.touch) {
- this.virtualGamepad.style.display = "";
+ try {
+ this.initAudio();
+
+ const args = [];
+ if (this.debug) args.push('-v');
+ args.push('/'+this.fileName);
+ console.log(args);
+ this.Module.callMain(args);
+ this.Module.resumeMainLoop();
+ this.started = true;
+ this.paused = false;
+ if (this.touch) {
+ this.virtualGamepad.style.display = "";
+ }
+
+ this.checkSupportedOpts();
+ this.setupSettingsMenu();
+ this.loadSettings();
+ this.updateCheatUI();
+ this.updateGamepadLabels();
+ this.setVolume(this.volume);
+ this.elements.parent.focus();
+ this.textElem.remove();
+ this.textElem = null;
+ this.game.classList.remove("ejs_game");
+ this.game.appendChild(this.canvas);
+ this.handleResize();
+ } catch(e) {
+ console.warn("failed to start game", e);
+ this.textElem.innerText = "Failed to start game";
+ this.textElem.style.color = "red";
}
-
- this.checkSupportedOpts();
- this.setupSettingsMenu();
- this.handleResize();
- this.updateCheatUI();
- this.updateGamepadLabels();
- this.setVolume(this.volume);
- this.elements.parent.focus();
this.callEvent("start");
}
bindListeners() {
@@ -652,11 +659,11 @@ class EmulatorJS {
this.createCheatsMenu()
this.setVirtualGamepad();
this.addEventListener(this.elements.parent, "keydown keyup", this.keyChange.bind(this));
- this.addEventListener(this.elements.parent, "mousedown mouseup click touchstart touchend touchcancel", (e) => {
- this.elements.parent.focus();
+ this.addEventListener(this.elements.parent, "mousedown touchstart", (e) => {
+ if (document.activeElement !== this.elements.parent) this.elements.parent.focus();
})
this.addEventListener(window, "resize", this.handleResize.bind(this));
- //this.addEventListener(window, "blur", e => console.log(e), true); //TODO - add "click to make keyboard keys work" message
+ //this.addEventListener(window, "blur", e => console.log(e), true); //TODO - add "click to make keyboard keys work" message?
this.gamepad = new GamepadHandler(); //https://github.com/ethanaobrien/Gamepad
this.gamepad.on('connected', (e) => {
if (!this.gamepadLabels) return;
@@ -962,6 +969,7 @@ class EmulatorJS {
this.setVolume(0);
}, volumeSettings);
const unmuteButton = addButton("Unmute", '', () => {
+ if (this.volume === 0) this.volume = 0.5;
muteButton.style.display = "";
unmuteButton.style.display = "none";
this.muted = false;
@@ -982,6 +990,7 @@ class EmulatorJS {
volumeSlider.setAttribute("aria-valuemax", 100);
this.setVolume = (volume) => {
+ this.saveSettings();
this.muted = (volume === 0);
volumeSlider.value = volume;
volumeSlider.setAttribute("aria-valuenow", volume*100);
@@ -990,6 +999,8 @@ class EmulatorJS {
if (this.gameManager) {
//this.gameManager.setVolume(volume);
}
+ unmuteButton.style.display = (volume === 0) ? "" : "none";
+ muteButton.style.display = (volume === 0) ? "none" : "";
}
this.initAudio = () => {
RA.queueAudio = () => {
@@ -1023,10 +1034,10 @@ class EmulatorJS {
this.addEventListener(volumeSlider, "change mousemove touchmove mousedown touchstart mouseup", (e) => {
setTimeout(() => {
- this.volume = parseFloat(volumeSlider.value);
+ const newVal = parseFloat(volumeSlider.value);
+ if (newVal === 0 && this.muted) return;
+ this.volume = newVal;
this.setVolume(this.volume);
- unmuteButton.style.display = (this.volume === 0) ? "" : "none";
- muteButton.style.display = (this.volume === 0) ? "none" : "";
}, 5);
})
@@ -1216,10 +1227,12 @@ class EmulatorJS {
"Reset": () => {
this.controls = JSON.parse(JSON.stringify(this.defaultControllers));
this.checkGamepadInputs();
+ this.saveSettings();
},
"Clear": () => {
this.controls = {0:{},1:{},2:{},3:{}};
this.checkGamepadInputs();
+ this.saveSettings();
},
"Close": () => {
this.controlMenu.style.display = "none";
@@ -1519,6 +1532,7 @@ class EmulatorJS {
this.controls[player][num].value = e.key.toLowerCase();
this.controlPopup.parentElement.setAttribute("hidden", "");
this.checkGamepadInputs();
+ this.saveSettings();
return;
}
if (this.settingsMenu.style.display !== "none" || this.isPopupOpen()) return;
@@ -1551,6 +1565,7 @@ class EmulatorJS {
this.controls[player][num].value2 = (e.type === "axischanged" ? e.axis+":"+value : e.index);
this.controlPopup.parentElement.setAttribute("hidden", "");
this.checkGamepadInputs();
+ this.saveSettings();
return;
}
if (this.settingsMenu.style.display !== "none" || this.isPopupOpen()) return;
@@ -2003,7 +2018,53 @@ class EmulatorJS {
'height': height
};
}
+ saveSettings() {
+ if (!window.localStorage || !this.settingsLoaded) return;
+ const coreSpecific = {
+ controlSettings: this.controls,
+ settings: this.settings,
+ cheats: this.cheats
+ }
+ const ejs_settings = {
+ volume: this.volume,
+ muted: this.muted
+ }
+ localStorage.setItem("ejs-settings", JSON.stringify(ejs_settings));
+ localStorage.setItem("ejs-"+this.getCore()+"-settings", JSON.stringify(coreSpecific));
+ }
+ loadSettings() {
+ if (!window.localStorage) return;
+ this.settingsLoaded = true;
+ let ejs_settings = localStorage.getItem("ejs-settings");
+ let coreSpecific = localStorage.getItem("ejs-"+this.getCore()+"-settings");
+ if (coreSpecific) {
+ try {
+ coreSpecific = JSON.parse(coreSpecific);
+ if (!(coreSpecific.controlSettings instanceof Object) || !(coreSpecific.settings instanceof Object) || !(coreSpecific.cheats instanceof Object)) return;
+ this.controls = coreSpecific.controlSettings;
+ this.checkGamepadInputs();
+ for (const k in coreSpecific.settings) {
+ this.changeSettingOption(k, coreSpecific.settings[k]);
+ }
+ this.cheats = coreSpecific.cheats;
+ } catch(e) {
+ console.warn("Could not load previous settings", e);
+ }
+ }
+ if (ejs_settings) {
+ try {
+ ejs_settings = JSON.parse(ejs_settings);
+ if (typeof ejs_settings.volume !== "number" || typeof ejs_settings.muted !== "boolean") return;
+ this.volume = ejs_settings.volume;
+ this.muted = ejs_settings.muted;
+ this.setVolume(this.muted ? 0 : this.volume);
+ } catch(e) {
+ console.warn("Could not load previous settings", e);
+ }
+ }
+ }
menuOptionChanged(option, value) {
+ this.saveSettings();
if (option === "shader") {
try {
this.Module.FS.unlink("/shader/shader.glslp");
@@ -2035,9 +2096,13 @@ class EmulatorJS {
home.classList.add("ejs_setting_home");
home.classList.add("ejs_setting_menu");
nested.appendChild(home);
+ let funcs = [];
+ this.changeSettingOption = (title, newValue) => {
+ this.settings[title] = newValue;
+ funcs.forEach(e => e(title));
+ }
const addToMenu = (title, id, options, defaultOption) => {
-
const menuOption = this.createElement("div");
menuOption.classList.add("ejs_settings_main_bar");
const span = this.createElement("span");
@@ -2094,9 +2159,19 @@ class EmulatorJS {
}
}
+ funcs.push((title) => {
+ if (id !== title) return;
+ for (let j=0; j