From 69074600cc4327fa6ad2bfc05fc0ca7da334b716 Mon Sep 17 00:00:00 2001 From: jaby Date: Sun, 21 Aug 2022 13:06:39 +0200 Subject: [PATCH] Ported psxcdgen over --- src/Tools/psxcdgen/.gitignore | 4 + src/Tools/psxcdgen/cdtypes/Cargo.toml | 11 + src/Tools/psxcdgen/cdtypes/src/cd/mod.rs | 292 +++++++++ src/Tools/psxcdgen/cdtypes/src/cd/reader.rs | 114 ++++ src/Tools/psxcdgen/cdtypes/src/cd/sector.rs | 118 ++++ src/Tools/psxcdgen/cdtypes/src/lib.rs | 45 ++ src/Tools/psxcdgen/cdtypes/src/types/bcd.rs | 54 ++ .../psxcdgen/cdtypes/src/types/cdstring.rs | 85 +++ .../psxcdgen/cdtypes/src/types/cue/mod.rs | 204 +++++++ .../psxcdgen/cdtypes/src/types/cue/read.rs | 20 + .../psxcdgen/cdtypes/src/types/cue/writer.rs | 25 + src/Tools/psxcdgen/cdtypes/src/types/date.rs | 293 +++++++++ .../psxcdgen/cdtypes/src/types/dir_record.rs | 259 ++++++++ .../cdtypes/src/types/error_correction/mod.rs | 120 ++++ .../src/types/error_correction/tables.rs | 133 ++++ .../psxcdgen/cdtypes/src/types/helper.rs | 56 ++ .../psxcdgen/cdtypes/src/types/lsb_msb.rs | 115 ++++ src/Tools/psxcdgen/cdtypes/src/types/mod.rs | 12 + .../psxcdgen/cdtypes/src/types/path_table.rs | 73 +++ src/Tools/psxcdgen/cdtypes/src/types/pvd.rs | 143 +++++ .../psxcdgen/cdtypes/src/types/sector.rs | 512 ++++++++++++++++ src/Tools/psxcdgen/cdtypes/src/types/time.rs | 90 +++ src/Tools/psxcdgen/psxcdgen.code-workspace | 84 +++ src/Tools/psxcdgen/psxcdgen/Cargo.toml | 13 + .../psxcdgen/psxcdgen/src/file_helper.rs | 42 ++ .../psxcdgen/src/iso_writer/cd_desc.rs | 465 ++++++++++++++ .../psxcdgen/src/iso_writer/lba_map.rs | 47 ++ .../psxcdgen/psxcdgen/src/iso_writer/mod.rs | 72 +++ .../src/iso_writer/psx/encoder/helper.rs | 71 +++ .../src/iso_writer/psx/encoder/mod.rs | 570 ++++++++++++++++++ .../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/psxcdgen/src/lib.rs | 5 + src/Tools/psxcdgen/psxcdgen/src/main.rs | 105 ++++ .../psxcdgen/src/xml_reader/mkpsxiso.rs | 333 ++++++++++ .../psxcdgen/psxcdgen/src/xml_reader/mod.rs | 93 +++ src/Tools/psxcdgen/psxcdread/Cargo.toml | 9 + .../psxcdread/src/complex_dump/mod.rs | 137 +++++ src/Tools/psxcdgen/psxcdread/src/lib.rs | 1 + src/Tools/psxcdgen/psxcdread/src/main.rs | 379 ++++++++++++ 41 files changed, 5520 insertions(+) create mode 100644 src/Tools/psxcdgen/.gitignore create mode 100644 src/Tools/psxcdgen/cdtypes/Cargo.toml create mode 100644 src/Tools/psxcdgen/cdtypes/src/cd/mod.rs create mode 100644 src/Tools/psxcdgen/cdtypes/src/cd/reader.rs create mode 100644 src/Tools/psxcdgen/cdtypes/src/cd/sector.rs create mode 100644 src/Tools/psxcdgen/cdtypes/src/lib.rs create mode 100644 src/Tools/psxcdgen/cdtypes/src/types/bcd.rs create mode 100644 src/Tools/psxcdgen/cdtypes/src/types/cdstring.rs create mode 100644 src/Tools/psxcdgen/cdtypes/src/types/cue/mod.rs create mode 100644 src/Tools/psxcdgen/cdtypes/src/types/cue/read.rs create mode 100644 src/Tools/psxcdgen/cdtypes/src/types/cue/writer.rs create mode 100644 src/Tools/psxcdgen/cdtypes/src/types/date.rs create mode 100644 src/Tools/psxcdgen/cdtypes/src/types/dir_record.rs create mode 100644 src/Tools/psxcdgen/cdtypes/src/types/error_correction/mod.rs create mode 100644 src/Tools/psxcdgen/cdtypes/src/types/error_correction/tables.rs create mode 100644 src/Tools/psxcdgen/cdtypes/src/types/helper.rs create mode 100644 src/Tools/psxcdgen/cdtypes/src/types/lsb_msb.rs create mode 100644 src/Tools/psxcdgen/cdtypes/src/types/mod.rs create mode 100644 src/Tools/psxcdgen/cdtypes/src/types/path_table.rs create mode 100644 src/Tools/psxcdgen/cdtypes/src/types/pvd.rs create mode 100644 src/Tools/psxcdgen/cdtypes/src/types/sector.rs create mode 100644 src/Tools/psxcdgen/cdtypes/src/types/time.rs create mode 100644 src/Tools/psxcdgen/psxcdgen.code-workspace create mode 100644 src/Tools/psxcdgen/psxcdgen/Cargo.toml create mode 100644 src/Tools/psxcdgen/psxcdgen/src/file_helper.rs create mode 100644 src/Tools/psxcdgen/psxcdgen/src/iso_writer/cd_desc.rs create mode 100644 src/Tools/psxcdgen/psxcdgen/src/iso_writer/lba_map.rs create mode 100644 src/Tools/psxcdgen/psxcdgen/src/iso_writer/mod.rs create mode 100644 src/Tools/psxcdgen/psxcdgen/src/iso_writer/psx/encoder/helper.rs create mode 100644 src/Tools/psxcdgen/psxcdgen/src/iso_writer/psx/encoder/mod.rs create mode 100644 src/Tools/psxcdgen/psxcdgen/src/iso_writer/psx/mod.rs create mode 100644 src/Tools/psxcdgen/psxcdgen/src/iso_writer/types/builder.rs create mode 100644 src/Tools/psxcdgen/psxcdgen/src/iso_writer/types/mod.rs create mode 100644 src/Tools/psxcdgen/psxcdgen/src/lib.rs create mode 100644 src/Tools/psxcdgen/psxcdgen/src/main.rs create mode 100644 src/Tools/psxcdgen/psxcdgen/src/xml_reader/mkpsxiso.rs create mode 100644 src/Tools/psxcdgen/psxcdgen/src/xml_reader/mod.rs create mode 100644 src/Tools/psxcdgen/psxcdread/Cargo.toml create mode 100644 src/Tools/psxcdgen/psxcdread/src/complex_dump/mod.rs create mode 100644 src/Tools/psxcdgen/psxcdread/src/lib.rs create mode 100644 src/Tools/psxcdgen/psxcdread/src/main.rs diff --git a/src/Tools/psxcdgen/.gitignore b/src/Tools/psxcdgen/.gitignore new file mode 100644 index 00000000..01cb7728 --- /dev/null +++ b/src/Tools/psxcdgen/.gitignore @@ -0,0 +1,4 @@ +**/target +Input/** +Output/** +*.lock \ No newline at end of file diff --git a/src/Tools/psxcdgen/cdtypes/Cargo.toml b/src/Tools/psxcdgen/cdtypes/Cargo.toml new file mode 100644 index 00000000..b6ef204c --- /dev/null +++ b/src/Tools/psxcdgen/cdtypes/Cargo.toml @@ -0,0 +1,11 @@ +[package] +name = "cdtypes" +version = "0.5.5" +edition = "2021" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +byteorder = "*" +paste = "*" +chrono = "*" \ No newline at end of file diff --git a/src/Tools/psxcdgen/cdtypes/src/cd/mod.rs b/src/Tools/psxcdgen/cdtypes/src/cd/mod.rs new file mode 100644 index 00000000..3c64cfc9 --- /dev/null +++ b/src/Tools/psxcdgen/cdtypes/src/cd/mod.rs @@ -0,0 +1,292 @@ +pub mod reader; +pub mod sector; + +use sector::*; +use reader::Reader as CDReader; +use super::{Error, types as types}; +use types::{cue::{Specifier, DataType, DataTypeEnd}, lsb_msb::ReadWriteEndian, pvd::PrimaryVolumeDescriptor, sector::{Mode2Form1, SubHeaderForm}}; +use std::fs::File; + +pub struct DirectoryRecordIterator<'a> { + parent: &'a CD, + cur_sector_id: usize, + cur_data: &'a [u8], + is_last: bool +} + +impl<'a> DirectoryRecordIterator<'a> { + pub fn new(parent: &CD, sector: usize) -> DirectoryRecordIterator { + let mut new_iter = DirectoryRecordIterator{parent: parent, cur_sector_id: sector, cur_data: &[], is_last: true}; + + if let Some((data, is_last)) = new_iter.load(sector) { + new_iter.cur_data = data; + new_iter.is_last = is_last; + } + + new_iter + } + + fn load(&self, sector_id: usize) -> Option<(&'a [u8], bool)> { + if let Some(sector) = self.parent.get_sector(sector_id) { + if let Some(sub_header) = sector.get_sub_header() { + return Some((sector.get_data(), sub_header.sub_mode.is_eof())); + } + + else { + return None; + } + } + + else { + return None; + } + } +} + +impl<'a> std::iter::Iterator for DirectoryRecordIterator<'a> { + type Item = &'a types::dir_record::DirectoryRecord; + + fn next(&mut self) -> Option { + if self.cur_data.is_empty() { + if self.is_last { + None + } + + else { + self.cur_sector_id += 1; + if let Some((data, is_last)) = self.load(self.cur_sector_id) { + self.cur_data = data; + self.is_last = is_last; + + self.next() + } + + else { + None + } + } + } + + else { + let mut data_range = self.cur_data.as_ptr_range(); + unsafe { + if let Some(cur_dir) = (data_range.start as *const types::dir_record::DirectoryRecord).as_ref() { + let dir_length = cur_dir.length[0] as usize; + if dir_length == 0 { + self.cur_data = &[]; + self.next() + } + + else { + data_range.start = data_range.start.add(dir_length); + + self.cur_data = std::slice::from_raw_parts(data_range.start, data_range.end.offset_from(data_range.start) as usize); + Some(cur_dir) + } + } + + else { + None + } + } + } + } +} + +pub struct PathTableIterator<'a> { + path_table: Box<[u8]>, + cur_idx: usize, + phantom: std::marker::PhantomData<&'a u8> +} + +impl<'a> PathTableIterator<'a> { + pub fn new(cd: &CD, mut sector: usize) -> PathTableIterator { + let mut data = Vec::::new(); + + loop { + if let Some(sector) = cd.get_sector(sector) { + if let Some(sub_header) = sector.get_sub_header() { + for byte in sector.get_data() { + data.push(*byte); + } + + if sub_header.sub_mode.is_eof() { + return PathTableIterator{path_table: data.into_boxed_slice(), cur_idx: 0usize, phantom: std::marker::PhantomData::default()}; + } + } + + else { + return PathTableIterator::default(); + } + } + + else { + return PathTableIterator::default(); + } + sector += 1; + } + } +} + +impl<'a> std::iter::Iterator for PathTableIterator<'a> { + type Item = &'a types::path_table::PathTableL; + + fn next(&mut self) -> Option { + if (self.cur_idx + std::mem::size_of::()) < self.path_table.len() { + unsafe { + if let Some(entry) = (self.path_table.as_ptr().add(self.cur_idx) as *const types::path_table::PathTableL).as_ref() { + if entry.name_length[0] > 0 { + self.cur_idx += entry.get_size(); + Some(entry) + } + + else { + None + } + } + + else { + None + } + } + } + + else { + None + } + } +} + +impl<'a> std::default::Default for PathTableIterator<'a> { + fn default() -> PathTableIterator<'a> { + PathTableIterator{path_table: Box::default(), cur_idx: 0usize, phantom: std::marker::PhantomData::default()} + } +} + +pub struct SectorIterator<'a> { + parent: &'a CD, + cur_sec_idx: usize, +} + +impl<'a> SectorIterator<'a> { + pub fn new(cd: &'a CD) -> SectorIterator<'a> { + SectorIterator{parent: cd, cur_sec_idx: 0} + } +} + +impl<'a> std::iter::Iterator for SectorIterator<'a> { + type Item = &'a Sector; + + fn next(&mut self) -> Option { + let value = self.parent.get_sector(self.cur_sec_idx); + + self.cur_sec_idx += 1; + value + } +} + +pub struct CD { + sectors: Vec, + track_info: Vec, +} + +impl CD { + pub fn from_file(file: File, specifier: Option>) -> Result { + let data_type_ends = { + if let Some(specifier) = specifier { + DataTypeEnd::parse_cue_specifier(specifier)? + } + + else { + Vec::new() + } + }; + let reader = CDReader::new(file, &data_type_ends)?; + let mut sectors = Vec::new(); + + for sector in reader { + sectors.push(sector?); + } + + Ok(CD{sectors, track_info: TrackInfo::new(data_type_ends)}) + } + + pub fn sector_count(&self) -> usize { + self.sectors.len() + } + + pub fn last_sector_idx(&self) -> usize { + Self::sector_count(self) - 1 + } + + pub fn get_sector(&self, idx: usize) -> Option<&Sector> { + self.sectors.get(idx) + } + + pub fn has_tracks(&self) -> bool { + !self.track_info.is_empty() + } + + pub fn get_primary_volume_descriptor(&self) -> Result<&PrimaryVolumeDescriptor, Error> { + if let Some(pvd_sec) = self.get_sector(16) { + if let Sector::CDXAData(pvd_sec) = pvd_sec { + unsafe { + match pvd_sec.sub_header.get_form() { + SubHeaderForm::Form1 => Ok(std::mem::transmute::<&[u8; Mode2Form1::DATA_SIZE], &PrimaryVolumeDescriptor>(&pvd_sec.data)), + _ => Err(Error::GenericError("Sector is not CD-XA Data Form 1".to_string())) + + } + } + } + + else { + Err(Error::GenericError("Sector is not CD-XA Data".to_string())) + } + } + + else { + Err(Error::GenericError("Sector not found".to_string())) + } + } + + pub fn directory_record_iter(&self, sector: usize) -> DirectoryRecordIterator { + DirectoryRecordIterator::new(self, sector) + } + + pub fn path_table_iter(&self) -> PathTableIterator { + if let Ok(pvd) = self.get_primary_volume_descriptor() { + PathTableIterator::new(self, pvd.path_table_1.read() as usize) + } + + else { + PathTableIterator::default() + } + } + + pub fn sector_iter(&self) -> SectorIterator { + SectorIterator::new(self) + } + + pub fn track_info_iter(&self) -> std::slice::Iter { + self.track_info.iter() + } +} + +pub struct TrackInfo { + pub r#type: DataType, + pub start: usize, +} + +impl TrackInfo { + pub fn new(data_type_ends: Vec) -> Vec { + let mut data = Vec::new(); + let mut start = 0; + + for data_type_end in data_type_ends { + data.push(TrackInfo{r#type: data_type_end.r#type, start}); + start = data_type_end.end; + } + + data + } +} \ No newline at end of file diff --git a/src/Tools/psxcdgen/cdtypes/src/cd/reader.rs b/src/Tools/psxcdgen/cdtypes/src/cd/reader.rs new file mode 100644 index 00000000..f6aa8150 --- /dev/null +++ b/src/Tools/psxcdgen/cdtypes/src/cd/reader.rs @@ -0,0 +1,114 @@ +use super::sector::Sector; +use super::super::{Error, types::{cue::{DataType, DataTypeEnd}, sector::*}}; +use std::io::Read; + +pub struct Reader<'a> { + file: std::fs::File, + data_type_guide: &'a Vec, + lba: usize, + active: bool +} + +impl<'a> Reader<'a> { + pub fn new(file: std::fs::File, data_type_guide: &'a Vec) -> Result { + Ok(Reader{ + file, data_type_guide, lba: 0, active: true + }) + } + + fn next_data_type(&mut self) -> Option { + self.lba += 1; + for data_type in self.data_type_guide.iter() { + if self.lba < data_type.end { + return Some(data_type.r#type.clone()); + } + } + + None + } + + fn process_audio_sector(&mut self) -> Result, Error> { + let mut buffer = [0;std::mem::size_of::