Files
STARTLINER/rust/src/modules/segatools.rs
2025-03-18 23:27:17 +00:00

147 lines
5.2 KiB
Rust

use std::path::PathBuf;
use anyhow::{anyhow, Result};
use ini::Ini;
use crate::{model::{profile::{Aime, Segatools}, segatools_base::segatools_base}, profiles::ProfilePaths, util::{self, PathStr}};
use crate::pkg_store::PackageStore;
impl Segatools {
pub fn fix(&mut self, store: &PackageStore) {
macro_rules! remove_if_nonpresent {
($item:expr,$key:expr,$emptyval:expr,$store:expr) => {
if let Ok(pkg) = $store.get($key) {
if pkg.loc.is_none() {
$item = $emptyval;
}
} else {
$item = $emptyval;
}
}
}
if let Some(key) = &self.hook {
remove_if_nonpresent!(self.hook, key, None, store);
}
if let Some(key) = &self.io {
remove_if_nonpresent!(self.io, key, None, store);
}
match &self.aime {
Aime::AMNet(key) => remove_if_nonpresent!(self.aime, key, Aime::BuiltIn, store),
Aime::Other(key) => remove_if_nonpresent!(self.aime, key, Aime::BuiltIn, store),
_ => {},
}
}
pub async fn line_up(&self, p: &impl ProfilePaths) -> Result<Ini> {
log::debug!("begin line-up: segatools");
let pfx_dir = p.data_dir();
let exe_dir = self.target.parent().ok_or_else(|| anyhow!("Invalid target path"))?;
log::debug!("segatools: {:?} {:?}", pfx_dir, exe_dir);
let ini_path = p.config_dir().join("segatools-base.ini");
if !ini_path.exists() {
tokio::fs::write(&ini_path, segatools_base()).await
.map_err(|e| anyhow!("Error creating {:?}: {}", ini_path, e))?;
}
if !pfx_dir.exists() {
tokio::fs::create_dir(&pfx_dir).await
.map_err(|e| anyhow!("Error creating {:?}: {}", pfx_dir, e))?;
}
let ini_in = tokio::fs::read_to_string(&ini_path).await?;
let ini_in = Ini::load_from_str(&ini_in)?;
let opt_dir_out = &pfx_dir.join("option");
let opt_dir_in = if self.option.as_os_str().len() > 0 && self.option.is_relative() {
exe_dir.join(&self.option)
} else {
self.option.clone()
};
let mut ini_out = ini_in.clone();
ini_out.with_section(Some("vfs"))
.set(
"option",
opt_dir_out.stringify()?
)
.set("amfs", self.amfs.stringify()?)
.set("appdata", self.appdata.stringify()?);
ini_out.with_section(Some("unity"))
.set("enable", "1")
.set(
"targetAssembly",
pfx_dir.join("BepInEx").join("core").join("BepInEx.Preloader.dll").stringify()?
);
if self.aime != Aime::Disabled {
ini_out.with_section(Some("aime"))
.set("enable", "1")
.set("aimePath", p.config_dir().join("aime.txt").stringify()?);
if let Aime::AMNet(key) = &self.aime {
let mut aimeio = ini_out.with_section(Some("aimeio"));
aimeio
.set("path", util::pkg_dir().join(key.to_string()).join("segatools").join("aimeio.dll").stringify()?)
.set("gameId", "SDDT")
.set("serverAddress", &self.amnet.addr)
.set("useAimeDBForPhysicalCards", if self.amnet.physical { "1" } else { "0" })
.set("enableKeyboardMode", "0");
if let Ok(keyboard_code) = std::fs::read_to_string(p.config_dir().join("aime.txt")) {
log::debug!("{} {}", keyboard_code, keyboard_code.len());
if keyboard_code.len() == 20 {
aimeio.set("enableKeyboardMode", "1");
}
}
if self.amnet.name.len() > 0 {
aimeio.set("serverName", &self.amnet.name);
}
}
} else {
ini_out.with_section(Some("aime"))
.set("enable", "0");
}
if let Some(io) = &self.io {
ini_out.with_section(Some("mu3io"))
.set("path", util::pkg_dir().join(io.to_string()).join("segatools").join("mu3io.dll").stringify()?);
} else {
ini_out.with_section(Some("mu3io"))
.set("path", "");
}
log::debug!("option dir: {:?} -> {:?}", opt_dir_in, opt_dir_out);
if !opt_dir_out.exists() {
tokio::fs::create_dir(opt_dir_out).await?;
}
if opt_dir_in.as_os_str().len() > 0 {
for opt in opt_dir_in.read_dir()? {
let opt = opt?;
util::symlink(&opt.path(), opt_dir_out.join(opt.file_name())).await?;
}
}
if !exe_dir.join("DEVICE").join("ca.crt").exists() {
util::copy_directory(
util::pkg_dir().join(self.hook_dir()?).join("DEVICE"),
exe_dir.join("DEVICE"),
false
)?;
}
log::debug!("end line-up: segatools");
Ok(ini_out)
}
pub fn hook_dir(&self) -> Result<PathBuf> {
Ok(util::pkg_dir()
.join(self.hook.as_ref().ok_or_else(|| anyhow!("No hook"))?.to_string())
.join("segatools"))
}
}