Support writing LBA information into main file

This commit is contained in:
Björn Gaier 2023-02-03 13:22:17 +01:00
parent aeb09855ff
commit bc6e483bcf
7 changed files with 97 additions and 47 deletions

View File

@ -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<int>(enum_struct::EndOfRequest)] = {0}
const volatile JabyEngine::AutoLBAEntry __section(".header.lbas") lba[static_cast<int>(enum_struct::EndOfRequest)] = {0}
#endif //!__JABYENGINE_AUTO_LBA_DECLARATION_HPP__

View File

@ -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<File, Error> {
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<File, Error> {
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<File, Error> {
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<PathBuf, Error> {
if let Some(path) = node.text() {
Ok(path_with_env_from(path))
}
else {
Err(Error::from_text(format!("No path specified for {}", name)))
}
}

View File

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

View File

@ -0,0 +1,5 @@
pub fn skip_to_lba_area(content: &mut Vec<u8>) -> &mut [u8] {
const PSX_HEADER_SIZE:usize = 2048;
&mut content[PSX_HEADER_SIZE..]
}

View File

@ -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<String>;
mod main;
#[repr(packed)]
struct OverlayHeader {
_start_adr: u32,
@ -60,16 +62,34 @@ pub fn update_content(content: &mut Vec<u8>, 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<u8>, lba_names: &LBANameVec, file_map: &FileSystemMap, length_func: LengthCalculatorFunction) -> Result<Vec<u8>, 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<F: FnMut(usize, (u16, usize)) -> 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<u8>, lba_names: &LBANameVec, file_map: &
}
}
Ok(tool_helper::compress::psx_default::lz4(content)?)
Ok(())
}
fn load_content(file_path: &PathBuf) -> Result<Vec<u8>, Error> {

View File

@ -8,5 +8,6 @@ edition = "2021"
[dependencies]
byteorder = "*"
cdtypes = {path = "../cdtypes"}
envmnt = "*"
lz4 = "*"
paste = "*"

View File

@ -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<F: Fn(String) -> 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<BufWriter<std::fs::File>, Error> {
Ok(std::io::BufWriter::new(std::fs::File::create(output_path)?))
}