From f276b7dd857c7e50f17a90341bb419131f28a05a Mon Sep 17 00:00:00 2001 From: themitosan Date: Sun, 25 Feb 2024 21:19:52 -0300 Subject: [PATCH] Game list: Implement basic fpPS4 compat check, Main: Disable fpPS4 updater if current user is offline --- App/css/style.css | 34 ++++++++- App/index.htm | 7 +- App/js/gamelist.js | 176 +++++++++++++++++++++----------------------- App/js/language.js | 13 +++- App/js/main.js | 38 ++++++++-- App/js/updateEmu.js | 2 +- package.json | 2 +- 7 files changed, 167 insertions(+), 105 deletions(-) diff --git a/App/css/style.css b/App/css/style.css index f86e6be..195593a 100644 --- a/App/css/style.css +++ b/App/css/style.css @@ -415,10 +415,10 @@ img { cursor: help; display: flex; overflow: hidden; + font-size: small; max-width: 114px; max-height: 42px; margin-left: 4px; - font-size: small; flex-wrap: nowrap; align-items: center; flex-direction: row; @@ -427,7 +427,9 @@ img { background-color: #000; justify-content: center; padding: 4px 0px 4px 0px; + transition-duration: 0.4s; text-shadow: 1px 1px 2px #000; + box-shadow: 0px 0px 0px #0000 inset; } .DIV_ICON_STATUS_OK { background-image: linear-gradient(180deg, #0f0, #0b0); @@ -440,6 +442,36 @@ img { border-radius: 3px 8px 3px 8px; background-image: linear-gradient(180deg, #63fdf6, #28b1ab); } + +/* + Game compat status +*/ +.DIV_COMPAT_STATUS_UNKNOWN { + border-radius: 0px; + background-image: linear-gradient(180deg, #aaa, #666); +} +.DIV_COMPAT_STATUS_BOOTS { + border-radius: 10px 4px 10px 4px; + background-image: linear-gradient(180deg, #f00, #a00); +} +.DIV_COMPAT_STATUS_MENUS { + border-radius: 4px; + background-image: linear-gradient(180deg, #45a6ff, #2157a5); +} +.DIV_COMPAT_STATUS_INGAME { + border-radius: 8px 8px 4px 4px; + background-image: linear-gradient(180deg, #fbe800, #9f8d0c); +} +.DIV_COMPAT_STATUS_NOTHING { + border-radius: 4px; + box-shadow: 0px 0px 10px #000 inset; + background-image: linear-gradient(180deg, #000, #282828); +} +.DIV_COMPAT_STATUS_PLAYABLE { + border-radius: 10px; + background-image: linear-gradient(180deg, #0f0, #0b0); +} + .DIV_noGameFound { top: 0px; left: 0px; diff --git a/App/index.htm b/App/index.htm index 1057d59..c0a3a5e 100644 --- a/App/index.htm +++ b/App/index.htm @@ -333,7 +333,12 @@
- :
+ :
+
+ + +
+ :
diff --git a/App/js/gamelist.js b/App/js/gamelist.js index f9c651c..f6d573d 100644 --- a/App/js/gamelist.js +++ b/App/js/gamelist.js @@ -29,8 +29,7 @@ temp_GAMELIST = { usePatch: data.usePatch, isHomebrew: data.isHomebrew, gamepadMode: data.gamepadMode, - patchLocation: data.patchLocation, - importedModules: data.importedModules + patchLocation: data.patchLocation }; // Check if title location exists @@ -237,7 +236,7 @@ temp_GAMELIST = { paramSfoAvailable = APP.fs.existsSync(paramSfoPath), iconList = ['sce_sys/icon0.png', 'sce_sys/icon1.png'], backgroundList = ['sce_sys/pic1.png', 'sce_sys/pic0.png']; - + // If eboot.bin doesn't exists, look for any .elf file if (APP.fs.existsSync(executableName) !== !0){ @@ -265,7 +264,7 @@ temp_GAMELIST = { break; } } - + // Seek App Background for (var i = 0; i < backgroundList.length; i++){ if (APP.fs.existsSync(pathBase + backgroundList[i]) === !0){ @@ -330,7 +329,7 @@ temp_GAMELIST = { } } - + }); } else { @@ -367,10 +366,8 @@ temp_GAMELIST = { APP.design.update(); } - // Process search query + // Create vars and process search query if current search mode is title id var tempList, listRender = {}; - - // Case game search mode is TITLE_ID if (APP.settings.data.gameSearchMode === 'titleId'){ tempList = gameListArray.filter(function(cItem){ @@ -384,11 +381,12 @@ temp_GAMELIST = { // If game search mode is APP_NAME if (APP.settings.data.gameSearchMode === 'appName'){ + // Reset temp list and process game list tempList = []; gameListArray.forEach(function(cTitle){ + // Get title name and check if current search is case-sensitive var titleName = APP.gameList.list[cTitle].name; - if (APP.settings.data.searchCaseSensitive === !1){ titleName = APP.gameList.list[cTitle].name.toLowerCase(); searchQuery = searchQuery.toLowerCase(); @@ -418,7 +416,7 @@ temp_GAMELIST = { // Render normal game list APP.gameList.load(); - + } }, @@ -426,13 +424,15 @@ temp_GAMELIST = { // Check dump status checkDumpStatus: function(){ + // Declare main vars var cGameStatus = 'OK', + fileList = [ 'param.sfo' ], + cGameComapStatus = 'UNKNOWN', cGame = this.list[this.selectedGame], - fileList = [ - 'param.sfo' - ], - cGameStatusList = ['DIV_ICON_STATUS_OK', 'DIV_ICON_STATUS_WARN', 'DIV_ICON_STATUS_HB'], - gPath = `${APP.settings.data.gamePath}/${cGame.folderName}`; + displayGameCompatHolderCss = { 'display': 'none' }, + gPath = `${APP.settings.data.gamePath}/${cGame.folderName}`, + cDumpStatusList = [ 'DIV_ICON_STATUS_OK', 'DIV_ICON_STATUS_WARN', 'DIV_ICON_STATUS_HB' ], + cGameComapStatusList = [ 'BOOTS', 'MENUS', 'INGAME', 'UNKNOWN', 'NOTHING', 'PLAYABLE', 'HOMEBREW' ]; // Process check for single files (like param.sfo) fileList.forEach(function(cFile){ @@ -443,27 +443,87 @@ temp_GAMELIST = { // Check if playgo-chunk.dat exists if (APP.fs.existsSync(`${gPath}/sce_sys/playgo-chunk.dat`) !== !0){ - + // Set current game status to warn and check if playgo-chunk.dat is inside app folder cGameStatus = 'WARN'; if (APP.fs.existsSync(`${gPath}/sce_sys/app/playgo-chunk.dat`) === !0){ APP.fs.copyFileSync(`${gPath}/sce_sys/app/playgo-chunk.dat`, `${gPath}/sce_sys/playgo-chunk.dat`); - APP.log(APP.lang.getVariable('checkDumpPlayGoOnApp', [this.list[this.selectedGame].name])); + APP.log(APP.lang.getVariable('checkDumpPlayGoOnApp', [cGame.name])); } - + + } + + // Set current compat css / status + const updateCompat = function(){ + + // Remove all other conditions and set current one + TMS.css('DIV_FPPS4_GAME_STATUS', displayGameCompatHolderCss); + cGameComapStatusList.forEach(function(cStatus){ + TMS.removeClass('DIV_selectedGameStatus_compat', `DIV_COMPAT_STATUS_${cStatus}`); + }); + TMS.addClass('DIV_selectedGameStatus_compat', `DIV_COMPAT_STATUS_${cGameComapStatus}`); + document.getElementById('DIV_selectedGameStatus_compat').innerHTML = APP.lang.getVariable(`cGameCompatStatus_${cGameComapStatus}`); + + } + + // Check if can display game compat status + if (APP.webConnection === !0){ + + // Update display css and if game isn't a homebrew, get compat data from fpps4.net + displayGameCompatHolderCss = { 'display': 'flex' }; + if (cGame.isHomebrew !== !0){ + + // Get current game conde and try getting data + const cGameCode = structuredClone(APP.gameList.selectedGame); + fetch(`https://fpps4.net/_scripts/search.php?q=${cGameCode}`) + .then(function(resp){ + return resp.json(); + }).then(function(gData){ + + // Check if data is defined + if (gData !== void 0){ + + // Process game list + var gFound = !1; + for (let i = 0; i < gData.games.length; i++){ + + // Check if current game code matches + if (gData.games[i].code === cGameCode){ + cGameComapStatus = gData.games[i].tag.toUpperCase(); + gFound = !0; + break; + } + + } + + // Log warn if failed to find game compat status + if (gFound === !1){ + APP.log(APP.lang.getVariable('warnUnableFindGameCompatDb', [APP.gameList.list[cGameCode].name, cGameCode])); + } + updateCompat(); + + } + + }); + + } else { + updateCompat(); + } + } // Check if is homebrew (.elf) if (cGame.isHomebrew === !0){ cGameStatus = 'HB'; + cGameComapStatus = 'UNKNOWN'; } // Set app / game dump status - cGameStatusList.forEach(function(cList){ - TMS.removeClass('DIV_selectedGameStatus', cList); + cDumpStatusList.forEach(function(cList){ + TMS.removeClass('DIV_selectedGameStatus_dump', cList); }); - TMS.addClass('DIV_selectedGameStatus', `DIV_ICON_STATUS_${cGameStatus}`); - document.getElementById('DIV_selectedGameStatus').innerHTML = APP.lang.getVariable(`dumpStatus_${cGameStatus}`); + TMS.addClass('DIV_selectedGameStatus_dump', `DIV_ICON_STATUS_${cGameStatus}`); + document.getElementById('DIV_selectedGameStatus_dump').innerHTML = APP.lang.getVariable(`dumpStatus_${cGameStatus}`); }, @@ -494,6 +554,7 @@ temp_GAMELIST = { // Reset current game settings resetGameSettings: function(){ + // Create main vars const cGame = this.selectedGame, fName = `${APP.settings.data.gamePath}/${this.list[cGame].folderName}/launcherSettings.json`, @@ -515,82 +576,13 @@ temp_GAMELIST = { } catch (err) { - console.error(err); APP.log(APP.lang.getVariable('settingsRemoveGameSettingsError', [cGame, err])); - - } - - } - - }, - - // Process remove modules - removeAllModules: function(){ - - // Check if this process already happened - if (APP.settings.data.removedLibModules === !1){ - - try { - - const gList = Object.keys(APP.gameList.list); - gList.forEach(function(gName){ - - APP.design.selectGame(gName); - APP.gameList.removeImportedModules(); - - }); - - // Update settings - APP.settings.data.removedLibModules = !0; - APP.settings.save(); - - // Log - APP.log(APP.lang.getVariable('removedLibModules')); - - } catch (err) { console.error(err); + } } - }, - - // Removed Imported modules - removeImportedModules: function(){ - - if (this.selectedGame !== '' && this.cGameSettings.importedModules.length > 0){ - - var cMessage = '', - gName = this.selectedGame, - mList = this.cGameSettings.importedModules, - mDir = `${APP.settings.data.gamePath}/${APP.gameList.list[gName].folderName}/sce_module/`; - - // Try removing modules - mList.forEach(function(mName){ - - try { - - APP.fs.unlinkSync(mDir + mName); - mList.splice(mList.indexOf(mName), 1); - cMessage = APP.lang.getVariable('removeLibModule', [gName, mName]); - - } catch (err) { - - console.error(err); - cMessage = APP.lang.getVariable('removeModuleError', [err]); - - } - - // Log status - APP.log(cMessage); - - }); - - // Update settings file - this.saveGameSettings(!0); - - } - } } \ No newline at end of file diff --git a/App/js/language.js b/App/js/language.js index c8f26d4..1b86ed3 100644 --- a/App/js/language.js +++ b/App/js/language.js @@ -114,11 +114,20 @@ temp_LANGUAGE = { "Sdl2NotFound": "SDL2.dll is not found in the Emu folder, please install it to use SDL2.", "errorListUnableLocateGamePath": "ERROR - Unable to locate \"%VARIABLE_0%\" settings path! In order to prevent issues, game list will be reloaded.\nPath: %VARIABLE_1%", "updateEmuSettingsWorkflow404": "ERROR - (Updater) Unable to find (%VARIABLE_0%) on fpPS4 worflow list! %VARIABLE_1% will be used as fallback.", - "nonWindowsOsWarn": "WARN - You are running fpPS4 Temmie's Launcher on a non-windows operating system!\n\nIn order to run fpPS4, you will need Wine installed on your OS.\n\nBe aware that running main compatibility layer through tools like Wine can result in more glitches, degraded performance / experience." + "nonWindowsOsWarn": "WARN - You are running fpPS4 Temmie's Launcher on a non-windows operating system!\n\nIn order to run fpPS4, you will need Wine installed on your OS.\n\nBe aware that running main compatibility layer through tools like Wine can result in more glitches, degraded performance / experience.", + "cGameCompatStatus_BOOTS": "Boots", + "cGameCompatStatus_MENUS": "Menus", + "cGameCompatStatus_INGAME": "In-Game", + "cGameCompatStatus_UNKNOWN": "Unknown", + "cGameCompatStatus_NOTHING": "Nothing", + "cGameCompatStatus_PLAYABLE": "Playable", + "warnUnableFindGameCompatDb": "WARN - Unable to find game compatibility for %VARIABLE_0% (%VARIABLE_1%) on fpPS4 game database!", + "warnUserOffline": "WARN - You are offline! Some features (like game compatibility status and fpPS4 updater) will not be available until you connect to the internet again." }, "title": { - "DIV_selectedGameStatus": "Green: All files are present\nYellow: Some files are missing - check log for more details\nCyan: Executable is a .elf file" + "DIV_selectedGameStatus_dump": "Green: All files are present\nYellow: Some files are missing - check log for more details\nCyan: Executable is a .elf file", + "DIV_selectedGameStatus_compat": "Playable: You can play this title from start to end.\nIn-game: You can play parts / segments of this title, but can't finish.\nMenus: This title boots into main menu, but can't start main game.\nBoots: This title start loading main game contents, but fails at some point.\nNothing: This title doesn't display nothing on window.\nUnknown: There is no data about this title on fpPS4 database." } }, diff --git a/App/js/main.js b/App/js/main.js index 2bdd1a3..0553a91 100644 --- a/App/js/main.js +++ b/App/js/main.js @@ -42,6 +42,9 @@ const APP = { version: '', appVersion: void 0, + // Internet connection + webConnection: !1, + // Import app modules tools: temp_TOOLS, lang: temp_LANGUAGE, @@ -173,6 +176,7 @@ const APP = { parseArgs = args.toString().replace(RegExp(',', 'gi'), ' ').replace(args[args.indexOf('-e') + 1], gPath), execLine = `${wineCommand}start ${cmdWinTitle} ${winMode} cmd /C ${emuExecPath} ${parseArgs} ${pressAnyKey}`; + // Run process APP.execProcess = APP.childProcess.exec(execLine); } else { @@ -187,8 +191,8 @@ const APP = { // Set emu running and stream as string (UTF-8) APP.emuManager.emuRunning = !0; - APP.execProcess.stdout.setEncoding('utf8'); - APP.execProcess.stderr.setEncoding('utf8'); + APP.execProcess.stdout.setEncoding('utf-8'); + APP.execProcess.stderr.setEncoding('utf-8'); // Log on stdout and stderr APP.execProcess.stdout.on('data', function(data){ @@ -276,6 +280,28 @@ const APP = { }, + // Check current user internet connection + startOnlineCheck: function(){ + + // Create update connection function + const updateConnectionStatus = function(){ + APP.webConnection = navigator.onLine; + }; + + // Set current connection status and crerate event listeners + APP.webConnection = navigator.onLine; + window.addEventListener('online', function(){ + updateConnectionStatus(); + document.getElementById('BTN_UPDATE_FPPS4').disabled = !1; + }); + window.addEventListener('offline', function(){ + updateConnectionStatus(); + APP.log(APP.lang.getVariable('warnUserOffline')); + document.getElementById('BTN_UPDATE_FPPS4').disabled = !0; + }); + + }, + // About screen about: function(){ window.alert(this.lang.getVariable('about', [this.version])); @@ -318,21 +344,19 @@ window.onload = function(){ APP.appVersion = APP.lang.getVariable('mainLog', [APP.version, process.versions.nw, process.versions['nw-flavor'].toUpperCase()]); APP.log(APP.appVersion); - // Load remaining settings, kill fpPS4 process if is active and check currert OS + // Start connection check, load remaining settings, kill fpPS4 process if is active and check currert OS APP.settings.checkPaths(); APP.design.renderSettings(); APP.emuManager.killEmu(!0); + APP.startOnlineCheck(); APP.checkCurrentOs(); // Rener hack list, gamepad modes and focus input search field APP.design.renderHacklist(); TMS.focus('INPUT_gameListSearch'); - // Load game list and remove all previous modules + // Load game list, Get all available workflows from updater and check if fpPS4 have any update (silently) APP.gameList.load(); - APP.gameList.removeAllModules(); - - // Updater: Get all available workflows and check if fpPS4 have any update (silently) APP.emuManager.update.getWorkflows(); if (APP.emuManager.update.skipLoadingCheck === !1){ APP.emuManager.update.check({ silent: !0 }); diff --git a/App/js/updateEmu.js b/App/js/updateEmu.js index 081d304..5078f59 100644 --- a/App/js/updateEmu.js +++ b/App/js/updateEmu.js @@ -25,7 +25,7 @@ temp_EMU_UPDATE = { fetchData: async function(url, callback){ // If url was provided - if (url !== void 0 && navigator.onLine === !0 && typeof callback === 'function'){ + if (url !== void 0 && APP.webConnection === !0 && typeof callback === 'function'){ // Get error message and fetch data fetch(url).then(function(resp){ diff --git a/package.json b/package.json index a18b4a8..c240169 100644 --- a/package.json +++ b/package.json @@ -13,7 +13,7 @@ "height": 710, "toolbar": true, "min_width": 1102, - "min_height": 626, + "min_height": 680, "fullscreen": false, "position": "center", "theme-color": "#000",