Support writing LBA information into main file
This commit is contained in:
parent
aeb09855ff
commit
bc6e483bcf
|
@ -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__
|
|
@ -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)))
|
||||
}
|
||||
}
|
|
@ -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
|
||||
}
|
||||
};
|
||||
|
|
|
@ -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..]
|
||||
}
|
|
@ -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> {
|
||||
|
|
|
@ -8,5 +8,6 @@ edition = "2021"
|
|||
[dependencies]
|
||||
byteorder = "*"
|
||||
cdtypes = {path = "../cdtypes"}
|
||||
envmnt = "*"
|
||||
lz4 = "*"
|
||||
paste = "*"
|
|
@ -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)?))
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue