Added partial support of wincompatlib
This commit is contained in:
parent
a647e68665
commit
7ac3935ab1
9 changed files with 62 additions and 103 deletions
10
Cargo.lock
generated
10
Cargo.lock
generated
|
@ -66,6 +66,7 @@ dependencies = [
|
||||||
"serde",
|
"serde",
|
||||||
"serde_json",
|
"serde_json",
|
||||||
"wait_not_await",
|
"wait_not_await",
|
||||||
|
"wincompatlib",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
@ -2300,6 +2301,15 @@ version = "0.4.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
|
checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "wincompatlib"
|
||||||
|
version = "0.1.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "0fb138cb8c6312731e7385e4500a2491be768ff4c8cfc04544dcc9227533f250"
|
||||||
|
dependencies = [
|
||||||
|
"regex",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "windows"
|
name = "windows"
|
||||||
version = "0.37.0"
|
version = "0.37.0"
|
||||||
|
|
|
@ -21,6 +21,7 @@ adw = { package = "libadwaita", version = "0.2.0-alpha.3", features = ["v1_2"] }
|
||||||
rfd = { version = "0.10", features = ["xdg-portal"], default-features = false }
|
rfd = { version = "0.10", features = ["xdg-portal"], default-features = false }
|
||||||
|
|
||||||
anime-game-core = { path = "anime-game-core", features = ["all", "static", "genshin"] }
|
anime-game-core = { path = "anime-game-core", features = ["all", "static", "genshin"] }
|
||||||
|
wincompatlib = { version = "0.1.0", features = ["dxvk"] }
|
||||||
|
|
||||||
serde = { version = "1.0", features = ["derive"] }
|
serde = { version = "1.0", features = ["derive"] }
|
||||||
serde_json = "1.0"
|
serde_json = "1.0"
|
||||||
|
|
|
@ -1,10 +1,11 @@
|
||||||
use serde::{Serialize, Deserialize};
|
use serde::{Serialize, Deserialize};
|
||||||
|
|
||||||
use std::io::{Error, ErrorKind};
|
use std::process::Output;
|
||||||
use std::process::{Command, Output};
|
use std::path::PathBuf;
|
||||||
|
|
||||||
use lazy_static::lazy_static;
|
use lazy_static::lazy_static;
|
||||||
use regex::Regex;
|
|
||||||
|
use wincompatlib::prelude::*;
|
||||||
|
|
||||||
use crate::lib::config;
|
use crate::lib::config;
|
||||||
|
|
||||||
|
@ -94,50 +95,13 @@ impl Version {
|
||||||
None => (String::from("wine64"), String::from("wineserver"), String::from("wineboot"))
|
None => (String::from("wine64"), String::from("wineserver"), String::from("wineboot"))
|
||||||
};
|
};
|
||||||
|
|
||||||
let mut apply_script = std::fs::read_to_string(&apply_path)?;
|
Dxvk::install(
|
||||||
|
PathBuf::from(apply_path),
|
||||||
lazy_static! {
|
PathBuf::from(prefix_path.to_string()),
|
||||||
static ref WINE: Regex = Regex::new("wine=\".*\"").unwrap();
|
PathBuf::from(&wine_path),
|
||||||
static ref WINE64: Regex = Regex::new("wine64=\".*\"").unwrap();
|
PathBuf::from(wine_path),
|
||||||
static ref WINEBOOT: Regex = Regex::new("wineboot=\".*\"").unwrap();
|
PathBuf::from(wineboot_path),
|
||||||
}
|
PathBuf::from(wineserver_path)
|
||||||
|
)
|
||||||
// Update wine paths
|
|
||||||
apply_script = WINE.replace_all(&apply_script, &format!("wine=\"{}\"", &wine_path)).to_string();
|
|
||||||
apply_script = WINE64.replace_all(&apply_script, &format!("wine64=\"{}\"", &wine_path)).to_string();
|
|
||||||
apply_script = WINEBOOT.replace_all(&apply_script, &format!("wineboot=\"{}\"", &wineboot_path)).to_string();
|
|
||||||
|
|
||||||
// Use wine64 to update wine prefix instead of running wineboot
|
|
||||||
// so we can get rid of 32bit support
|
|
||||||
apply_script = apply_script.replace("$wineboot -u", "\"$wine64\" -u");
|
|
||||||
|
|
||||||
// Fix issues related to spaces in paths to the runners folder
|
|
||||||
apply_script = apply_script.replace("which $wineboot", "which \"$wineboot\"");
|
|
||||||
apply_script = apply_script.replace("$wine --version", "\"$wine\" --version");
|
|
||||||
apply_script = apply_script.replace("$wine64 winepath", "\"$wine64\" winepath");
|
|
||||||
apply_script = apply_script.replace("$wine winepath", "\"$wine\" winepath");
|
|
||||||
apply_script = apply_script.replace("$wine reg", "\"$wine\" reg");
|
|
||||||
|
|
||||||
// Old GE builds return specific --version output which can break
|
|
||||||
// DXVK installation script
|
|
||||||
apply_script = apply_script.replace("grep wine", "grep \"wine\\|GE\"");
|
|
||||||
|
|
||||||
std::fs::write(&apply_path, apply_script)?;
|
|
||||||
|
|
||||||
let output = Command::new("bash")
|
|
||||||
.arg(&apply_path)
|
|
||||||
.arg("install")
|
|
||||||
.env("WINEARCH", "win64")
|
|
||||||
.env("WINESERVER", wineserver_path)
|
|
||||||
.env("WINEPREFIX", prefix_path.to_string())
|
|
||||||
.output()?;
|
|
||||||
|
|
||||||
if output.status.success() {
|
|
||||||
Ok(output)
|
|
||||||
}
|
|
||||||
|
|
||||||
else {
|
|
||||||
Err(Error::new(ErrorKind::Other, String::from_utf8_lossy(&output.stderr)))
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,9 +1,10 @@
|
||||||
|
use std::path::PathBuf;
|
||||||
|
|
||||||
use anime_game_core::prelude::*;
|
use anime_game_core::prelude::*;
|
||||||
use anime_game_core::genshin::prelude::*;
|
use anime_game_core::genshin::prelude::*;
|
||||||
|
|
||||||
use crate::lib::consts;
|
use crate::lib::consts;
|
||||||
use crate::lib::config;
|
use crate::lib::config;
|
||||||
use crate::lib::wine_prefix::WinePrefix;
|
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub enum LauncherState {
|
pub enum LauncherState {
|
||||||
|
@ -55,7 +56,7 @@ impl LauncherState {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check prefix existence
|
// Check prefix existence
|
||||||
if !WinePrefix::exists_in(&config.game.wine.prefix) {
|
if !PathBuf::from(&config.game.wine.prefix).join("drive_c").exists() {
|
||||||
return Ok(Self::PrefixNotExists);
|
return Ok(Self::PrefixNotExists);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -3,7 +3,6 @@ pub mod config;
|
||||||
pub mod game;
|
pub mod game;
|
||||||
pub mod dxvk;
|
pub mod dxvk;
|
||||||
pub mod wine;
|
pub mod wine;
|
||||||
pub mod wine_prefix;
|
|
||||||
pub mod launcher;
|
pub mod launcher;
|
||||||
pub mod prettify_bytes;
|
pub mod prettify_bytes;
|
||||||
pub mod fps_unlocker;
|
pub mod fps_unlocker;
|
||||||
|
|
|
@ -1,5 +1,9 @@
|
||||||
|
use std::path::PathBuf;
|
||||||
|
|
||||||
use serde::{Serialize, Deserialize};
|
use serde::{Serialize, Deserialize};
|
||||||
|
|
||||||
|
use wincompatlib::prelude::*;
|
||||||
|
|
||||||
lazy_static::lazy_static! {
|
lazy_static::lazy_static! {
|
||||||
static ref GROUPS: Vec<Group> = vec![
|
static ref GROUPS: Vec<Group> = vec![
|
||||||
Group {
|
Group {
|
||||||
|
@ -79,8 +83,19 @@ impl Version {
|
||||||
Ok(List::get()[0].versions[0].clone())
|
Ok(List::get()[0].versions[0].clone())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn is_downloaded_in<T: ToString>(&self, folder: T) -> bool {
|
pub fn is_downloaded_in<T: Into<PathBuf>>(&self, folder: T) -> bool {
|
||||||
std::path::Path::new(&format!("{}/{}", folder.to_string(), self.name)).exists()
|
folder.into().join(&self.name).exists()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn to_wine(&self) -> Wine {
|
||||||
|
Wine::new(
|
||||||
|
&self.files.wine64,
|
||||||
|
None,
|
||||||
|
Some(WineArch::Win64),
|
||||||
|
Some(&self.files.wineboot),
|
||||||
|
Some(&self.files.wineserver),
|
||||||
|
WineLoader::Current
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,39 +0,0 @@
|
||||||
use std::path::Path;
|
|
||||||
use std::process::{Command, Output};
|
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
|
||||||
pub struct WinePrefix {
|
|
||||||
pub path: String
|
|
||||||
}
|
|
||||||
|
|
||||||
impl WinePrefix {
|
|
||||||
pub fn new<T: ToString>(path: T) -> Self {
|
|
||||||
Self { path: path.to_string() }
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn exists(&self) -> bool {
|
|
||||||
Self::exists_in(&self.path)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn exists_in<T: ToString>(path: T) -> bool {
|
|
||||||
Path::new(&format!("{}/drive_c", path.to_string())).exists()
|
|
||||||
}
|
|
||||||
|
|
||||||
fn wine<T: ToString>(&self, wine_binary: T, command: &str) -> std::io::Result<Output> {
|
|
||||||
let mut wine_command = Command::new(wine_binary.to_string());
|
|
||||||
|
|
||||||
wine_command.env("WINEARCH", "win64")
|
|
||||||
.env("WINEPREFIX", &self.path)
|
|
||||||
.arg(command);
|
|
||||||
|
|
||||||
Ok(wine_command.output()?)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn update<T: ToString>(&self, runners_folder: T, runner: super::wine::Version) -> std::io::Result<Output> {
|
|
||||||
self.update_with(format!("{}/{}/{}", runners_folder.to_string(), runner.name, runner.files.wine64))
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn update_with<T: ToString>(&self, wine_binary: T) -> std::io::Result<Output> {
|
|
||||||
self.wine(wine_binary, "-u")
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -10,6 +10,8 @@ use std::path::PathBuf;
|
||||||
|
|
||||||
use anime_game_core::prelude::*;
|
use anime_game_core::prelude::*;
|
||||||
|
|
||||||
|
use wincompatlib::prelude::*;
|
||||||
|
|
||||||
mod welcome;
|
mod welcome;
|
||||||
mod dependencies;
|
mod dependencies;
|
||||||
mod tos_warning;
|
mod tos_warning;
|
||||||
|
@ -23,7 +25,6 @@ use crate::ui::traits::prelude::*;
|
||||||
use crate::ui::components::progress_bar::*;
|
use crate::ui::components::progress_bar::*;
|
||||||
|
|
||||||
use crate::lib;
|
use crate::lib;
|
||||||
use crate::lib::wine_prefix::WinePrefix;
|
|
||||||
use crate::lib::config;
|
use crate::lib::config;
|
||||||
|
|
||||||
/// This structure is used to describe widgets used in application
|
/// This structure is used to describe widgets used in application
|
||||||
|
@ -303,7 +304,6 @@ impl App {
|
||||||
|
|
||||||
ProgressUpdateResult::Finished => {
|
ProgressUpdateResult::Finished => {
|
||||||
let mut config = config::get().unwrap();
|
let mut config = config::get().unwrap();
|
||||||
let prefix = WinePrefix::new(&config.game.wine.prefix);
|
|
||||||
|
|
||||||
// Update wine config
|
// Update wine config
|
||||||
if let Some(wine_version) = &wine_version {
|
if let Some(wine_version) = &wine_version {
|
||||||
|
@ -318,7 +318,13 @@ impl App {
|
||||||
let sender_dxvk = sender_dxvk.clone();
|
let sender_dxvk = sender_dxvk.clone();
|
||||||
|
|
||||||
std::thread::spawn(move || {
|
std::thread::spawn(move || {
|
||||||
match prefix.update_with(config.try_get_wine_executable().expect("None of wine builds are available")) {
|
let wine = config.try_get_wine_executable()
|
||||||
|
.expect("None of wine builds are available");
|
||||||
|
|
||||||
|
let wine = Wine::from_binary(wine)
|
||||||
|
.with_arch(WineArch::Win64);
|
||||||
|
|
||||||
|
match wine.update_prefix(&config.game.wine.prefix) {
|
||||||
Ok(output) => {
|
Ok(output) => {
|
||||||
println!("Wine prefix created:\n\n{}", String::from_utf8_lossy(&output.stdout));
|
println!("Wine prefix created:\n\n{}", String::from_utf8_lossy(&output.stdout));
|
||||||
|
|
||||||
|
|
|
@ -14,6 +14,8 @@ use wait_not_await::Await;
|
||||||
use anime_game_core::prelude::*;
|
use anime_game_core::prelude::*;
|
||||||
use anime_game_core::genshin::prelude::*;
|
use anime_game_core::genshin::prelude::*;
|
||||||
|
|
||||||
|
use wincompatlib::prelude::*;
|
||||||
|
|
||||||
use crate::ui::*;
|
use crate::ui::*;
|
||||||
|
|
||||||
use super::preferences::PreferencesStack;
|
use super::preferences::PreferencesStack;
|
||||||
|
@ -28,7 +30,6 @@ use crate::lib::wine::{
|
||||||
Version as WineVersion,
|
Version as WineVersion,
|
||||||
List as WineList
|
List as WineList
|
||||||
};
|
};
|
||||||
use crate::lib::wine_prefix::WinePrefix;
|
|
||||||
|
|
||||||
/// This structure is used to describe widgets used in application
|
/// This structure is used to describe widgets used in application
|
||||||
///
|
///
|
||||||
|
@ -496,16 +497,17 @@ impl App {
|
||||||
}
|
}
|
||||||
|
|
||||||
LauncherState::PrefixNotExists => {
|
LauncherState::PrefixNotExists => {
|
||||||
let prefix = WinePrefix::new(&config.game.wine.prefix);
|
match config.try_get_wine_executable() {
|
||||||
|
|
||||||
match config.try_get_selected_wine_info() {
|
|
||||||
Some(wine) => {
|
Some(wine) => {
|
||||||
let this = this.clone();
|
let this = this.clone();
|
||||||
|
|
||||||
std::thread::spawn(move || {
|
std::thread::spawn(move || {
|
||||||
this.widgets.launch_game.set_sensitive(false);
|
this.widgets.launch_game.set_sensitive(false);
|
||||||
|
|
||||||
if let Err(err) = prefix.update(&config.game.wine.builds, wine) {
|
let wine = Wine::from_binary(wine)
|
||||||
|
.with_arch(WineArch::Win64);
|
||||||
|
|
||||||
|
if let Err(err) = wine.update_prefix(&config.game.wine.prefix) {
|
||||||
this.update(Actions::Toast(Rc::new((
|
this.update(Actions::Toast(Rc::new((
|
||||||
String::from("Failed to create wine prefix"), err.to_string()
|
String::from("Failed to create wine prefix"), err.to_string()
|
||||||
)))).unwrap();
|
)))).unwrap();
|
||||||
|
|
Loading…
Reference in a new issue