forked from akanyan/STARTLINER
feat: segatools.ini loading
This commit is contained in:
@ -1,5 +1,7 @@
|
||||
use ini::Ini;
|
||||
use log;
|
||||
use std::collections::HashMap;
|
||||
use std::path::PathBuf;
|
||||
use tokio::sync::Mutex;
|
||||
use tokio::fs;
|
||||
use tauri::{AppHandle, Manager, State};
|
||||
@ -319,7 +321,7 @@ pub async fn get_current_profile(state: State<'_, Mutex<AppData>>) -> Result<Opt
|
||||
|
||||
#[tauri::command]
|
||||
pub async fn sync_current_profile(state: State<'_, Mutex<AppData>>, data: ProfileData) -> Result<(), String> {
|
||||
log::debug!("invoke: sync_current_profile");
|
||||
log::debug!("invoke: sync_current_profile {:?}", data);
|
||||
|
||||
let mut appd = state.lock().await;
|
||||
if let Some(p) = &mut appd.profile {
|
||||
@ -345,6 +347,27 @@ pub async fn save_current_profile(state: State<'_, Mutex<AppData>>) -> Result<()
|
||||
}
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
pub async fn load_segatools_ini(state: State<'_, Mutex<AppData>>, path: PathBuf) -> Result<(), String> {
|
||||
log::debug!("invoke: load_segatools_ini({:?})", path);
|
||||
|
||||
let mut appd = state.lock().await;
|
||||
if let Some(p) = &mut appd.profile {
|
||||
let str = std::fs::read_to_string(path).map_err(|e| e.to_string())?;
|
||||
// Stupid path escape hack for the ini reader
|
||||
let str = str.replace("\\", "\\\\").replace("\\\\\\\\", "\\\\");
|
||||
let ini = Ini::load_from_str(&str).map_err(|e| e.to_string())?;
|
||||
p.data.sgt.load_from_ini(&ini);
|
||||
p.data.network.load_from_ini(&ini).map_err(|e| e.to_string())?;
|
||||
if let Some(kb) = &mut p.data.keyboard {
|
||||
kb.load_from_ini(&ini).map_err(|e| e.to_string())?;
|
||||
}
|
||||
p.save().map_err(|e| e.to_string())?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
pub async fn list_platform_capabilities() -> Result<Vec<String>, ()> {
|
||||
log::debug!("invoke: list_platform_capabilities");
|
||||
@ -413,4 +436,10 @@ pub async fn list_directories() -> Result<util::Dirs, ()> {
|
||||
log::debug!("invoke: list_directores");
|
||||
|
||||
Ok(util::all_dirs().clone())
|
||||
}
|
||||
|
||||
// Tauri fs api is useless
|
||||
#[tauri::command]
|
||||
pub async fn file_exists(path: String) -> Result<bool, ()> {
|
||||
Ok(std::fs::exists(path).unwrap_or(false))
|
||||
}
|
@ -71,8 +71,8 @@ pub async fn run(_args: Vec<String>) {
|
||||
} else {
|
||||
tauri::WebviewWindowBuilder::new(app, "main", tauri::WebviewUrl::App("index.html".into()))
|
||||
.title("STARTLINER")
|
||||
.inner_size(760f64, 480f64)
|
||||
.min_inner_size(760f64, 480f64)
|
||||
.inner_size(900f64, 480f64)
|
||||
.min_inner_size(900f64, 480f64)
|
||||
.build()?;
|
||||
start_immediately = false;
|
||||
}
|
||||
@ -199,6 +199,7 @@ pub async fn run(_args: Vec<String>) {
|
||||
cmd::get_current_profile,
|
||||
cmd::sync_current_profile,
|
||||
cmd::save_current_profile,
|
||||
cmd::load_segatools_ini,
|
||||
|
||||
cmd::get_global_config,
|
||||
cmd::set_global_config,
|
||||
@ -206,6 +207,7 @@ pub async fn run(_args: Vec<String>) {
|
||||
cmd::list_displays,
|
||||
cmd::list_platform_capabilities,
|
||||
cmd::list_directories,
|
||||
cmd::file_exists,
|
||||
])
|
||||
.build(tauri::generate_context!())
|
||||
.expect("error while building tauri application");
|
||||
|
@ -65,8 +65,8 @@ impl Game {
|
||||
|
||||
pub fn has_module(&self, module: ProfileModule) -> bool {
|
||||
match self {
|
||||
Game::Ongeki => make_bitflags!(ProfileModule::{Segatools | Display | Network | BepInEx | Mu3Ini}),
|
||||
Game::Chunithm => make_bitflags!(ProfileModule::{Segatools | Network}),
|
||||
Game::Ongeki => make_bitflags!(ProfileModule::{Segatools | Display | Network | BepInEx | Mu3Ini | Keyboard}),
|
||||
Game::Chunithm => make_bitflags!(ProfileModule::{Segatools | Network | Keyboard}),
|
||||
}.contains(module)
|
||||
}
|
||||
}
|
||||
|
@ -162,6 +162,75 @@ pub struct Mu3Ini {
|
||||
pub blacklist: Option<(i32, i32)>,
|
||||
}
|
||||
|
||||
#[derive(Deserialize, Serialize, Clone, Debug)]
|
||||
pub struct OngekiKeyboard {
|
||||
pub use_mouse: bool,
|
||||
pub coin: i32,
|
||||
pub svc: i32,
|
||||
pub test: i32,
|
||||
pub lmenu: i32,
|
||||
pub rmenu: i32,
|
||||
pub l1: i32,
|
||||
pub l2: i32,
|
||||
pub l3: i32,
|
||||
pub r1: i32,
|
||||
pub r2: i32,
|
||||
pub r3: i32,
|
||||
pub lwad: i32,
|
||||
pub rwad: i32,
|
||||
}
|
||||
|
||||
impl Default for OngekiKeyboard {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
use_mouse: true,
|
||||
test: 0x70,
|
||||
svc: 0x71,
|
||||
coin: 0x72,
|
||||
lmenu: 0x55,
|
||||
rmenu: 0x4F,
|
||||
lwad: 0x01,
|
||||
rwad: 0x02,
|
||||
l1: 0x41,
|
||||
l2: 0x53,
|
||||
l3: 0x44,
|
||||
r1: 0x4A,
|
||||
r2: 0x4B,
|
||||
r3: 0x4C
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Deserialize, Serialize, Clone, Debug)]
|
||||
pub struct ChunithmKeyboard {
|
||||
pub split_ir: bool,
|
||||
pub coin: i32,
|
||||
pub svc: i32,
|
||||
pub test: i32,
|
||||
pub cell: [i32; 32],
|
||||
pub ir: [i32; 6],
|
||||
}
|
||||
|
||||
impl Default for ChunithmKeyboard {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
split_ir: false,
|
||||
test: 0x70,
|
||||
svc: 0x71,
|
||||
coin: 0x72,
|
||||
cell: Default::default(),
|
||||
ir: Default::default(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Deserialize, Serialize, Clone, Debug)]
|
||||
#[serde(tag = "game", content = "data")]
|
||||
pub enum Keyboard {
|
||||
Ongeki(OngekiKeyboard),
|
||||
Chunithm(ChunithmKeyboard),
|
||||
}
|
||||
|
||||
#[bitflags]
|
||||
#[repr(u8)]
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Serialize, Deserialize)]
|
||||
@ -170,5 +239,6 @@ pub enum ProfileModule {
|
||||
Network,
|
||||
Display,
|
||||
BepInEx,
|
||||
Mu3Ini
|
||||
Mu3Ini,
|
||||
Keyboard,
|
||||
}
|
@ -38,49 +38,7 @@ cabLedOutputSerial=0
|
||||
; Output slider LED data to the named pipe
|
||||
controllerLedOutputPipe=1
|
||||
; Output slider LED data to the serial port
|
||||
controllerLedOutputSerial=0
|
||||
|
||||
[io4]
|
||||
; Test button virtual-key code. Default is the F1 key.
|
||||
test=0x70
|
||||
; Service button virtual-key code. Default is the F2 key.
|
||||
service=0x71
|
||||
; Keyboard button to increment coin counter. Default is the F3 key.
|
||||
coin=0x72
|
||||
|
||||
; Set \"1\" to enable mouse lever emulation, \"0\" to use XInput
|
||||
mouse=1
|
||||
|
||||
; XInput input bindings
|
||||
;
|
||||
; Left Stick Lever
|
||||
; Left Trigger Lever (move to the left)
|
||||
; Right Trigger Lever (move to the right)
|
||||
; Left Left red button
|
||||
; Up Left green button
|
||||
; Right Left blue button
|
||||
; Left Shoulder Left side button
|
||||
; Right Shoulder Right side button
|
||||
; X Right red button
|
||||
; Y Right green button
|
||||
; A Right blue button
|
||||
; Back Left menu button
|
||||
; Start Right menu button
|
||||
|
||||
; Keyboard input bindings
|
||||
left1=0x41 ; A
|
||||
left2=0x53 ; S
|
||||
left3=0x44 ; D
|
||||
|
||||
leftSide=0x01 ; Mouse Left
|
||||
rightSide=0x02 ; Mouse Right
|
||||
|
||||
right1=0x4A ; J
|
||||
right2=0x4B ; K
|
||||
right3=0x4C ; L
|
||||
|
||||
leftMenu=0x55 ; U
|
||||
rightMenu=0x4F ; O".to_owned(),
|
||||
controllerLedOutputSerial=0".to_owned(),
|
||||
Game::Chunithm => "
|
||||
[vfd]
|
||||
; Enable VFD emulation. Disable to use a real VFD
|
||||
@ -179,120 +137,6 @@ controllerLedOutputOpeNITHM=0
|
||||
; x86 chuniio to path32, x64 to path64. Both are necessary.
|
||||
;path32=
|
||||
;path64=
|
||||
|
||||
; -----------------------------------------------------------------------------
|
||||
; Input settings
|
||||
; -----------------------------------------------------------------------------
|
||||
|
||||
; Keyboard bindings are specified as hexadecimal (prefixed with 0x) or decimal
|
||||
; (not prefixed with 0x) virtual-key codes, a list of which can be found here:
|
||||
;
|
||||
; https://docs.microsoft.com/en-us/windows/win32/inputdev/virtual-key-codes
|
||||
;
|
||||
; This is, admittedly, not the most user-friendly configuration method in the
|
||||
; world. An improved solution will be provided later.
|
||||
|
||||
[io3]
|
||||
|
||||
test=0x31
|
||||
|
||||
service=0x32
|
||||
|
||||
coin=0x33
|
||||
|
||||
ir=0x00
|
||||
|
||||
ir6=0x39
|
||||
|
||||
ir5=0x38
|
||||
|
||||
ir4=0x37
|
||||
|
||||
ir3=0x36
|
||||
|
||||
ir2=0x35
|
||||
|
||||
ir1=0x34
|
||||
|
||||
[ir]
|
||||
|
||||
ir6=0x39
|
||||
|
||||
ir5=0x38
|
||||
|
||||
ir4=0x37
|
||||
|
||||
ir3=0x36
|
||||
|
||||
ir2=0x35
|
||||
|
||||
ir1=0x34
|
||||
|
||||
[slider]
|
||||
|
||||
cell32=0x51
|
||||
|
||||
cell30=0x5A
|
||||
|
||||
cell28=0x53
|
||||
|
||||
cell26=0x45
|
||||
|
||||
cell24=0x43
|
||||
|
||||
cell22=0x46
|
||||
|
||||
cell20=0x54
|
||||
|
||||
cell18=0x42
|
||||
|
||||
cell16=0x48
|
||||
|
||||
cell14=0x55
|
||||
|
||||
cell12=0x4D
|
||||
|
||||
cell10=0x4B
|
||||
|
||||
cell8=0x4F
|
||||
|
||||
cell6=190
|
||||
|
||||
cell4=186
|
||||
|
||||
cell2=219
|
||||
|
||||
cell31=0x41
|
||||
|
||||
cell29=0x57
|
||||
|
||||
cell27=0x58
|
||||
|
||||
cell25=0x44
|
||||
|
||||
cell23=0x52
|
||||
|
||||
cell21=0x56
|
||||
|
||||
cell19=0x47
|
||||
|
||||
cell17=0x59
|
||||
|
||||
cell15=0x4E
|
||||
|
||||
cell13=0x4A
|
||||
|
||||
cell11=0x49
|
||||
|
||||
cell9=188
|
||||
|
||||
cell7=0x4C
|
||||
|
||||
cell5=0x50
|
||||
|
||||
cell3=191
|
||||
|
||||
cell1=222
|
||||
".to_owned()
|
||||
}
|
||||
}
|
120
rust/src/modules/keyboard.rs
Normal file
120
rust/src/modules/keyboard.rs
Normal file
@ -0,0 +1,120 @@
|
||||
use ini::Ini;
|
||||
use anyhow::Result;
|
||||
use crate::model::profile::Keyboard;
|
||||
|
||||
macro_rules! parse_int_field {
|
||||
($section:expr,$sgt:expr,$sl:expr) => {
|
||||
if let Some(field) = $section.get($sgt) {
|
||||
let field = &field[0..field.chars().position(|c| c == ';').unwrap_or(field.len())].trim();
|
||||
log::debug!("loading {}={}", $sgt, field);
|
||||
|
||||
let res = if field.starts_with("0x") {
|
||||
i32::from_str_radix(&field.trim()[2..], 16)
|
||||
} else {
|
||||
field.trim().parse::<i32>()
|
||||
};
|
||||
|
||||
match res {
|
||||
Ok(v) => $sl = v,
|
||||
Err(e) => log::warn!("unable to read a segatools.ini field key={} value={}: {:?}", $sgt, field.trim(), e)
|
||||
};
|
||||
} else {
|
||||
log::debug!("unable to load {}", $sgt);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Keyboard {
|
||||
pub fn load_from_ini(&mut self, ini: &Ini) -> Result<()> {
|
||||
log::debug!("loading kb");
|
||||
match self {
|
||||
Keyboard::Ongeki(kb) => {
|
||||
if let Some(s) = ini.section(Some("io4")) {
|
||||
parse_int_field!(s, "test", kb.test);
|
||||
parse_int_field!(s, "service", kb.svc);
|
||||
parse_int_field!(s, "coin", kb.coin);
|
||||
parse_int_field!(s, "left1", kb.l1);
|
||||
parse_int_field!(s, "left2", kb.l2);
|
||||
parse_int_field!(s, "left3", kb.l3);
|
||||
parse_int_field!(s, "right1", kb.r1);
|
||||
parse_int_field!(s, "right2", kb.r2);
|
||||
parse_int_field!(s, "right3", kb.r3);
|
||||
parse_int_field!(s, "leftMenu", kb.lmenu);
|
||||
parse_int_field!(s, "rightMenu", kb.rmenu);
|
||||
parse_int_field!(s, "leftSide", kb.lwad);
|
||||
parse_int_field!(s, "rightSide", kb.rwad);
|
||||
|
||||
let mut mouse: i32 = 1;
|
||||
parse_int_field!(s, "mouse", mouse);
|
||||
kb.use_mouse = if mouse == 1 { true } else { false };
|
||||
}
|
||||
}
|
||||
Keyboard::Chunithm(kb) => {
|
||||
if let Some(s) = ini.section(Some("io3")) {
|
||||
parse_int_field!(s, "test", kb.test);
|
||||
parse_int_field!(s, "service", kb.svc);
|
||||
parse_int_field!(s, "coin", kb.coin);
|
||||
|
||||
let mut ir: i32 = 1;
|
||||
parse_int_field!(s, "ir", ir);
|
||||
kb.split_ir = if ir == 0 { true } else { false };
|
||||
}
|
||||
|
||||
if let Some(s) = ini.section(Some("slider")) {
|
||||
for i in 0..kb.cell.len() {
|
||||
parse_int_field!(s, format!("cell{}", i + 1), kb.cell[i]);
|
||||
}
|
||||
}
|
||||
|
||||
if let Some(s) = ini.section(Some("ir")) {
|
||||
for i in 0..kb.ir.len() {
|
||||
parse_int_field!(s, format!("ir{}", i + 1), kb.ir[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
// This is assumed to run in sync after the segatools module
|
||||
pub fn line_up(&self, ini: &mut Ini) -> Result<()> {
|
||||
match self {
|
||||
Keyboard::Ongeki(kb) => {
|
||||
ini.with_section(Some("io4"))
|
||||
.set("test", kb.test.to_string())
|
||||
.set("service", kb.svc.to_string())
|
||||
.set("coin", kb.coin.to_string())
|
||||
.set("left1", kb.l1.to_string())
|
||||
.set("left2", kb.l2.to_string())
|
||||
.set("left3", kb.l3.to_string())
|
||||
.set("right1", kb.r1.to_string())
|
||||
.set("right2", kb.r2.to_string())
|
||||
.set("right3", kb.r3.to_string())
|
||||
.set("leftSide", kb.lwad.to_string())
|
||||
.set("rightSide", kb.rwad.to_string())
|
||||
.set("leftMenu", kb.lmenu.to_string())
|
||||
.set("rightMenu", kb.rmenu.to_string())
|
||||
.set("mouse", if kb.use_mouse { "1" } else { "0" });
|
||||
}
|
||||
Keyboard::Chunithm(kb) => {
|
||||
for (i, cell) in kb.cell.iter().enumerate() {
|
||||
ini.with_section(Some("slider")).set(format!("cell{}", i + 1), cell.to_string());
|
||||
}
|
||||
if kb.split_ir {
|
||||
for (i, ir) in kb.ir.iter().enumerate() {
|
||||
ini.with_section(Some("ir")).set(format!("ir{}", i + 1), ir.to_string());
|
||||
}
|
||||
} else {
|
||||
ini.with_section(Some("io3")).set("ir", kb.ir[0].to_string());
|
||||
}
|
||||
ini.with_section(Some("io3"))
|
||||
.set("test", kb.test.to_string())
|
||||
.set("service", kb.svc.to_string())
|
||||
.set("coin", kb.coin.to_string());
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
@ -3,6 +3,7 @@ pub mod segatools;
|
||||
pub mod network;
|
||||
pub mod bepinex;
|
||||
pub mod mu3ini;
|
||||
pub mod keyboard;
|
||||
|
||||
#[cfg(target_os = "windows")]
|
||||
pub mod display_windows;
|
@ -5,6 +5,32 @@ use ini::Ini;
|
||||
use crate::model::profile::{Network, NetworkType};
|
||||
|
||||
impl Network {
|
||||
pub fn load_from_ini(&mut self, ini: &Ini) -> Result<()> {
|
||||
log::debug!("loading network");
|
||||
if let Some(s) = ini.section(Some("dns")) {
|
||||
if let Some(default) = s.get("default") {
|
||||
if default.starts_with("192.") || default.starts_with("127.") {
|
||||
self.network_type = NetworkType::Artemis;
|
||||
} else {
|
||||
self.network_type = NetworkType::Remote;
|
||||
self.remote_address = default.to_owned();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if let Some(s) = ini.section(Some("netenv")) {
|
||||
s.get("addrSuffix").map(|v|
|
||||
self.suffix = v.parse::<i32>().ok()
|
||||
);
|
||||
}
|
||||
|
||||
if let Some(s) = ini.section(Some("keychip")) {
|
||||
s.get("subnet").map(|v| self.subnet = v.to_owned());
|
||||
s.get("id").map(|v| self.keychip = v.to_owned());
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
pub fn line_up(&self, ini: &mut Ini) -> Result<()> {
|
||||
log::debug!("begin line-up: network");
|
||||
|
||||
|
@ -31,6 +31,14 @@ impl Segatools {
|
||||
_ => {},
|
||||
}
|
||||
}
|
||||
pub fn load_from_ini(&mut self, ini: &Ini) {
|
||||
log::debug!("loading sgt");
|
||||
if let Some(s) = ini.section(Some("vfs")) {
|
||||
s.get("amfs").map(|v| self.amfs = PathBuf::from(v));
|
||||
s.get("appdata").map(|v| self.appdata = PathBuf::from(v));
|
||||
s.get("option").map(|v| self.option = PathBuf::from(v));
|
||||
}
|
||||
}
|
||||
pub async fn line_up(&self, p: &impl ProfilePaths, game: Game) -> Result<Ini> {
|
||||
log::debug!("begin line-up: segatools");
|
||||
|
||||
|
@ -1,7 +1,7 @@
|
||||
use serde::{Deserialize, Serialize};
|
||||
use tauri::AppHandle;
|
||||
use std::{collections::BTreeSet, path::{Path, PathBuf}};
|
||||
use crate::{model::{misc::Game, profile::{Aime, Mu3Ini, ProfileModule}}, modules::package::prepare_packages, pkg::PkgKey, pkg_store::PackageStore, util};
|
||||
use crate::{model::{misc::Game, profile::{Aime, ChunithmKeyboard, Keyboard, Mu3Ini, OngekiKeyboard, ProfileModule}}, modules::package::prepare_packages, pkg::PkgKey, pkg_store::PackageStore, util};
|
||||
use tauri::Emitter;
|
||||
use std::process::Stdio;
|
||||
use crate::model::profile::BepInEx;
|
||||
@ -54,7 +54,10 @@ pub struct ProfileData {
|
||||
pub wine: crate::model::profile::Wine,
|
||||
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub mu3_ini: Option<Mu3Ini>
|
||||
pub mu3_ini: Option<Mu3Ini>,
|
||||
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub keyboard: Option<Keyboard>
|
||||
}
|
||||
|
||||
impl Profile {
|
||||
@ -74,6 +77,12 @@ impl Profile {
|
||||
#[cfg(not(target_os = "windows"))]
|
||||
wine: crate::model::profile::Wine::default(),
|
||||
mu3_ini: if meta.game == Game::Ongeki { Some(Mu3Ini { audio: None, blacklist: None }) } else { None },
|
||||
keyboard:
|
||||
if meta.game == Game::Ongeki {
|
||||
Some(Keyboard::Ongeki(OngekiKeyboard::default()))
|
||||
} else {
|
||||
Some(Keyboard::Chunithm(ChunithmKeyboard::default()))
|
||||
},
|
||||
},
|
||||
meta: meta.clone()
|
||||
};
|
||||
@ -87,11 +96,18 @@ impl Profile {
|
||||
pub fn load(game: Game, name: String) -> Result<Self> {
|
||||
let path = util::profile_config_dir(game, &name).join("profile.json");
|
||||
if let Ok(s) = std::fs::read_to_string(&path) {
|
||||
let data = serde_json::from_str::<ProfileData>(&s)
|
||||
let mut data = serde_json::from_str::<ProfileData>(&s)
|
||||
.map_err(|e| anyhow!("Unable to parse {:?}: {:?}", path, e))?;
|
||||
|
||||
log::debug!("{:?}", data);
|
||||
|
||||
if game == Game::Ongeki && data.keyboard.is_none() {
|
||||
data.keyboard = Some(Keyboard::Ongeki(OngekiKeyboard::default()));
|
||||
}
|
||||
if game == Game::Chunithm && data.keyboard.is_none() {
|
||||
data.keyboard = Some(Keyboard::Chunithm(ChunithmKeyboard::default()));
|
||||
}
|
||||
|
||||
Ok(Profile {
|
||||
meta: ProfileMeta {
|
||||
game, name
|
||||
@ -163,6 +179,10 @@ impl Profile {
|
||||
if self.meta.game.has_module(ProfileModule::Mu3Ini) && source.mu3_ini.is_some() {
|
||||
self.data.mu3_ini = source.mu3_ini;
|
||||
}
|
||||
|
||||
if self.meta.game.has_module(ProfileModule::Keyboard) && source.keyboard.is_some() {
|
||||
self.data.keyboard = source.keyboard;
|
||||
}
|
||||
}
|
||||
pub async fn line_up(&self, pkg_hash: String, refresh: bool, _app: AppHandle) -> Result<()> {
|
||||
let info = match &self.data.display {
|
||||
@ -200,6 +220,10 @@ impl Profile {
|
||||
.map_err(|e| anyhow!("segatools configuration failed:\n{:?}", e))?;
|
||||
self.data.network.line_up(&mut ini)?;
|
||||
|
||||
if let Some(keyboard) = &self.data.keyboard {
|
||||
keyboard.line_up(&mut ini)?;
|
||||
}
|
||||
|
||||
ini.write_to_file(self.data_dir().join("segatools.ini"))
|
||||
.map_err(|e| anyhow!("Error writing segatools.ini: {}", e))?;
|
||||
|
||||
|
@ -1,7 +1,7 @@
|
||||
{
|
||||
"$schema": "https://schema.tauri.app/config/2",
|
||||
"productName": "STARTLINER",
|
||||
"version": "0.4.0",
|
||||
"version": "0.5.0",
|
||||
"identifier": "zip.patafour.startliner",
|
||||
"build": {
|
||||
"beforeDevCommand": "bun run dev",
|
||||
|
Reference in New Issue
Block a user