Parse and write PathTable

This commit is contained in:
jaby 2022-10-25 19:56:50 +02:00
parent 6ee4b7103f
commit 469bce16ab
4 changed files with 99 additions and 11 deletions

View File

@ -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<T>(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<SubMode>, data: Vec<u8>) -> Vec<Mode2Form1> {
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()]
}

View File

@ -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;

View File

@ -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<PathTable>,
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<Directory>, _sec_writer: &mut dyn SectorWriter) -> Result<(), Error> {
fn process_path_table(path_table: &PathTable, root_dir: SharedPtr<Directory>, 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> {

View File

@ -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<usize, Error> {
self.write(Sector::Audio(sector))
}
fn write_empty(&mut self, sector: sector::Mode0) -> Result<usize, Error> {
self.write(Sector::Empty(sector))
}
fn write_cd_data(&mut self, sector: sector::Mode1) -> Result<usize, Error> {
self.write(Sector::CDData(sector))
}
fn write_cd_xa_data(&mut self, sector: sector::Mode2Form1) -> Result<usize, Error> {
self.write(Sector::CDXAData(sector))
}
fn write_cd_xa_audio(&mut self, sector: sector::Mode2Form2) -> Result<usize, Error> {
self.write(Sector::CDXAAudio(sector))
}
fn write(&mut self, sector: Sector) -> Result<usize, Error>;
}