forked from akanyan/STARTLINER
152 lines
4.2 KiB
Rust
152 lines
4.2 KiB
Rust
use anyhow::Result;
|
|
use std::fs::File;
|
|
use std::path::PathBuf;
|
|
use tokio::process::Command;
|
|
use tauri::{AppHandle, Emitter};
|
|
use std::process::Stdio;
|
|
use crate::profile::Profile;
|
|
use crate::util;
|
|
|
|
#[cfg(target_os = "windows")]
|
|
static CREATE_NO_WINDOW: u32 = 0x08000000;
|
|
|
|
pub fn start(p: &Profile, app: AppHandle) -> Result<()> {
|
|
use tokio::task::JoinSet;
|
|
|
|
let ini_path = p.dir().join("segatools.ini");
|
|
|
|
log::debug!("With path {}", ini_path.to_string_lossy());
|
|
|
|
let mut game_builder;
|
|
let mut amd_builder;
|
|
|
|
#[cfg(target_os = "windows")]
|
|
{
|
|
game_builder = Command::new(p.exe_dir.join("inject.exe"));
|
|
amd_builder = Command::new("cmd.exe");
|
|
}
|
|
#[cfg(target_os = "linux")]
|
|
{
|
|
let wine = p.data.wine_runtime.clone()
|
|
.unwrap_or_else(|| PathBuf::from("/usr/bin/wine"));
|
|
|
|
game_builder = Command::new(&wine);
|
|
amd_builder = Command::new(&wine);
|
|
|
|
game_builder.arg(p.data.exe_dir.join("inject.exe"));
|
|
amd_builder.arg("cmd.exe");
|
|
}
|
|
|
|
let display_mode = p.get_str("display-mode", "borderless");
|
|
|
|
amd_builder.env(
|
|
"SEGATOOLS_CONFIG_PATH",
|
|
&ini_path,
|
|
)
|
|
.current_dir(&p.data.exe_dir)
|
|
.args([
|
|
"/C",
|
|
&util::path_to_str(p.data.exe_dir.join("inject.exe"))?, "-d", "-k", "mu3hook.dll",
|
|
"amdaemon.exe", "-f", "-c", "config_common.json", "config_server.json", "config_client.json"
|
|
]);
|
|
game_builder
|
|
.env(
|
|
"SEGATOOLS_CONFIG_PATH",
|
|
ini_path,
|
|
)
|
|
.current_dir(&p.data.exe_dir)
|
|
.args([
|
|
"-d", "-k", "mu3hook.dll",
|
|
"mu3.exe", "-monitor 1",
|
|
"-screen-width", &p.get_int("rez-w", 1080).to_string(),
|
|
"-screen-height", &p.get_int("rez-h", 1920).to_string(),
|
|
"-screen-fullscreen", if display_mode == "fullscreen" { "1" } else { "0" }
|
|
]);
|
|
|
|
if display_mode == "borderless" {
|
|
game_builder.arg("-popupwindow");
|
|
}
|
|
|
|
#[cfg(target_os = "linux")]
|
|
{
|
|
let wineprefix = p.data.wine_prefix.clone().unwrap_or_else(||
|
|
directories::UserDirs::new()
|
|
.expect("No home directory")
|
|
.home_dir()
|
|
.join(".wine")
|
|
);
|
|
amd_builder.env("WINEPREFIX", &wineprefix);
|
|
game_builder.env("WINEPREFIX", &wineprefix);
|
|
}
|
|
|
|
|
|
let amd_log = File::create(p.dir().join("amdaemon.log"))?;
|
|
let game_log = File::create(p.dir().join("mu3.log"))?;
|
|
|
|
amd_builder
|
|
.stdout(Stdio::from(amd_log));
|
|
// do they use stderr?
|
|
|
|
game_builder
|
|
.stdout(Stdio::from(game_log));
|
|
|
|
#[cfg(target_os = "windows")]
|
|
{
|
|
amd_builder.creation_flags(CREATE_NO_WINDOW);
|
|
game_builder.creation_flags(CREATE_NO_WINDOW);
|
|
}
|
|
|
|
if p.get_bool("intel", false) == true {
|
|
amd_builder.env("OPENSSL_ia32cap", ":~0x20000000");
|
|
}
|
|
|
|
log::info!("Launching amdaemon: {:?}", amd_builder);
|
|
log::info!("Launching mu3: {:?}", game_builder);
|
|
|
|
let mut amd = amd_builder.spawn()?;
|
|
let mut game = game_builder.spawn()?;
|
|
|
|
tauri::async_runtime::spawn(async move {
|
|
let mut set = JoinSet::new();
|
|
|
|
set.spawn(async move {
|
|
(amd.wait().await.expect("amdaemon failed to run"), "amdaemon.exe")
|
|
});
|
|
|
|
set.spawn(async move {
|
|
(game.wait().await.expect("mu3 failed to run"), "mu3.exe")
|
|
});
|
|
|
|
_ = app.emit("launch-start", "");
|
|
|
|
let (rc, process_name) = set.join_next().await.expect("No spawn").expect("No result");
|
|
|
|
log::info!("{} died with return code {}", process_name, rc);
|
|
|
|
if process_name == "amdaemon.exe" {
|
|
pkill("mu3.exe").await;
|
|
} else {
|
|
pkill("amdaemon.exe").await;
|
|
}
|
|
|
|
set.join_next().await.expect("No spawn").expect("No result");
|
|
|
|
log::debug!("Fin");
|
|
|
|
_ = app.emit("launch-end", "");
|
|
});
|
|
|
|
Ok(())
|
|
}
|
|
|
|
#[cfg(target_os = "windows")]
|
|
pub async fn pkill(process_name: &str) {
|
|
_ = Command::new("taskkill.exe").arg("/f").arg("/im").arg(process_name)
|
|
.creation_flags(CREATE_NO_WINDOW).output().await;
|
|
}
|
|
|
|
#[cfg(target_os = "linux")]
|
|
pub async fn pkill(process_name: &str) {
|
|
_ = Command::new("pkill").arg(process_name)
|
|
.output().await;
|
|
} |