diff --git a/src/common.rs b/src/common.rs index 4cc0a68..5a89059 100755 --- a/src/common.rs +++ b/src/common.rs @@ -57,3 +57,12 @@ pub enum Region { pub fn read_version(p: &Path) -> Option { fs::read_to_string(p).ok() } + +#[binrw] +#[brw(repr = u16)] +#[derive(Clone, Debug, PartialEq)] +pub enum Platform { + Win32, + PS3, + PS4, +} diff --git a/src/gamedata.rs b/src/gamedata.rs index 73f79c7..c6fb179 100755 --- a/src/gamedata.rs +++ b/src/gamedata.rs @@ -8,7 +8,7 @@ use std::path::PathBuf; use tracing::{debug, warn}; -use crate::common::{Language, read_version}; +use crate::common::{Language, Platform, read_version}; use crate::dat::DatFile; use crate::exd::EXD; use crate::exh::EXH; @@ -63,48 +63,41 @@ impl GameData { /// This will return _None_ if the game directory is not valid, but it does not check the validity /// of each individual file. /// - /// **Note**: None of the repositories are searched, and it's required to call `reload_repositories()`. - /// /// # Example /// /// ``` - /// # use physis::gamedata::GameData; - /// GameData::from_existing("$FFXIV/game"); + /// # use physis::common::Platform; + /// use physis::gamedata::GameData; + /// GameData::from_existing(Platform::Win32, "$FFXIV/game"); /// ``` - pub fn from_existing(directory: &str) -> Option { + pub fn from_existing(platform: Platform, directory: &str) -> Option { debug!(directory, "Loading game directory"); match is_valid(directory) { - true => Some(Self { - game_directory: String::from(directory), - repositories: vec![], - index_files: HashMap::new(), - index2_files: HashMap::new() - }), + true => { + let mut data = Self { + game_directory: String::from(directory), + repositories: vec![], + index_files: HashMap::new(), + index2_files: HashMap::new() + }; + data.reload_repositories(platform); + Some(data) + } false => { warn!("Game data is not valid!"); None } } } - - /// Reloads all repository information from disk. This is a fast operation, as it's not actually - /// reading any dat files yet. - /// - /// # Example - /// - /// ```should_panic - /// # use physis::gamedata::GameData; - /// let mut game = GameData::from_existing("$FFXIV/game").unwrap(); - /// game.reload_repositories(); - /// ``` - pub fn reload_repositories(&mut self) { + + fn reload_repositories(&mut self, platform: Platform) { self.repositories.clear(); let mut d = PathBuf::from(self.game_directory.as_str()); // add initial ffxiv directory - if let Some(base_repository) = Repository::from_existing_base(d.to_str().unwrap()) { + if let Some(base_repository) = Repository::from_existing_base(platform.clone(), d.to_str().unwrap()) { self.repositories.push(base_repository); } @@ -120,7 +113,7 @@ impl GameData { .collect(); for repository_path in repository_paths { - if let Some(expansion_repository) = Repository::from_existing_expansion(repository_path.path().to_str().unwrap()) { + if let Some(expansion_repository) = Repository::from_existing_expansion(platform.clone(), repository_path.path().to_str().unwrap()) { self.repositories.push(expansion_repository); } } @@ -149,8 +142,9 @@ impl GameData { /// # Example /// /// ```should_panic - /// # use physis::gamedata::GameData; - /// # let mut game = GameData::from_existing("SquareEnix/Final Fantasy XIV - A Realm Reborn/game").unwrap(); + /// # use physis::common::Platform; + /// use physis::gamedata::GameData; + /// # let mut game = GameData::from_existing(Platform::Win32, "SquareEnix/Final Fantasy XIV - A Realm Reborn/game").unwrap(); /// if game.exists("exd/cid.exl") { /// println!("Cid really does exist!"); /// } else { @@ -181,7 +175,8 @@ impl GameData { /// ```should_panic /// # use physis::gamedata::GameData; /// # use std::io::Write; - /// # let mut game = GameData::from_existing("SquareEnix/Final Fantasy XIV - A Realm Reborn/game").unwrap(); + /// use physis::common::Platform; + /// # let mut game = GameData::from_existing(Platform::Win32, "SquareEnix/Final Fantasy XIV - A Realm Reborn/game").unwrap(); /// let data = game.extract("exd/root.exl").unwrap(); /// /// let mut file = std::fs::File::create("root.exl").unwrap(); @@ -447,13 +442,12 @@ mod tests { d.push("valid_sqpack"); d.push("game"); - GameData::from_existing(d.to_str().unwrap()).unwrap() + GameData::from_existing(Platform::Win32, d.to_str().unwrap()).unwrap() } #[test] fn repository_ordering() { let mut data = common_setup_data(); - data.reload_repositories(); assert_eq!(data.repositories[0].name, "ffxiv"); assert_eq!(data.repositories[1].name, "ex1"); @@ -463,7 +457,6 @@ mod tests { #[test] fn repository_and_category_parsing() { let mut data = common_setup_data(); - data.reload_repositories(); assert_eq!( data.parse_repository_category("exd/root.exl").unwrap(), diff --git a/src/index.rs b/src/index.rs index 2ab1663..66d5935 100755 --- a/src/index.rs +++ b/src/index.rs @@ -8,22 +8,14 @@ use std::io::SeekFrom; use binrw::BinRead; use binrw::binrw; use modular_bitfield::prelude::*; +use crate::common::Platform; use crate::crc::Jamcrc; -#[binrw] -#[brw(repr = u8)] -#[derive(Debug, PartialEq)] -enum PlatformId { - Windows, - PS3, - PS4, -} - #[binrw] #[br(magic = b"SqPack")] pub struct SqPackHeader { #[br(pad_before = 2)] - platform_id: PlatformId, + platform_id: Platform, #[br(pad_before = 3)] size: u32, version: u32, diff --git a/src/patch.rs b/src/patch.rs index 30d3ac6..a0323f7 100755 --- a/src/patch.rs +++ b/src/patch.rs @@ -12,7 +12,7 @@ use binrw::BinRead; use binrw::binrw; use tracing::{debug, warn}; -use crate::common::Region; +use crate::common::{Platform, Region}; use crate::sqpack::read_data_block_patch; #[binread] @@ -263,20 +263,11 @@ struct SqpkFileOperationData { path: String, } -#[binrw] -#[brw(repr = u16)] -#[derive(Debug, PartialEq)] -enum PlatformId { - Windows, - PS3, - PS4, -} - -fn get_platform_string(id: &PlatformId) -> &'static str { +fn get_platform_string(id: &Platform) -> &'static str { match &id { - PlatformId::Windows => "win32", - PlatformId::PS3 => "ps3.d", - PlatformId::PS4 => "ps4.d", + Platform::Win32 => "win32", + Platform::PS3 => "ps3.d", + Platform::PS4 => "ps4.d", } } @@ -284,7 +275,7 @@ fn get_platform_string(id: &PlatformId) -> &'static str { #[br(big)] struct SqpkTargetInfo { #[br(pad_before = 3)] - platform: PlatformId, + platform: Platform, region: Region, #[br(map = | x : u16 | x == 1)] is_debug: bool, diff --git a/src/repository.rs b/src/repository.rs index af160ba..64ea430 100755 --- a/src/repository.rs +++ b/src/repository.rs @@ -4,8 +4,9 @@ use std::cmp::Ordering; use std::cmp::Ordering::{Greater, Less}; use std::path::{Path, PathBuf}; +use binrw::binrw; -use crate::common::read_version; +use crate::common::{Platform, read_version}; use crate::repository::RepositoryType::{Base, Expansion}; /// The type of repository, discerning game data from expansion data. @@ -27,6 +28,8 @@ pub enum RepositoryType { pub struct Repository { /// The folder name, such as "ex1". pub name: String, + /// The platform this repository is designed for. + pub platform: Platform, /// The type of repository, such as "base game" or "expansion". pub repo_type: RepositoryType, /// The version of the game data. @@ -125,7 +128,7 @@ pub fn string_to_category(string: &str) -> Option { impl Repository { /// Creates a new base `Repository`, from an existing directory. This may return `None` if /// the directory is invalid, e.g. a version file is missing. - pub fn from_existing_base(dir: &str) -> Option { + pub fn from_existing_base(platform: Platform, dir: &str) -> Option { let path = Path::new(dir); if path.metadata().is_err() { return None; @@ -137,6 +140,7 @@ impl Repository { let version = read_version(d.as_path()); Some(Repository { name: "ffxiv".to_string(), + platform, repo_type: Base, version, }) @@ -144,7 +148,7 @@ impl Repository { /// Creates a new expansion `Repository`, from an existing directory. This may return `None` if /// the directory is invalid, e.g. a version file is missing. - pub fn from_existing_expansion(dir: &str) -> Option { + pub fn from_existing_expansion(platform: Platform, dir: &str) -> Option { let path = Path::new(dir); if path.metadata().is_err() { return None; @@ -158,6 +162,7 @@ impl Repository { Some(Repository { name, + platform, repo_type: Expansion { number: expansion_number, }, @@ -207,6 +212,7 @@ impl Repository { #[cfg(test)] mod tests { use std::path::PathBuf; + use crate::common::Platform; use crate::repository::Repository; @@ -216,7 +222,7 @@ mod tests { d.push("resources/tests"); d.push("ffxiv"); - let repository = Repository::from_existing_base(d.to_str().unwrap()); + let repository = Repository::from_existing_base(Platform::Win32, d.to_str().unwrap()); assert!(repository.is_some()); assert_eq!(repository.unwrap().version.unwrap(), "2012.01.01.0000.0000"); } @@ -227,7 +233,7 @@ mod tests { d.push("resources/tests"); d.push("ex1"); - let repository = Repository::from_existing_expansion(d.to_str().unwrap()); + let repository = Repository::from_existing_expansion(Platform::Win32, d.to_str().unwrap()); assert!(repository.is_some()); assert_eq!(repository.unwrap().version.unwrap(), "2012.01.01.0000.0000"); } diff --git a/tests/integration_test.rs b/tests/integration_test.rs index 04021d1..be6d8a5 100755 --- a/tests/integration_test.rs +++ b/tests/integration_test.rs @@ -9,6 +9,7 @@ use walkdir::WalkDir; use physis::patch::apply_patch; use std::collections::HashMap; +use physis::common::Platform; use physis::fiin::FileInfo; use physis::index; @@ -28,10 +29,8 @@ fn test_gamedata_extract() { let game_dir = env::var("FFXIV_GAME_DIR").unwrap(); let mut gamedata = - physis::gamedata::GameData::from_existing(format!("{}/game", game_dir).as_str()).unwrap(); - - gamedata.reload_repositories(); - + physis::gamedata::GameData::from_existing(Platform::Win32, format!("{}/game", game_dir).as_str()).unwrap(); + assert!(gamedata.extract("exd/root.exl").is_some()); }