Integrate all the progress into master #6
|
@ -3,7 +3,7 @@ PKG_OUTPUT ?= $(REGION)/$(ARTIFACT).pkg
|
|||
|
||||
$(CD_OUTPUT): always
|
||||
@mkdir -p $(REGION)
|
||||
psxcdgen_ex --list $(REGION)/$(ARTIFACT).lba -o $(REGION)/$(ARTIFACT) psx bin-cue Config.xml
|
||||
psxcdgen_ex --list $(REGION)/$(ARTIFACT).lba -o $(REGION)/$(ARTIFACT) bin-cue Config.xml
|
||||
|
||||
$(PKG_OUTPUT): always
|
||||
@mkdir -p $(REGION)
|
||||
|
|
|
@ -6,40 +6,59 @@ use tool_helper::{BufferedInputFile, format_if_error, open_input_file_buffered,
|
|||
use std::io::{Read, Seek, SeekFrom};
|
||||
|
||||
const ROOT_DIR_NAME:&'static str = "\x00";
|
||||
const SYSTEM_AREA_SECTOR_COUNT:usize = 16;
|
||||
const PVD_SECTOR_COUNT:usize = 2;
|
||||
|
||||
pub fn calculate_psx_length_for(element: &Layout) -> LengthInfo {
|
||||
match element {
|
||||
Layout::SystemArea(_) => LengthInfo{bytes: None, sectors: SYSTEM_AREA_SECTOR_COUNT},
|
||||
Layout::PVD(_) => LengthInfo{bytes: None, sectors: PVD_SECTOR_COUNT},
|
||||
Layout::PathTables(root, _) => {
|
||||
let path_table_size = PathTable::calculate_size_for(root.clone());
|
||||
LengthInfo{bytes: Some(path_table_size), sectors: sector_count_mode2_form1(path_table_size)}
|
||||
},
|
||||
Layout::Directory(dir) => {
|
||||
let dir = dir.borrow();
|
||||
let properties = dir.properties.borrow_mut();
|
||||
let size_bytes = properties.get_padded_size();
|
||||
pub mod length_of {
|
||||
use cdtypes::types::helper::{sector_count_mode2_form1, sector_count_mode2_form2};
|
||||
use crate::types::FileType;
|
||||
use super::{Directory, File, LengthInfo, PathTable};
|
||||
|
||||
pub const SYSTEM_AREA_SECTOR_COUNT:usize = 16;
|
||||
pub const PVD_SECTOR_COUNT:usize = 2;
|
||||
|
||||
return LengthInfo{bytes: Some(size_bytes), sectors: sector_count_mode2_form1(size_bytes)};
|
||||
},
|
||||
Layout::File(file) => {
|
||||
let file = file.borrow();
|
||||
let fake_size = file.properties.get_padded_size();
|
||||
pub const fn system_area() -> LengthInfo {
|
||||
LengthInfo{bytes: None, sectors: SYSTEM_AREA_SECTOR_COUNT}
|
||||
}
|
||||
|
||||
if matches!(file.content, FileType::XAAudio(_)) {
|
||||
return LengthInfo{bytes: Some(fake_size), sectors: sector_count_mode2_form2(fake_size)};
|
||||
}
|
||||
pub const fn pvd() -> LengthInfo {
|
||||
LengthInfo{bytes: None, sectors: PVD_SECTOR_COUNT}
|
||||
}
|
||||
|
||||
else {
|
||||
return LengthInfo{bytes: Some(fake_size), sectors: sector_count_mode2_form1(fake_size)};
|
||||
}
|
||||
pub fn path_tables(root: &Directory) -> LengthInfo {
|
||||
let path_table_size = PathTable::calculate_size_for(root);
|
||||
LengthInfo{bytes: Some(path_table_size), sectors: sector_count_mode2_form1(path_table_size)}
|
||||
}
|
||||
|
||||
pub fn directory(dir: &Directory) -> LengthInfo {
|
||||
let properties = dir.properties.borrow_mut();
|
||||
let size_bytes = properties.get_padded_size();
|
||||
|
||||
LengthInfo{bytes: Some(size_bytes), sectors: sector_count_mode2_form1(size_bytes)}
|
||||
}
|
||||
|
||||
pub fn file(file: &File) -> LengthInfo {
|
||||
let fake_size = file.properties.get_padded_size();
|
||||
|
||||
if matches!(file.content, FileType::XAAudio(_)) {
|
||||
LengthInfo{bytes: Some(fake_size), sectors: sector_count_mode2_form2(fake_size)}
|
||||
}
|
||||
|
||||
else {
|
||||
LengthInfo{bytes: Some(fake_size), sectors: sector_count_mode2_form1(fake_size)}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn calculate_psx_lbas(cd_desc: &mut CDDesc) {
|
||||
pub fn calculate_length_for(element: &Layout) -> LengthInfo {
|
||||
match element {
|
||||
Layout::SystemArea(_) => length_of::system_area(),
|
||||
Layout::PVD(_) => length_of::pvd(),
|
||||
Layout::PathTables(root, _) => length_of::path_tables(&root.borrow()),
|
||||
Layout::Directory(dir) => length_of::directory(&dir.borrow()),
|
||||
Layout::File(file) => length_of::file(&file.borrow()),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn calculate_lbas(cd_desc: &mut CDDesc) {
|
||||
let mut cur_lba = 0;
|
||||
let track_offset = LBA::FIRST_TRACK_OFFSET;
|
||||
|
||||
|
@ -52,7 +71,7 @@ pub fn calculate_psx_lbas(cd_desc: &mut CDDesc) {
|
|||
cur_lba + content_sector_size
|
||||
}
|
||||
|
||||
let element_size_info = calculate_psx_length_for(&element);
|
||||
let element_size_info = calculate_length_for(&element);
|
||||
match element {
|
||||
Layout::SystemArea(system_area) => {
|
||||
let mut system_area = system_area.borrow_mut();
|
||||
|
@ -101,7 +120,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> {
|
||||
pub fn encode_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() {
|
||||
|
@ -202,7 +221,7 @@ fn process_system_area(system_area: &SystemArea, sec_writer: &mut dyn SectorWrit
|
|||
else {
|
||||
// No license specified - filling it with zeros
|
||||
print_warning("WARNING: No license file provided. Some emulators (like No$PSX) will not boot this CD.".to_owned());
|
||||
write_dummy(sec_writer, SYSTEM_AREA_SECTOR_COUNT)
|
||||
write_dummy(sec_writer, length_of::SYSTEM_AREA_SECTOR_COUNT)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -267,7 +286,7 @@ fn process_path_table(path_table: &PathTable, root_dir: SharedPtr<Directory>, se
|
|||
let mut path_table_raw_b = vec![0u8; path_table.size_bytes];
|
||||
|
||||
validate_path_table(path_table)?;
|
||||
let path_table = PathTable::collect_member(root_dir);
|
||||
let path_table = PathTable::collect_member(&root_dir.borrow());
|
||||
|
||||
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)?};
|
|
@ -1,19 +1,9 @@
|
|||
use super::{file_writer::{SectorWriter}, types::{CDDesc, Error, layout::Layout}};
|
||||
use super::{file_writer::SectorWriter, types::{CDDesc, Error}};
|
||||
|
||||
pub mod psx;
|
||||
pub mod cd;
|
||||
pub mod builder;
|
||||
|
||||
pub type LengthCalculatorFunction = fn(&Layout) -> LengthInfo;
|
||||
pub type LbaCalculatorFunction = fn(&mut CDDesc);
|
||||
pub type ImageEncoderFunction = fn(&CDDesc, &mut dyn SectorWriter) -> Result<(), Error>;
|
||||
|
||||
pub struct LengthInfo {
|
||||
pub bytes: Option<usize>,
|
||||
pub sectors: usize,
|
||||
}
|
||||
|
||||
pub struct EncodingFunctions {
|
||||
pub length_calculator: LengthCalculatorFunction,
|
||||
pub lba_calculator: LbaCalculatorFunction,
|
||||
pub encoder: ImageEncoderFunction
|
||||
}
|
|
@ -4,7 +4,7 @@ pub use cdtypes::{cd::sector::Sector, types::*};
|
|||
use sector::Mode0;
|
||||
|
||||
use crate::types::helper::InterleavedXASector;
|
||||
use super::{encoder::ImageEncoderFunction, types::CDDesc};
|
||||
use super::{encoder::cd::encode_image, types::CDDesc};
|
||||
use bin_cue::BinCueWriter;
|
||||
use clap::ValueEnum;
|
||||
use std::path::PathBuf;
|
||||
|
@ -48,7 +48,7 @@ pub trait SectorWriter {
|
|||
fn cd_da_start(&mut self) -> Result<(), Error>;
|
||||
}
|
||||
|
||||
pub fn write_image(cd_desc: &CDDesc, encoder: ImageEncoderFunction, image_type: ImageType, mut output_path: PathBuf) -> Result<(), Error> {
|
||||
pub fn write_image(cd_desc: &CDDesc, image_type: ImageType, mut output_path: PathBuf) -> Result<(), Error> {
|
||||
match image_type {
|
||||
ImageType::BinCue => {
|
||||
output_path.set_extension("bin");
|
||||
|
@ -62,7 +62,7 @@ pub fn write_image(cd_desc: &CDDesc, encoder: ImageEncoderFunction, image_type:
|
|||
|
||||
let mut writer = BinCueWriter::new(open_output_file(&output_path)?, &output_path)?;
|
||||
|
||||
encoder(cd_desc, &mut writer)?;
|
||||
encode_image(cd_desc, &mut writer)?;
|
||||
// TODO: Write times here?!
|
||||
writer.write_cue(open_output_file(&cue_output_path)?)
|
||||
}
|
||||
|
|
|
@ -8,7 +8,7 @@ pub mod types;
|
|||
use crate::types::RawData;
|
||||
use cdtypes::types::sector::AudioSample;
|
||||
use config_reader::LZ4State;
|
||||
use encoder::{LbaCalculatorFunction, LengthCalculatorFunction};
|
||||
use encoder::cd::{calculate_lbas, calculate_length_for};
|
||||
use tool_helper::{format_if_error, Output, read_file};
|
||||
use types::{layout::Layout, CDDesc, Directory, File, FileType, FileSystemMap, Properties, SharedPtr};
|
||||
use std::path::PathBuf;
|
||||
|
@ -24,29 +24,29 @@ struct ContentDumpAlignment {
|
|||
|
||||
const DEFAULT_CONTENT_ALIGNMENT:ContentDumpAlignment = ContentDumpAlignment{name: 24, lba_pair: 16, size: 8, ex_size: 8};
|
||||
|
||||
pub fn process(config: config_reader::Configuration, calculate_lba: LbaCalculatorFunction) -> Result<(CDDesc, LBAEmbeddedFiles), Error> {
|
||||
pub fn process(config: config_reader::Configuration) -> Result<(CDDesc, LBAEmbeddedFiles), Error> {
|
||||
let (mut cd_desc, lba_embedded_files) = parse_configuration(config)?;
|
||||
|
||||
calculate_lba(&mut cd_desc);
|
||||
calculate_lbas(&mut cd_desc);
|
||||
Ok((cd_desc, lba_embedded_files))
|
||||
}
|
||||
|
||||
pub fn process_files(file_map: FileSystemMap, lba_embedded_files: LBAEmbeddedFiles, length_func: LengthCalculatorFunction) -> Result<(), Error> {
|
||||
pub fn process_files(file_map: FileSystemMap, lba_embedded_files: LBAEmbeddedFiles) -> Result<(), Error> {
|
||||
for lba_embedded_file_raw in lba_embedded_files {
|
||||
let new_content_info = {
|
||||
let mut lba_embedded_file = lba_embedded_file_raw.borrow_mut();
|
||||
|
||||
match &mut lba_embedded_file.content {
|
||||
FileType::Overlay(content, lba_names) => Some(types::overlay::update_content(content, lba_names, &file_map, length_func)?),
|
||||
FileType::Main(content, lba_names) => Some(types::overlay::update_content_for_main(content, lba_names, &file_map, length_func)?),
|
||||
FileType::Overlay(content, lba_names) => Some(types::overlay::update_content(content, lba_names, &file_map)?),
|
||||
FileType::Main(content, lba_names) => Some(types::overlay::update_content_for_main(content, lba_names, &file_map)?),
|
||||
_ => None
|
||||
}
|
||||
};
|
||||
|
||||
if let Some(new_content) = new_content_info {
|
||||
let old_size_info = length_func(&Layout::File(lba_embedded_file_raw.clone()));
|
||||
let old_size_info = calculate_length_for(&Layout::File(lba_embedded_file_raw.clone()));
|
||||
lba_embedded_file_raw.borrow_mut().make_regular(new_content);
|
||||
let new_size_info = length_func(&Layout::File(lba_embedded_file_raw.clone()));
|
||||
let new_size_info = calculate_length_for(&Layout::File(lba_embedded_file_raw.clone()));
|
||||
|
||||
if new_size_info.sectors != old_size_info.sectors {
|
||||
let lba_embedded_file = lba_embedded_file_raw.borrow();
|
||||
|
|
|
@ -1,14 +1,11 @@
|
|||
use clap::{Parser, ValueEnum};
|
||||
use psxcdgen_ex::{encoder::{EncodingFunctions, psx::{calculate_psx_lbas, calculate_psx_length_for, encode_psx_image}}, file_writer::{ImageType, write_image}, config_reader};
|
||||
use clap::Parser;
|
||||
use psxcdgen_ex::{file_writer::{ImageType, write_image}, config_reader};
|
||||
use std::path::PathBuf;
|
||||
use tool_helper::{Error, exit_with_error, read_file_to_string};
|
||||
|
||||
#[derive(Parser)]
|
||||
#[clap(about = "Creates an ISO image from a description file", long_about = None)]
|
||||
struct CommandLine {
|
||||
#[clap(value_enum, value_parser, help="Specifies the system for which to create the disc image")]
|
||||
system_type: SystemType,
|
||||
|
||||
#[clap(value_enum, value_parser, help="Specifies the disc image type")]
|
||||
output_type: ImageType,
|
||||
|
||||
|
@ -22,27 +19,13 @@ struct CommandLine {
|
|||
input_file: PathBuf,
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, ValueEnum)]
|
||||
enum SystemType {
|
||||
Psx
|
||||
}
|
||||
|
||||
impl SystemType {
|
||||
pub fn get_encoding_functions(self) -> EncodingFunctions {
|
||||
match self {
|
||||
SystemType::Psx => EncodingFunctions{length_calculator: calculate_psx_length_for, lba_calculator: calculate_psx_lbas, encoder: encode_psx_image}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn run_main(cmd_line: CommandLine) -> Result<(), Error> {
|
||||
const PKG_MINIMUM_CONTENT_SIZE:usize = 512*1024;
|
||||
|
||||
let encoding_functions = cmd_line.system_type.get_encoding_functions();
|
||||
let (mut desc, lba_embedded_files) = psxcdgen_ex::process(config_reader::parse_xml(read_file_to_string(&cmd_line.input_file)?)?, encoding_functions.lba_calculator)?;
|
||||
let (mut desc, lba_embedded_files) = psxcdgen_ex::process(config_reader::parse_xml(read_file_to_string(&cmd_line.input_file)?)?)?;
|
||||
let file_map = desc.create_file_map();
|
||||
|
||||
psxcdgen_ex::process_files(file_map, lba_embedded_files, encoding_functions.length_calculator)?;
|
||||
psxcdgen_ex::process_files(file_map, lba_embedded_files)?;
|
||||
let content_size = desc.get_content_size();
|
||||
if content_size < PKG_MINIMUM_CONTENT_SIZE {
|
||||
let missing_size = PKG_MINIMUM_CONTENT_SIZE - content_size;
|
||||
|
@ -50,7 +33,7 @@ fn run_main(cmd_line: CommandLine) -> Result<(), Error> {
|
|||
tool_helper::print_warning(format!("Content size {}b smaller then {}b.\nCD will be padded with {}b to work as a .pkg", content_size, PKG_MINIMUM_CONTENT_SIZE, missing_size));
|
||||
}
|
||||
|
||||
write_image(&desc, encoding_functions.encoder, cmd_line.output_type, cmd_line.output_file)?;
|
||||
write_image(&desc, cmd_line.output_type, cmd_line.output_file)?;
|
||||
|
||||
if let Some(list_content_option) = cmd_line.list_content {
|
||||
psxcdgen_ex::dump_content(&desc, tool_helper::open_output(&list_content_option)?)
|
||||
|
|
|
@ -54,7 +54,7 @@ impl DirectoryRecordMember {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn collect_path_table_member(root: SharedPtr<Directory>) -> Vec<PathTableMember> {
|
||||
pub fn collect_path_table_member(root: &Directory) -> Vec<PathTableMember> {
|
||||
fn collect_path_table_for(collection: &mut Vec<PathTableMember>, dirs: &Vec<SharedPtr<Directory>>, parent_id: usize) {
|
||||
let mut cur_dirs = Vec::new();
|
||||
|
||||
|
@ -76,7 +76,6 @@ pub fn collect_path_table_member(root: SharedPtr<Directory>) -> Vec<PathTableMem
|
|||
}
|
||||
}
|
||||
let mut collection = Vec::new();
|
||||
let root = root.borrow();
|
||||
|
||||
collection.push(PathTableMember{name: CURRENT_DIR_NAME.to_owned(), track_rel_lba: root.get_track_rel_lba(), parent_table_id: 1});
|
||||
collect_path_table_for(&mut collection, &root.dirs, 1);
|
||||
|
|
|
@ -118,11 +118,11 @@ impl PathTable {
|
|||
PathTable{lba: LBA::default(), size_bytes: 0}
|
||||
}
|
||||
|
||||
pub fn collect_member(root: SharedPtr<Directory>) -> Vec<helper::PathTableMember> {
|
||||
pub fn collect_member(root: &Directory) -> Vec<helper::PathTableMember> {
|
||||
helper::collect_path_table_member(root)
|
||||
}
|
||||
|
||||
pub fn calculate_size_for(root: SharedPtr<Directory>) -> usize {
|
||||
pub fn calculate_size_for(root: &Directory) -> usize {
|
||||
let mut size_bytes = 0;
|
||||
|
||||
Self::collect_member(root).into_iter().for_each(|element| {
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
use super::RawData;
|
||||
use super::{layout::Layout, File, FileSystemMap};
|
||||
use super::super::encoder::LengthCalculatorFunction;
|
||||
use super::super::encoder::cd::calculate_length_for;
|
||||
use std::path::PathBuf;
|
||||
use no_comment::{IntoWithoutComments as _, languages};
|
||||
use tool_helper::{bits::{Bit, BitRange}, Error, format_if_error, read_file, read_file_to_string, format_if_error_drop_cause};
|
||||
|
@ -57,28 +57,28 @@ pub fn load_for_main(file_name: &str, content: RawData, lba_source: PathBuf) ->
|
|||
File::new_main(file_name, content, load_lba_names(lba_source)?)
|
||||
}
|
||||
|
||||
pub fn update_content(content: &mut RawData, lba_names: &LBANameVec, file_map: &FileSystemMap, length_func: LengthCalculatorFunction) -> Result<RawData, Error> {
|
||||
pub fn update_content(content: &mut RawData, lba_names: &LBANameVec, file_map: &FileSystemMap) -> Result<RawData, Error> {
|
||||
let lba_header = skip_to_lba_header(content);
|
||||
let lba_header = unsafe{std::slice::from_raw_parts_mut(lba_header.as_mut_ptr() as *mut LBAEntry, lba_names.len())};
|
||||
|
||||
for_each_lba_name(lba_names, file_map, length_func, |idx, (lba, bytes), is_lz4| {
|
||||
for_each_lba_name(lba_names, file_map, |idx, (lba, bytes), is_lz4| {
|
||||
lba_header[idx].write_entry(lba, bytes, is_lz4)
|
||||
})?;
|
||||
|
||||
Ok(tool_helper::compress::psx_default::lz4(content)?)
|
||||
}
|
||||
|
||||
pub fn update_content_for_main(content: &mut RawData, lba_names: &LBANameVec, file_map: &FileSystemMap, length_func: LengthCalculatorFunction) -> Result<RawData, Error> {
|
||||
pub fn update_content_for_main(content: &mut RawData, lba_names: &LBANameVec, file_map: &FileSystemMap) -> Result<RawData, Error> {
|
||||
let lba_header = unsafe{std::slice::from_raw_parts_mut(main::skip_to_lba_area(content).as_mut_ptr() as *mut LBAEntry, lba_names.len())};
|
||||
|
||||
for_each_lba_name(lba_names, file_map, length_func, |idx, (lba, bytes), is_lz4| {
|
||||
for_each_lba_name(lba_names, file_map, |idx, (lba, bytes), is_lz4| {
|
||||
lba_header[idx].write_entry(lba, bytes, is_lz4)
|
||||
})?;
|
||||
|
||||
Ok(content.clone())
|
||||
}
|
||||
|
||||
fn for_each_lba_name<F: FnMut(usize, (usize, usize), bool) -> Result<(), Error>>(lba_names: &LBANameVec, file_map: &FileSystemMap, length_func: LengthCalculatorFunction, mut functor: F) -> Result<(), Error> {
|
||||
fn for_each_lba_name<F: FnMut(usize, (usize, usize), bool) -> Result<(), Error>>(lba_names: &LBANameVec, file_map: &FileSystemMap, mut functor: F) -> Result<(), Error> {
|
||||
let mut idx = 0;
|
||||
for lba_name in lba_names {
|
||||
if let Some(file) = file_map.get(lba_name) {
|
||||
|
@ -90,7 +90,7 @@ fn for_each_lba_name<F: FnMut(usize, (usize, usize), bool) -> Result<(), Error>>
|
|||
}
|
||||
|
||||
else {
|
||||
length_func(&Layout::File(file.clone())).bytes
|
||||
calculate_length_for(&Layout::File(file.clone())).bytes
|
||||
}
|
||||
});
|
||||
let is_lz4 = file_ref.properties.is_lz4;
|
||||
|
|
Loading…
Reference in New Issue