From 53b01f19b1767f0ed1dea8cfcd95fe916392dcce Mon Sep 17 00:00:00 2001 From: Jaby Date: Fri, 3 Feb 2023 13:22:17 +0100 Subject: [PATCH] Support writing LBA information into main file --- include/PSX/AutoLBA/auto_lba_declaration.hpp | 4 +- .../psxcdgen_ex/src/config_reader/xml.rs | 69 +++++++++++-------- src/Tools/psxcdgen_ex/src/lib.rs | 10 +-- .../psxcdgen_ex/src/types/overlay/main.rs | 5 ++ .../psxcdgen_ex/src/types/overlay/mod.rs | 36 +++++++--- src/Tools/tool_helper/Cargo.toml | 1 + src/Tools/tool_helper/src/lib.rs | 19 +++++ 7 files changed, 97 insertions(+), 47 deletions(-) create mode 100644 src/Tools/psxcdgen_ex/src/types/overlay/main.rs diff --git a/include/PSX/AutoLBA/auto_lba_declaration.hpp b/include/PSX/AutoLBA/auto_lba_declaration.hpp index d43e08ca..ae8fea74 100644 --- a/include/PSX/AutoLBA/auto_lba_declaration.hpp +++ b/include/PSX/AutoLBA/auto_lba_declaration.hpp @@ -1,9 +1,9 @@ #ifndef __JABYENGINE_AUTO_LBA_DECLARATION_HPP__ #define __JABYENGINE_AUTO_LBA_DECLARATION_HPP__ -extern const JabyEngine::AutoLBAEntry lba[]; +extern const volatile JabyEngine::AutoLBAEntry lba[]; #define __declare_lba_header(enum_struct) \ [[gnu::used]] \ -const JabyEngine::AutoLBAEntry __section(".header.lbas") lba[static_cast(enum_struct::EndOfRequest)] = {0} +const volatile JabyEngine::AutoLBAEntry __section(".header.lbas") lba[static_cast(enum_struct::EndOfRequest)] = {0} #endif //!__JABYENGINE_AUTO_LBA_DECLARATION_HPP__ \ No newline at end of file diff --git a/src/Tools/psxcdgen_ex/src/config_reader/xml.rs b/src/Tools/psxcdgen_ex/src/config_reader/xml.rs index 2646efdf..9f6c49bc 100644 --- a/src/Tools/psxcdgen_ex/src/config_reader/xml.rs +++ b/src/Tools/psxcdgen_ex/src/config_reader/xml.rs @@ -1,5 +1,5 @@ use std::path::PathBuf; -use tool_helper::format_if_error; +use tool_helper::{format_if_error, path_with_env_from}; use crate::config_reader::Directory; use super::{CommonProperties, Configuration, Error, File, FileKind}; @@ -30,7 +30,23 @@ fn parse_iso_project(iso_project: roxmltree::Node, config: &mut Configuration) - if node.is_element() { match node.tag_name().name() { "Description" => parse_description(node, config), - "Track" => parse_track(node, config)?, + "Track" => parse_track(node, config), + _ => Ok(()) + }?; + } + } + + Ok(()) +} + +fn parse_description(description: roxmltree::Node, config: &mut Configuration) -> Result<(), Error> { + const LICENSE_STR:&str = "License"; + + for node in description.descendants() { + if node.is_element() { + match node.tag_name().name() { + "Publisher" => config.publisher = Some(String::from(node.text().unwrap_or_default())), + LICENSE_STR => config.license_path = Some(path_from_node(&node, LICENSE_STR)?), _ => () } } @@ -39,34 +55,20 @@ fn parse_iso_project(iso_project: roxmltree::Node, config: &mut Configuration) - Ok(()) } -fn parse_description(description: roxmltree::Node, config: &mut Configuration) { - for node in description.descendants() { - if node.is_element() { - match node.tag_name().name() { - "Publisher" => config.publisher = Some(String::from(node.text().unwrap_or_default())), - "License" => config.license_path = Some(PathBuf::from(node.text().unwrap_or_default())), - _ => () - } - } - } -} - fn parse_track(track: roxmltree::Node, config: &mut Configuration) -> Result<(), Error> { fn parse_regular_file(file: roxmltree::Node, is_hidden: bool) -> Result { - Ok(File{ - common: read_common_properties(&file, is_hidden)?, - path: PathBuf::from(file.text().unwrap_or_default()), - kind: FileKind::Regular - }) + let common = read_common_properties(&file, is_hidden)?; + let path = path_from_node(&file, &common.name)?; + + Ok(File{common, path, kind: FileKind::Regular}) } fn parse_main_file(file: roxmltree::Node, is_hidden: bool) -> Result { if let Some(lba_path) = file.attribute(attribute_names::LBA_SOURCE) { - Ok(File{ - common: read_common_properties(&file, is_hidden)?, - path: PathBuf::from(file.text().unwrap_or_default()), - kind: FileKind::Main(PathBuf::from(lba_path)) - }) + let common = read_common_properties(&file, is_hidden)?; + let path = path_from_node(&file, &common.name)?; + + Ok(File{common, path, kind: FileKind::Main(PathBuf::from(lba_path))}) } else { @@ -75,11 +77,10 @@ fn parse_track(track: roxmltree::Node, config: &mut Configuration) -> Result<(), } fn parse_overlay_file(file: roxmltree::Node, is_hidden: bool) -> Result { - Ok(File{ - common: read_common_properties(&file, is_hidden)?, - path: PathBuf::from(file.text().unwrap_or_default()), - kind: FileKind::Overlay(PathBuf::from(file.attribute(attribute_names::LBA_SOURCE).unwrap_or_default())), - }) + let common = read_common_properties(&file, is_hidden)?; + let path = path_from_node(&file, &common.name)?; + + Ok(File{common, path, kind: FileKind::Overlay(PathBuf::from(file.attribute(attribute_names::LBA_SOURCE).unwrap_or_default()))}) } fn parse_file_system(cur_node: roxmltree::Node, root: &mut Directory, mut is_hidden: bool) -> Result<(), Error> { @@ -140,4 +141,14 @@ fn parse_boolean_attribute(xml: &roxmltree::Node, attribute_name: &str) -> Resul else { Ok(false) } +} + +fn path_from_node(node: &roxmltree::Node, name: &str) -> Result { + if let Some(path) = node.text() { + Ok(path_with_env_from(path)) + } + + else { + Err(Error::from_text(format!("No path specified for {}", name))) + } } \ No newline at end of file diff --git a/src/Tools/psxcdgen_ex/src/lib.rs b/src/Tools/psxcdgen_ex/src/lib.rs index 68205d2d..b48b843f 100644 --- a/src/Tools/psxcdgen_ex/src/lib.rs +++ b/src/Tools/psxcdgen_ex/src/lib.rs @@ -33,14 +33,8 @@ pub fn process_files(file_map: FileSystemMap, lba_embedded_files: LBAEmbeddedFil let mut lba_embedded_file = lba_embedded_file_raw.borrow_mut(); match &mut lba_embedded_file.content { - FileType::Overlay(content, lba_names) => { - let new_content = types::overlay::update_content(content, lba_names, &file_map, length_func)?; - - Some(new_content) - }, - FileType::Main(_, _) => { - return Err(Error::not_implemented("process_files => FileType::Main")); - }, + 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)?), _ => None } }; diff --git a/src/Tools/psxcdgen_ex/src/types/overlay/main.rs b/src/Tools/psxcdgen_ex/src/types/overlay/main.rs new file mode 100644 index 00000000..8e162849 --- /dev/null +++ b/src/Tools/psxcdgen_ex/src/types/overlay/main.rs @@ -0,0 +1,5 @@ +pub fn skip_to_lba_area(content: &mut Vec) -> &mut [u8] { + const PSX_HEADER_SIZE:usize = 2048; + + &mut content[PSX_HEADER_SIZE..] +} \ No newline at end of file diff --git a/src/Tools/psxcdgen_ex/src/types/overlay/mod.rs b/src/Tools/psxcdgen_ex/src/types/overlay/mod.rs index a1e8cddf..da453ceb 100644 --- a/src/Tools/psxcdgen_ex/src/types/overlay/mod.rs +++ b/src/Tools/psxcdgen_ex/src/types/overlay/mod.rs @@ -2,10 +2,12 @@ use super::{layout::Layout, File, FileSystemMap}; use super::super::encoder::LengthCalculatorFunction; use std::path::PathBuf; use no_comment::{IntoWithoutComments as _, languages}; -use tool_helper::{Error, format_if_error, read_file}; +use tool_helper::{Error, format_if_error, read_file, format_if_error_drop_cause}; pub type LBANameVec = Vec; +mod main; + #[repr(packed)] struct OverlayHeader { _start_adr: u32, @@ -60,16 +62,34 @@ pub fn update_content(content: &mut Vec, lba_names: &LBANameVec, file_map: & let (lba_header, lba_count) = skip_to_lba_header(content); let lba_header = unsafe{std::slice::from_raw_parts_mut(lba_header.as_mut_ptr() as *mut LBAEntry, lba_count)}; + for_each_lba_name(lba_names, file_map, length_func, |idx, (lba, bytes)| { + if idx >= lba_count { + return Err(Error::from_text(format!("Trying to write more LBAs then there is space!"))); + } + + lba_header[idx].write_entry(lba, bytes) + })?; + + Ok(tool_helper::compress::psx_default::lz4(content)?) +} + +pub fn update_content_for_main(content: &mut Vec, lba_names: &LBANameVec, file_map: &FileSystemMap, length_func: LengthCalculatorFunction) -> Result, 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)| { + lba_header[idx].write_entry(lba, bytes) + })?; + + Ok(content.clone()) +} + +fn for_each_lba_name Result<(), Error>>(lba_names: &LBANameVec, file_map: &FileSystemMap, length_func: LengthCalculatorFunction, mut functor: F) -> Result<(), Error> { let mut idx = 0; for lba_name in lba_names { if let Some(file) = file_map.get(lba_name) { - let (lba, bytes) = (file.borrow().get_track_rel_lba(), length_func(&Layout::File(file.clone())).bytes); + let (lba, bytes) = (format_if_error_drop_cause!(file.try_borrow(), "Failed accessing file \"{}\" for writing LBA information.\nNote: You can not inject the LBA information of a file into itself.", lba_name)?.get_track_rel_lba(), length_func(&Layout::File(file.clone())).bytes); - if idx >= lba_count { - return Err(Error::from_text(format!("Trying to write more LBAs then there is space!"))); - } - - lba_header[idx].write_entry(lba as u16, bytes.ok_or(Error::from_text(format!("{} does not contain a size!", lba_name)))?)?; + functor(idx, (lba as u16, bytes.ok_or(Error::from_text(format!("{} does not contain a size!", lba_name)))?))?; idx += 1; } @@ -78,7 +98,7 @@ pub fn update_content(content: &mut Vec, lba_names: &LBANameVec, file_map: & } } - Ok(tool_helper::compress::psx_default::lz4(content)?) + Ok(()) } fn load_content(file_path: &PathBuf) -> Result, Error> { diff --git a/src/Tools/tool_helper/Cargo.toml b/src/Tools/tool_helper/Cargo.toml index 80ab4565..4a0c80a7 100644 --- a/src/Tools/tool_helper/Cargo.toml +++ b/src/Tools/tool_helper/Cargo.toml @@ -8,5 +8,6 @@ edition = "2021" [dependencies] byteorder = "*" cdtypes = {path = "../cdtypes"} +envmnt = "*" lz4 = "*" paste = "*" \ No newline at end of file diff --git a/src/Tools/tool_helper/src/lib.rs b/src/Tools/tool_helper/src/lib.rs index 706053c1..105e214c 100644 --- a/src/Tools/tool_helper/src/lib.rs +++ b/src/Tools/tool_helper/src/lib.rs @@ -1,4 +1,5 @@ use std::{boxed::Box, io::{BufReader, BufWriter, Read, Write}, path::PathBuf}; +use envmnt::{ExpandOptions, ExpansionType}; pub mod bits; pub mod compress; @@ -22,6 +23,20 @@ macro_rules! format_if_error { }; } +#[macro_export] +macro_rules! format_if_error_drop_cause { + ($result:expr, $format_text:literal) => { + tool_helper::callback_if_any_error($result, |error_text| { + format!($format_text) + }) + }; + ($result:expr, $format_text:literal, $($arg:expr)*) => { + tool_helper::callback_if_any_error($result, |error_text| { + format!($format_text, $($arg),*) + }) + }; +} + pub struct Error { pub exit_code: i32, pub text: String, @@ -123,6 +138,10 @@ pub fn callback_if_any_error String, T, E: std::string::ToStrin } } +pub fn path_with_env_from(path: &str) -> PathBuf { + PathBuf::from(envmnt::expand(path, Some(ExpandOptions{expansion_type: Some(ExpansionType::All), default_to_empty: false}))) +} + pub fn open_output_file(output_path: &PathBuf) -> Result, Error> { Ok(std::io::BufWriter::new(std::fs::File::create(output_path)?)) }