use super::{*, Sector, SectorWriter, {CDDesc, Error}}; use super::super::types::{layout::Layout, *}; use builder::SubModeBuilder; use cdtypes::types::{cdstring::{AString, DString}, date::Date, helper::sector_count_mode2_form1, pvd as cd_pvd, lsb_msb::*, sector::Mode2Form1}; const SYSTEM_AREA_SECTOR_COUNT:usize = 16; const PVD_SECTOR_COUNT:usize = 2; pub fn calculate_psx_lbas(cd_desc: &mut CDDesc) { let path_table_size = PathTable::calculate_size_for(cd_desc.root.clone()); let mut cur_lba = 0; cd_desc.vol_sector_count = 0; CDDesc::for_each_dir_mut(cd_desc.root.clone(), &|dir| {dir.update_content_size();}); for element in cd_desc.get_memory_layout() { fn update_lba(properties: &mut Properties, cur_lba: usize, content_sector_size: usize) -> usize { properties.track_rel_lba = cur_lba; cur_lba + content_sector_size } match element { Layout::SystemArea(system_area) => { let mut system_area = system_area.borrow_mut(); system_area.track_rel_lba = cur_lba; cur_lba += SYSTEM_AREA_SECTOR_COUNT; }, Layout::PVD(pvd) => { let mut pvd = pvd.borrow_mut(); pvd.track_rel_lba = cur_lba; cur_lba += PVD_SECTOR_COUNT; }, Layout::PathTables(path_table) => { let mut path_table = path_table.borrow_mut(); path_table.track_rel_lba = cur_lba; path_table.size_bytes = path_table_size; cur_lba += sector_count_mode2_form1(path_table.size_bytes)*4; }, Layout::Directory(dir) => { let sector_count = sector_count_mode2_form1(dir.borrow().get_size()); let mut dir = dir.borrow_mut(); cd_desc.vol_sector_count += sector_count; cur_lba = update_lba(&mut dir.properties, cur_lba, sector_count); }, Layout::File(file) => { let sector_count = { let file = file.borrow(); let fake_size = file.get_size(); sector_count_mode2_form1(fake_size) }; let mut file = file.borrow_mut(); cd_desc.vol_sector_count += sector_count; cur_lba = update_lba(&mut file.properties, cur_lba, sector_count); } } println!("cur_lba: {}", cur_lba); } } 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)?, Layout::PVD(pvd) => process_pvd(&pvd.borrow(), cd_desc.path_table.clone(), sec_writer, vol_sector_count)?, _ => () } } //Err(Error::not_implemented("encode_psx_image")) Ok(()) } fn process_system_area(system_area: &SystemArea, sec_writer: &mut dyn SectorWriter) -> Result<(), Error> { let system_area_lba = system_area.track_rel_lba; if system_area_lba != 0 { return Err(Error::from_text(format!("System Area required to start at sector 0 of Track - found LBA: {}", system_area_lba))); } for _ in 0..SYSTEM_AREA_SECTOR_COUNT { sec_writer.write(Sector::CDXAData(builder::create_xa_data_zero()))?; } Ok(()) } fn process_pvd(pvd: &PrimaryVolumeDescriptor, path_table: SharedPtr, sec_writer: &mut dyn SectorWriter, vol_sector_count: usize) -> Result<(), Error> { const PLAYSATATION_STR:&'static str = "PLAYSTATION"; let path_table = validate_path_table(&path_table)?; let pvd_lba = pvd.track_rel_lba; if pvd_lba != 16 { return Err(Error::from_text(format!("PVD required to start at sector 16 of Track - found LBA: {}", pvd_lba))); } let mut cd_pvd = cd_pvd::PrimaryVolumeDescriptor::new(); let now = Date::now(); //Config pvd here cd_pvd.system_id = AString::from_str(PLAYSATATION_STR)?; cd_pvd.volume_id = DString::from_str("PSX")?; cd_pvd.vol_space_size.write(vol_sector_count as u32); cd_pvd.path_table_size.write(path_table.size_bytes as u32); cd_pvd.path_table_1.write(path_table.get_track_rel_lba_for(1, sector_count_mode2_form1) as u32); cd_pvd.path_table_2.write(path_table.get_track_rel_lba_for(2, sector_count_mode2_form1) as u32); cd_pvd.path_table_3.write(path_table.get_track_rel_lba_for(3, sector_count_mode2_form1) as u32); cd_pvd.path_table_4.write(path_table.get_track_rel_lba_for(4, sector_count_mode2_form1) as u32); &cd_pvd.root_dir_record; cd_pvd.publisher_id = AString::from_str(pvd.publisher.as_str())?; cd_pvd.data_preparer = AString::from_str("JABYENGINE PSXCDGEN_EX")?; cd_pvd.app_id = AString::from_str(PLAYSATATION_STR)?; cd_pvd.vol_create_time = now; 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]; 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())))?; Ok(()) } fn validate_path_table(path_table: &SharedPtr) -> Result, Error> { let path_table = path_table.borrow(); if path_table.size_bytes > Mode2Form1::DATA_SIZE { Err(Error::from_text(format!("Path Tables are not allowed to be bigger then {} bytes - Path Table has {} bytes", Mode2Form1::DATA_SIZE, path_table.size_bytes))) } else { Ok(path_table) } }