From 38c1c90fd5e653734c1ef2ae3ec22f92ddafe8c2 Mon Sep 17 00:00:00 2001 From: Jaby Date: Sun, 26 May 2024 21:04:25 +0200 Subject: [PATCH] psxcdgen removed --- src/Tools/Tools.code-workspace | 2 +- src/Tools/psxcdgen/Cargo.toml | 14 - src/Tools/psxcdgen/src/file_helper.rs | 42 -- src/Tools/psxcdgen/src/iso_writer/cd_desc.rs | 465 -------------- src/Tools/psxcdgen/src/iso_writer/lba_map.rs | 47 -- src/Tools/psxcdgen/src/iso_writer/mod.rs | 72 --- .../src/iso_writer/psx/encoder/helper.rs | 71 --- .../src/iso_writer/psx/encoder/mod.rs | 571 ------------------ src/Tools/psxcdgen/src/iso_writer/psx/mod.rs | 73 --- .../psxcdgen/src/iso_writer/types/builder.rs | 64 -- .../psxcdgen/src/iso_writer/types/mod.rs | 179 ------ src/Tools/psxcdgen/src/lib.rs | 5 - src/Tools/psxcdgen/src/main.rs | 105 ---- src/Tools/psxcdgen/src/xml_reader/mkpsxiso.rs | 333 ---------- src/Tools/psxcdgen/src/xml_reader/mod.rs | 93 --- 15 files changed, 1 insertion(+), 2135 deletions(-) delete mode 100644 src/Tools/psxcdgen/Cargo.toml delete mode 100644 src/Tools/psxcdgen/src/file_helper.rs delete mode 100644 src/Tools/psxcdgen/src/iso_writer/cd_desc.rs delete mode 100644 src/Tools/psxcdgen/src/iso_writer/lba_map.rs delete mode 100644 src/Tools/psxcdgen/src/iso_writer/mod.rs delete mode 100644 src/Tools/psxcdgen/src/iso_writer/psx/encoder/helper.rs delete mode 100644 src/Tools/psxcdgen/src/iso_writer/psx/encoder/mod.rs delete mode 100644 src/Tools/psxcdgen/src/iso_writer/psx/mod.rs delete mode 100644 src/Tools/psxcdgen/src/iso_writer/types/builder.rs delete mode 100644 src/Tools/psxcdgen/src/iso_writer/types/mod.rs delete mode 100644 src/Tools/psxcdgen/src/lib.rs delete mode 100644 src/Tools/psxcdgen/src/main.rs delete mode 100644 src/Tools/psxcdgen/src/xml_reader/mkpsxiso.rs delete mode 100644 src/Tools/psxcdgen/src/xml_reader/mod.rs diff --git a/src/Tools/Tools.code-workspace b/src/Tools/Tools.code-workspace index 1c34b733..13609621 100644 --- a/src/Tools/Tools.code-workspace +++ b/src/Tools/Tools.code-workspace @@ -77,7 +77,7 @@ { "id": "project", "type": "pickString", - "options": ["cdtypes", "cpp_out", "jaby_engine_fconv", "mkoverlay", "psxreadmap", "psxcdgen", "psxcdgen_ex", "psxcdread", "tool_helper", "wslpath"], + "options": ["cdtypes", "cpp_out", "jaby_engine_fconv", "mkoverlay", "psxreadmap", "psxcdgen_ex", "psxcdread", "tool_helper", "wslpath"], "description": "project to build" }, { diff --git a/src/Tools/psxcdgen/Cargo.toml b/src/Tools/psxcdgen/Cargo.toml deleted file mode 100644 index 29296c70..00000000 --- a/src/Tools/psxcdgen/Cargo.toml +++ /dev/null @@ -1,14 +0,0 @@ -[package] -name = "psxcdgen" -version = "0.5.5" -edition = "2021" - -[profile.release] -panic = "abort" - -[dependencies] -cdtypes = {path = "../cdtypes"} -clap = {version = "*", features = ["derive"]} -fast-xml = "*" -paste = "*" -wav = "*" \ No newline at end of file diff --git a/src/Tools/psxcdgen/src/file_helper.rs b/src/Tools/psxcdgen/src/file_helper.rs deleted file mode 100644 index 9e6ba4bc..00000000 --- a/src/Tools/psxcdgen/src/file_helper.rs +++ /dev/null @@ -1,42 +0,0 @@ -use cdtypes::Error; -use std::{io::Read, fs::OpenOptions, path::PathBuf}; - -pub fn open_output_file(path: &str) -> Result { - Ok(convert_io_error(path, OpenOptions::new().write(true).create(true).truncate(true).open(path))?) -} - -pub fn read_file_to_string(path: &str) -> Result { - let mut buffer = String::new(); - if let Ok(_) = convert_io_error(path, OpenOptions::new().read(true).create(false).open(path))?.read_to_string(&mut buffer) { - Ok(buffer) - } - - else { - Err(Error::GenericError(format!("Failed reading file \"{}\" to String", path))) - } -} - -pub fn read_file_to_u8(path: &str) -> Result, Error> { - let mut buffer = Vec::default(); - if let Ok(_) = convert_io_error(path, OpenOptions::new().read(true).create(false).open(path))?.read_to_end(&mut buffer) { - Ok(buffer) - } - - else { - Err(Error::GenericError(format!("Failed reading file \"{}\" to Vec", path))) - } -} - -pub fn path_to_string(path: PathBuf) -> Result { - match path.into_os_string().into_string() { - Ok(str) => Ok(str), - Err(_) => Err(Error::GenericError(format!("Couldn't convert OS_String to proper string"))) - } -} - -fn convert_io_error(path: &str, value: Result) -> Result { - match value { - Ok(value) => Ok(value), - Err(io_error) => Err(Error::IOError(Some(path.to_string()), io_error)), - } -} diff --git a/src/Tools/psxcdgen/src/iso_writer/cd_desc.rs b/src/Tools/psxcdgen/src/iso_writer/cd_desc.rs deleted file mode 100644 index 40147cd8..00000000 --- a/src/Tools/psxcdgen/src/iso_writer/cd_desc.rs +++ /dev/null @@ -1,465 +0,0 @@ -use cdtypes::{Error, types::{cue::*, helper::{sector_count_mode2_form1, sector_count_mode2_form2, round_bytes_mode2_form1}, dir_record::DirectoryRecord, sector::AudioSample}}; -pub use super::types::{ProcessedFile, RequestedFile}; - -pub trait LBASize { - fn set_lba(&mut self, lba: usize); - fn set_lba_ret(&mut self, lba: usize) -> Result { - self.set_lba(lba); - - Ok(lba + self.get_length_lba()?) - } - fn get_lba(&self) -> usize; - - fn is_xa_audio(&self) -> Option; - - fn get_length(&self) -> usize; - fn get_length_lba(&self) -> Result { - self.default_get_length_lba() - } - - //Rust doesn't support super calls yet - fn default_get_length_lba(&self) -> Result { - let mut length = self.get_length(); - - if length == 0 { - length = 1; - } - - if let Some(is_xa_audio) = self.is_xa_audio() { - if is_xa_audio { - Ok(sector_count_mode2_form2(length)) - } - - else { - Ok(sector_count_mode2_form1(length)) - } - } - - else { - Err(Error::GenericError("Failed determining Sector type for LBA length calculation".to_owned())) - } - } -} - -pub struct CDDesc { - pub licence_path: String, - pub output_file: String, - pub pvd: PVD, - pub tracks: Vec, -} - -impl CDDesc { - pub fn new() -> CDDesc { - CDDesc{licence_path: String::new(), output_file: String::new(), pvd: PVD::new(), tracks: Vec::new()} - } -} - -#[derive(Debug)] -pub struct PVD { - pub volume_identifier: String, - pub publisher: String, - pub data_preparer: String, -} - -impl PVD { - pub fn new() -> PVD { - PVD{volume_identifier: String::new(), publisher: String::new(), data_preparer: String::new()} - } - - pub fn to_uppercase(&mut self) { - self.volume_identifier = self.volume_identifier.to_uppercase(); - self.publisher = self.publisher.to_uppercase(); - self.data_preparer = self.data_preparer.to_uppercase(); - } -} - -pub enum Track { - Data(DirectoryDataType), - Audio(Vec), -} - -#[derive(Clone)] -pub enum DataTrackType { - Directory(DirectoryDataType), - File(FileDataType) -} - -impl DataTrackType { - pub fn get_name(&self) -> &String { - match self { - DataTrackType::Directory(dir) => &dir.name, - DataTrackType::File(file) => &file.name, - } - } - - pub fn is_hidden(&self) -> bool { - match self { - DataTrackType::Directory(dir) => dir.is_hidden, - DataTrackType::File(file) => file.is_hidden, - } - } -} - -impl LBASize for DataTrackType { - fn set_lba(&mut self, lba: usize) { - match self { - DataTrackType::Directory(dir) => dir.set_lba(lba), - DataTrackType::File(file) => file.set_lba(lba), - } - } - - fn get_lba(&self) -> usize { - match self { - DataTrackType::Directory(dir) => dir.get_lba(), - DataTrackType::File(file) => file.get_lba(), - } - } - - fn get_length(&self) -> usize { - match self { - DataTrackType::Directory(dir) => dir.get_length(), - DataTrackType::File(file) => file.get_length(), - } - } - - fn is_xa_audio(&self) -> Option { - match self { - DataTrackType::Directory(dir) => dir.is_xa_audio(), - DataTrackType::File(file) => file.is_xa_audio(), - } - } -} - -#[derive(Clone)] -pub struct DirectoryDataType { - pub name: String, - member: Vec, - lba: usize, - length: usize, - pub is_hidden: bool, -} - -impl DirectoryDataType { - const CUR_DIR_NAME:&'static str = "\x00"; - const PARENT_DIR_NAME:&'static str = "\x01"; - - pub fn new(name: &str) -> DirectoryDataType { - DirectoryDataType{name: name.to_string(), member: Vec::new(), lba: 0usize, length: 0usize, is_hidden: false} - } - - pub fn new_pvd_root_dir(lba: usize) -> DirectoryDataType { - DirectoryDataType{ - name: Self::CUR_DIR_NAME.to_string(), - member: Vec::new(), - lba, - length: 34, - is_hidden: false, - } - } - - pub fn as_flat_cur_dir(&self) -> DirectoryDataType { - self.as_other_dir(Self::CUR_DIR_NAME, true) - } - - pub fn as_flat_parent_dir(&self) -> DirectoryDataType { - self.as_other_dir(Self::PARENT_DIR_NAME, true) - } - - pub fn add_file(&mut self, file: FileDataType) -> bool { - match self.get(file.name.as_ref()) { - Some(_) => false, - None => { - self.member.push(DataTrackType::File(file)); - return true; - } - } - } - - pub fn add_dir(&mut self, dir: DirectoryDataType) -> bool { - match self.get(dir.name.as_ref()) { - Some(_) => false, - None => { - self.member.push(DataTrackType::Directory(dir)); - return true; - } - } - } - - pub fn sort(&mut self) { - self.member.sort_by(|a, b| - a.get_name().cmp(b.get_name()) - ); - - for member in self.member.iter_mut() { - if let DataTrackType::Directory(dir) = member { - dir.sort(); - } - } - } - - pub fn calculate_lengthes(&mut self) { - if self.is_hidden { - self.length = 0; - } - - else { - let mut length = DirectoryRecord::calculate_size_for(Self::CUR_DIR_NAME, true) + DirectoryRecord::calculate_size_for(Self::PARENT_DIR_NAME, true); - - for member in self.member.iter_mut() { - match member { - DataTrackType::Directory(dir) => { - if !dir.is_hidden { - length += DirectoryRecord::calculate_size_for(dir.name.as_ref(), true); - } - dir.calculate_lengthes(); - } - DataTrackType::File(file) => { - if !file.is_hidden { - length += DirectoryRecord::calculate_size_for(file.name.as_ref(), true); - } - } - } - } - self.length = length; - } - } - - pub fn to_uppercase(&mut self) { - if !self.is_hidden { - self.name = self.name.to_uppercase(); - for member in self.member.iter_mut() { - match member { - DataTrackType::Directory(dir) => { - dir.to_uppercase(); - }, - DataTrackType::File(file) => { - file.to_uppercase(); - } - } - } - } - } - - pub fn iter(&self) -> impl Iterator { - self.member.iter() - } - - pub fn iter_mut(&mut self) -> impl Iterator { - self.member.iter_mut() - } - - pub fn iter_file_mut(&mut self) -> impl Iterator { - self.member.iter_mut().filter_map(|member| { - match member { - DataTrackType::Directory(_) => None, - DataTrackType::File(file) => Some(file), - } - }) - } - - pub fn iter_dir(&self) -> impl Iterator { - self.member.iter().filter_map(|member| { - match member { - DataTrackType::Directory(dir) => Some(dir), - DataTrackType::File(_) => None, - } - }) - } - - pub fn iter_dir_mut(&mut self) -> impl Iterator { - self.member.iter_mut().filter_map(|member| { - match member { - DataTrackType::Directory(dir) => Some(dir), - DataTrackType::File(_) => None, - } - }) - } - - fn get(&self, name: &str) -> Option<&DataTrackType> { - self.member.iter().find(|entry| { - entry.get_name() == name - }) - } - - fn as_other_dir(&self, name: &str, is_flat: bool) -> DirectoryDataType { - DirectoryDataType{ - name: name.to_string(), - member: if is_flat {Vec::new()} else {self.member.clone()}, - lba: self.lba, - length: self.length, - is_hidden: self.is_hidden - } - } -} - -impl LBASize for DirectoryDataType { - fn set_lba(&mut self, lba: usize) { - self.lba = lba; - } - - fn get_lba(&self) -> usize { - self.lba - } - - fn get_length(&self) -> usize { - round_bytes_mode2_form1(self.length) - } - - fn is_xa_audio(&self) -> Option { - Some(false) - } -} - -impl std::fmt::Display for DirectoryDataType { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - fn print_self(f: &mut std::fmt::Formatter<'_>, indent: usize, value: &Vec) -> std::fmt::Result { - for member in value.iter() { - match member { - DataTrackType::Directory(dir) => { - write!(f, "{:indent$}D: {} {{\n", "", dir.name, indent=indent)?; - print_self(f, indent + 4, &dir.member)?; - write!(f, "{:indent$}}}\n", "", indent=indent)?; - } - DataTrackType::File(file) => { - write!(f, "{:indent$}F: {}\n", "", file.name, indent=indent)?; - } - } - } - - Ok(()) - } - - print_self(f, 0, &self.member) - } -} - -#[derive(Clone)] -pub struct FileDataType { - pub name: String, - file_path: String, - content: FileContent, - lba: usize, - padded_lba_length: Option, - pub is_hidden: bool, -} - -impl FileDataType { - pub fn new(name: &str, content: FileContent) -> FileDataType { - FileDataType{name: name.to_string(), file_path: String::new(), content, lba: 0usize, padded_lba_length: None, is_hidden: false} - } - - pub fn process_content(&mut self) -> Result<(), Error> { - match &mut self.content { - FileContent::Request(file) => { - let result = std::mem::take(file).process()?; - - self.content = FileContent::Loaded(result.0); - self.file_path = result.1; - - if let Some(padded_lba_length) = self.padded_lba_length { - let lba_length = LBASize::default_get_length_lba(self)?; - if lba_length > padded_lba_length { - return Err(Error::GenericError(format!("{} padded lba length of {} exceeds calculated size of {}", self.file_path, padded_lba_length, lba_length))); - } - } - - Ok(()) - }, - FileContent::Loaded(_) => Ok(()) - } - } - - pub fn to_uppercase(&mut self) { - if !self.is_hidden { - self.name = self.name.to_uppercase(); - } - } - - pub fn get_data_ref(&self) -> Result<&ProcessedFile, Error> { - match &self.content { - FileContent::Request(_) => Err(Error::GenericError("Accessing raw data not possible for reuqested file".to_owned())), - FileContent::Loaded(data) => Ok(data) - } - } - - pub fn get_path(&self) -> &String { - match &self.content { - FileContent::Request(file) => file.get_path(), - FileContent::Loaded(_) => &self.file_path, - } - } - - pub fn set_lba_padding(&mut self, padded_lba_length: usize) { - if padded_lba_length > 0 { - self.padded_lba_length = Some(padded_lba_length); - } - } -} - -impl LBASize for FileDataType { - fn set_lba(&mut self, lba: usize) { - self.lba = lba; - } - - fn get_lba(&self) -> usize { - self.lba - } - - fn get_length(&self) -> usize { - match &self.content { - FileContent::Request(_) => 0, - FileContent::Loaded(data) => { - - data.len() - }, - } - } - - fn get_length_lba(&self) -> Result { - if let Some(padded_lba_length) = self.padded_lba_length { - Ok(padded_lba_length) - } - - else { - LBASize::default_get_length_lba(self) - } - } - - fn is_xa_audio(&self) -> Option { - match &self.content { - FileContent::Request(_) => None, - FileContent::Loaded(content) => Some(content.is_xa_audio()), - } - } -} - -#[derive(Clone)] -pub enum FileContent { - Request(RequestedFile), - Loaded(ProcessedFile), -} - -impl FileContent { - pub fn new_raw_data(path: String) -> FileContent { - FileContent::Request(RequestedFile::new_raw_data(path)) - } - - pub fn new_xa_audio(path: String) -> FileContent { - FileContent::Request(RequestedFile::new_xa_audio(path)) - } -} - -pub struct CUEDesc { - pub output_file: String, - pub output_bin_file: String -} - -impl CUEDesc { - pub fn new() -> CUEDesc { - CUEDesc{output_file: String::new(), output_bin_file: String::new()} - } - - pub fn deconstruct(self) -> (String, Vec) { - (self.output_file, vec!(Specifier::File{path: self.output_bin_file, format: Format::Binary})) - } -} diff --git a/src/Tools/psxcdgen/src/iso_writer/lba_map.rs b/src/Tools/psxcdgen/src/iso_writer/lba_map.rs deleted file mode 100644 index bec11180..00000000 --- a/src/Tools/psxcdgen/src/iso_writer/lba_map.rs +++ /dev/null @@ -1,47 +0,0 @@ -use cdtypes::Error; -use super::cd_desc::LBASize; - -pub type EntryVec = Vec; - -pub enum Entry { - Directory(DirectoryDataType), - File(FileDataType) -} - -pub struct DirectoryDataType { - pub name: String, - pub lba: usize, - pub size: usize, - pub lba_length: usize, - pub entries: EntryVec, - pub is_hidden: bool, -} - -impl DirectoryDataType { - pub fn new(name: String, lba_size: &dyn LBASize, is_hidden: bool) -> Result { - Ok(DirectoryDataType{name, lba: lba_size.get_lba(), size: lba_size.get_length(), lba_length: lba_size.get_length_lba()?, entries: Vec::new(), is_hidden}) - } -} - -pub struct FileDataType { - pub name: String, - pub file_path: String, - pub lba: usize, - pub size: usize, - pub lba_length: usize, - pub is_hidden: bool -} - -impl FileDataType { - pub fn new(name: String, file_path: String, lba_size: &dyn LBASize, is_hidden: bool) -> Result { - Ok(FileDataType{name, file_path, lba: lba_size.get_lba(), size: lba_size.get_length(), lba_length: lba_size.get_length_lba()?, is_hidden}) - } -} - -pub fn new_dir_entry(entry: DirectoryDataType) -> Entry { - Entry::Directory(entry) -} - -pub fn new_file_entry(name: String, file_path: String, lba_size: &dyn LBASize, is_hidden: bool) -> Result { - Ok(Entry::File(FileDataType::new(name, file_path, lba_size, is_hidden)?)) -} \ No newline at end of file diff --git a/src/Tools/psxcdgen/src/iso_writer/mod.rs b/src/Tools/psxcdgen/src/iso_writer/mod.rs deleted file mode 100644 index 4aca49d2..00000000 --- a/src/Tools/psxcdgen/src/iso_writer/mod.rs +++ /dev/null @@ -1,72 +0,0 @@ -pub mod types; -pub mod psx; -pub mod cd_desc; -pub mod lba_map; - -use cdtypes::{Error, types::{*, time::Time}}; -use types::EncodeBehaviour; -use std::io::Write; - -pub fn write_sectors(mut file: std::fs::File, sectors: Vec) -> Result<(), Error> { - let mut time = Time::cd_start(); - - for sector in sectors { - file.write(§or.encode(time.clone(), EncodeBehaviour::Mode0AsMode2From1)?)?; - time.add_sector()?; - } - - Ok(()) -} - -pub fn write_cue(file: std::fs::File, cue_specs: Vec) -> Result<(), Error> { - cue::writer::write(file, cue_specs) -} - -pub fn write_lba(file: &mut dyn std::io::Write, lba_map: lba_map::EntryVec, bin_path: &str, cue_path: &str) -> Result<(), Error> { - macro_rules! write_formatted_line { - ($file:ident, $type:expr, $name:expr, $length:expr, $lba:expr, $time_code:expr, $bytes:expr, $file_name:expr) => { - writeln!($file, "\t{: Result<(), Error> { - let is_hidden = dir.is_hidden; - - write_formatted_line!(file, if is_hidden {"!Dir"} else {"Dir"}, dir.name, dir.lba_length, dir.lba, "", dir.size, "")?; - for entry in dir.entries { - match entry { - lba_map::Entry::Directory(dir) => print_dir(file, dir)?, - lba_map::Entry::File(file_info) => print_file(file, file_info)?, - } - } - write_formatted_line!(file, "End", dir.name, "", "", "", "", "")?; - Ok(()) - } - - fn print_file(file: &mut dyn std::io::Write, file_info: lba_map::FileDataType) -> Result<(), Error> { - write_formatted_line!(file, if file_info.is_hidden {"!File"} else {"File"}, file_info.name, file_info.lba_length, file_info.lba, "", file_info.size, file_info.file_path)?; - Ok(()) - } - - writeln!(file, "File LBA log generated by PSXCDGEN v0.5.0\n")?; - writeln!(file, "Image bin file: {}", bin_path)?; - writeln!(file, "Image cue file: {}", cue_path)?; - writeln!(file, "\nFile System:\n\n")?; - - write_formatted_line!(file, "Type", "Name", "Length", "LBA", "Time Code", "Bytes", "File")?; - - for entry in lba_map { - match entry { - lba_map::Entry::Directory(dir) => print_dir(file, dir)?, - lba_map::Entry::File(file_info) => print_file(file, file_info)?, - } - } - - Ok(()) -} \ No newline at end of file diff --git a/src/Tools/psxcdgen/src/iso_writer/psx/encoder/helper.rs b/src/Tools/psxcdgen/src/iso_writer/psx/encoder/helper.rs deleted file mode 100644 index 97a4e6f3..00000000 --- a/src/Tools/psxcdgen/src/iso_writer/psx/encoder/helper.rs +++ /dev/null @@ -1,71 +0,0 @@ -use super::super::super::types::IntermediateSector; -use cdtypes::{Error, types::{sector as raw_sector, helper::sector_count_mode2_form1}}; - -pub fn copy_data<'a, T, const SIZE:usize>(dst: &mut [T; SIZE], src: &'a [T]) -> &'a [T] { - let data_size = { - if src.len() > SIZE { - SIZE - } - - else { - src.len() - } - }; - - unsafe{std::ptr::copy_nonoverlapping(src.as_ptr(), dst.as_mut_ptr(), data_size)}; - &src[data_size..src.len()] -} - -pub fn fill_sectors(sectors: &mut Vec, mut amount: usize) { - while amount > 0 { - sectors.push(IntermediateSector::Empty); - amount -= 1; - } -} - -pub fn fill_sectors_upto(sectors: &mut Vec, amount: usize) { - let cur_len = sectors.len(); - if cur_len < amount { - fill_sectors(sectors, amount - cur_len); - } -} - -pub fn write_cdxa_data(sectors: &mut Vec, mut start_idx: usize, mut data: &[u8], mut sub_header: raw_sector::SubHeader) -> Result<(), Error> { - let end_idx = start_idx + sector_count_mode2_form1(data.len()); - - while start_idx < end_idx { - let mut sec_data = [0u8; raw_sector::Mode2Form1::DATA_SIZE]; - data = copy_data(&mut sec_data, data); - - if start_idx + 1 == end_idx { - sub_header.sub_mode.set_eor(); - sub_header.sub_mode.set_eof(); - } - - if let Some(sector) = sectors.get_mut(start_idx) { - *sector = IntermediateSector::CDXAData(sec_data, sub_header.clone()); - start_idx += 1; - } - - else { - return Err(Error::NoSectorForLBA(start_idx)); - } - } - - Ok(()) -} - -pub fn write_cdxa_audio(sectors: &mut Vec, mut start_idx: usize, data: &Vec<(raw_sector::SubHeader, [u8; raw_sector::Mode2Form2::DATA_SIZE])>) -> Result<(), Error> { - for data in data { - if let Some(sector) = sectors.get_mut(start_idx) { - *sector = IntermediateSector::CDXAAudio(data.1, data.0.clone()); - start_idx += 1; - } - - else { - return Err(Error::NoSectorForLBA(start_idx)); - } - } - - Ok(()) -} \ No newline at end of file diff --git a/src/Tools/psxcdgen/src/iso_writer/psx/encoder/mod.rs b/src/Tools/psxcdgen/src/iso_writer/psx/encoder/mod.rs deleted file mode 100644 index 2323b25d..00000000 --- a/src/Tools/psxcdgen/src/iso_writer/psx/encoder/mod.rs +++ /dev/null @@ -1,571 +0,0 @@ -pub mod helper; - -use super::helper::{copy_data, fill_sectors, fill_sectors_upto, write_cdxa_data, write_cdxa_audio}; -use super::super::{types::{ProcessedFile, builder::*, IntermediateSector}, cd_desc::{DataTrackType, DirectoryDataType, LBASize, PVD as PVDDesc}, lba_map}; -use cdtypes::{ - Error, - types::{ - *, - pvd::{PrimaryVolumeDescriptor, VolumeDescriptorTerminator}, - cdstring::{AString, CDStringValidator, DStringValidator, DString}, - date::{Date, SmallDate}, - dir_record::DirectoryRecord, - helper::sector_count_mode2_form1, - lsb_msb::*, - path_table::{PathTableL, PathTableB}, - sector::{AudioSample, Mode2Form1}, - } -}; -use std::{fs::OpenOptions, io::{Read, Seek, SeekFrom}}; - -const PVD_IDX:usize = 16; -const VDT_IDX:usize = 16 + 1; - -pub struct PathTableLayout { - pub table_1: usize, - pub table_2: usize, - pub table_3: usize, - pub table_4: usize, - pub size: usize -} - -pub struct ContentLayout { - pub root_lba: usize, - pub path_table: PathTableLayout -} - -pub fn get_cd_header_size() -> usize { - VDT_IDX + 1 -} - -pub fn write_licence(licence_path: String, sectors: &mut Vec) -> Result<(), Error> { - fn read_licence_text(file: &mut std::fs::File) -> Result<[u8; Mode2Form1::DATA_SIZE], Error> { - let mut data = [0u8; Mode2Form1::DATA_SIZE]; - - file.seek(SeekFrom::Start(0x2488))?; - file.read_exact(&mut data)?; - - for i in 0..(data.len()-4) { - if data[i..i+4].starts_with(&[b'S', b'o', b'n', b'y']) { - data[i] = b'J'; - data[i+1] = b'a'; - data[i+2] = b'b'; - data[i+3] = b'y'; - } - } - - Ok(data) - } - - fn set_read_licence_logo(file: &mut std::fs::File) -> Result<(), Error> { - file.seek(SeekFrom::Start(0x2DA8))?; - Ok(()) - } - - fn read_licence_logo(file: &mut std::fs::File) -> Result<[u8; Mode2Form1::DATA_SIZE], Error> { - let mut data = [0u8; Mode2Form1::DATA_SIZE]; - - file.read_exact(&mut data)?; - file.seek(SeekFrom::Current(0x120))?; - - Ok(data) - } - - let mut licence_file = OpenOptions::new().read(true).open(licence_path)?; - - for i in 0..=15 { - if let Some(sector) = sectors.get_mut(i) { - *sector = { - match i { - 0..=3 => EmptySectorBuilder::CDXAData(), - 4 => { - let sector = IntermediateSector::CDXAData(read_licence_text(&mut licence_file)?, SubHeaderBuilder::DataDefault(false)); - set_read_licence_logo(&mut licence_file)?; - - sector - }, - 5..=11 => { - IntermediateSector::CDXAData(read_licence_logo(&mut licence_file)?, SubHeaderBuilder::DataDefault(false)) - }, - 12..=15 => EmptySectorBuilder::CDXAAudio(), - _ => { - return Err(Error::GenericError("SystemArea can't exceed 16 sectors".to_owned())); - } - } - }; - } - - else { - return Err(Error::GenericError(format!("Couldn't access sector {} of System Area", i))); - } - } - Ok(()) -} - -pub fn write_pvd(mut desc: PVDDesc, sectors: &mut Vec, content_layout: ContentLayout) -> Result<(), Error> { - fn write_root_dir_record(raw_pvd: &mut PrimaryVolumeDescriptor, lba: usize) { - let root_dir = raw_pvd.get_root_dir_record_mut(); - - write_dir_record_entry(&DataTrackType::Directory(DirectoryDataType::new_pvd_root_dir(lba)), root_dir, false); - } - - fn write_path_table(raw_pvd: &mut PrimaryVolumeDescriptor, layout: PathTableLayout) { - raw_pvd.path_table_size.write(layout.size as u32); - raw_pvd.path_table_1.write(layout.table_1 as u32); - raw_pvd.path_table_2.write(layout.table_2 as u32); - raw_pvd.path_table_3.write(layout.table_3 as u32); - raw_pvd.path_table_4.write(layout.table_4 as u32); - } - - //Make sure we have enough space and make all names upper case - fill_sectors_upto(sectors, VDT_IDX + 1); - desc.to_uppercase(); - - let sectors_size = sectors.len(); - let now_date = Date::now(); - let mut raw_pvd = PrimaryVolumeDescriptor::new(); - - raw_pvd.system_id = AString::from_str("PLAYSTATION")?; - if desc.volume_identifier.len() > 8 { - println!("Warning: PSX might not support volume identifiers bigger then 8 chars") - } - raw_pvd.volume_id = DString::from_str(desc.volume_identifier.as_str())?; - raw_pvd.publisher_id = AString::from_str(desc.publisher.as_str())?; - raw_pvd.data_preparer = AString::from_str(desc.data_preparer.as_str())?; - raw_pvd.app_id = AString::from_str("PLAYSTATION")?; - raw_pvd.vol_create_time = now_date; - raw_pvd.vol_space_size.write((sectors_size - 2) as u32); - raw_pvd.cd_xa_id = ['C' as u8, 'D' as u8, '-' as u8, 'X' as u8, 'A' as u8, '0' as u8, '0' as u8, '1' as u8]; - write_root_dir_record(&mut raw_pvd, content_layout.root_lba); - write_path_table(&mut raw_pvd, content_layout.path_table); - - if let Some(sector) = sectors.get_mut(PVD_IDX) { - *sector = SectorBuilder::CDXAData(raw_pvd, SubHeaderBuilder::VolumeDescriptorDefault(false)); - - if let Some(sector) = sectors.get_mut(VDT_IDX) { - - *sector = SectorBuilder::CDXAData(VolumeDescriptorTerminator::new(), SubHeaderBuilder::VolumeDescriptorDefault(true)); - Ok(()) - } - - else { - Err(Error::GenericError(String::from("Failed padding sectors to VDT"))) - } - } - - else { - Err(Error::GenericError(String::from("Failed padding sectors to PVD"))) - } -} - -pub fn write_content(mut root_dir: DirectoryDataType, sectors: &mut Vec, lba_map: Option<&mut lba_map::EntryVec>) -> Result { - let path_table_size = { - let lba_size = calculate_path_table_size(&root_dir); - if lba_size > Mode2Form1::DATA_SIZE { - println!("Warning: Path Table has size of {} bytes but PSX might only support Path Tables of one sector data size", lba_size); - } - lba_size - }; - let start_idx = sectors.len() + (path_table_size_sector_count(path_table_size)*4); - let new_sector_amount = arrange_content(&mut root_dir, start_idx)?; - - if let Some(lba_map) = lba_map { - append_lba_for_data_track(lba_map, &root_dir)?; - } - - root_dir.sort(); - let layout = write_path_tables(&root_dir, sectors, path_table_size)?; - write_arranged_content(root_dir, sectors, new_sector_amount)?; - - println!("I have {} sectors because I added {} new sectors (Start: {}, PathTableSize: {})", sectors.len(), new_sector_amount, start_idx, path_table_size); - Ok(ContentLayout{root_lba: start_idx, path_table: layout}) -} - -pub fn append_audio(pcm: Vec, sectors: &mut Vec) -> Result<(), Error> { - let mut pcm = &pcm[0..]; - - while pcm.len() > 0 { - let mut pcm_sector = [AudioSample::default(); sector::Audio::SAMPLE_SIZE]; - - pcm = copy_data(&mut pcm_sector, pcm); - sectors.push(IntermediateSector::Audio(pcm_sector)); - } - - Ok(()) -} - -pub fn decorate_names(root_dir: &mut DirectoryDataType) -> Result<(), Error> { - fn add_version_number(name: &mut String) -> Result<(), Error> { - if let Some(pos) = name.rfind(';') { - let version_str = &name[(pos + 1)..]; - - if !version_str.is_empty() { - if let Err(_) = version_str.parse::() { - return Err(Error::GenericError(format!("{} does not has a valid version number", name))); - } - } - - else { - name.push('1'); - } - } - - else { - name.push_str(";1"); - } - - Ok(()) - } - - fn get_file_name_extension(string: &String) -> (&str, &str) { - let mut name = string.as_ref(); - let mut ext = ""; - - if let Some(dot) = string.rfind('.') { - name = &string[0..dot]; - if let Some(semi) = string.rfind(';') { - ext = &string[(dot + 1)..semi]; - } - } - - (name, ext) - } - - root_dir.to_uppercase(); - for entry in root_dir.iter_mut() { - match entry { - DataTrackType::Directory(dir) => { - DStringValidator::is_valid_ascii(dir.name.as_bytes())?; - if dir.name.len() > 8 { - return Err(Error::GenericError(format!("Directory name {} must not have more then 8 characters", dir))); - } - decorate_names(dir)?; - }, - DataTrackType::File(file) => { - add_version_number(&mut file.name)?; - let (name, ext) = get_file_name_extension(&file.name); - if ext.is_empty() { - return Err(Error::GenericError(format!("Missing file extension for {}", file.name))); - } - - if name.len() > 8 { - return Err(Error::GenericError(format!("File name {} must not have more then 8 characters", name))); - } - - if ext.len() > 3 { - return Err(Error::GenericError(format!("File extension {} for file {} must not have more then 3 characters", ext, name))); - } - - DStringValidator::is_valid_ascii(name.as_bytes())?; - DStringValidator::is_valid_ascii(ext.as_bytes())?; - } - } - } - - Ok(()) -} - -fn append_lba_for_data_track(lba_map: &mut lba_map::EntryVec, root_dir: &DirectoryDataType) -> Result<(), Error> { - fn append_dir(dir: &DirectoryDataType, map: &mut Vec) -> Result<(), Error> { - for element in dir.iter() { - match element { - DataTrackType::Directory(dir) => { - let mut dir_entry = lba_map::DirectoryDataType::new(dir.name.clone(), dir, dir.is_hidden)?; - append_dir(dir, &mut dir_entry.entries)?; - - map.push(lba_map::new_dir_entry(dir_entry)); - }, - DataTrackType::File(file) => map.push(lba_map::new_file_entry(file.name.clone(), file.get_path().clone(), file, file.is_hidden)?), - } - } - - Ok(()) - } - - append_dir(root_dir, lba_map) -} - -fn arrange_content(root_dir: &mut DirectoryDataType, start_lba: usize) -> Result { - fn arrange_files(dir: &mut DirectoryDataType, mut lba: usize) -> Result { - for file in dir.iter_file_mut() { - lba = file.set_lba_ret(lba)?; - } - - Ok(lba) - } - - fn arrange_dirs(dir: &mut DirectoryDataType, mut lba: usize) -> Result { - for dir in dir.iter_dir_mut() { - if !dir.is_hidden { - lba = dir.set_lba_ret(lba)?; - } - } - - Ok(lba) - } - - fn arrange(dir: &mut DirectoryDataType, mut lba: usize) -> Result { - lba = arrange_files(dir, lba)?; - lba = arrange_dirs(dir, lba)?; - - for dir in dir.iter_dir_mut() { - lba = arrange(dir, lba)?; - } - - Ok(lba) - } - - fn _alt_arrange(dir: &mut DirectoryDataType, mut lba: usize) -> Result { - for entry in dir.iter_mut() { - match entry { - DataTrackType::Directory(dir) => { - lba = dir.set_lba_ret(lba)?; - lba = _alt_arrange(dir, lba)?; - }, - DataTrackType::File(file) => lba = file.set_lba_ret(lba)?, - } - } - - Ok(lba) - } - - root_dir.calculate_lengthes(); - - //Root is always sorted file first - let mut lba = start_lba; - - lba = root_dir.set_lba_ret(lba)?; - lba = arrange(root_dir, lba)?; - - Ok(lba - start_lba) -} - -fn write_dir_record_entry(entry: &DataTrackType, dir_rec: &mut DirectoryRecord, has_system_use: bool) { - enum XASystemUseType - { - Directory, - DataFile, - } - - unsafe {dir_rec.new(entry.get_name().as_ref(), has_system_use)}; - - dir_rec.data_block_number.write(entry.get_lba() as u32); - dir_rec.data_size.write(entry.get_length() as u32); - dir_rec.time_stamp = SmallDate::now(); - - let entry_type = { - match entry { - DataTrackType::Directory(_) => { - dir_rec.set_directory(); - XASystemUseType::Directory - } - - DataTrackType::File(_) => { - dir_rec.set_file(); - XASystemUseType::DataFile - } - } - }; - - if let Some(cdxa_entry) = dir_rec.get_cdxa_system_use_mut() { - match entry_type { - XASystemUseType::Directory => { - cdxa_entry.file_attribute.set_mode2(); - cdxa_entry.file_attribute.set_directory(); - } - XASystemUseType::DataFile => { - cdxa_entry.file_attribute.set_mode2(); - } - } - } -} - -fn path_table_size_sector_count(bytes: usize) -> usize { - sector_count_mode2_form1(bytes) -} - -fn write_path_tables(arranged_root_dir: &DirectoryDataType, sectors: &mut Vec, size: usize) -> Result { - type PseudoArray = (Vec, usize); - - fn push_table_entry(raw_buffer: &mut PseudoArray, name: &str, lba: usize, parent_table_id: usize) -> Result<(), Error> { - let entry_size = PathTableL::calculate_size_for(name); - if raw_buffer.1 + entry_size > raw_buffer.0.len() { - return Err(Error::GenericError(format!("Out of memory for Table Path Entry!"))); - } - - let path_entry = unsafe{ - let entry = std::mem::transmute::<&mut u8, &mut PathTableL>(&mut raw_buffer.0[raw_buffer.1]); - - entry.new(name); - entry - }; - - path_entry.directory_logical_block.write(lba as u32); - path_entry.parent_table_id.write(parent_table_id as u16); - raw_buffer.1 += entry_size; - - Ok(()) - } - - fn push_all_entries(raw_buffer: &mut PseudoArray, dir: &DirectoryDataType, mut parent: usize) -> Result<(), Error> { - if !dir.is_hidden { - for dir in dir.iter_dir() { - if !dir.is_hidden { - push_table_entry(raw_buffer, dir.name.as_ref(), dir.get_lba(), parent)?; - } - } - - for dir in dir.iter_dir() { - if !dir.is_hidden { - parent += 1; - push_all_entries(raw_buffer, dir, parent)?; - } - } - } - Ok(()) - } - - fn write_table(sectors: &mut Vec, mut idx: usize, length_lba: usize, data: &[u8]) -> Result { - for _ in 0..2 { - write_cdxa_data(sectors, idx, &data, SubHeaderBuilder::DataDefault(false))?; - idx += length_lba; - } - - Ok(idx) - } - - fn transform_table(data_l: &mut [u8]) { - let mut idx = 0; - while idx < data_l.len() { - let org_value = unsafe {std::mem::transmute::<&u8, &PathTableL>(&data_l[idx])}; - let new_value = unsafe {std::mem::transmute::<&mut u8, &mut PathTableB>(&mut data_l[idx])}; - - new_value.directory_logical_block.write(org_value.directory_logical_block.read()); - new_value.parent_table_id.write(org_value.parent_table_id.read()); - - idx += new_value.get_size(); - } - } - - let mut raw_buffer_table = (vec![0u8; size], 0); - - push_table_entry(&mut raw_buffer_table, "\x00", arranged_root_dir.get_lba(), 1)?; - push_all_entries(&mut raw_buffer_table, arranged_root_dir, 1)?; - - let mut table_idx = sectors.len(); - let size_lba = path_table_size_sector_count(size); - - let layout = PathTableLayout{table_1: table_idx, table_2: table_idx + size_lba, table_3: table_idx + (2*size_lba), table_4: table_idx + (3*size_lba), size: size}; - - fill_sectors(sectors, size_lba*4); - table_idx = write_table(sectors, table_idx, size_lba, &raw_buffer_table.0)?; - transform_table(&mut raw_buffer_table.0); - write_table(sectors, table_idx, size_lba, &raw_buffer_table.0)?; - - Ok(layout) -} - -fn write_arranged_content(arranged_root_dir: DirectoryDataType, sectors: &mut Vec, amount: usize) -> Result<(), Error> { - fn write_dir(dir: &DirectoryDataType, parent: &DirectoryDataType, sectors: &mut Vec) -> Result<(), Error> { - fn set_sector(data: [u8; Mode2Form1::DATA_SIZE], is_last: bool, lba: usize, sectors: &mut Vec) -> Result<(), Error> { - if let Some(sector) = sectors.get_mut(lba) { - *sector = IntermediateSector::CDXAData(data, SubHeaderBuilder::DirectoryRecordDefault(is_last)); - Ok(()) - } - - else { - Err(Error::NoSectorForLBA(lba)) - } - } - - if dir.is_hidden { - Ok(()) - } - - else { - let entry_length = dir.get_length_lba()?; - let mut sector_buffer = [0u8; Mode2Form1::DATA_SIZE]; - let mut sector_idx = 0usize; - let mut lba = dir.get_lba(); - let mut write_entry = |entry: &DataTrackType| -> Result<(), Error> { - if entry.is_hidden() { - Ok(()) - } - - else { - let name = entry.get_name().as_ref(); - let size = DirectoryRecord::calculate_size_for(name, true); - if sector_idx + size > Mode2Form1::DATA_SIZE { - set_sector(sector_buffer, false, lba, sectors)?; - - sector_buffer = [0u8; Mode2Form1::DATA_SIZE]; - lba += 1; - } - - let dir_rec = unsafe {std::mem::transmute::<&mut u8, &mut DirectoryRecord>(&mut sector_buffer[sector_idx])}; - write_dir_record_entry(entry, dir_rec, true); - - sector_idx += size; - Ok(()) - } - }; - - if entry_length > 1 { - println!("Warning: Directory {} spans {} sectors and might not be supported by PSX", dir.name, entry_length); - } - - //Write current and parent dir - write_entry(&DataTrackType::Directory(dir.as_flat_cur_dir()))?; - write_entry(&DataTrackType::Directory(parent.as_flat_parent_dir()))?; - - for entry in dir.iter() { - write_entry(entry)?; - } - set_sector(sector_buffer, true, lba, sectors)?; - Ok(()) - } - } - - fn write(parent_dir: &DirectoryDataType, sectors: &mut Vec) -> Result<(), Error> { - for entry in parent_dir.iter() { - match entry { - DataTrackType::Directory(dir) => { - write_dir(dir, parent_dir, sectors)?; - write(dir, sectors)?; - }, - - DataTrackType::File(file) => { - match file.get_data_ref()? { - ProcessedFile::Raw(raw_data) => write_cdxa_data(sectors, file.get_lba(), raw_data.as_ref(), SubHeaderBuilder::DataDefault(false))?, - ProcessedFile::XAAudio(raw_data) => write_cdxa_audio(sectors, file.get_lba(), raw_data)?, - } - } - } - } - Ok(()) - } - - fill_sectors(sectors, amount); - - write_dir(&arranged_root_dir, &arranged_root_dir, sectors)?; - write(&arranged_root_dir, sectors) -} - -fn calculate_path_table_size(root_dir: &DirectoryDataType) -> usize { - if root_dir.is_hidden { - 0 - } - - else { - let mut size = PathTableL::calculate_size_for("\x00"); - - for sub_dir in root_dir.iter_dir() { - if !sub_dir.is_hidden { - size += PathTableL::calculate_size_for(sub_dir.name.as_ref()); - size += calculate_path_table_size(sub_dir) - } - } - - size - } -} \ No newline at end of file diff --git a/src/Tools/psxcdgen/src/iso_writer/psx/mod.rs b/src/Tools/psxcdgen/src/iso_writer/psx/mod.rs deleted file mode 100644 index 3824c0a6..00000000 --- a/src/Tools/psxcdgen/src/iso_writer/psx/mod.rs +++ /dev/null @@ -1,73 +0,0 @@ -use super::{types::IntermediateSector, cd_desc::{CDDesc, DataTrackType, DirectoryDataType, Track}, lba_map}; -use cdtypes::{types::{*, time::Time}, Error}; -use encoder::helper; - -pub mod encoder; - -pub fn encode(cd_desc: CDDesc, cue_specs: &mut Vec) -> Result<(Vec, Option), Error> { - let header_size = encoder::get_cd_header_size(); - let mut sectors = Vec::new(); - let mut content_layout = None; - let mut cur_track = 1; - let mut cur_time = Time::cue_start(); - let mut lba_map = Vec::new(); - - // Creates enough space for the PVD - helper::fill_sectors_upto(&mut sectors, header_size); - - // Write Licence - if !cd_desc.licence_path.is_empty() { - encoder::write_licence(cd_desc.licence_path, &mut sectors)?; - } - - for track in cd_desc.tracks { - match track { - Track::Data(mut dir) => { - process_dir(&mut dir)?; - // Decorate and verify the names for content creation - encoder::decorate_names(&mut dir)?; - let new_content_layout = encoder::write_content(dir, &mut sectors, Some(&mut lba_map))?; - - if content_layout.is_none() { - content_layout = Some(new_content_layout); - } - - cue_specs.push(cue::Specifier::Track{number: cur_track, data_type: cue::DataType::Mode2_2352}); - cue_specs.push(cue::Specifier::Index{number: 1, time: cur_time}); - } - - Track::Audio(pcm) => { - encoder::append_audio(pcm, &mut sectors)?; - - cue_specs.push(cue::Specifier::Track{number: cur_track, data_type: cue::DataType::Audio}); - cue_specs.push(cue::Specifier::PreGap{time: Time::cd_pregap()}); - cue_specs.push(cue::Specifier::Index{number: 1, time: cur_time}); - } - } - - cur_track += 1; - cur_time = Time::from_lba(sectors.len()); - } - - if let Some(content_layout) = content_layout { - // Now write the PVD cause write_content eventaully tells us where to start - encoder::write_pvd(cd_desc.pvd, &mut sectors, content_layout)?; - } - - else { - return Err(Error::GenericError("No Data track found!".to_owned())); - } - - Ok((sectors, Some(lba_map))) -} - -fn process_dir(dir: &mut DirectoryDataType) -> Result<(), Error> { - for entry in dir.iter_mut() { - match entry { - DataTrackType::Directory(dir) => process_dir(dir)?, - DataTrackType::File(file) => file.process_content()?, - } - } - - Ok(()) -} \ No newline at end of file diff --git a/src/Tools/psxcdgen/src/iso_writer/types/builder.rs b/src/Tools/psxcdgen/src/iso_writer/types/builder.rs deleted file mode 100644 index 5746ab8e..00000000 --- a/src/Tools/psxcdgen/src/iso_writer/types/builder.rs +++ /dev/null @@ -1,64 +0,0 @@ -use cdtypes::types::sector::{Mode2Form1, Mode2Form2, SubHeader}; -use super::IntermediateSector; - -pub struct SectorBuilder{} -pub struct SubHeaderBuilder{} -pub struct EmptySectorBuilder{} - -#[allow(non_snake_case)] -impl SectorBuilder { - pub fn CDXAData(data: T, sub_header: SubHeader) -> IntermediateSector { - unsafe { - let ref_data = std::mem::transmute::<&T, &[u8; Mode2Form1::DATA_SIZE]>(&data); - IntermediateSector::CDXAData(*ref_data, sub_header) - } - } -} - -#[allow(non_snake_case)] -impl SubHeaderBuilder { - pub fn VolumeDescriptorDefault(is_eof: bool) -> SubHeader { - let mut sub_header = SubHeader::default(); - - sub_header.sub_mode.set_eor(); - sub_header.sub_mode.set_data(); - - if is_eof { - sub_header.sub_mode.set_eof(); - } - - sub_header - } - - pub fn DirectoryRecordDefault(is_last: bool) -> SubHeader { - let mut sub_header = SubHeader::default(); - - sub_header.sub_mode.set_data(); - if is_last { - sub_header.sub_mode.set_eor(); - sub_header.sub_mode.set_eof(); - } - sub_header - } - - pub fn DataDefault(is_last: bool) -> SubHeader { - Self::DirectoryRecordDefault(is_last) - } -} - -#[allow(non_snake_case)] -impl EmptySectorBuilder { - pub fn CDXAData() -> IntermediateSector { - IntermediateSector::CDXAData([0u8; Mode2Form1::DATA_SIZE], SubHeaderBuilder::DataDefault(false)) - } - - pub fn CDXAAudio() -> IntermediateSector { - let sub_header = { - let mut sub_header = SubHeader::default_form2(); - - sub_header.sub_mode.clear_audio(); - sub_header - }; - IntermediateSector::CDXAAudio([0u8; Mode2Form2::DATA_SIZE], sub_header) - } -} \ No newline at end of file diff --git a/src/Tools/psxcdgen/src/iso_writer/types/mod.rs b/src/Tools/psxcdgen/src/iso_writer/types/mod.rs deleted file mode 100644 index 6c019e07..00000000 --- a/src/Tools/psxcdgen/src/iso_writer/types/mod.rs +++ /dev/null @@ -1,179 +0,0 @@ -pub mod builder; - -use cdtypes::{Error, types::{error_correction, sector, time::Time}}; -use builder::SubHeaderBuilder; -use super::super::file_helper::read_file_to_u8; - -type ByteSector = [u8; sector::SECTOR_SIZE]; - -pub enum EncodeBehaviour { - Normal, - Mode0AsMode2From1 -} - -pub enum IntermediateSector { - Empty, - Audio([sector::AudioSample; sector::Audio::SAMPLE_SIZE]), - CDData([u8; sector::Mode1::DATA_SIZE]), - CDXAData([u8;sector::Mode2Form1::DATA_SIZE], sector::SubHeader), - CDXAAudio([u8;sector::Mode2Form2::DATA_SIZE], sector::SubHeader), -} - -impl IntermediateSector { - pub fn encode(self, time: Time, behaviour: EncodeBehaviour) -> Result { - match self { - Self::Empty => - match behaviour { - EncodeBehaviour::Normal => Ok(Self::encode_mode0(time)), - EncodeBehaviour::Mode0AsMode2From1 => Ok(Self::encode_mode0_as_mode2_form1(time)) - }, - Self::Audio(data) => Ok(unsafe {std::mem::transmute::<[sector::AudioSample; sector::Audio::SAMPLE_SIZE], ByteSector>(data)}), - Self::CDData(data) => Ok(Self::encode_mode1(time, data)), - Self::CDXAData(data, sub_header) => Ok(Self::encode_mode2_form1(time, data, sub_header)), - Self::CDXAAudio(data, sub_header) => Ok(Self::encode_mode2_form2(time, data, sub_header)), - } - } - - fn encode_mode0(time: Time) -> ByteSector { - let mut sector = sector::Mode0::new(); - - sector.header.set_time(time); - unsafe { - std::mem::transmute::(sector) - } - } - - fn encode_mode0_as_mode2_form1(time: Time) -> ByteSector { - Self::encode_mode2_form1(time, [0u8; sector::Mode1::DATA_SIZE], SubHeaderBuilder::DataDefault(true)) - } - - fn encode_mode1(time: Time, data: [u8; sector::Mode1::DATA_SIZE]) -> ByteSector { - let mut sector = sector::Mode1::new(); - - sector.header.set_time(time); - sector.data = data; - sector.finalize(); - - unsafe { - std::mem::transmute::(sector) - } - } - - fn encode_mode2_form1(time: Time, data: [u8; sector::Mode2Form1::DATA_SIZE], sub_header: sector::SubHeader) -> ByteSector { - let mut sector = sector::Mode2Form1::new(); - - sector.header.set_time(time); - sector.data = data; - sector.sub_header = sub_header; - - sector.finalize(); - unsafe { - std::mem::transmute::(sector) - } - } - - fn encode_mode2_form2(time: Time, data: [u8; sector::Mode2Form2::DATA_SIZE], sub_header: sector::SubHeader) -> ByteSector { - let mut sector = sector::Mode2Form2::new(); - - sector.header.set_time(time); - sector.data = data; - sector.sub_header = sub_header; - - sector.finalize(); - unsafe { - std::mem::transmute::(sector) - } - } -} - -#[derive(Clone)] -pub struct RequestedFile { - path: String, - data_type: DataType, -} - -impl RequestedFile { - pub fn new_raw_data(file_path: String) -> RequestedFile { - Self::new_simple(file_path, DataType::RawData) - } - - pub fn new_xa_audio(file_path: String) -> RequestedFile { - Self::new_simple(file_path, DataType::XAAudio) - } - - pub fn process(self) -> Result<(ProcessedFile, String), Error> { - let data = read_file_to_u8(self.path.as_ref())?; - - match self.data_type { - DataType::None => Ok((ProcessedFile::Raw(Vec::new()), self.path)), - DataType::RawData => Ok((ProcessedFile::Raw(data), self.path)), - DataType::XAAudio => Ok((Self::parse_xa_audio(data), self.path)), - } - } - - pub fn get_path(&self) -> &String { - &self.path - } - - fn new_simple(file_path: String, data_type: DataType) -> RequestedFile { - RequestedFile{path: file_path, data_type} - } - - fn parse_xa_audio(data: Vec) -> ProcessedFile { - const XAAUDIOFILE_SIZE:usize = std::mem::size_of::(); - - let mut data = &data[..]; - let mut xa_data = Vec::new(); - - while data.len() >= XAAUDIOFILE_SIZE { - let content = unsafe {&*(data.as_ptr() as *const XAAudioFile)}; - - xa_data.push((content.sub_header.clone(), content.data)); - data = &data[XAAUDIOFILE_SIZE..]; - } - ProcessedFile::XAAudio(xa_data) - } -} - -impl std::default::Default for RequestedFile { - fn default() -> RequestedFile { - RequestedFile{path: String::new(), data_type: DataType::None} - } -} - -#[derive(Clone)] -pub enum ProcessedFile { - Raw(Vec), - XAAudio(Vec<(sector::SubHeader, [u8; sector::Mode2Form2::DATA_SIZE])>), -} - -impl ProcessedFile { - pub fn len(&self) -> usize { - match self { - Self::Raw(data) => data.len(), - Self::XAAudio(data) => data.len()*sector::Mode2Form2::DATA_SIZE, - } - } - - pub fn is_xa_audio(&self) -> bool { - match self { - Self::XAAudio(_) => true, - _ => false - } - } -} - -#[derive(Clone)] -enum DataType { - None, - RawData, - XAAudio, -} - -#[repr(packed(1))] -struct XAAudioFile { - pub sub_header: sector::SubHeader, - pub _sub_header_copy: sector::SubHeader, - pub data: [u8; sector::Mode2Form2::DATA_SIZE], - pub _edc: error_correction::EDC -} \ No newline at end of file diff --git a/src/Tools/psxcdgen/src/lib.rs b/src/Tools/psxcdgen/src/lib.rs deleted file mode 100644 index 61e6f6d3..00000000 --- a/src/Tools/psxcdgen/src/lib.rs +++ /dev/null @@ -1,5 +0,0 @@ -pub mod iso_writer; -pub mod xml_reader; -pub mod file_helper; - -pub use xml_reader::parse_mkpsxiso; diff --git a/src/Tools/psxcdgen/src/main.rs b/src/Tools/psxcdgen/src/main.rs deleted file mode 100644 index 1da97ec5..00000000 --- a/src/Tools/psxcdgen/src/main.rs +++ /dev/null @@ -1,105 +0,0 @@ -use psxcdgen::{*, file_helper::{read_file_to_string, open_output_file, path_to_string}, iso_writer::{psx, cd_desc::*}}; -use cdtypes::Error; -use clap::{Parser}; -use std::{env, path::PathBuf}; - -#[derive(Parser)] -#[clap(about = "Generates a PSX ISO", long_about = None)] -struct CommandLine { - //Overrides output (not supported) - #[clap(short='y')] - override_output: bool, - - //Output file for the lba values (not supported) - #[clap(long="lba")] - lba_file: Option, - - //Output header file for the lba values (not supported) - #[clap(long="lbahead")] - lbahead_file: Option, - - //Disables iso generation (not supported) - #[clap(long="noisogen")] - no_isogen: bool, - - //The input XML - input_path: PathBuf -} - -struct TaskError { - name: String, - error: Error, -} - -impl std::fmt::Display for TaskError { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - write!(f, "{} failed with: \"{}\"", self.name, self.error) - } -} - -fn start_task(name: &str, result: Result) -> Result { - match result { - Ok(value) => Ok(value), - Err(error) => Err(TaskError{name: name.to_owned(), error}) - } -} - -fn write_desc(mut cd_desc: CDDesc, cue_desc: CUEDesc) -> Result<(), TaskError> { - let cd_output_file = std::mem::take(&mut cd_desc.output_file); - let (cue_path, mut cue_specs) = cue_desc.deconstruct(); - let file = start_task("Open iso output file", open_output_file(cd_output_file.as_ref()))?; - let cue_file = start_task("Open cue output file", open_output_file(cue_path.as_ref()))?; - let (encoded_sector, lba_map) = start_task("Encode CD sectors", psx::encode(cd_desc, &mut cue_specs))?; - - start_task("Writing ISO image", iso_writer::write_sectors(file, encoded_sector))?; - start_task("Writing CUE file", iso_writer::write_cue(cue_file, cue_specs))?; - if let Some(lba_map) = lba_map { - start_task("Write LBA file", iso_writer::write_lba(&mut std::io::stdout(), lba_map, cd_output_file.as_ref(), cue_path.as_ref()))?; - } - - Ok(()) -} - -fn run_main(arguments: CommandLine) -> Result<(), TaskError> { - if !arguments.no_isogen { - let input_path = start_task("Opening XML file", path_to_string(arguments.input_path))?; - let input_content = start_task("Reading XML file", read_file_to_string(input_path.as_ref()))?; - let (cd_desc, cue_desc) = start_task("Parsing XML file like mkpsxiso", xml_reader::parse_mkpsxiso(input_content))?; - - write_desc(cd_desc, cue_desc) - } - - else { - Ok(()) - } -} - -fn main() { - //Only needed if running in mkpsxiso mode (Currently) the default - fn edit_env_args() -> Vec { - let mut args = Vec::new(); - - for argument in env::args() { - let mut argument = argument.to_owned(); - - if argument.len() > 2 && argument.starts_with('-') { - argument.insert(0, '-'); - } - args.push(argument); - } - - args - } - - //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - - match CommandLine::try_parse_from(edit_env_args().iter()) { - Ok(arguments) => { - match run_main(arguments) { - Ok(()) => println!("Succees!"), - Err(error) => println!("{}", error) - } - }, - Err(error) => println!("{}", error) - } -} \ No newline at end of file diff --git a/src/Tools/psxcdgen/src/xml_reader/mkpsxiso.rs b/src/Tools/psxcdgen/src/xml_reader/mkpsxiso.rs deleted file mode 100644 index a19e2c27..00000000 --- a/src/Tools/psxcdgen/src/xml_reader/mkpsxiso.rs +++ /dev/null @@ -1,333 +0,0 @@ -use cdtypes::{types::sector::AudioSample, Error}; -use super::{ - XMLReader, - super::iso_writer::cd_desc::{CDDesc, CUEDesc, Track, DirectoryDataType, FileContent, FileDataType} -}; -use fast_xml::events::{attributes::Attributes, Event}; - -macro_rules! make_tag_name { - ($name:expr) => { - paste::item! { - const [< $name:upper _TAG>]: &'static str = $name; - const [< $name:upper _TAG_B>]:&'static [u8] = [< $name:upper _TAG>].as_bytes(); - } - }; -} - -make_tag_name!("iso_project"); -make_tag_name!("track"); -make_tag_name!("identifiers"); -make_tag_name!("directory_tree"); -make_tag_name!("dir"); - -struct Desc { - cd: CDDesc, - cue: CUEDesc, -} - -impl Desc { - fn new() -> Desc { - Desc{cd: CDDesc::new(), cue: CUEDesc::new()} - } -} - -pub fn parse(xml: String) -> Result<(CDDesc, CUEDesc), Error> { - let mut desc = Desc::new(); - let mut parser = XMLReader::new(xml.as_ref()); - - loop { - match parser.next()? { - Event::Start(tag) => { - match tag.name() { - ISO_PROJECT_TAG_B => { - handle_iso_project_attributes(&mut desc, tag.attributes())?; - handle_iso_project(&mut desc, &mut parser)?; - }, - _ => (), - } - }, - Event::Eof => { - return Ok((desc.cd, desc.cue)); - }, - _ => (), - } - } -} - -fn handle_iso_project_attributes(desc: &mut Desc, attributes: Attributes) -> Result<(), Error> { - XMLReader::for_each_attribute(attributes, |attribute| { - match attribute.key { - b"image_name" => { - desc.cd.output_file = XMLReader::get_attribute_value_str(&attribute)?.to_string(); - desc.cue.output_bin_file = desc.cd.output_file.clone(); - }, - b"cue_sheet" => { - desc.cue.output_file = XMLReader::get_attribute_value_str(&attribute)?.to_string(); - }, - _ => XMLReader::print_attribute_not_supported(attribute.key, ISO_PROJECT_TAG), - } - - Ok(()) - }) -} - -fn handle_iso_project(desc: &mut Desc, parser: &mut XMLReader) -> Result<(), Error> { - enum TrackType { - None, - Data, - Audio, - } - - loop { - match parser.next()? { - Event::Start(tag) => { - match tag.name() { - - TRACK_TAG_B => { - let mut track_type = TrackType::None; - let mut source = String::default(); - - XMLReader::for_each_attribute(tag.attributes(), |attribute| { - match attribute.key { - b"type" => { - let attribute_value = XMLReader::get_attribute_value_str(&attribute)?; - match attribute_value { - "data" => track_type = TrackType::Data, - "audio" => track_type = TrackType::Audio, - _ => println!("Unkown track type {}", attribute_value), - } - }, - b"source" => { - source = XMLReader::get_attribute_value_str(&attribute)?.to_owned(); - }, - _ => XMLReader::print_attribute_not_supported(attribute.key, TRACK_TAG) - } - - Ok(()) - })?; - - match track_type { - TrackType::None | - TrackType::Data => handle_data_track(desc, parser)?, - TrackType::Audio => handle_audio_track(desc, source)?, - } - } - _ => (), - } - }, - Event::End(tag) => { - match tag.name() { - ISO_PROJECT_TAG_B => { - return Ok(()); - } - _ => (), - } - } - - Event::Eof => break, - _ => (), - } - } - - Err(Error::EOF) -} - -fn handle_data_track(desc: &mut Desc, parser: &mut XMLReader) -> Result<(), Error> { - loop { - match parser.next()? { - Event::Start(tag) => { - match tag.name() { - IDENTIFIERS_TAG_B => handle_identifiers_attributes(desc, tag.attributes())?, - b"license" => { - if let Some(attribute) = XMLReader::find_attribute(tag.attributes(), b"file")? { - desc.cd.licence_path = XMLReader::get_attribute_value_str(&attribute)?.to_owned(); - } - - else { - println!("No file specified for licence!"); - } - }, - DIRECTORY_TREE_TAG_B => { - let mut dir = DirectoryDataType::new("track"); - handle_directory(&mut dir, parser)?; - - desc.cd.tracks.push(Track::Data(dir)); - }, - _ => (), - } - }, - Event::End(tag) => { - match tag.name() { - TRACK_TAG_B => { - // Push track here? - return Ok(()); - }, - _ => () - } - } - Event::Eof => break, - _ => () - } - } - Err(Error::EOF) -} - -fn handle_identifiers_attributes(desc: &mut Desc, attributes: Attributes) -> Result<(), Error> { - XMLReader::for_each_attribute(attributes, |attribute| { - match attribute.key { - b"system" | b"application" => { - let value = XMLReader::get_attribute_value_str(&attribute)?; - if value != "PLAYSTATION" { - println!("System/Application Identifier \"{}\" will be ignored", value); - } - }, - b"volume" => { - desc.cd.pvd.volume_identifier = XMLReader::get_attribute_value_str(&attribute)?.to_owned(); - }, - b"volume_set" | b"copyright" => { - println!("{} with \"{}\" ignored", XMLReader::get_attribute_key_str(&attribute)?, XMLReader::get_attribute_value_str(&attribute)?); - }, - b"publisher" => { - desc.cd.pvd.publisher = XMLReader::get_attribute_value_str(&attribute)?.to_string(); - }, - b"data_preparer" => { - desc.cd.pvd.data_preparer = XMLReader::get_attribute_value_str(&attribute)?.to_string(); - }, - _ => { - XMLReader::print_attribute_not_supported(attribute.key, IDENTIFIERS_TAG); - } - } - - Ok(()) - }) -} - -fn handle_directory(dir: &mut DirectoryDataType, parser: &mut XMLReader) -> Result<(), Error> { - enum FileType { - None, - Data, - Xa, - } - - loop { - match parser.next()? { - Event::Start(tag) => { - match tag.name() { - b"file" => { - let mut file_type = FileType::None; - let mut file_name = String::default(); - let mut file_source = String::default(); - - XMLReader::for_each_attribute(tag.attributes(), |attribute| { - match attribute.key { - b"name" => { - file_name = XMLReader::get_attribute_value_str(&attribute)?.to_string(); - Ok(()) - }, - b"source" => { - file_source = XMLReader::get_attribute_value_str(&attribute)?.to_string(); - Ok(()) - }, - b"type" => { - if let Ok(r#type) = XMLReader::get_attribute_value_str(&attribute) { - if r#type == "data" { - file_type = FileType::Data; - Ok(()) - } - - else if r#type == "xa" { - file_type = FileType::Xa; - Ok(()) - } - - else { - println!("File type: \"{}\" not supported yet", r#type); - Err(Error::NotImplemented) - } - } - - else { - Err(Error::GenericError("Attribute \"type\" needs to be either data or xa".to_owned())) - } - } - _ => Ok(()), - } - })?; - - match file_type { - FileType::None | FileType::Data => { - let mut file = FileDataType::new(file_name.as_ref(), FileContent::new_raw_data(file_source)); - - if file.name == "SCES_003.90" { - file.set_lba_padding(0); - file.is_hidden = false; - } - dir.add_file(file); - }, - FileType::Xa => { - dir.add_file(FileDataType::new(file_name.as_ref(), FileContent::new_xa_audio(file_source))); - } - } - }, - DIR_TAG_B => { - if let Some(dir_name) = XMLReader::find_attribute(tag.attributes(), b"name")? { - let mut new_dir = DirectoryDataType::new(XMLReader::get_attribute_value_str(&dir_name)?); - - if new_dir.name == "XB" { - new_dir.is_hidden = false; - } - handle_directory(&mut new_dir, parser)?; - dir.add_dir(new_dir); - } - - else { - return Err(Error::GenericError("Dir requires name".to_owned())); - } - }, - _ => (), - } - }, - Event::End(tag) => { - match tag.name() { - DIRECTORY_TREE_TAG_B | DIR_TAG_B => { - return Ok(()); - }, - _ => () - } - } - Event::Eof => break, - _ => () - } - } - Err(Error::EOF) -} - -fn handle_audio_track(desc: &mut Desc, file: String) -> Result<(), Error> { - fn convert_into_16(data: wav::bit_depth::BitDepth) -> Result, Error> { - match data.try_into_sixteen() { - Ok(data) => { - let mut samples = Vec::new(); - - for (left, right) in data.iter().step_by(2).zip(data.iter().skip(1).step_by(2)) { - samples.push(AudioSample::new(*left, *right)) - } - - Ok(samples) - }, - Err(_) => Err(Error::GenericError("Couldn't convert samples to 16bit".to_owned())), - } - } - - let (header, data) = wav::read(&mut std::fs::File::open(file)?)?; - - if header.audio_format != wav::header::WAV_FORMAT_PCM { - return Err(Error::GenericError("Only WAV PCM is supported for Audio tracks".to_owned())); - } - - if header.sampling_rate != 44_100 { - return Err(Error::GenericError("Only a sampling rate of 44.1kHz is supported for Audio tracks".to_owned())); - } - - desc.cd.tracks.push(Track::Audio(convert_into_16(data)?)); - Ok(()) -} \ No newline at end of file diff --git a/src/Tools/psxcdgen/src/xml_reader/mod.rs b/src/Tools/psxcdgen/src/xml_reader/mod.rs deleted file mode 100644 index d1fa2341..00000000 --- a/src/Tools/psxcdgen/src/xml_reader/mod.rs +++ /dev/null @@ -1,93 +0,0 @@ -mod mkpsxiso; -use cdtypes::{Error, types::helper::{convert_ascii_to_str, force_convert_ascii_to_str}}; -use fast_xml::{events::{Event, attributes::{AttrError, Attribute, Attributes}}, Reader}; -use core::ops::Deref; - -pub use mkpsxiso::parse as parse_mkpsxiso; - -#[derive(Clone)] -struct XMLReader<'a> { - reader: Reader<&'a [u8]>, - buffer: Vec, -} - -impl<'a> XMLReader<'a> { - pub fn new(xml: &str) -> XMLReader { - let mut reader = Reader::from_str(xml.as_ref()); - - reader.trim_text(true); - reader.expand_empty_elements(true); - reader.check_end_names(true); - - XMLReader{reader, buffer: Vec::new()} - } - - pub fn next(&mut self) -> Result { - self.buffer.clear(); - Self::convert_error(self.reader.read_event(&mut self.buffer)) - } - - pub fn get_attribute(attribute: Result) -> Result { - match attribute { - Ok(attribute) => Ok(attribute), - Err(error) => Err(Error::GenericError(error.to_string())), - } - } - - pub fn get_attribute_value_str<'b>(attribute: &'b Attribute) -> Result<&'b str, Error> { - if let Some(str) = convert_ascii_to_str(attribute.value.deref()) { - Ok(str) - } - - else { - Err(Error::GenericError("Invalid UTF-8 for attribute value".to_string())) - } - } - - pub fn get_attribute_key_str<'b>(attribute: &'b Attribute) -> Result<&'b str, Error> { - if let Some(str) = convert_ascii_to_str(attribute.key) { - Ok(str) - } - - else { - Err(Error::GenericError("Invalid UTF-8 for attribute key".to_string())) - } - } - - pub fn find_attribute<'b>(attributes: Attributes<'b>, name: &[u8]) -> Result>, Error> { - for attribute in attributes { - match attribute { - Ok(attribute) => { - if attribute.key == name { - return Ok(Some(attribute)); - } - }, - - Err(error) => { - return Err(Error::GenericError(error.to_string())); - } - } - } - - Ok(None) - } - - pub fn for_each_attribute<'b, F>(attributes: Attributes<'b>, mut callback: F) -> Result<(), Error> where F: FnMut(Attribute) -> Result<(), Error> { - for attribute in attributes { - callback(Self::get_attribute(attribute)?)?; - } - - Ok(()) - } - - pub fn print_attribute_not_supported(name: &[u8], tag_name: &str) { - println!("Attribute \"{}\" not yet supported for tag \"{}\"", force_convert_ascii_to_str(name), tag_name); - } - - fn convert_error(result: Result) -> Result { - match result { - Ok(result) => Ok(result), - Err(error) => Err(Error::GenericError(error.to_string())), - } - } -} \ No newline at end of file