mirror of
https://github.com/open-goal/launcher.git
synced 2024-10-20 04:57:38 -04:00
Merge pull request #27 from xTVaser/v/requirements
setup: Check for minimum requirements before allowing installation
This commit is contained in:
commit
c0c14da9ec
|
@ -20,3 +20,4 @@ if (process.platform === "win32") {
|
|||
writeFileSync(`./src-tauri/bin/extractor${extension}`, "dummy");
|
||||
writeFileSync(`./src-tauri/bin/gk${extension}`, "dummy");
|
||||
writeFileSync(`./src-tauri/bin/goalc${extension}`, "dummy");
|
||||
writeFileSync(`./src-tauri/bin/glewinfo${extension}`, "dummy");
|
||||
|
|
|
@ -35,6 +35,12 @@ async function main() {
|
|||
`src-tauri/bin/goalc-${targetTriple}${extension}`
|
||||
);
|
||||
}
|
||||
if (existsSync(`src-tauri/bin/glewinfo${extension}`)) {
|
||||
renameSync(
|
||||
`src-tauri/bin/glewinfo${extension}`,
|
||||
`src-tauri/bin/glewinfo-${targetTriple}${extension}`
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
main().catch((e) => {
|
||||
|
|
|
@ -27,3 +27,7 @@ copyFileSync(
|
|||
"../jak-project/out/build/Release/bin/goalc.exe",
|
||||
"./src-tauri/bin/goalc.exe"
|
||||
);
|
||||
copyFileSync(
|
||||
"./third-party/glew_2.1.0/windows/glewinfo.exe",
|
||||
"./src-tauri/bin/glewinfo.exe"
|
||||
);
|
||||
|
|
30
src-tauri/src/commands.rs
Normal file
30
src-tauri/src/commands.rs
Normal file
|
@ -0,0 +1,30 @@
|
|||
use tauri::{command};
|
||||
|
||||
|
||||
#[derive(Debug, serde::Serialize)]
|
||||
pub enum CommandError {
|
||||
ArchitectureNotx86,
|
||||
AVXNotSupported,
|
||||
Unknown
|
||||
}
|
||||
|
||||
#[command]
|
||||
pub fn get_highest_simd() -> Result<String, CommandError> {
|
||||
return highest_simd();
|
||||
}
|
||||
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
fn highest_simd() -> Result<String, CommandError> {
|
||||
if is_x86_feature_detected!("avx2") {
|
||||
return Ok("AVX2".to_string());
|
||||
} else if is_x86_feature_detected!("avx") {
|
||||
return Ok("AVX".to_string());
|
||||
} else {
|
||||
return Err(CommandError::AVXNotSupported);
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(not(target_arch = "x86_64"))]
|
||||
fn highest_simd() -> Result<String, CommandError> {
|
||||
return Err(CommandError::ArchitectureNotx86);
|
||||
}
|
|
@ -5,9 +5,15 @@
|
|||
|
||||
use tauri_plugin_store::PluginBuilder;
|
||||
|
||||
mod commands;
|
||||
use commands::{get_highest_simd};
|
||||
|
||||
fn main() {
|
||||
tauri::Builder::default()
|
||||
.plugin(PluginBuilder::default().build())
|
||||
.invoke_handler(tauri::generate_handler![
|
||||
get_highest_simd,
|
||||
])
|
||||
.run(tauri::generate_context!())
|
||||
.expect("error while running tauri application");
|
||||
}
|
||||
|
|
|
@ -22,7 +22,7 @@
|
|||
"icons/icon.ico"
|
||||
],
|
||||
"resources": [],
|
||||
"externalBin": ["bin/extractor", "bin/gk", "bin/goalc"],
|
||||
"externalBin": ["bin/extractor", "bin/gk", "bin/goalc", "bin/glewinfo"],
|
||||
"copyright": "",
|
||||
"category": "DeveloperTool",
|
||||
"shortDescription": "",
|
||||
|
@ -75,6 +75,12 @@
|
|||
"sidecar": true,
|
||||
"cmd": "ignored",
|
||||
"args": true
|
||||
},
|
||||
{
|
||||
"name": "bin/glewinfo",
|
||||
"sidecar": true,
|
||||
"cmd": "ignored",
|
||||
"args": true
|
||||
}]
|
||||
}
|
||||
},
|
||||
|
|
|
@ -159,6 +159,7 @@ body {
|
|||
height: 100vh;
|
||||
width: 90vw;
|
||||
max-width: 90vw;
|
||||
overflow-y: auto;
|
||||
}
|
||||
|
||||
.flex-center {
|
||||
|
@ -271,3 +272,21 @@ body {
|
|||
details > summary:hover {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.progress-row a {
|
||||
text-decoration: none;
|
||||
color: #ffa500;
|
||||
}
|
||||
|
||||
.progress-row a:hover {
|
||||
color: #ffbd42;
|
||||
}
|
||||
|
||||
.orange-text {
|
||||
color: #ffa500;
|
||||
}
|
||||
|
||||
ul.no-decoration {
|
||||
list-style-type: none;
|
||||
padding-left: 2em;
|
||||
}
|
||||
|
|
13
src/lib/commands.js
Normal file
13
src/lib/commands.js
Normal file
|
@ -0,0 +1,13 @@
|
|||
import { invoke } from "@tauri-apps/api/tauri";
|
||||
|
||||
export async function getHighestSimd() {
|
||||
try {
|
||||
return await invoke("get_highest_simd");
|
||||
} catch (e) {
|
||||
if (e === "AVXNotSupported") {
|
||||
return "noavx";
|
||||
} else {
|
||||
return undefined;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,5 +1,7 @@
|
|||
import { Command } from "@tauri-apps/api/shell";
|
||||
import { resourceDir } from "@tauri-apps/api/path";
|
||||
import { os } from "@tauri-apps/api";
|
||||
import { getHighestSimd } from "/src/lib/commands";
|
||||
|
||||
export class InstallationStatus {
|
||||
static Pending = Symbol("pending");
|
||||
|
@ -8,6 +10,13 @@ export class InstallationStatus {
|
|||
static Success = Symbol("success");
|
||||
}
|
||||
|
||||
export class RequirementStatus {
|
||||
static Unknown = Symbol("unknown");
|
||||
static Met = Symbol("met");
|
||||
static Failed = Symbol("failed");
|
||||
static Checking = Symbol("checking");
|
||||
}
|
||||
|
||||
// TODO - is this set to `production` properly in release mode?
|
||||
function isInDebugMode() {
|
||||
return process.env.NODE_ENV === "development";
|
||||
|
@ -21,6 +30,37 @@ if (isInDebugMode()) {
|
|||
debugPath += "\\launcher\\bundle-test\\data";
|
||||
}
|
||||
|
||||
export async function isAVXSupported() {
|
||||
let highestSIMD = await getHighestSimd();
|
||||
if (highestSIMD === undefined) {
|
||||
return RequirementStatus.Unknown;
|
||||
}
|
||||
if (highestSIMD.toLowerCase().startsWith("avx")) {
|
||||
return RequirementStatus.Met;
|
||||
}
|
||||
return RequirementStatus.Failed;
|
||||
}
|
||||
|
||||
export async function isOpenGLVersionSupported(version) {
|
||||
// TODO - glewinfo not pre-compiled to work on linux yet!
|
||||
if ((await os.platform()) === "darwin") {
|
||||
return RequirementStatus.Unknown;
|
||||
}
|
||||
// Otherwise, query for the version
|
||||
let command = Command.sidecar("bin/glewinfo", ["-version", version], {
|
||||
cwd: "bin",
|
||||
});
|
||||
try {
|
||||
let output = await command.execute();
|
||||
if (output.code === 0) {
|
||||
return RequirementStatus.Met;
|
||||
}
|
||||
return RequirementStatus.Failed;
|
||||
} catch {
|
||||
return RequirementStatus.Failed;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {String} filePath
|
||||
* @returns {Promise<ChildProcess>}
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
<script>
|
||||
import { onMount } from "svelte";
|
||||
import { Link, navigate } from "svelte-routing";
|
||||
import { filePrompt } from "/src/lib/utils/file";
|
||||
import {
|
||||
|
@ -6,9 +7,11 @@
|
|||
decompileGameData,
|
||||
extractISO,
|
||||
validateGameData,
|
||||
isAVXSupported,
|
||||
isOpenGLVersionSupported,
|
||||
} from "/src/lib/setup";
|
||||
import { SupportedGame, setInstallStatus } from "/src/lib/config";
|
||||
import { InstallationStatus } from "/src/lib/setup";
|
||||
import { InstallationStatus, RequirementStatus } from "/src/lib/setup";
|
||||
import {
|
||||
appendToInstallLog,
|
||||
appendToInstallErrorLog,
|
||||
|
@ -18,6 +21,19 @@
|
|||
let setupInProgress = false;
|
||||
let isoPath = undefined;
|
||||
|
||||
let requirementChecks = [
|
||||
{
|
||||
status: RequirementStatus.Checking,
|
||||
text: `CPU Supports <a href="https://en.wikipedia.org/wiki/Advanced_Vector_Extensions"><strong>AVX or AVX2</strong></a>`,
|
||||
check: async () => await isAVXSupported(),
|
||||
},
|
||||
{
|
||||
status: RequirementStatus.Checking,
|
||||
text: `GPU Supports OpenGL <span class="orange-text"><strong>4.3</strong></span>`,
|
||||
check: async () => await isOpenGLVersionSupported("4.3"),
|
||||
},
|
||||
];
|
||||
|
||||
let currStep = 0;
|
||||
let installSteps = [
|
||||
{
|
||||
|
@ -46,18 +62,42 @@
|
|||
},
|
||||
];
|
||||
|
||||
// TODO - move this to the enum
|
||||
function statusIndicator(status) {
|
||||
if (status === InstallationStatus.InProgress) {
|
||||
return `spinner`;
|
||||
} else if (status === InstallationStatus.Success) {
|
||||
if (
|
||||
status === InstallationStatus.InProgress ||
|
||||
status === RequirementStatus.Checking
|
||||
) {
|
||||
return `<div class="loader" />`;
|
||||
} else if (
|
||||
status === InstallationStatus.Success ||
|
||||
status === RequirementStatus.Met
|
||||
) {
|
||||
return "✅";
|
||||
} else if (status === InstallationStatus.Failed) {
|
||||
} else if (
|
||||
status === InstallationStatus.Failed ||
|
||||
status === RequirementStatus.Failed
|
||||
) {
|
||||
return "❌";
|
||||
} else if (status === RequirementStatus.Unknown) {
|
||||
return "⚠️";
|
||||
} else {
|
||||
return "⏳";
|
||||
}
|
||||
}
|
||||
|
||||
function areRequirementsMet(checks) {
|
||||
for (let i = 0; i < checks.length; i++) {
|
||||
if (
|
||||
checks[i].status !== RequirementStatus.Met &&
|
||||
checks[i].status !== RequirementStatus.Unknown
|
||||
) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
function finishStep(output) {
|
||||
appendLogs(output);
|
||||
installSteps[currStep].status =
|
||||
|
@ -72,7 +112,10 @@
|
|||
|
||||
async function appendLogs(output) {
|
||||
const separator = `----${installSteps[currStep].text}----\n`;
|
||||
await appendToInstallLog(SupportedGame.Jak1, "\n" + separator + output.stdout);
|
||||
await appendToInstallLog(
|
||||
SupportedGame.Jak1,
|
||||
"\n" + separator + output.stdout
|
||||
);
|
||||
await appendToInstallErrorLog(
|
||||
SupportedGame.Jak1,
|
||||
"\n" + separator + output.stderr
|
||||
|
@ -111,6 +154,12 @@
|
|||
}
|
||||
|
||||
// Events
|
||||
onMount(async () => {
|
||||
for (let i = 0; i < requirementChecks.length; i++) {
|
||||
requirementChecks[i].status = await requirementChecks[i].check();
|
||||
}
|
||||
});
|
||||
|
||||
async function onClickBrowse() {
|
||||
isoPath = await filePrompt();
|
||||
installProcess();
|
||||
|
@ -119,9 +168,26 @@
|
|||
|
||||
<div class="content">
|
||||
<h1>Setup Process</h1>
|
||||
<h2>Minimum Requirements</h2>
|
||||
<ul class="no-decoration">
|
||||
{#each requirementChecks as check}
|
||||
<li>
|
||||
<span class="progress-row">
|
||||
{@html statusIndicator(check.status)}
|
||||
{@html check.text}
|
||||
</span>
|
||||
{#if check.status === RequirementStatus.Unknown}
|
||||
<ul class="no-decoration">
|
||||
<li>Unable to determine this requirement</li>
|
||||
</ul>
|
||||
{/if}
|
||||
</li>
|
||||
{/each}
|
||||
</ul>
|
||||
{#if areRequirementsMet(requirementChecks)}
|
||||
<p>Browse for your ISO - Obtained by dumping your own legitimate copy</p>
|
||||
<div>
|
||||
<button class="btn" on:click={onClickBrowse}>Browse for ISO</button>
|
||||
<button class="btn" disabled={setupInProgress} on:click={onClickBrowse}>Browse for ISO</button>
|
||||
{#if isoPath}
|
||||
{isoPath}
|
||||
{/if}
|
||||
|
@ -136,15 +202,11 @@
|
|||
{:else}
|
||||
<div>
|
||||
<h2>Progress</h2>
|
||||
<ul>
|
||||
<ul class="no-decoration">
|
||||
{#each installSteps as step}
|
||||
<li>
|
||||
<span class="progress-row">
|
||||
{#if step.status === InstallationStatus.InProgress}
|
||||
<div class="loader" />
|
||||
{:else}
|
||||
{statusIndicator(step.status)}
|
||||
{/if}
|
||||
{@html statusIndicator(step.status)}
|
||||
{step.text}
|
||||
</span>
|
||||
</li>
|
||||
|
@ -169,4 +231,5 @@
|
|||
</details>
|
||||
</div>
|
||||
{/if}
|
||||
{/if}
|
||||
</div>
|
||||
|
|
73
third-party/glew_2.1.0/LICENSE
vendored
Normal file
73
third-party/glew_2.1.0/LICENSE
vendored
Normal file
|
@ -0,0 +1,73 @@
|
|||
The OpenGL Extension Wrangler Library
|
||||
Copyright (C) 2002-2007, Milan Ikits <milan ikits[]ieee org>
|
||||
Copyright (C) 2002-2007, Marcelo E. Magallon <mmagallo[]debian org>
|
||||
Copyright (C) 2002, Lev Povalahev
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
* The name of the author may be used to endorse or promote products
|
||||
derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
|
||||
THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
|
||||
Mesa 3-D graphics library
|
||||
Version: 7.0
|
||||
|
||||
Copyright (C) 1999-2007 Brian Paul All Rights Reserved.
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a
|
||||
copy of this software and associated documentation files (the "Software"),
|
||||
to deal in the Software without restriction, including without limitation
|
||||
the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
and/or sell copies of the Software, and to permit persons to whom the
|
||||
Software is furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included
|
||||
in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
|
||||
AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
|
||||
Copyright (c) 2007 The Khronos Group Inc.
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a
|
||||
copy of this software and/or associated documentation files (the
|
||||
"Materials"), to deal in the Materials without restriction, including
|
||||
without limitation the rights to use, copy, modify, merge, publish,
|
||||
distribute, sublicense, and/or sell copies of the Materials, and to
|
||||
permit persons to whom the Materials are furnished to do so, subject to
|
||||
the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included
|
||||
in all copies or substantial portions of the Materials.
|
||||
|
||||
THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||
MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
|
BIN
third-party/glew_2.1.0/linux/glewinfo_2.1.0
vendored
Normal file
BIN
third-party/glew_2.1.0/linux/glewinfo_2.1.0
vendored
Normal file
Binary file not shown.
BIN
third-party/glew_2.1.0/windows/glewinfo.exe
vendored
Normal file
BIN
third-party/glew_2.1.0/windows/glewinfo.exe
vendored
Normal file
Binary file not shown.
Loading…
Reference in a new issue