From a2c7af2e12ea1a04c35022004cc707e0e345dec6 Mon Sep 17 00:00:00 2001 From: Jaby Date: Wed, 12 Apr 2023 21:59:36 +0200 Subject: [PATCH] Prepare new LBA representation --- include/PSX/AutoLBA/auto_lba.hpp | 34 ++++++++++++-- .../internal-include/CD/cd_internal.hpp | 2 +- src/Library/internal-include/CD/cd_types.hpp | 19 ++------ src/Library/src/CD/cd.cpp | 14 +++--- .../src/File/Processor/cd_file_processor.cpp | 5 +- src/Tools/psxcdgen_ex/src/types/bits.rs | 42 +++++++++++++++++ src/Tools/psxcdgen_ex/src/types/mod.rs | 1 + .../psxcdgen_ex/src/types/overlay/mod.rs | 47 +++++++++++-------- 8 files changed, 114 insertions(+), 50 deletions(-) create mode 100644 src/Tools/psxcdgen_ex/src/types/bits.rs diff --git a/include/PSX/AutoLBA/auto_lba.hpp b/include/PSX/AutoLBA/auto_lba.hpp index d211535d..e1dc7358 100644 --- a/include/PSX/AutoLBA/auto_lba.hpp +++ b/include/PSX/AutoLBA/auto_lba.hpp @@ -1,6 +1,6 @@ #ifndef __JABYENGINE_AUTO_LBA_HPP__ #define __JABYENGINE_AUTO_LBA_HPP__ -#include "../../stdint.h" +#include "../Auxiliary/bits.hpp" namespace JabyEngine { #define __jabyengine_start_lba_request @@ -8,8 +8,36 @@ namespace JabyEngine { #define __jabyengine_end_lba_request EndOfRequest struct __attribute__((packed)) AutoLBAEntry { - uint16_t lba; - uint16_t size_words; + // This layout should make it a bit easier to read the "BitRange" values + static constexpr auto SizeInSectors = BitRange::from_to(22, 31); + static constexpr auto IsLZ4Compressed = Bit(19); + static constexpr auto LBAValue = BitRange::from_to(0, 18); + + uint32_t value; + + constexpr uint32_t get_lba() const { + return bit::value::get_normalized(this->value, AutoLBAEntry::LBAValue); + } + + constexpr uint32_t get_lba() const volatile { + return const_cast(this)->get_lba(); + } + + constexpr uint32_t get_size_in_sectors() const { + return this->value >> SizeInSectors.pos; + } + + constexpr uint32_t get_size_in_sectors() const volatile { + return const_cast(this)->get_size_in_sectors(); + } + + constexpr bool isLZ4() const { + return bit::is_set(this->value, AutoLBAEntry::IsLZ4Compressed); + } + + constexpr bool isLZ4() const volatile { + return const_cast(this)->isLZ4(); + } }; } diff --git a/src/Library/internal-include/CD/cd_internal.hpp b/src/Library/internal-include/CD/cd_internal.hpp index aab215c5..aad04e32 100644 --- a/src/Library/internal-include/CD/cd_internal.hpp +++ b/src/Library/internal-include/CD/cd_internal.hpp @@ -44,7 +44,7 @@ namespace JabyEngine { return const_cast(current_state); } - void read_file(FileInfo file_info, const SectorBufferAllocator& buffer_allocator); + void read_file(AutoLBAEntry file_info, const SectorBufferAllocator& buffer_allocator); void continue_reading(); } } diff --git a/src/Library/internal-include/CD/cd_types.hpp b/src/Library/internal-include/CD/cd_types.hpp index cfb75e54..5e1f07d6 100644 --- a/src/Library/internal-include/CD/cd_types.hpp +++ b/src/Library/internal-include/CD/cd_types.hpp @@ -17,15 +17,6 @@ namespace JabyEngine { Error, }; - struct FileInfo { - uint16_t lba; - uint16_t sectors; - - static constexpr FileInfo from(const AutoLBAEntry& entry) { - return FileInfo{entry.lba, CD_IO::DataSector::words_to_sectors(entry.size_words)}; - } - }; - class SectorBufferAllocator { private: typedef CD_IO::DataSector* (*AllocatorFunction)(void* ctx); @@ -61,17 +52,13 @@ namespace JabyEngine { uint8_t sec; uint8_t sector; - static constexpr CDTimeStamp from(uint16_t lba) { - const auto [min, new_lba] = div_and_mod(lba, static_cast(MaxSector*MaxSeconds)); - const auto [sec, sectors] = div_and_mod(new_lba, static_cast(MaxSector)); + static constexpr CDTimeStamp from(uint32_t lba) { + const auto [min, new_lba] = div_and_mod(lba, MaxSector*MaxSeconds); + const auto [sec, sectors] = div_and_mod(new_lba, MaxSector); return CDTimeStamp{static_cast(min), static_cast(sec), static_cast(sectors)}; } - static constexpr CDTimeStamp from(const FileInfo& file_info) { - return CDTimeStamp::from(file_info.lba); - } - constexpr uint8_t get_min_cd() const { return to_bcd(this->min); } diff --git a/src/Library/src/CD/cd.cpp b/src/Library/src/CD/cd.cpp index 66590264..9ef12677 100644 --- a/src/Library/src/CD/cd.cpp +++ b/src/Library/src/CD/cd.cpp @@ -12,8 +12,8 @@ namespace JabyEngine { static void interrupt_handler(uint32_t); static SectorBufferAllocator sector_allocator; - static uint16_t cur_lba; - static uint16_t dst_lba; + static uint32_t cur_lba; + static uint32_t dst_lba; CD_IO::Interrupt::Type last_interrupt = CD_IO::Interrupt::Type::None; uint8_t cmd_interrupt_bit = 0; @@ -30,7 +30,7 @@ namespace JabyEngine { } // Requires Index0 - static void read_cd(uint16_t lba) { + static void read_cd(uint32_t lba) { const auto loc = CDTimeStamp::from(lba); Command::send_wait(CD_IO::Command::SetLoc, loc.get_min_cd(), loc.get_sec_cd(), loc.get_sector_cd()); @@ -117,16 +117,16 @@ namespace JabyEngine { __syscall_ReturnFromException(); } - void read_file(FileInfo file_info, const SectorBufferAllocator& buffer_allocator) { - cur_lba = file_info.lba; - dst_lba = file_info.lba + file_info.sectors; + void read_file(AutoLBAEntry file_info, const SectorBufferAllocator& buffer_allocator) { + cur_lba = file_info.get_lba(); + dst_lba = cur_lba + file_info.get_size_in_sectors(); sector_allocator = buffer_allocator; Command::wait_completed(); CD_IO::PortIndex0::change_to(); Command::send_wait(CD_IO::Command::SetMode, DataSectorMode); - read_cd(file_info.lba); + read_cd(cur_lba); } void continue_reading() { diff --git a/src/Library/src/File/Processor/cd_file_processor.cpp b/src/Library/src/File/Processor/cd_file_processor.cpp index 88b1d891..5e191bb9 100644 --- a/src/Library/src/File/Processor/cd_file_processor.cpp +++ b/src/Library/src/File/Processor/cd_file_processor.cpp @@ -7,7 +7,6 @@ namespace JabyEngine { static constexpr auto DisabledCircularBufferSize = 512; void CDFileProcessor :: start_cur_job() { - using CD::internal::FileInfo; using CD::internal::SectorBufferAllocator; const auto configurate_for = [this](const CDFile& file) { const auto disable_lz4 = [this](uint32_t* work_area, size_t size, uint32_t* overwrite_dst = nullptr) -> uint32_t* { @@ -47,13 +46,13 @@ namespace JabyEngine { const auto& cur_lba = this->lba[cur_job.rel_lba_idx]; configurate_for(cur_job); - CD::internal::read_file(FileInfo::from(cur_lba), SectorBufferAllocator::create(this, + CD::internal::read_file(cur_lba, SectorBufferAllocator::create(this, [](void* ctx) -> CD_IO::DataSector* { CDFileProcessor &self = *reinterpret_cast(ctx); return self.circular_buffer.allocate(); })); - printf(">>> CD needs to load LBA: %i -> %i\n", cur_lba.lba, cur_lba.size_words); + printf(">>> CD needs to load LBA: %i -> %i\n", cur_lba.get_lba(), cur_lba.get_size_in_sectors()); } bool CDFileProcessor :: process_data() { diff --git a/src/Tools/psxcdgen_ex/src/types/bits.rs b/src/Tools/psxcdgen_ex/src/types/bits.rs new file mode 100644 index 00000000..c9b899df --- /dev/null +++ b/src/Tools/psxcdgen_ex/src/types/bits.rs @@ -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 + } + } +} \ No newline at end of file diff --git a/src/Tools/psxcdgen_ex/src/types/mod.rs b/src/Tools/psxcdgen_ex/src/types/mod.rs index 68d00414..60023c9e 100644 --- a/src/Tools/psxcdgen_ex/src/types/mod.rs +++ b/src/Tools/psxcdgen_ex/src/types/mod.rs @@ -1,3 +1,4 @@ +pub mod bits; pub (super) mod helper; pub mod layout; pub mod file_map; diff --git a/src/Tools/psxcdgen_ex/src/types/overlay/mod.rs b/src/Tools/psxcdgen_ex/src/types/overlay/mod.rs index 512ace87..6bca45e0 100644 --- a/src/Tools/psxcdgen_ex/src/types/overlay/mod.rs +++ b/src/Tools/psxcdgen_ex/src/types/overlay/mod.rs @@ -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; 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::(); + 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, lba_names: &LBANameVec, fi Ok(content.clone()) } -fn for_each_lba_name Result<(), Error>>(lba_names: &LBANameVec, file_map: &FileSystemMap, length_func: LengthCalculatorFunction, mut functor: F) -> Result<(), Error> { +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) = (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; }