From 50c811e8a2f39636611a78bf5ef8fb79a1c0876e Mon Sep 17 00:00:00 2001 From: Ethan O'Brien <77750390+ethanaobrien@users.noreply.github.com> Date: Mon, 7 Aug 2023 11:31:20 -0500 Subject: [PATCH] Add fast forward, bump version --- CHANGES.md | 9 ++++++++- data/GameManager.js | 16 ++++++++++++++-- data/emulator.js | 34 ++++++++++++++++++++++++++++++---- data/emulator.min.js | 2 +- data/version.json | 2 +- 5 files changed, 54 insertions(+), 9 deletions(-) diff --git a/CHANGES.md b/CHANGES.md index 5c1d04a..11b8f5b 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -1,6 +1,13 @@ # Changes -# 4.0.5 +# 4.0.6 +- Fixed n64 on iOS safari +- virtual gamepads for atari2600, atari7800, lynx, jaguar, vb, 3do (Thanks to [@n-at](https://github.com/n-at)) +- control buttons for gba, vb, 3do, atari2600, atari7800, lynx, jaguar (Thanks to [@n-at](https://github.com/n-at)) +- Added `EJS_controlScheme` (Thanks to [@n-at](https://github.com/n-at)) +- Added Fast Forward + +# 4.0.5 [View Tree](https://github.com/EmulatorJS/EmulatorJS/tree/5307e6294ed9df5daabd6958b2b307bae01f59f1) - Added `pcsx_rearmed` core - Made `pcsx_rearmed` core the default `psx` core (better compatibility) - Added `fbneo` core diff --git a/data/GameManager.js b/data/GameManager.js index 1d64b11..bc4c830 100644 --- a/data/GameManager.js +++ b/data/GameManager.js @@ -23,7 +23,9 @@ class EJS_GameManager { saveSaveFiles: this.Module.cwrap('cmd_savefiles', '', []), supportsStates: this.Module.cwrap('supports_states', 'number', []), loadSaveFiles: this.Module.cwrap('refresh_save_files', 'null', []), - setVolume: this.Module.cwrap('set_volume', 'null', ['number']) + setVolume: this.Module.cwrap('set_volume', 'null', ['number']), + toggleFastForward: this.Module.cwrap('toggle_fastforward', 'null', ['number']), + setFastForwardRatio: this.Module.cwrap('set_ff_ratio', 'null', ['number']) } this.mkdir("/home"); this.mkdir("/home/web_user"); @@ -62,6 +64,7 @@ class EJS_GameManager { "video_top_portrait_viewport = true\n" + "video_vsync = true\n" + "video_smooth = false\n" + + "fastforward_ratio = 3.0\n" + "savefile_directory = \"/data/saves\"\n"; } initShaders() { @@ -139,7 +142,7 @@ class EJS_GameManager { this.EJS.netplay.simulateInput(player, index, value); return; } - if ([24, 25, 26].includes(index)) { + if ([24, 25, 26, 27].includes(index)) { if (index === 24 && value === 1) { const slot = this.EJS.settings['save-state-slot'] ? this.EJS.settings['save-state-slot'] : "1"; this.quickSave(slot); @@ -161,6 +164,9 @@ class EJS_GameManager { this.EJS.displayMessage(this.EJS.localization("SET SAVE STATE SLOT TO")+" "+newSlot); this.EJS.changeSettingOption('save-state-slot', newSlot.toString()); } + if (index === 27) { + this.functions.toggleFastForward(value); + } return; } this.functions.simulateInput(player, index, value); @@ -295,6 +301,12 @@ class EJS_GameManager { loadSaveFiles() { this.functions.loadSaveFiles(); } + setFastForwardRatio(ratio) { + this.functions.setFastForwardRatio(ratio); + } + toggleFastForward(active) { + this.functions.toggleFastForward(active); + } } window.EJS_GameManager = EJS_GameManager; diff --git a/data/emulator.js b/data/emulator.js index 4b7af63..2395db5 100644 --- a/data/emulator.js +++ b/data/emulator.js @@ -1,5 +1,5 @@ class EmulatorJS { - version = 4; //Increase by 1 when cores are updated + version = 5; //Increase by 1 when cores are updated getCore(generic) { const core = this.config.system; /*todo: @@ -229,8 +229,8 @@ class EmulatorJS { }) } constructor(element, config) { - this.ejs_version = "4.0.5"; - this.ejs_num_version = 40.5; + this.ejs_version = "4.0.6"; + this.ejs_num_version = 40.6; this.debug = (window.EJS_DEBUG_XX === true); if (this.debug || (window.location && ['localhost', '127.0.0.1'].includes(location.hostname))) this.checkForUpdates(); this.netplayEnabled = (window.EJS_DEBUG_XX === true) && (window.EJS_EXPERIMENTAL_NETPLAY === true); @@ -1798,6 +1798,7 @@ class EmulatorJS { {id: 24, label: this.localization('QUICK SAVE STATE')}, {id: 25, label: this.localization('QUICK LOAD STATE')}, {id: 26, label: this.localization('CHANGE STATE SLOT')}, + {id: 27, label: this.localization('FAST FORWARD')}, ]; } else if ('snes' === this.getControlScheme()) { buttons = [ @@ -1816,6 +1817,7 @@ class EmulatorJS { {id: 24, label: this.localization('QUICK SAVE STATE')}, {id: 25, label: this.localization('QUICK LOAD STATE')}, {id: 26, label: this.localization('CHANGE STATE SLOT')}, + {id: 27, label: this.localization('FAST FORWARD')}, ]; } else if ('n64' === this.getControlScheme()) { buttons = [ @@ -1840,6 +1842,7 @@ class EmulatorJS { {id: 24, label: this.localization('QUICK SAVE STATE')}, {id: 25, label: this.localization('QUICK LOAD STATE')}, {id: 26, label: this.localization('CHANGE STATE SLOT')}, + {id: 27, label: this.localization('FAST FORWARD')}, ]; } else if ('gba' === this.getControlScheme()) { buttons = [ @@ -1856,6 +1859,7 @@ class EmulatorJS { {id: 24, label: this.localization('QUICK SAVE STATE')}, {id: 25, label: this.localization('QUICK LOAD STATE')}, {id: 26, label: this.localization('CHANGE STATE SLOT')}, + {id: 27, label: this.localization('FAST FORWARD')}, ]; } else if ('nds' === this.getControlScheme()) { buttons = [ @@ -1875,6 +1879,7 @@ class EmulatorJS { {id: 24, label: this.localization('QUICK SAVE STATE')}, {id: 25, label: this.localization('QUICK LOAD STATE')}, {id: 26, label: this.localization('CHANGE STATE SLOT')}, + {id: 27, label: this.localization('FAST FORWARD')}, ]; } else if ('vb' === this.getControlScheme()) { buttons = [ @@ -1895,6 +1900,7 @@ class EmulatorJS { {id: 24, label: this.localization('QUICK SAVE STATE')}, {id: 25, label: this.localization('QUICK LOAD STATE')}, {id: 26, label: this.localization('CHANGE STATE SLOT')}, + {id: 27, label: this.localization('FAST FORWARD')}, ]; } else if (['segaMD', 'segaCD', 'sega32x'].includes(this.getControlScheme())) { buttons = [ @@ -1913,6 +1919,7 @@ class EmulatorJS { {id: 24, label: this.localization('QUICK SAVE STATE')}, {id: 25, label: this.localization('QUICK LOAD STATE')}, {id: 26, label: this.localization('CHANGE STATE SLOT')}, + {id: 27, label: this.localization('FAST FORWARD')}, ]; } else if ('segaMS' === this.getControlScheme()) { buttons = [ @@ -1925,6 +1932,7 @@ class EmulatorJS { {id: 24, label: this.localization('QUICK SAVE STATE')}, {id: 25, label: this.localization('QUICK LOAD STATE')}, {id: 26, label: this.localization('CHANGE STATE SLOT')}, + {id: 27, label: this.localization('FAST FORWARD')}, ]; } else if ('segaGG' === this.getControlScheme()) { buttons = [ @@ -1938,6 +1946,7 @@ class EmulatorJS { {id: 24, label: this.localization('QUICK SAVE STATE')}, {id: 25, label: this.localization('QUICK LOAD STATE')}, {id: 26, label: this.localization('CHANGE STATE SLOT')}, + {id: 27, label: this.localization('FAST FORWARD')}, ]; } else if ('segaSaturn' === this.getControlScheme()) { buttons = [ @@ -1957,6 +1966,7 @@ class EmulatorJS { {id: 24, label: this.localization('QUICK SAVE STATE')}, {id: 25, label: this.localization('QUICK LOAD STATE')}, {id: 26, label: this.localization('CHANGE STATE SLOT')}, + {id: 27, label: this.localization('FAST FORWARD')}, ]; } else if ('3do' === this.getControlScheme()) { buttons = [ @@ -1974,6 +1984,7 @@ class EmulatorJS { {id: 24, label: this.localization('QUICK SAVE STATE')}, {id: 25, label: this.localization('QUICK LOAD STATE')}, {id: 26, label: this.localization('CHANGE STATE SLOT')}, + {id: 27, label: this.localization('FAST FORWARD')}, ]; } else if ('atari2600' === this.getControlScheme()) { buttons = [ @@ -1985,6 +1996,7 @@ class EmulatorJS { {id: 24, label: this.localization('QUICK SAVE STATE')}, {id: 25, label: this.localization('QUICK LOAD STATE')}, {id: 26, label: this.localization('CHANGE STATE SLOT')}, + {id: 27, label: this.localization('FAST FORWARD')}, ]; } else if ('atari7800' === this.getControlScheme()) { buttons = [ @@ -1997,6 +2009,7 @@ class EmulatorJS { {id: 24, label: this.localization('QUICK SAVE STATE')}, {id: 25, label: this.localization('QUICK LOAD STATE')}, {id: 26, label: this.localization('CHANGE STATE SLOT')}, + {id: 27, label: this.localization('FAST FORWARD')}, ]; } else if ('lynx' === this.getControlScheme()) { buttons = [ @@ -2012,6 +2025,7 @@ class EmulatorJS { {id: 24, label: this.localization('QUICK SAVE STATE')}, {id: 25, label: this.localization('QUICK LOAD STATE')}, {id: 26, label: this.localization('CHANGE STATE SLOT')}, + {id: 27, label: this.localization('FAST FORWARD')}, ]; } else if ('jaguar' === this.getControlScheme()) { buttons = [ @@ -2027,6 +2041,7 @@ class EmulatorJS { {id: 24, label: this.localization('QUICK SAVE STATE')}, {id: 25, label: this.localization('QUICK LOAD STATE')}, {id: 26, label: this.localization('CHANGE STATE SLOT')}, + {id: 27, label: this.localization('FAST FORWARD')}, ]; } else { buttons = [ @@ -2057,6 +2072,7 @@ class EmulatorJS { {id: 24, label: this.localization('QUICK SAVE STATE')}, {id: 25, label: this.localization('QUICK LOAD STATE')}, {id: 26, label: this.localization('CHANGE STATE SLOT')}, + {id: 27, label: this.localization('FAST FORWARD')}, ]; } if (['arcade', 'mame'].includes(this.getControlScheme())) { @@ -2367,7 +2383,7 @@ class EmulatorJS { e.preventDefault(); const special = [16, 17, 18, 19, 20, 21, 22, 23]; for (let i=0; i<4; i++) { - for (let j=0; j<27; j++) { + for (let j=0; j<28; j++) { if (this.controls[i][j] && this.controls[i][j].value === e.key.toLowerCase()) { this.gameManager.simulateInput(i, j, (e.type === 'keyup' ? 0 : (special.includes(j) ? 0x7fff : 1))); } @@ -3120,6 +3136,12 @@ class EmulatorJS { this.toggleVirtualGamepad(value !== "disabled"); } else if (option === "virtual-gamepad-left-handed-mode") { this.toggleVirtualGamepadLeftHanded(value !== "disabled"); + } else if (option === "ff-ratio") { + if (value === "unlimited") { + this.gameManager.setFastForwardRatio(0); + } else if (!isNaN(value)) { + this.gameManager.setFastForwardRatio(parseFloat(value)); + } } this.gameManager.setVariable(option, value); } @@ -3291,6 +3313,10 @@ class EmulatorJS { 'hide': this.localization("hide") }, 'hide'); + addToMenu(this.localization('Fast Forward Ratio'), 'ff-ratio', [ + "1.5", "2.0", "2.5", "3.0", "3.5", "4.0", "4.5", "5.0", "5.5", "6.0", "6.5", "7.0", "7.5", "8.0", "8.5", "9.0", "9.5", "10.0", "unlimited" + ], "3.0"); + if (this.saveInBrowserSupported()) { addToMenu(this.localization('Save State Slot'), 'save-state-slot', ["1", "2", "3", "4", "5", "6", "7", "8", "9"], "1"); addToMenu(this.localization('Save State Location'), 'save-state-location', { diff --git a/data/emulator.min.js b/data/emulator.min.js index 464f944..9ceca6c 100644 --- a/data/emulator.min.js +++ b/data/emulator.min.js @@ -1 +1 @@ -!function(e,t){"object"==typeof exports&&"object"==typeof module?module.exports=t():"function"==typeof define&&define.amd?define("nipplejs",[],t):"object"==typeof exports?exports.nipplejs=t():e.nipplejs=t()}(window,function(){return n=[function(e,t,n){"use strict";n.r(t);function _(e,t){var n=t.x-e.x,t=t.y-e.y;return Math.sqrt(n*n+t*t)}function b(e){return e*(Math.PI/180)}function o(e){f.has(e)&&clearTimeout(f.get(e)),f.set(e,setTimeout(e,100))}function s(e,t,n){for(var i,o=t.split(/[ ,]+/g),s=0;sthis.options.threshold){var r,l={};for(r in this.direction)this.direction.hasOwnProperty(r)&&(l[r]=this.direction[r]);var c={};for(r in this.direction={x:n,y:i,angle:t},e.direction=this.direction,l)l[r]===this.direction[r]&&(c[r]=!0);if(c.x&&c.y&&c.angle)return e;c.x&&c.y||this.trigger("plain",e),c.x||this.trigger("plain:"+n,e),c.y||this.trigger("plain:"+i,e),c.angle||this.trigger("dir dir:"+t,e)}else this.resetDirection();return e};var x=E;function w(e,t){this.nipples=[],this.idles=[],this.actives=[],this.ids=[],this.pressureIntervals={},this.manager=e,this.id=w.id,w.id+=1,this.defaults={zone:document.body,multitouch:!1,maxNumberOfNipples:10,mode:"dynamic",position:{top:0,left:0},catchDistance:200,size:100,threshold:.1,color:"white",fadeTime:250,dataOnly:!1,restJoystick:!0,restOpacity:.5,lockX:!1,lockY:!1,shape:"circle",dynamicPage:!1,follow:!1},this.config(t),"static"!==this.options.mode&&"semi"!==this.options.mode||(this.options.multitouch=!1),this.options.multitouch||(this.options.maxNumberOfNipples=1);e=getComputedStyle(this.options.zone.parentElement);return e&&"flex"===e.display&&(this.parentIsFlex=!0),this.updateBox(),this.prepareNipples(),this.bindings(),this.begin(),this.nipples}w.prototype=new m,(w.constructor=w).id=0,w.prototype.prepareNipples=function(){var i=this.nipples;i.on=this.on.bind(this),i.off=this.off.bind(this),i.options=this.options,i.destroy=this.destroy.bind(this),i.ids=this.ids,i.id=this.id,i.processOnMove=this.processOnMove.bind(this),i.processOnEnd=this.processOnEnd.bind(this),i.get=function(e){if(void 0===e)return i[0];for(var t=0,n=i.length;t