feat: hardware aime

This commit is contained in:
2025-04-11 23:07:45 +00:00
parent 1a68eda8c1
commit 28269c5d75
13 changed files with 276 additions and 68 deletions

View File

@ -43,7 +43,7 @@ impl AppData {
.map_err(|e| log::error!("unable to load patch set: {e}"))
.unwrap_or_default();
log::debug!("Recent profile: {:?}", profile);
log::info!("recent profile: {:?}", profile);
AppData {
profile: profile,

View File

@ -1,6 +1,6 @@
use ini::Ini;
use log;
use std::collections::HashMap;
use std::collections::{BTreeMap, HashMap};
use std::path::PathBuf;
use tokio::sync::Mutex;
use tokio::fs;
@ -445,6 +445,21 @@ pub async fn file_exists(path: String) -> Result<bool, ()> {
Ok(std::fs::exists(path).unwrap_or(false))
}
#[tauri::command]
pub async fn list_com_ports() -> Result<BTreeMap<String, i32>, String> {
let ports = serialport::available_ports().unwrap_or(Vec::new());
let mut res = BTreeMap::new();
for p in ports {
log::debug!("port {}", p.port_name);
if p.port_name.starts_with("COM") {
if let Ok(parsed) = (p.port_name[3..]).parse() {
res.insert(p.port_name, parsed);
}
}
}
Ok(res)
}
#[tauri::command]
pub async fn list_patches(state: State<'_, Mutex<AppData>>, target: String) -> Result<Vec<Patch>, String> {
log::debug!("invoke: list_patches({})", target);

View File

@ -43,7 +43,7 @@ impl DownloadHandler {
let mut cache_file_w = File::create(&zip_path_part).await?;
let mut byte_stream = reqwest::get(&rmt.download_url).await?.bytes_stream();
log::info!("Downloading: {}", rmt.download_url);
log::info!("downloading: {}", rmt.download_url);
while let Some(item) = byte_stream.next().await {
let i = item?;
cache_file_w.write_all(&mut i.as_ref()).await?;
@ -51,7 +51,7 @@ impl DownloadHandler {
cache_file_w.sync_all().await?;
tokio::fs::rename(&zip_path_part, &zip_path).await?;
log::debug!("Downloaded to {:?}", zip_path);
log::debug!("downloaded to {:?}", zip_path);
app.emit("download-end", pkg_key)?;

View File

@ -9,10 +9,11 @@ mod modules;
mod profiles;
mod patcher;
use std::sync::OnceLock;
use std::{sync::OnceLock, time::SystemTime};
use anyhow::anyhow;
use closure::closure;
use appdata::{AppData, ToggleAction};
use fern::colors::{Color, ColoredLevelConfig};
use model::misc::Game;
use pkg::PkgKey;
use pkg_store::Payload;
@ -26,16 +27,6 @@ static EXIT_REQUESTED: OnceLock<()> = OnceLock::new();
#[cfg_attr(mobile, tauri::mobile_entry_point)]
pub async fn run(_args: Vec<String>) {
simple_logger::init_with_env().expect("Unable to initialize the logger");
log::info!(
"Running from {}",
std::env::current_dir()
.unwrap_or_default()
.to_str()
.unwrap_or_default()
);
let tauri = tauri::Builder::default()
.plugin(tauri_plugin_updater::Builder::new().build())
.plugin(tauri_plugin_single_instance::init(|app, args, _cwd| {
@ -58,6 +49,51 @@ pub async fn run(_args: Vec<String>) {
util::init_dirs(&apph);
let mut fern_builder;
{
let colors = ColoredLevelConfig::new()
.debug(Color::Green)
.info(Color::Blue)
.warn(Color::Yellow)
.error(Color::Red);
fern_builder = fern::Dispatch::new()
.format(move |out, message, record| {
out.finish(format_args!(
"[{} {} {}] {}",
humantime::format_rfc3339_seconds(SystemTime::now()),
colors.color(record.level()),
record.target(),
message
))
})
.chain(std::io::stdout())
.chain(fern::log_file(util::data_dir().join("log.txt")).expect("unable to initialize the logger"));
}
#[cfg(debug_assertions)]
{
fern_builder = fern_builder.level(log::LevelFilter::Debug);
}
#[cfg(not(debug_assertions))]
{
if std::env::var("DEBUG_LOG") {
fern_builder = fern_builder.level(log::LevelFilter::Debug);
} else {
fern_builder = fern_builder.level(log::LevelFilter::Info);
}
}
fern_builder.apply()?;
log::info!(
"running from {}",
std::env::current_dir()
.unwrap_or_default()
.to_str()
.unwrap_or_default()
);
let mut app_data = AppData::new(app.handle().clone());
let start_immediately;
@ -210,6 +246,8 @@ pub async fn run(_args: Vec<String>) {
cmd::list_directories,
cmd::file_exists,
cmd::list_com_ports,
cmd::list_patches
])
.build(tauri::generate_context!())
@ -245,7 +283,7 @@ fn deep_link(app: AppHandle, args: Vec<String>) {
let url = &args[1];
let proto = "rainycolor://";
if &url[..proto.len()] == proto {
log::info!("Deep link: {}", url);
log::info!("deep link: {}", url);
let regex = regex::Regex::new(
r"rainycolor://v1/install/rainy\.patafour\.zip/([^/]+)/([^/]+)/[0-9]+\.[0-9]+\.[0-9]+/"

View File

@ -59,7 +59,7 @@ impl Game {
pub fn amd_args(&self) -> Vec<&'static str> {
match self {
Game::Ongeki => vec!["-f", "-c", "config_common.json", "config_server.json", "config_client.json"],
Game::Chunithm => vec!["-c", "config_common.json", "config_server.json", "config_client.json", "config_cvt.json", "config_sp.json", "config_hook.json"]
Game::Chunithm => vec!["-c", "config_common.json", "config_server.json", "config_client.json", "config_cvt.json", "config_sp.json"]
}
}
@ -86,4 +86,28 @@ pub enum StartCheckError {
MissingLocalPackage(PkgKey),
MissingDependency(PkgKey, PkgKey),
MissingTool(PkgKey),
}
#[derive(Default, Serialize, Deserialize, Clone)]
pub struct ConfigHook {
#[serde(skip_serializing_if = "Option::is_none")]
pub allnet_auth: Option<ConfigHookAuth>,
#[serde(skip_serializing_if = "Option::is_none")]
pub aime: Option<ConfigHookAime>,
}
#[derive(Default, Serialize, Deserialize, Clone)]
pub struct ConfigHookAuth {
pub r#type: String
}
#[derive(Default, Serialize, Deserialize, Clone)]
pub struct ConfigHookAime {
pub unit: Vec<ConfigHookAimeUnit>
}
#[derive(Default, Serialize, Deserialize, Clone)]
pub struct ConfigHookAimeUnit {
pub port: i32,
pub id: i32
}

View File

@ -39,6 +39,7 @@ pub struct Segatools {
pub intel: bool,
#[serde(default)]
pub amnet: AMNet,
pub aime_port: Option<i32>,
}
impl Segatools {
@ -56,6 +57,7 @@ impl Segatools {
aime: Aime::default(),
intel: false,
amnet: AMNet::default(),
aime_port: None
}
}
}

View File

@ -1,7 +1,7 @@
use std::path::{PathBuf, Path};
use anyhow::{anyhow, Result};
use ini::Ini;
use crate::{model::{misc::Game, profile::{Aime, Segatools}}, profiles::ProfilePaths, util::{self, PathStr}};
use crate::{model::{misc::{ConfigHook, ConfigHookAime, ConfigHookAimeUnit, ConfigHookAuth, Game}, profile::{Aime, Segatools}}, profiles::ProfilePaths, util::{self, PathStr}};
use crate::pkg_store::PackageStore;
impl Segatools {
@ -171,6 +171,31 @@ impl Segatools {
)?;
}
let mut cfg_hook = ConfigHook::default();
if game == Game::Chunithm {
cfg_hook.allnet_auth = Some({
ConfigHookAuth {
r#type: "1.0".to_owned()
}
})
}
if let Some(port) = self.aime_port {
if self.aime == Aime::Disabled {
cfg_hook.aime = Some({
ConfigHookAime {
unit: vec![
ConfigHookAimeUnit {
port,
id: 1
}
]
}
})
}
}
std::fs::write(pfx_dir.join("config_hook.json"), serde_json::to_string(&cfg_hook)?)?;
log::debug!("end line-up: segatools");
Ok(ini_out)

View File

@ -142,7 +142,7 @@ impl Profile {
}
std::fs::write(&path, s)
.map_err(|e| anyhow!("error when writing to {:?}: {}", path, e))?;
log::info!("Written to {:?}", path);
log::info!("profile written to {:?}", path);
Ok(())
}
@ -293,6 +293,9 @@ impl Profile {
.arg(sgt_dir.join(self.meta.game.hook_amd()))
.arg("amdaemon.exe")
.args(self.meta.game.amd_args());
amd_builder.arg(self.data_dir().join("config_hook.json"));
game_builder
.env(
"SEGATOOLS_CONFIG_PATH",
@ -351,8 +354,8 @@ impl Profile {
util::pkill("amdaemon.exe").await;
log::info!("Launching amdaemon: {:?}", amd_builder);
log::info!("Launching {}: {:?}", self.meta.game, game_builder);
log::info!("launching amdaemon: {:?}", amd_builder);
log::info!("launching {}: {:?}", self.meta.game, game_builder);
let mut amd = amd_builder.spawn()?;
let mut game = game_builder.spawn()?;