Capture Overhaul (#1011)

* screenshot

* newline

* nice screenshots

* screenShot function

* Screen Record

* takeScreenshot

* retroarch if 0

* change to this.capture

* normalize "

* no no

* no no again

* use `this.settings`

* newline and fix merge

* Quality to Upscale

* fix settings call

* add checkForEmptyMenu
This commit is contained in:
Allan Niles 2025-06-18 08:46:30 -06:00 committed by GitHub
parent a796c4a386
commit 88d4a05615
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
10 changed files with 1036 additions and 798 deletions

View File

@ -10,15 +10,15 @@
"compression.js"
];
const folderPath = (path) => path.substring(0, path.length - path.split('/').pop().length);
const folderPath = (path) => path.substring(0, path.length - path.split("/").pop().length);
let scriptPath = (typeof window.EJS_pathtodata === "string") ? window.EJS_pathtodata : folderPath((new URL(document.currentScript.src)).pathname);
if (!scriptPath.endsWith('/')) scriptPath += '/';
if (!scriptPath.endsWith("/")) scriptPath += "/";
//console.log(scriptPath);
function loadScript(file) {
return new Promise(function(resolve) {
let script = document.createElement('script');
let script = document.createElement("script");
script.src = function() {
if ('undefined' != typeof EJS_paths && typeof EJS_paths[file] === 'string') {
if ("undefined" != typeof EJS_paths && typeof EJS_paths[file] === "string") {
return EJS_paths[file];
} else if (file.endsWith("emulator.min.js")) {
return scriptPath + file;
@ -36,10 +36,10 @@
function loadStyle(file) {
return new Promise(function(resolve) {
let css = document.createElement('link');
css.rel = 'stylesheet';
let css = document.createElement("link");
css.rel = "stylesheet";
css.href = function() {
if ('undefined' != typeof EJS_paths && typeof EJS_paths[file] === 'string') {
if ("undefined" != typeof EJS_paths && typeof EJS_paths[file] === "string") {
return EJS_paths[file];
} else {
return scriptPath + file;
@ -64,19 +64,19 @@
await loadScript(scripts[i]);
}
} else {
await loadStyle('emulator.css');
await loadStyle("emulator.css");
}
}
}
if (('undefined' != typeof EJS_DEBUG_XX && true === EJS_DEBUG_XX)) {
if (("undefined" != typeof EJS_DEBUG_XX && true === EJS_DEBUG_XX)) {
for (let i = 0; i < scripts.length; i++) {
await loadScript(scripts[i]);
}
await loadStyle('emulator.css');
await loadStyle("emulator.css");
} else {
await loadScript('emulator.min.js');
await loadStyle('emulator.min.css');
await loadScript("emulator.min.js");
await loadStyle("emulator.min.css");
}
const config = {};
config.gameUrl = window.EJS_gameUrl;
@ -113,7 +113,7 @@
config.disableCue = window.EJS_disableCue;
config.startBtnName = window.EJS_startButtonName;
config.softLoad = window.EJS_softLoad;
config.screenRecording = window.EJS_screenRecording;
config.capture = window.EJS_screenCapture;
config.externalFiles = window.EJS_externalFiles;
config.dontExtractBIOS = window.EJS_dontExtractBIOS;
config.disableDatabases = window.EJS_disableDatabases;
@ -133,7 +133,7 @@
try {
let path;
console.log("Loading language", language);
if ('undefined' != typeof EJS_paths && typeof EJS_paths[language] === 'string') {
if ("undefined" != typeof EJS_paths && typeof EJS_paths[language] === "string") {
path = EJS_paths[language];
} else {
path = scriptPath + "localization/" + language + ".json";

View File

@ -121,8 +121,8 @@
"EmulatorJS": "EmulatorJS",
"Clear All": "Effacer tout",
"Take Screenshot": "Prendre une capture d'écran",
"Start screen recording": "Démarrer l'enregistrement de l'écran",
"Stop screen recording": "Arrêter l'enregistrement de l'écran",
"Start Screen Recording": "Démarrer l'enregistrement de l'écran",
"Stop Screen Recording": "Arrêter l'enregistrement de l'écran",
"Quick Save": "Enregistrement rapide",
"Quick Load": "Chargement rapide",
"REWIND": "REMBOBINER",

View File

@ -121,8 +121,8 @@
"EmulatorJS": "EmulatorJS",
"Clear All": "Clear All",
"Take Screenshot": "Take Screenshot",
"Start screen recording": "Start screen recording",
"Stop screen recording": "Stop screen recording",
"Start Screen Recording": "Start Screen Recording",
"Stop Screen Recording": "Stop Screen Recording",
"Quick Save": "Quick Save",
"Quick Load": "Quick Load",
"REWIND": "REWIND",

View File

@ -121,8 +121,8 @@
"EmulatorJS": "EmulatorJS",
"Clear All": "Limpiar todo",
"Take Screenshot": "Tomar Captura de Pantalla",
"Start screen recording": "Iniciar grabación de pantalla",
"Stop screen recording": "Detener grabación de pantalla",
"Start Screen Recording": "Iniciar grabación de pantalla",
"Stop Screen Recording": "Detener grabación de pantalla",
"Quick Save": "Guardado Rápido",
"Quick Load": "Carga Rápida",
"REWIND": "REBOBINAR",

View File

@ -121,8 +121,8 @@
"EmulatorJS": "EmulatorJS",
"Clear All": "پاک کردن همه",
"Take Screenshot": "اسکرین شات بگیرید",
"Start screen recording": "شروع ضبط صفحه",
"Stop screen recording": "ضبط صفحه را متوقف کنید",
"Start Screen Recording": "شروع ضبط صفحه",
"Stop Screen Recording": "ضبط صفحه را متوقف کنید",
"Quick Save": "ذخیره سریع",
"Quick Load": "بارگذاری سریع",
"REWIND": "عقب",

View File

@ -307,4 +307,4 @@
"DPAD_DOWN": "DPAD_DOWN",
"DPAD_LEFT": "DPAD_LEFT",
"DPAD_RIGHT": "DPAD_RIGHT"
}
}

View File

@ -121,8 +121,8 @@
"EmulatorJS": "EmulatorJS",
"Clear All": "Hepsini Temizle",
"Take Screenshot": "Ekran Görüntüsü Al",
"Start screen recording": "Ekran kaydı başlat",
"Stop screen recording": "Ekran kaydını durdur",
"Start Screen Recording": "Ekran kaydı başlat",
"Stop Screen Recording": "Ekran kaydını durdur",
"Quick Save": "Hızlı Kaydet",
"Quick Load": "Hızlı Yükle",
"REWIND": "GERİ SAR",

View File

@ -4,34 +4,35 @@ class EJS_GameManager {
this.Module = Module;
this.FS = this.Module.FS;
this.functions = {
restart: this.Module.cwrap('system_restart', '', []),
saveStateInfo: this.Module.cwrap('save_state_info', 'string', []),
loadState: this.Module.cwrap('load_state', 'number', ['string', 'number']),
screenshot: this.Module.cwrap('cmd_take_screenshot', '', []),
simulateInput: this.Module.cwrap('simulate_input', 'null', ['number', 'number', 'number']),
toggleMainLoop: this.Module.cwrap('toggleMainLoop', 'null', ['number']),
getCoreOptions: this.Module.cwrap('get_core_options', 'string', []),
setVariable: this.Module.cwrap('ejs_set_variable', 'null', ['string', 'string']),
setCheat: this.Module.cwrap('set_cheat', 'null', ['number', 'number', 'string']),
resetCheat: this.Module.cwrap('reset_cheat', 'null', []),
toggleShader: this.Module.cwrap('shader_enable', 'null', ['number']),
getDiskCount: this.Module.cwrap('get_disk_count', 'number', []),
getCurrentDisk: this.Module.cwrap('get_current_disk', 'number', []),
setCurrentDisk: this.Module.cwrap('set_current_disk', 'null', ['number']),
getSaveFilePath: this.Module.cwrap('save_file_path', 'string', []),
saveSaveFiles: this.Module.cwrap('cmd_savefiles', '', []),
supportsStates: this.Module.cwrap('supports_states', 'number', []),
loadSaveFiles: this.Module.cwrap('refresh_save_files', 'null', []),
toggleFastForward: this.Module.cwrap('toggle_fastforward', 'null', ['number']),
setFastForwardRatio: this.Module.cwrap('set_ff_ratio', 'null', ['number']),
toggleRewind: this.Module.cwrap('toggle_rewind', 'null', ['number']),
setRewindGranularity: this.Module.cwrap('set_rewind_granularity', 'null', ['number']),
toggleSlowMotion: this.Module.cwrap('toggle_slow_motion', 'null', ['number']),
setSlowMotionRatio: this.Module.cwrap('set_sm_ratio', 'null', ['number']),
getFrameNum: this.Module.cwrap('get_current_frame_count', 'number', ['']),
setVSync: this.Module.cwrap('set_vsync', 'null', ['number']),
setVideoRoation: this.Module.cwrap('set_video_rotation', 'null', ['number']),
setKeyboardEnabled: this.Module.cwrap('ejs_set_keyboard_enabled', 'null', ['number'])
restart: this.Module.cwrap("system_restart", "", []),
saveStateInfo: this.Module.cwrap("save_state_info", "string", []),
loadState: this.Module.cwrap("load_state", "number", ["string", "number"]),
screenshot: this.Module.cwrap("cmd_take_screenshot", "", []),
simulateInput: this.Module.cwrap("simulate_input", "null", ["number", "number", "number"]),
toggleMainLoop: this.Module.cwrap("toggleMainLoop", "null", ["number"]),
getCoreOptions: this.Module.cwrap("get_core_options", "string", []),
setVariable: this.Module.cwrap("ejs_set_variable", "null", ["string", "string"]),
setCheat: this.Module.cwrap("set_cheat", "null", ["number", "number", "string"]),
resetCheat: this.Module.cwrap("reset_cheat", "null", []),
toggleShader: this.Module.cwrap("shader_enable", "null", ["number"]),
getDiskCount: this.Module.cwrap("get_disk_count", "number", []),
getCurrentDisk: this.Module.cwrap("get_current_disk", "number", []),
setCurrentDisk: this.Module.cwrap("set_current_disk", "null", ["number"]),
getSaveFilePath: this.Module.cwrap("save_file_path", "string", []),
saveSaveFiles: this.Module.cwrap("cmd_savefiles", "", []),
supportsStates: this.Module.cwrap("supports_states", "number", []),
loadSaveFiles: this.Module.cwrap("refresh_save_files", "null", []),
toggleFastForward: this.Module.cwrap("toggle_fastforward", "null", ["number"]),
setFastForwardRatio: this.Module.cwrap("set_ff_ratio", "null", ["number"]),
toggleRewind: this.Module.cwrap("toggle_rewind", "null", ["number"]),
setRewindGranularity: this.Module.cwrap("set_rewind_granularity", "null", ["number"]),
toggleSlowMotion: this.Module.cwrap("toggle_slow_motion", "null", ["number"]),
setSlowMotionRatio: this.Module.cwrap("set_sm_ratio", "null", ["number"]),
getFrameNum: this.Module.cwrap("get_current_frame_count", "number", [""]),
setVSync: this.Module.cwrap("set_vsync", "null", ["number"]),
setVideoRoation: this.Module.cwrap("set_video_rotation", "null", ["number"]),
getVideoDimensions: this.Module.cwrap("get_video_dimensions", "number", ["string"]),
setKeyboardEnabled: this.Module.cwrap("ejs_set_keyboard_enabled", "null", ["number"])
}
this.writeFile("/home/web_user/.config/retroarch/retroarch.cfg", this.getRetroArchCfg());
@ -47,7 +48,7 @@ class EJS_GameManager {
this.saveSaveFiles();
}
this.toggleMainLoop(0);
this.FS.unmount('/data/saves');
this.FS.unmount("/data/saves");
setTimeout(() => {
try {
this.Module.abort();
@ -67,7 +68,7 @@ class EJS_GameManager {
return new Promise(async resolve => {
this.mkdir("/data");
this.mkdir("/data/saves");
this.FS.mount(this.FS.filesystems.IDBFS, { autoPersist: true }, '/data/saves');
this.FS.mount(this.FS.filesystems.IDBFS, { autoPersist: true }, "/data/saves");
this.FS.syncfs(true, resolve);
});
}
@ -84,7 +85,7 @@ class EJS_GameManager {
}
loadExternalFiles() {
return new Promise(async (resolve, reject) => {
if (this.EJS.config.externalFiles && this.EJS.config.externalFiles.constructor.name === 'Object') {
if (this.EJS.config.externalFiles && this.EJS.config.externalFiles.constructor.name === "Object") {
for (const key in this.EJS.config.externalFiles) {
await new Promise(done => {
this.EJS.downloadFile(this.EJS.config.externalFiles[key], null, true, { responseType: "arraybuffer", method: "GET" }).then(async (res) => {
@ -168,7 +169,7 @@ class EJS_GameManager {
this.mkdir("/shader");
for (const shaderFileName in this.EJS.config.shaders) {
const shader = this.EJS.config.shaders[shaderFileName];
if (typeof shader === 'string') {
if (typeof shader === "string") {
this.FS.writeFile(`/shader/${shaderFileName}`, shader);
}
}
@ -196,20 +197,20 @@ class EJS_GameManager {
}
loadState(state) {
try {
this.FS.unlink('game.state');
this.FS.unlink("game.state");
} catch(e) {}
this.FS.writeFile('/game.state', state);
this.FS.writeFile("/game.state", state);
this.clearEJSResetTimer();
this.functions.loadState("game.state", 0);
setTimeout(() => {
try {
this.FS.unlink('game.state');
this.FS.unlink("game.state");
} catch(e) {}
}, 5000)
}
screenshot() {
try {
this.FS.unlink('screenshot.png');
this.FS.unlink("screenshot.png");
} catch(e) {}
this.functions.screenshot();
return new Promise(async resolve => {
@ -224,13 +225,13 @@ class EJS_GameManager {
}
quickSave(slot) {
if (!slot) slot = 1;
let name = slot + '-quick.state';
let name = slot + "-quick.state";
try {
this.FS.unlink(name);
} catch(e) {}
try {
let data = this.getState();
this.FS.writeFile('/' + name, data);
this.FS.writeFile("/" + name, data);
} catch(e) {
return false;
}
@ -239,7 +240,7 @@ class EJS_GameManager {
quickLoad(slot) {
if (!slot) slot = 1;
(async () => {
let name = slot + '-quick.state';
let name = slot + "-quick.state";
this.clearEJSResetTimer();
this.functions.loadState(name, 0);
})();
@ -251,7 +252,7 @@ class EJS_GameManager {
}
if ([24, 25, 26, 27, 28, 29].includes(index)) {
if (index === 24 && value === 1) {
const slot = this.EJS.settings['save-state-slot'] ? this.EJS.settings['save-state-slot'] : "1";
const slot = this.EJS.settings["save-state-slot"] ? this.EJS.settings["save-state-slot"] : "1";
if (this.quickSave(slot)) {
this.EJS.displayMessage(this.EJS.localization("SAVED STATE TO SLOT") + " " + slot);
} else {
@ -259,20 +260,20 @@ class EJS_GameManager {
}
}
if (index === 25 && value === 1) {
const slot = this.EJS.settings['save-state-slot'] ? this.EJS.settings['save-state-slot'] : "1";
const slot = this.EJS.settings["save-state-slot"] ? this.EJS.settings["save-state-slot"] : "1";
this.quickLoad(slot);
this.EJS.displayMessage(this.EJS.localization("LOADED STATE FROM SLOT") + " " + slot);
}
if (index === 26 && value === 1) {
let newSlot;
try {
newSlot = parseFloat(this.EJS.settings['save-state-slot'] ? this.EJS.settings['save-state-slot'] : "1") + 1;
newSlot = parseFloat(this.EJS.settings["save-state-slot"] ? this.EJS.settings["save-state-slot"] : "1") + 1;
} catch(e) {
newSlot = 1;
}
if (newSlot > 9) newSlot = 1;
this.EJS.displayMessage(this.EJS.localization("SET SAVE STATE SLOT TO") + " " + newSlot);
this.EJS.changeSettingOption('save-state-slot', newSlot.toString());
this.EJS.changeSettingOption("save-state-slot", newSlot.toString());
}
if (index === 27) {
this.functions.toggleFastForward(this.EJS.isFastForward ? !value : value);
@ -342,10 +343,10 @@ class EJS_GameManager {
}
loadPpssppAssets() {
return new Promise(resolve => {
this.EJS.downloadFile('cores/ppsspp-assets.zip', null, false, { responseType: "arraybuffer", method: "GET" }).then((res) => {
this.EJS.downloadFile("cores/ppsspp-assets.zip", null, false, { responseType: "arraybuffer", method: "GET" }).then((res) => {
this.EJS.checkCompression(new Uint8Array(res.data), this.EJS.localization("Decompress Game Data")).then((pspassets) => {
if (pspassets === -1) {
this.EJS.textElem.innerText = this.localization('Network Error');
this.EJS.textElem.innerText = this.localization("Network Error");
this.EJS.textElem.style.color = "red";
return;
}
@ -443,8 +444,11 @@ class EJS_GameManager {
return this.functions.getFrameNum();
}
setVideoRotation(rotation) {
this.functions.setVideoRoation(rotation);
}
getVideoDimensions(type) {
try {
this.functions.setVideoRoation(rotation);
return this.functions.getVideoDimensions(type);
} catch(e) {
console.warn(e);
}

View File

@ -5,11 +5,11 @@ class EJS_COMPRESSION {
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))) {
return 'zip';
return "zip";
} else if (data[0] === 55 && data[1] === 122 && data[2] === 188 && data[3] === 175 && data[4] === 39 && data[5] === 28) {
return '7z';
return "7z";
} else if ((data[0] === 82 && data[1] === 97 && data[2] === 114 && data[3] === 33 && data[4] === 26 && data[5] === 7) && ((data[6] === 0) || (data[6] === 1 && data[7] == 0))) {
return 'rar';
return "rar";
}
return null;
}
@ -38,13 +38,13 @@ class EJS_COMPRESSION {
}
const res = await this.EJS.downloadFile(path, null, false, { responseType: "text", method: "GET" });
if (res === -1) {
this.EJS.startGameError(this.EJS.localization('Network Error'));
this.EJS.startGameError(this.EJS.localization("Network Error"));
return;
}
if (method === "rar") {
const res2 = await this.EJS.downloadFile("compression/libunrar.wasm", null, false, { responseType: "arraybuffer", method: "GET" });
if (res2 === -1) {
this.EJS.startGameError(this.EJS.localization('Network Error'));
this.EJS.startGameError(this.EJS.localization("Network Error"));
return;
}
const path = URL.createObjectURL(new Blob([res2.data], { type: "application/wasm" }));
@ -61,7 +61,7 @@ class EJS_COMPRESSION {
onRuntimeInitialized: function() {},
locateFile: function(file) {
console.log("locateFile");
return '` + path + `';
return "` + path + `";
}
};
` + res.data + `
@ -77,9 +77,9 @@ class EJS_COMPRESSION {
}), password, cb)
let rec = function(entry) {
if (!entry) return;
if (entry.type === 'file') {
if (entry.type === "file") {
postMessage({ "t": 2, "file": entry.fullFileName, "size": entry.fileSize, "data": entry.fileContent });
} else if (entry.type === 'dir') {
} else if (entry.type === "dir") {
Object.keys(entry.ls).forEach(function(k) {
rec(entry.ls[k]);
});
@ -92,16 +92,16 @@ class EJS_COMPRESSION {
return rarContent;
};
onmessage = function(data) {
dataToPass.push({ name: 'test.rar', content: data.data });
dataToPass.push({ name: "test.rar", content: data.data });
};
`;
const blob = new Blob([script], {
type: 'application/javascript'
type: "application/javascript"
})
resolve(blob);
} else {
const blob = new Blob([res.data], {
type: 'application/javascript'
type: "application/javascript"
})
resolve(blob);
}
@ -119,7 +119,7 @@ class EJS_COMPRESSION {
const pg = data.data;
const num = Math.floor(pg.current / pg.total * 100);
if (isNaN(num)) return;
const progress = ' ' + num.toString() + '%';
const progress = " " + num.toString() + "%";
updateMsg(progress, true);
}
if (data.data.t === 2) {

File diff suppressed because it is too large Load Diff