forked from akanyan/STARTLINER
feat: chusanApp.exe patching
This commit is contained in:
@ -1,7 +1,6 @@
|
||||
use serde::{Deserialize, Serialize};
|
||||
use tauri::AppHandle;
|
||||
pub use types::{Profile, ProfileData, ProfileMeta, ProfilePaths, StartPayload};
|
||||
use std::{collections::{BTreeMap, BTreeSet}, path::{Path, PathBuf}};
|
||||
use crate::{model::{misc::Game, patch::PatchSelection, profile::{Aime, ChunithmKeyboard, Keyboard, Mu3Ini, OngekiKeyboard, ProfileModule}}, modules::package::prepare_packages, pkg::PkgKey, pkg_store::PackageStore, util};
|
||||
use crate::{model::{misc::Game, patch::{PatchFileVec, PatchSelection}, profile::{Aime, ChunithmKeyboard, Keyboard, Mu3Ini, OngekiKeyboard, ProfileModule}}, modules::{display_windows::DisplayInfo, package::prepare_packages}, pkg::PkgKey, pkg_store::PackageStore, util};
|
||||
use tauri::Emitter;
|
||||
use std::process::Stdio;
|
||||
use crate::model::profile::BepInEx;
|
||||
@ -11,57 +10,7 @@ use std::fs::File;
|
||||
use tokio::process::Command;
|
||||
use tokio::task::JoinSet;
|
||||
|
||||
pub trait ProfilePaths {
|
||||
fn config_dir(&self) -> PathBuf;
|
||||
fn data_dir(&self) -> PathBuf;
|
||||
}
|
||||
|
||||
#[derive(Deserialize, Serialize, Clone, Debug, PartialEq)]
|
||||
pub struct ProfileMeta {
|
||||
pub game: Game,
|
||||
pub name: String
|
||||
}
|
||||
|
||||
impl ProfilePaths for ProfileMeta {
|
||||
fn config_dir(&self) -> PathBuf {
|
||||
util::profile_config_dir(self.game, &self.name)
|
||||
}
|
||||
|
||||
fn data_dir(&self) -> PathBuf {
|
||||
util::data_dir().join(format!("profile-{}-{}", &self.game, &self.name))
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Deserialize, Serialize, Clone)]
|
||||
pub struct Profile {
|
||||
pub meta: ProfileMeta,
|
||||
pub data: ProfileData,
|
||||
}
|
||||
|
||||
#[derive(Deserialize, Serialize, Clone, Debug)]
|
||||
pub struct ProfileData {
|
||||
pub mods: BTreeSet<PkgKey>,
|
||||
pub sgt: Segatools,
|
||||
pub network: Network,
|
||||
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub display: Option<Display>,
|
||||
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub bepinex: Option<BepInEx>,
|
||||
|
||||
#[cfg(not(target_os = "windows"))]
|
||||
pub wine: crate::model::profile::Wine,
|
||||
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub mu3_ini: Option<Mu3Ini>,
|
||||
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub keyboard: Option<Keyboard>,
|
||||
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub patches: Option<PatchSelection>,
|
||||
}
|
||||
pub mod types;
|
||||
|
||||
impl Profile {
|
||||
pub fn new(mut meta: ProfileMeta) -> Result<Self> {
|
||||
@ -205,27 +154,15 @@ impl Profile {
|
||||
self.data.patches = source.patches;
|
||||
}
|
||||
}
|
||||
pub async fn line_up(&self, pkg_hash: String, refresh: bool, _app: AppHandle) -> Result<()> {
|
||||
pub fn prepare_display(&self) -> Result<Option<DisplayInfo>> {
|
||||
let info = match &self.data.display {
|
||||
None => None,
|
||||
Some(display) => display.prepare()?
|
||||
};
|
||||
|
||||
let res = self.line_up_the_rest(pkg_hash, refresh).await;
|
||||
|
||||
#[cfg(target_os = "windows")]
|
||||
if let Some(info) = info {
|
||||
use crate::model::profile::Display;
|
||||
if res.is_ok() {
|
||||
Display::wait_for_exit(_app, info);
|
||||
} else {
|
||||
Display::clean_up(&info)?;
|
||||
}
|
||||
}
|
||||
|
||||
res
|
||||
Ok(info)
|
||||
}
|
||||
async fn line_up_the_rest(&self, pkg_hash: String, refresh: bool) -> Result<()> {
|
||||
pub async fn line_up(&self, pkg_hash: String, refresh: bool, patch_files: &PatchFileVec) -> Result<()> {
|
||||
if !self.data_dir().exists() {
|
||||
tokio::fs::create_dir(self.data_dir()).await?;
|
||||
}
|
||||
@ -235,10 +172,13 @@ impl Profile {
|
||||
util::clean_up_opts(self.data_dir().join("option"))?;
|
||||
|
||||
let hash_check = Self::hash_check(&hash_path, &pkg_hash).await? || refresh;
|
||||
|
||||
prepare_packages(&self.meta, &self.data.mods, hash_check).await
|
||||
.map_err(|e| anyhow!("package configuration failed:\n{:?}", e))?;
|
||||
|
||||
let mut ini = self.data.sgt.line_up(&self.meta, self.meta.game).await
|
||||
.map_err(|e| anyhow!("segatools configuration failed:\n{:?}", e))?;
|
||||
|
||||
self.data.network.line_up(&mut ini)?;
|
||||
|
||||
if let Some(display) = &self.data.display {
|
||||
@ -260,10 +200,18 @@ impl Profile {
|
||||
mu3ini.line_up(&self.data.sgt.target.parent().unwrap())?;
|
||||
}
|
||||
|
||||
if let Some(patches) = &self.data.patches {
|
||||
futures::try_join!(
|
||||
patches.render_to_file("amdaemon.exe", patch_files, self.data_dir().join("patch-amd.mph")),
|
||||
patches.render_to_file("chusanApp.exe", patch_files, self.data_dir().join("patch-game.mph"))
|
||||
)?;
|
||||
}
|
||||
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub async fn start(&self, app: AppHandle) -> Result<()> {
|
||||
pub async fn start(&self, payload: StartPayload) -> Result<()> {
|
||||
let ini_path = self.data_dir().join("segatools.ini");
|
||||
|
||||
log::debug!("With path {:?}", ini_path);
|
||||
@ -294,10 +242,23 @@ impl Profile {
|
||||
&ini_path,
|
||||
)
|
||||
.current_dir(&exe_dir)
|
||||
.arg("/C")
|
||||
.raw_arg("/C")
|
||||
.arg(&sgt_dir.join(self.meta.game.inject_amd()))
|
||||
.args(["-d", "-k"])
|
||||
.arg(sgt_dir.join(self.meta.game.hook_amd()))
|
||||
.raw_arg("-d")
|
||||
.raw_arg("-k")
|
||||
.arg(sgt_dir.join(self.meta.game.hook_amd()));
|
||||
|
||||
// for dll in payload.amd_dlls {
|
||||
// amd_builder.arg("-k");
|
||||
// amd_builder.arg(dll);
|
||||
// }
|
||||
|
||||
// if self.meta.game.has_module(ProfileModule::Mempatcher) {
|
||||
// amd_builder.arg("--mempatch");
|
||||
// amd_builder.arg(self.data_dir().join("patch-amd.mph"));
|
||||
// }
|
||||
|
||||
amd_builder
|
||||
.arg("amdaemon.exe")
|
||||
.args(self.meta.game.amd_args());
|
||||
|
||||
@ -317,9 +278,16 @@ impl Profile {
|
||||
self.config_dir().join("saekawa.toml"),
|
||||
)
|
||||
.current_dir(&exe_dir)
|
||||
.args(["-d", "-k"])
|
||||
.arg(sgt_dir.join(self.meta.game.hook_exe()))
|
||||
.arg(self.meta.game.exe());
|
||||
.raw_arg("-d")
|
||||
.raw_arg("-k")
|
||||
.arg(sgt_dir.join(self.meta.game.hook_exe()));
|
||||
|
||||
for dll in payload.game_dlls {
|
||||
game_builder.raw_arg("-k");
|
||||
game_builder.arg(dll);
|
||||
}
|
||||
|
||||
game_builder.arg(self.meta.game.exe());
|
||||
|
||||
if self.meta.game.has_module(ProfileModule::BepInEx) {
|
||||
if let Some(display) = &self.data.display {
|
||||
@ -339,6 +307,11 @@ impl Profile {
|
||||
}
|
||||
}
|
||||
|
||||
if self.meta.game.has_module(ProfileModule::Mempatcher) {
|
||||
game_builder.arg("--mempatch");
|
||||
game_builder.arg(self.data_dir().join("patch-game.mph"));
|
||||
}
|
||||
|
||||
#[cfg(target_os = "linux")]
|
||||
{
|
||||
amd_builder.env("WINEPREFIX", &self.wine.prefix);
|
||||
@ -383,7 +356,7 @@ impl Profile {
|
||||
(game.wait().await.expect("game failed to run"), "game")
|
||||
});
|
||||
|
||||
if let Err(e) = app.emit("launch-start", "") {
|
||||
if let Err(e) = payload.app.emit("launch-start", "") {
|
||||
log::warn!("Unable to emit launch-start: {}", e);
|
||||
}
|
||||
|
||||
@ -401,7 +374,7 @@ impl Profile {
|
||||
|
||||
log::debug!("Fin");
|
||||
|
||||
if let Err(e) = app.emit("launch-end", "") {
|
||||
if let Err(e) = payload.app.emit("launch-end", "") {
|
||||
log::warn!("Unable to emit launch-end: {}", e);
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user