Files
STARTLINER/rust/src/start.rs

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;
}