From 6611b025a466ae7d9b215db5409ec4a9c2095fbb Mon Sep 17 00:00:00 2001 From: Jaby Date: Tue, 25 Oct 2022 19:56:50 +0200 Subject: [PATCH] Parse and write PathTable --- src/Tools/psxcdgen_ex/src/encoder/builder.rs | 51 +++++++++++++++++++- src/Tools/psxcdgen_ex/src/encoder/mod.rs | 2 +- src/Tools/psxcdgen_ex/src/encoder/psx.rs | 35 +++++++++++--- src/Tools/psxcdgen_ex/src/file_writer/mod.rs | 22 ++++++++- 4 files changed, 99 insertions(+), 11 deletions(-) diff --git a/src/Tools/psxcdgen_ex/src/encoder/builder.rs b/src/Tools/psxcdgen_ex/src/encoder/builder.rs index 9425d871..934c79f9 100644 --- a/src/Tools/psxcdgen_ex/src/encoder/builder.rs +++ b/src/Tools/psxcdgen_ex/src/encoder/builder.rs @@ -1,4 +1,4 @@ -use cdtypes::types::sector::*; +use cdtypes::types::{helper::*, sector::*}; pub struct SubModeBuilder { sub_mode: SubMode @@ -38,6 +38,55 @@ pub fn create_xa_data_for(sub_mode: SubMode, data: &T) -> Mode2Form1 { create_xa_data_for_raw(sub_mode, unsafe {std::mem::transmute::<&T, &[u8; Mode2Form1::DATA_SIZE]>(data)}) } +pub fn create_xa_data_for_vec(sub_mode: Option, data: Vec) -> Vec { + let sectors_to_parse = sector_count_mode2_form1(data.len()); + let mut data = &data[0..data.len()]; + let mut sectors = vec![Mode2Form1::new(); sectors_to_parse]; + let sub_mode = { + if let Some(sub_mode) = sub_mode { + sub_mode + } + + else { + SubMode::default_form1() + } + }; + + for cur_sector in 0..sectors_to_parse { + let mut raw_data = [0u8; Mode2Form1::DATA_SIZE]; + let sub_mode = { + let mut sub_mode = sub_mode.clone(); + + if cur_sector + 1 == sectors_to_parse { + sub_mode.set_eof(); + sub_mode.set_eor(); + } + + sub_mode + }; + + data = copy_array(&mut raw_data, data); + sectors[cur_sector] = create_xa_data_for_raw(sub_mode, &raw_data); + } + + sectors +} + pub fn create_xa_data_zero() -> Mode2Form1 { create_xa_data_for_raw(SubMode::default_form1(), &[0u8; Mode2Form1::DATA_SIZE]) +} + +fn copy_array<'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()] } \ No newline at end of file diff --git a/src/Tools/psxcdgen_ex/src/encoder/mod.rs b/src/Tools/psxcdgen_ex/src/encoder/mod.rs index 8f7ff676..c54476c4 100644 --- a/src/Tools/psxcdgen_ex/src/encoder/mod.rs +++ b/src/Tools/psxcdgen_ex/src/encoder/mod.rs @@ -1,4 +1,4 @@ -use super::{file_writer::{Sector, SectorWriter}, types::{CDDesc, Error}}; +use super::{file_writer::{SectorWriter}, types::{CDDesc, Error}}; pub mod psx; pub mod builder; diff --git a/src/Tools/psxcdgen_ex/src/encoder/psx.rs b/src/Tools/psxcdgen_ex/src/encoder/psx.rs index cff1d32f..e9fa68e1 100644 --- a/src/Tools/psxcdgen_ex/src/encoder/psx.rs +++ b/src/Tools/psxcdgen_ex/src/encoder/psx.rs @@ -1,4 +1,4 @@ -use super::{*, Sector, SectorWriter, {CDDesc, Error}}; +use super::{*, SectorWriter, {CDDesc, Error}}; use super::super::types::{helper::PathTableMember, layout::Layout, *}; use builder::SubModeBuilder; use cdtypes::types::{cdstring::{AString, DString}, date::*, dir_record::DirectoryRecord, helper::sector_count_mode2_form1, path_table::*, pvd as cd_pvd, lsb_msb::*, sector::Mode2Form1}; @@ -72,7 +72,7 @@ pub fn calculate_psx_lbas(cd_desc: &mut CDDesc) { pub fn encode_psx_image(cd_desc: CDDesc, sec_writer: &mut dyn SectorWriter) -> Result<(), Error> { let vol_sector_count = cd_desc.vol_sector_count; - + for element in cd_desc.get_memory_layout() { match element { Layout::SystemArea(system_area) => process_system_area(&system_area.borrow(), sec_writer)?, @@ -93,7 +93,7 @@ fn process_system_area(system_area: &SystemArea, sec_writer: &mut dyn SectorWrit } for _ in 0..SYSTEM_AREA_SECTOR_COUNT { - sec_writer.write(Sector::CDXAData(builder::create_xa_data_zero()))?; + sec_writer.write_cd_xa_data(builder::create_xa_data_zero())?; } Ok(()) } @@ -138,22 +138,41 @@ fn process_pvd(pvd: &PrimaryVolumeDescriptor, path_table: SharedPtr, cd_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 PVD and VDT - sec_writer.write(Sector::CDXAData(builder::create_xa_data_for(SubModeBuilder::new_mode1().set_eor().create(), &cd_pvd)))?; - sec_writer.write(Sector::CDXAData(builder::create_xa_data_for(SubModeBuilder::new_mode1().set_eor().set_eof().create(), &cd_pvd::VolumeDescriptorTerminator::new())))?; + sec_writer.write_cd_xa_data(builder::create_xa_data_for(SubModeBuilder::new_mode1().set_eor().create(), &cd_pvd))?; + sec_writer.write_cd_xa_data(builder::create_xa_data_for(SubModeBuilder::new_mode1().set_eor().set_eof().create(), &cd_pvd::VolumeDescriptorTerminator::new()))?; Ok(()) } -fn process_path_table(path_table: &PathTable, root_dir: SharedPtr, _sec_writer: &mut dyn SectorWriter) -> Result<(), Error> { +fn process_path_table(path_table: &PathTable, root_dir: SharedPtr, sec_writer: &mut dyn SectorWriter) -> Result<(), Error> { + macro_rules! write_path_table_twice { + ($table:ident) => { + for sector in $table.clone() { + sec_writer.write_cd_xa_data(sector)?; + } + + for sector in $table { + sec_writer.write_cd_xa_data(sector)?; + } + }; + } let mut bytes_used = 0; let mut path_table_raw_l = vec![0u8; path_table.size_bytes]; let mut path_table_raw_b = vec![0u8; path_table.size_bytes]; - let path_table = PathTable::collect_member(root_dir); + validate_path_table(path_table)?; + let path_table = PathTable::collect_member(root_dir); + for entry in path_table { bytes_used += unsafe{update_path_table_entry(std::mem::transmute::<&mut u8, &mut PathTableL>(&mut path_table_raw_l[bytes_used]), std::mem::transmute::<&mut u8, &mut PathTableB>(&mut path_table_raw_b[bytes_used]), entry)?}; } - Err(Error::not_implemented("process_path_table")) + let path_table_l = builder::create_xa_data_for_vec(None, path_table_raw_l); + let path_table_b = builder::create_xa_data_for_vec(None, path_table_raw_b); + + write_path_table_twice!(path_table_l); + write_path_table_twice!(path_table_b); + + Ok(()) } fn validate_path_table(path_table: &PathTable) -> Result<(), Error> { diff --git a/src/Tools/psxcdgen_ex/src/file_writer/mod.rs b/src/Tools/psxcdgen_ex/src/file_writer/mod.rs index 5ebc971f..7d6f34b8 100644 --- a/src/Tools/psxcdgen_ex/src/file_writer/mod.rs +++ b/src/Tools/psxcdgen_ex/src/file_writer/mod.rs @@ -1,6 +1,6 @@ pub mod bin_cue; -pub use cdtypes::cd::sector::Sector; +pub use cdtypes::{cd::sector::Sector, types::*}; use super::{encoder::EncoderFunction, types::CDDesc}; use bin_cue::BinCueWriter; @@ -12,6 +12,26 @@ pub enum ImageType { } pub trait SectorWriter { + fn write_audio(&mut self, sector: sector::Audio) -> Result { + self.write(Sector::Audio(sector)) + } + + fn write_empty(&mut self, sector: sector::Mode0) -> Result { + self.write(Sector::Empty(sector)) + } + + fn write_cd_data(&mut self, sector: sector::Mode1) -> Result { + self.write(Sector::CDData(sector)) + } + + fn write_cd_xa_data(&mut self, sector: sector::Mode2Form1) -> Result { + self.write(Sector::CDXAData(sector)) + } + + fn write_cd_xa_audio(&mut self, sector: sector::Mode2Form2) -> Result { + self.write(Sector::CDXAAudio(sector)) + } + fn write(&mut self, sector: Sector) -> Result; }