diff --git a/App/css/style.css b/App/css/style.css new file mode 100644 index 0000000..c92da86 --- /dev/null +++ b/App/css/style.css @@ -0,0 +1,188 @@ +/* + Styles.css +*/ +html, body { + color: #fff; + overflow: hidden; + user-select: none; + font-family: monospace; + background-color: #000; + text-shadow: 2px 2px 4px #000; +} +input[type='button'], input[type='checkbox'] { + outline: none; + cursor: pointer; +} +input[disabled="disabled"], input[disabled] { + cursor: no-drop; +} +::-webkit-scrollbar { + width: 8px; + height: 8px; + border-radius: 4px; +} +::-webkit-scrollbar-track { + border-radius: 4px; + margin: 6px 0px 6px 0px; +} +::-webkit-scrollbar-thumb { + border-radius: 4px; + background: #e7e7e7; +} +::-webkit-scrollbar-thumb:hover { + border-radius: 4px; + background: #f0f0f0; +} +::-webkit-scrollbar-thumb:active { + background: #fff; + border-radius: 4px; +} + +/* + Divs +*/ +.DIV_LIST { + top: 38px; + left: 0px; + position: absolute; + width: calc(100% - 280px); + height: calc(100% - 286px); + background-image: linear-gradient(146deg, #090f1b, #162a50); +} +.DIV_LOG { + left: 0px; + bottom: 0px; + width: 100%; + height: 248px; + position: absolute; + background-size: auto 50%; + background-position: center; + background-repeat: no-repeat; + background-image: url('../img/logo.png'); +} +.DIV_ACTIONS { + top: 0px; + left: 0px; + width: 100%; + height: 22px; + padding: 8px; + position: absolute; + background-image: linear-gradient(45deg, #28467f, #1c325f); +} +.DIV_OPTIONS { + top: 38px; + right: 0px; + padding: 6px; + width: 268px; + position: absolute; + height: calc(100% - 298px); + background-image: linear-gradient(0deg, #162a50, #2a4a86); +} +.DIV_TITLE { + font-size: 28px; + margin-top: 10px; + font-weight: bold; + text-align: center; + margin-bottom: 10px; +} +.DIV_LIST_INTERNAL { + top: 0px; + left: 0px; + width: 100%; + height: 100%; + overflow: auto; + transition: 0.4s; + position: absolute; + background-size: cover; + background-color: #0000; + background-position: center; + background-repeat: no-repeat; +} +.GAME_ENTRY { + margin: 6px; + display: flex; + cursor: pointer; + overflow: hidden; + max-height: 92px; + flex-wrap: nowrap; + border-radius: 6px; + align-items: center; + align-content: center; + width: calc(100% - 12px); + backdrop-filter: blur(4px) invert(0.1); + background-image: linear-gradient(90deg, #3a4b6b82, #0000); +} +.GAME_ENTRY:hover { + box-shadow: 0px 0px 10px #0006; + background-image: linear-gradient(90deg, #3a4b6b82, #3a4b6b82); +} +.GAME_ENTRY:active { + box-shadow: 0px 0px 10px #0006 inset; + backdrop-filter: invert(0.68) blur(6px); +} +.GAME_DETAILS { + cursor: pointer; + width: calc(100% - 88px); +} +.DIV_RUN_BTN { + bottom: 4px; + position: absolute; + width: calc(100% - 12px); +} + +/* + Images +*/ +.GAME_ICON { + width: 66px; + margin: 6px; + cursor: pointer; + border-radius: 6px; +} + +/* + Input +*/ +.APP_LOG { + color: #0f0; + height: 100%; + resize: none; + border: none; + cursor: text; + outline: none; + width: calc(100% - 4px); + background-repeat: no-repeat; + text-shadow: 2px 2px 2px #000; + background-image: linear-gradient(180deg, #000000db, #090f1b); +} +.BTN_RUN { + left: 8px; + width: 100%; + bottom: 18px; + height: 50px; + font-size: 18px; + margin-top: 2px; +} + +/* + Labels +*/ +.LABEL_checkbox { + cursor: pointer; + font-size: 16px; + font-style: italic; +} +.LABEL_emuColor { + color: #fffb8e; +} +.LABEL_gameTtitle { + font-size: 20px; + cursor: pointer; +} + +/* + Misc +*/ +.none { + display: none; +} \ No newline at end of file diff --git a/App/img/404.png b/App/img/404.png new file mode 100644 index 0000000..ca18e8c Binary files /dev/null and b/App/img/404.png differ diff --git a/App/img/404_BG.png b/App/img/404_BG.png new file mode 100644 index 0000000..e0e8e33 Binary files /dev/null and b/App/img/404_BG.png differ diff --git a/App/img/logo.png b/App/img/logo.png new file mode 100644 index 0000000..9cc705d Binary files /dev/null and b/App/img/logo.png differ diff --git a/App/index.htm b/App/index.htm new file mode 100644 index 0000000..78b6096 --- /dev/null +++ b/App/index.htm @@ -0,0 +1,70 @@ + + + + + + fpPS4 Temmie's Launcher + + + + + + + +
+ + + + + + +
+ + +
+ +
PS4 Options
+ +
+ +
+ + +
+ + +
+ +
+ + +
+
+ +
+
+ + +
+ +
+ + +
+ + + + + + + + + + + + + +
+ + + \ No newline at end of file diff --git a/App/js/TMS.js b/App/js/TMS.js new file mode 100644 index 0000000..bb5922a --- /dev/null +++ b/App/js/TMS.js @@ -0,0 +1,308 @@ +/* + ******************************************************************************* + TMS.js - By @TheMitoSan + + This file is an original replacement - Because I don't want to deal with jQuery + anymore! + + Original source / motivation: http://youmightnotneedjquery.com/ + ******************************************************************************* +*/ +tmsTemp = {}; +tmsTemp['logWarnings'] = false; +/* + Warn if something goes wrong +*/ +tmsTemp['warn'] = function(warnText){ + if (TMS.logWarnings === true){ + console.warn(warnText); + }; +}; +/* + CSS +*/ +tmsTemp['css'] = function(elementId, cssChanges){ + var canStart = true, eReason = ''; + const elId = document.getElementById(elementId); + if (elId === null){ + canStart = false; + eReason = eReason + '\nDOM does not exist! (' + elementId + ')'; + }; + if (typeof cssChanges !== 'object'){ + canStart = false; + eReason = eReason + '\nYou must insert an object for CSS data (Current type: ' + typeof cssChanges + ')'; + }; + // End + if (canStart === true){ + Object.keys(cssChanges).forEach(function(cItem){ + elId.style[cItem] = cssChanges[cItem]; + }); + } else { + TMS.warn('TMS - Unable to apply CSS data!' + eReason); + }; +}; +/* + Animate + + elementId = HTML DOM id + cssChanges = Object {width: x, height, y} + animationTime = Number (Min: 0) + animationEase = CSS for transition option, like cubic-bezier +*/ +tmsTemp['animate'] = function(elementId, cssChanges, animationTime, animationEase){ + var canStart = true, eReason = transitionString = ''; + const elId = document.getElementById(elementId); + if (elId === null){ + canStart = false; + eReason = eReason + '\nDOM does not exist! (' + elementId + ')'; + } + if (typeof cssChanges !== 'object'){ + canStart = false; + eReason = eReason + '\nYou must insert an object for CSS data (Current type: ' + typeof cssChanges + ')'; + } + if (typeof animationTime !== 'number'){ + canStart = false; + eReason = eReason + '\nYou must insert a number on animation time (Current type: ' + typeof animationTime + ')'; + } + // End + if (canStart === true){ + if (animationEase === undefined){ + animationEase = ''; + } + if (animationTime < 0){ + animationTime = 0; + } + Object.keys(cssChanges).forEach(function(cItem){ + elId.style[cItem] = cssChanges[cItem]; + transitionString = transitionString + cItem + ' ' + (animationTime / 1000) + 's '; + elId.style['transition'] = transitionString + animationEase; + }); + setTimeout(function(){ + elId.style['transition'] = 'none 0s'; + }, (animationTime + 1)); + } else { + TMS.warn('TMS - Unable to animate!' + eReason); + } +} +/* + Focus Element + sTimeout = time [ms] +*/ +tmsTemp['focus'] = function(elementId, sTimeout){ + const elId = document.getElementById(elementId); + if (elId !== null){ + if (sTimeout !== undefined && parseInt(sTimeout) !== NaN){ + setTimeout(function(){ + elId.focus(); + }, sTimeout); + } else { + elId.focus(); + }; + } else { + TMS.warn('TMS - Unable to focus element because it does not exist! (' + elementId + ')'); + }; +}; +/* + Disable Element +*/ +tmsTemp['disableElement'] = function(idList){ + var disableList = []; + if (typeof idList === 'object'){ + disableList = idList; + } else { + disableList.push(idList); + }; + // End + disableList.forEach(function(cItem){ + const elId = document.getElementById(cItem); + if (elId !== null){ + elId.disabled = 'disabled'; + // If is + if (elId.type === 'button'){ + TMS.css(cItem, {'filter': 'grayscale(1) blur(0.8px)', 'cursor': 'not-allowed', 'opacity': '0.6'}); + }; + } else { + TMS.warn('TMS - Unable to disable element because it does not exist! (' + cItem + ')'); + }; + }); +}; +/* + Enable Element +*/ +tmsTemp['enableElement'] = function(elementId){ + const elId = document.getElementById(elementId); + if (elId !== null){ + elId.disabled = ''; + // If is + if (elId.type === 'button'){ + TMS.css(elementId, {'filter': 'grayscale(0) blur(0px)', 'cursor': 'pointer', 'opacity': '1'}); + }; + } else { + TMS.warn('TMS - Unable to enable element because it does not exist! (' + elementId + ')'); + }; +}; +/* + Get CSS data + Returns the attr value from CSS propriety +*/ +tmsTemp['getCssData'] = function(elementId, cssAttrName){ + var elId = document.getElementById(elementId), + result = ''; + if (elId !== null){ + result = elId.style[cssAttrName]; + } else { + TMS.warn('TMS - Unable to get element because it does not exist! (' + elementId + ')'); + }; + return result; +}; +/* + Scroll top + Usage: elementObjects = {HTML_DOM_ID_0: scrollInt, HTML_DOM_ID_1: scrollInt2} and goes on +*/ +tmsTemp['scrollTop'] = function(elementObjects){ + Object.keys(elementObjects).forEach(function(cItem){ + const elId = document.getElementById(cItem); + if (elId !== null){ + elId.scrollTop = elementObjects[cItem]; + } else { + TMS.warn('TMS - Unable to scroll element because it does not exist! (' + elementId + ')'); + }; + }); +}; +/* + Append data +*/ +tmsTemp['append'] = function(elementId, newData){ + const elId = document.getElementById(elementId); + if (elId !== null){ + var pHTML = elId.innerHTML; + elId.innerHTML = pHTML + newData; + } else { + TMS.warn('TMS - Unable to append element data because parent DOM does not exist! (' + elementId + ')'); + }; +}; +/* + Add Class +*/ +tmsTemp['addClass'] = function(elementId, className){ + const elId = document.getElementById(elementId); + if (elId !== null){ + elId.classList.add(className); + } else { + TMS.warn('TMS - Unable to add class because DOM does not exist! (' + elementId + ')'); + }; +}; +/* + Add Class +*/ +tmsTemp['removeClass'] = function(elementId, className){ + const elId = document.getElementById(elementId); + if (elId !== null){ + elId.classList.remove(className); + } else { + TMS.warn('TMS - Unable to remove class because DOM does not exist! (' + elementId + ')'); + }; +}; +/* + Clear + Removes all HTML inside +*/ +tmsTemp['clear'] = function(elementId){ + const elId = document.getElementById(elementId); + if (elId !== null){ + elId.innerHTML = ''; + } else { + TMS.warn('TMS - Unable to clear inner data because DOM does not exist! (' + elementId + ')'); + }; +}; +/* + triggerClick +*/ +tmsTemp['triggerClick'] = function(elementId){ + const elId = document.getElementById(elementId); + if (elId !== null){ + elId.click(); + } else { + TMS.warn('TMS - Unable to clear inner data because DOM does not exist! (' + elementId + ')'); + }; +}; +/* + fadeIn +*/ +tmsTemp['fadeIn'] = function(elementId, animationTime){ + const elId = document.getElementById(elementId), tagType = { + 'DIV': 'block', + 'IMG': 'inline' + }; + if (elId !== null){ + var dTime = 1000, dMode = 'block', finalOpacity = 1, eStyles = getComputedStyle(elId); + if (animationTime !== undefined && animationTime !== NaN){ + dTime = parseInt(animationTime); + if (dTime < 0){ + dTime = 1; + }; + }; + if (tagType[elId.tagType] !== undefined){ + dMode = tagType[elId.tagType]; + }; + if (eStyles.opacity !== ''){ + finalOpacity = eStyles.opacity; + }; + TMS.css(elementId, {'display': dMode, 'opacity': finalOpacity, 'transition': 'opacity ' + dTime + 'ms'}); + setTimeout(function(){ + TMS.css(elementId, {'transition': 'none'}); + }, (dTime + 1)); + } else { + TMS.warn('TMS - Unable to fade in because DOM does not exist! (' + elementId + ')'); + }; +}; +/* + fadeOut +*/ +tmsTemp['fadeOut'] = function(elementId, animationTime){ + const elId = document.getElementById(elementId); + if (elId !== null){ + var dTime = 1000; + if (animationTime !== undefined && animationTime !== NaN){ + dTime = parseInt(animationTime); + if (dTime < 0){ + dTime = 1; + }; + }; + TMS.css(elementId, {'opacity': '0', 'transition': 'opacity ' + dTime + 'ms'}); + setTimeout(function(){ + TMS.css(elementId, {'transition': 'none', 'display': 'none'}); + }, (dTime + 1)); + } else { + TMS.warn('TMS - Unable to fade out because DOM does not exist! (' + elementId + ')'); + }; +}; +/* + scrollCenter +*/ +tmsTemp['scrollCenter'] = function(elementId){ + const elId = document.getElementById(elementId); + if (elId !== null){ + var parentDom = elId.parentElement, + parentHeight = parentDom.offsetHeight; + parentDom.scrollTo(0, (elId.offsetTop - (parentHeight / 2))) + } else { + TMS.warn('TMS - Unable to fade out because DOM does not exist! (' + elementId + ')'); + }; +}; +/* + setInnerHtml +*/ +tmsTemp['setInnerHtml'] = function(elementId, htmlData){ + const elId = document.getElementById(elementId); + if (elId !== null){ + document.getElementById(elementId).innerHTML = htmlData; + } else { + TMS.warn('TMS - Unable to set innerHTML because DOM does not exist! (' + elementId + ')'); + }; +}; +/* + END +*/ +const TMS = tmsTemp; +delete(tmsTemp); \ No newline at end of file diff --git a/App/js/design.js b/App/js/design.js new file mode 100644 index 0000000..2510675 --- /dev/null +++ b/App/js/design.js @@ -0,0 +1,123 @@ +/* + design.js +*/ + +temp_DESIGN = { + + /* + Hack List + */ + hackList: [ + 'DEPTH_DISABLE_HACK', + 'COMPUTE_DISABLE_HACK', + 'MEMORY_BOUND_HACK', + 'IMAGE_TEST_HACK', + 'IMAGE_LOAD_HACK', + 'DISABLE_SRGB_HACK' + ], + + // Process checkbox status + processCheckbox: function(domName){ + + var res = !1, + domId = document.getElementById(domName).checked; + + if (domId === !1){ + res = !0; + } + + document.getElementById(domName).checked = res; + + }, + + // Render hack list + renderHacklist: function(){ + + var htmlTemp = ''; + + this.hackList.forEach(function(hackName){ + htmlTemp = htmlTemp + '
'; + }); + + document.getElementById('DIV_HACK_LIST').innerHTML = htmlTemp; + + }, + + // Render game list + renderGameList: function(){ + + var gList = APP.gameList.list, + tempHtml = ''; + + Object.keys(gList).forEach(function(cGame){ + tempHtml = tempHtml + '

' + 'Path: ' + gList[cGame].eboot + '
'; + }); + + // Insert HTML + document.getElementById('DIV_LIST_INTERNAL').innerHTML = tempHtml; + + // Clear BG image + TMS.css('DIV_LIST_INTERNAL', {'background-image': 'none'}); + + }, + + // Select game + selectGame: function(gameName){ + + if (APP.gameList.list[gameName] !== void 0){ + + const cGame = APP.gameList.list[gameName]; + TMS.css('DIV_LIST_INTERNAL', { + 'background-image': 'url("' + cGame.bg + '")' + }); + + APP.gameList.selectedGame = gameName; + APP.design.updateRunButtons(); + + } + + }, + + // Enable or Disable Run / Stop buttons + updateRunButtons: function(){ + + // Check if emu is present before allowing to run + if (APP.fs.existsSync(APP.settings.data.emuPath) === !0){ + + var btnRun = '', + logHeight = '248px', + btnKill = 'disabled', + hackDisplay = 'inline', + listHeight = 'calc(100% - 286px)', + optionsHeight = 'calc(100% - 298px)'; + + // If emu is running + if (APP.emuManager.emuRunning === !0){ + + btnKill = ''; + btnRun = 'disabled'; + listHeight = '172px'; + hackDisplay = 'none'; + optionsHeight = '160px'; + logHeight = 'calc(100% - 210px)'; + + } + + // Update GUI + TMS.css('DIV_LOG', {'height': logHeight}); + TMS.css('DIV_LIST', {'height': listHeight}); + TMS.css('DIV_OPTIONS', {'height': optionsHeight}); + TMS.css('DIV_HACK_LIST', {'display': hackDisplay}); + + // Update Buttons + document.getElementById('BTN_RUN').disabled = btnRun; + document.getElementById('BTN_KILL').disabled = btnKill; + + } + + } + +} \ No newline at end of file diff --git a/App/js/emumanager.js b/App/js/emumanager.js new file mode 100644 index 0000000..1caa903 --- /dev/null +++ b/App/js/emumanager.js @@ -0,0 +1,51 @@ +/* + emumanager.js +*/ + +temp_EMUMANAGER = { + + // Emulator is running + emuRunning: !1, + + // Run emu + runGame: function(){ + + // If user selected a game + if (APP.gameList.list[APP.gameList.selectedGame] !== void 0){ + + // Set main variables + var ebootPath = APP.gameList.list[APP.gameList.selectedGame].eboot, + emuArgs = ['-e', ebootPath], + hList = APP.design.hackList; + + // Get enabled hacks + hList.forEach(function(hackName){ + if (document.getElementById('CHECK_' + hackName).checked === !0){ + emuArgs.push('-h'); + emuArgs.push(hackName); + } + }); + + // Log emu args + APP.log('\nINFO - Running fpPS4 with args: ' + emuArgs.toString().replace(RegExp(',', 'gi'), ' ') + '\n\n'); + + // Run fpPS4 + APP.runExec(APP.settings.data.emuPath, emuArgs); + this.emuRunning = !0; + + // Update GUI + APP.design.updateRunButtons(); + + } + + }, + + // Kill emu process + killEmu: function(){ + + process.kill(APP.execProcess.pid); + this.emuRunning = !1; + + } + +} \ No newline at end of file diff --git a/App/js/filemanager.js b/App/js/filemanager.js new file mode 100644 index 0000000..a270110 --- /dev/null +++ b/App/js/filemanager.js @@ -0,0 +1,30 @@ +/* + filemanager.js +*/ + +temp_FILEMANAGER = { + + // Select path + selectPath: function(postAction){ + + if (postAction !== void 0){ + + document.getElementById('APP_FOLDER_LOADER').onchange = function(){ + + const cFile = document.getElementById('APP_FOLDER_LOADER').files[0]; + + if (cFile.path !== null && cFile.path !== void 0 && cFile.path !== ''){ + postAction(cFile.path.replace(RegExp('\\\\', 'gi'), '/')); + document.getElementById('APP_FOLDER_LOADER').value = ''; + document.getElementById('APP_FOLDER_LOADER').accept = ''; + } + + } + + document.getElementById('APP_FOLDER_LOADER').click(); + + } + + } + +} \ No newline at end of file diff --git a/App/js/gamelist.js b/App/js/gamelist.js new file mode 100644 index 0000000..18303ca --- /dev/null +++ b/App/js/gamelist.js @@ -0,0 +1,125 @@ +/* + gamelist.js +*/ + +temp_GAMELIST = { + + // Game List + list: {}, + + // Selected game + selectedGame: '', + + // Select game path + selectPath: function(){ + + APP.fileManager.selectPath(function(newGamePath){ + APP.settings.data.gamePath = newGamePath; + APP.settings.save(); + APP.gameList.load(); + }); + + }, + + // Load list + load: function(){ + + // Check if path exists + if (APP.fs.existsSync(APP.settings.data.gamePath) === !0){ + + // Reset game list + APP.gameList.list = {}; + + // Get game list + const gList = APP.fs.readdirSync(APP.settings.data.gamePath); + + if (gList.length > 0){ + + // Process game list + gList.forEach(function(gPath){ + + var addGame = !0, + elfName = '', + ebootName = '', + pathBase = APP.settings.data.gamePath + '/' + gPath, + + appBg0 = pathBase + '/pic0.png', + appBg1 = pathBase + '/pic1.png', + appIcon = pathBase + '/icon.png', + + finalBg = appBg0, + finalIcon = appIcon, + + ebootFile = pathBase + '/eboot.bin'; + + if (APP.fs.existsSync(ebootFile) === !0){ + ebootName = 'eboot.bin'; + } + + // If eboot.bin doesn't exists, look for any .elf file + if (APP.fs.existsSync(ebootFile) !== !0){ + + var fList = APP.fs.readdirSync(pathBase), + execName = fList.filter(function(fName){ + if (fName.toLowerCase().indexOf('.elf') !== -1){ + return fName; + } + })[0]; + + ebootName = execName; + + // If not found (undefined), skip + if (execName === void 0){ + addGame = !1; + } + + } + + // Set icon + if (APP.fs.existsSync(appIcon) === !1){ + finalIcon = APP.settings.data.nwPath + '/app/img/404.png'; + } + + // Set BG image + if (APP.fs.existsSync(appBg0) === !1){ + finalBg = appBg1; + if (APP.fs.existsSync(appBg1) === !1){ + finalBg = APP.settings.data.nwPath + '/app/img/404_BG.png'; + } + } + + // If executable exists, set data + if (addGame === !0){ + APP.gameList.list[gPath] = { + bg: finalBg, + name: gPath, + icon: finalIcon, + eboot: APP.settings.data.gamePath + '/' + gPath + '/' + ebootName + } + } + + }); + + } else { + + // No games / homebrew found + APP.log('INFO - No games / homebrew were detected on current path (' + APP.settings.data.gamePath + ')'); + + } + + // Render game list + APP.design.renderGameList(); + + } + + }, + + // Open game folder + openFolder: function(){ + + // Spawn explorer + APP.childProcess.exec('start "" "' + APP.settings.data.gamePath + '"'); + + } + +} \ No newline at end of file diff --git a/App/js/main.js b/App/js/main.js new file mode 100644 index 0000000..3a624cb --- /dev/null +++ b/App/js/main.js @@ -0,0 +1,124 @@ +/* + main.js +*/ + +var APP = { + + // App version + version: '1.0.0', + + // Import nw modules + fs: require('fs'), + path: require('path'), + childProcess: require('child_process'), + + // Import app modules + design: temp_DESIGN, + gameList: temp_GAMELIST, + settings: temp_SETTINGS, + emuManager: temp_EMUMANAGER, + fileManager: temp_FILEMANAGER, + + // Log function and variables + logData: '', + log: function(text, skipLog){ + + if (text !== '' && text !== void 0){ + + var textarea = document.getElementById('APP_LOG'), + previousLog = textarea.value, + newLog = previousLog + '\n' + text; + + if (previousLog == ''){ + newLog = text; + } + + if (previousLog.slice(previousLog.length - 1, previousLog.length) === '\n'){ + newLog = previousLog + text; + } + + textarea.value = newLog; + APP.logData = newLog; + + // If true, skip internal log + if (skipLog !== !0){ + console.log(text); + } + + // Scroll log + textarea.scrollTop = textarea.scrollHeight; + + } + + }, + + // Run external software + execProcess: void 0, + runExec: function(exe, args){ + + if (exe !== void 0 && exe !== ''){ + + /* + Spawn process + It will change running dir to current exe location + */ + process.chdir(APP.path.parse(exe).dir); + APP.execProcess = APP.childProcess.spawn(exe, args); + + // Log on stdout and stderr + APP.execProcess.stdout.on('data', function(data){ + APP.log(data.toString(), !0); + }); + APP.execProcess.stderr.on('data', function(data){ + APP.log(data.toString(), !0); + }); + + // Log on close + APP.execProcess.on('close', function(code){ + process.chdir(APP.settings.data.nwPath); + APP.emuManager.emuRunning = !1; + APP.log('INFO - ' + APP.path.parse(exe).base + ' was closed returning code ' + code); + APP.design.updateRunButtons(); + return code; + }); + + } + + }, + + // About screen + about: function(){ + window.alert('fpPS4 Temmie\'s Launcher - Version: ' + this.version + '\nCreated by TemmieHeartz\n(https://twitter.com/themitosan)\n\nfpPS4 main emulator is created by red-prig\n(https://github.com/red-prig/fpPS4)'); + }, + + // Reload app + reload: function(){ + location.reload(); + } + +} + +// Delete modules +delete temp_DESIGN; +delete temp_SETTINGS; +delete temp_GAMELIST; +delete temp_EMUMANAGER; +delete temp_FILEMANAGER; + +// Start +window.onload = function(){ + + // Main log + APP.log('fpPS4 Temmie\'s Launcher - Version: ' + APP.version + '\nRunning on nw.js (node-webkit) version ' + process.versions.nw); + + // Load settings + APP.settings.load(); + APP.settings.checkPaths(); + + // Load game list + APP.gameList.load(); + + // Rener hack list + APP.design.renderHacklist(); + +} \ No newline at end of file diff --git a/App/js/settings.js b/App/js/settings.js new file mode 100644 index 0000000..c8a5165 --- /dev/null +++ b/App/js/settings.js @@ -0,0 +1,69 @@ +/* + settings.js +*/ + +temp_SETTINGS = { + + // Settings list + data: { + nwPath: '', + emuPath: '', + gamePath: '' + }, + + // Load settings + load: function() { + + // Create save + if (localStorage.getItem('settings') === null){ + APP.settings.save(); + } + + const settings = localStorage.getItem('settings'); + this.data = JSON.parse(settings); + + }, + + // Save settings + save: function() { + localStorage.setItem('settings', JSON.stringify(this.data)); + }, + + // Check paths + checkPaths: function(){ + + // Fix path + this.data.nwPath = nw.__dirname.replace(RegExp('\\\\', 'gi'), '/'); + + const mainPath = this.data.nwPath, + pathList = [ + '/Emu', + '/Games' + ]; + + // Try create required paths + pathList.forEach(function(cPath){ + if (APP.fs.existsSync(mainPath + cPath) !== !0){ + try { + APP.fs.mkdirSync(mainPath + cPath); + } catch (err) { + APP.log('Unable to create path!\n(' + mainPath + cPath + ')\n' + err); + } + } + }); + + // Set Games / Emu paths and check if fpPS4 exe is present + this.data.gamePath = mainPath + '/Games'; + this.data.emuPath = mainPath + '/Emu/fpPS4.exe'; + + if (APP.fs.existsSync(this.data.emuPath) === !0){ + APP.log('INFO - Main fpPS4 was found!'); + } else { + const errMsg = 'ERROR - Unable to locate main fpPS4 executable!\nMake sure to insert it on \"Emu\" folder and click on ok.'; + window.alert(errMsg); + APP.log(errMsg); + } + + } + +} \ No newline at end of file diff --git a/package.json b/package.json new file mode 100644 index 0000000..c54ea74 --- /dev/null +++ b/package.json @@ -0,0 +1,25 @@ +{ + "version": "1.0.0", + "license": "GPL-2", + "main": "App/index.htm", + "author": "TemmieHeartz", + "name": "fpPS4 Temmie's Launcher", + "description": "A simple launcher for fpPS4 project", + "repository": "https://github.com/themitosan/fpPS4-Temmie-s-Launcher", + "window": { + "frame": true, + "width": 1180, + "height": 710, + "toolbar": true, + "min_width": 1180, + "min_height": 710, + "fullscreen": false, + "position": "center", + "theme-color": "#000", + "icon": "App/img/logo.png", + "title": "fpPS4 Temmie's Launcher" + }, + "webkit": { + "plugin": true + } +} \ No newline at end of file