Prepare new LBA representation
This commit is contained in:
42
src/Tools/psxcdgen_ex/src/types/bits.rs
Normal file
42
src/Tools/psxcdgen_ex/src/types/bits.rs
Normal file
@@ -0,0 +1,42 @@
|
||||
pub struct BitRange {
|
||||
start: usize,
|
||||
length: usize
|
||||
}
|
||||
|
||||
impl BitRange {
|
||||
pub const fn from_to(start_bit: usize, end_bit: usize) -> Self {
|
||||
Self{start: start_bit, length: (end_bit - start_bit) + 1}
|
||||
}
|
||||
|
||||
pub const fn get_mask(&self) -> usize {
|
||||
self.max_value()
|
||||
}
|
||||
|
||||
pub const fn max_value(&self) -> usize {
|
||||
(1 << self.length) - 1
|
||||
}
|
||||
|
||||
pub const fn or_value(&self, dst_value: usize, value: usize) -> usize {
|
||||
dst_value | ((value & self.get_mask()) << self.start)
|
||||
}
|
||||
}
|
||||
|
||||
pub struct Bit {
|
||||
pos: usize
|
||||
}
|
||||
|
||||
impl Bit {
|
||||
pub const fn at(pos: usize) -> Self {
|
||||
Bit{pos}
|
||||
}
|
||||
|
||||
pub const fn or_value(&self, dst_value: usize, is_set: bool) -> usize {
|
||||
if is_set {
|
||||
dst_value | (1 << self.pos)
|
||||
}
|
||||
|
||||
else {
|
||||
dst_value
|
||||
}
|
||||
}
|
||||
}
|
@@ -1,3 +1,4 @@
|
||||
pub mod bits;
|
||||
pub (super) mod helper;
|
||||
pub mod layout;
|
||||
pub mod file_map;
|
||||
|
@@ -1,4 +1,4 @@
|
||||
use super::{layout::Layout, File, FileSystemMap};
|
||||
use super::{bits::{Bit, BitRange}, layout::Layout, File, FileSystemMap};
|
||||
use super::super::encoder::LengthCalculatorFunction;
|
||||
use std::path::PathBuf;
|
||||
use no_comment::{IntoWithoutComments as _, languages};
|
||||
@@ -8,32 +8,39 @@ pub type LBANameVec = Vec<String>;
|
||||
|
||||
mod main;
|
||||
|
||||
/*
|
||||
Size in sectors [22, 31];
|
||||
Is LZ4 compressed [19];
|
||||
LBA value [0, 18]
|
||||
*/
|
||||
#[repr(packed)]
|
||||
struct LBAEntry {
|
||||
lba: u16,
|
||||
size_words: u16,
|
||||
raw: u32,
|
||||
}
|
||||
|
||||
impl LBAEntry {
|
||||
pub fn write_entry(&mut self, lba: u16, mut size_bytes: usize) -> Result<(), Error> {
|
||||
const WORD_SIZE:usize = std::mem::size_of::<u32>();
|
||||
const SIZE_IN_SECTOR_RANGE:BitRange = BitRange::from_to(22, 31);
|
||||
const _IS_LZ4_COMPRESSED:Bit = Bit::at(19);
|
||||
const LBA_VALUE_RANGE:BitRange = BitRange::from_to(0, 18);
|
||||
|
||||
if self.lba != 0 || self.size_words != 0 {
|
||||
pub fn write_entry(&mut self, lba: usize, size_bytes: usize) -> Result<(), Error> {
|
||||
if lba > Self::LBA_VALUE_RANGE.max_value() {
|
||||
return Err(Error::from_text(format!("LBA of value {} is impossible and can not be encoded! Maximum LBA value is: {}", lba, Self::LBA_VALUE_RANGE.max_value())));
|
||||
}
|
||||
|
||||
let size_in_sectors = cdtypes::types::helper::sector_count_mode2_form1(size_bytes);
|
||||
if size_in_sectors > Self::SIZE_IN_SECTOR_RANGE.max_value() {
|
||||
return Err(Error::from_text(format!("{} sectors can not be encoded into 10bit", size_in_sectors)));
|
||||
}
|
||||
|
||||
let lba = usize::from_ne_bytes(lba.to_le_bytes());
|
||||
let size_in_sectors = usize::from_ne_bytes(size_in_sectors.to_le_bytes());
|
||||
|
||||
if self.raw != 0 {
|
||||
return Err(Error::from_str("LBA Entry will overwrite non-zero value!\nIs no space allocated for the LBA Entries?"));
|
||||
}
|
||||
|
||||
size_bytes = (size_bytes + (WORD_SIZE - 1))/WORD_SIZE;
|
||||
|
||||
if (size_bytes as u16) as usize != size_bytes {
|
||||
return Err(Error::from_text(format!("{} words can not be encoded into 16bit", size_bytes)));
|
||||
}
|
||||
|
||||
let lba = lba.to_le_bytes();
|
||||
let size_bytes = (size_bytes as u16).to_le_bytes();
|
||||
|
||||
self.lba = u16::from_ne_bytes(lba);
|
||||
self.size_words = u16::from_ne_bytes(size_bytes);
|
||||
|
||||
self.raw = Self::SIZE_IN_SECTOR_RANGE.or_value(Self::LBA_VALUE_RANGE.or_value(0, lba), size_in_sectors) as u32;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
@@ -71,13 +78,13 @@ pub fn update_content_for_main(content: &mut Vec<u8>, lba_names: &LBANameVec, fi
|
||||
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> {
|
||||
fn for_each_lba_name<F: FnMut(usize, (usize, 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) = (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_absolute_lba(), length_func(&Layout::File(file.clone())).bytes);
|
||||
|
||||
functor(idx, (lba as u16, bytes.ok_or(Error::from_text(format!("{} does not contain a size!", lba_name)))?))?;
|
||||
functor(idx, (lba, bytes.ok_or(Error::from_text(format!("{} does not contain a size!", lba_name)))?))?;
|
||||
idx += 1;
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user