Improve psxcdread

This commit is contained in:
jaby 2024-07-28 13:22:39 -05:00
parent 27287773b7
commit 5ec7acb803
6 changed files with 43 additions and 25 deletions

View File

@ -1,6 +1,6 @@
[package] [package]
name = "cdtypes" name = "cdtypes"
version = "0.7.1" version = "0.7.2"
edition = "2021" edition = "2021"
[profile.release] [profile.release]

View File

@ -2,7 +2,7 @@ pub mod reader;
pub mod sector; pub mod sector;
use sector::*; use sector::*;
use reader::Reader as CDReader; use reader::{UnknownSectorBehavior, Reader as CDReader};
use super::{Error, types as types}; use super::{Error, types as types};
use types::{cue::{Specifier, DataType, DataTypeEnd}, lsb_msb::ReadWriteEndian, pvd::PrimaryVolumeDescriptor, sector::{Mode2Form1, SubHeaderForm}}; use types::{cue::{Specifier, DataType, DataTypeEnd}, lsb_msb::ReadWriteEndian, pvd::PrimaryVolumeDescriptor, sector::{Mode2Form1, SubHeaderForm}};
use std::fs::File; use std::fs::File;
@ -191,7 +191,7 @@ pub struct CD {
} }
impl CD { impl CD {
pub fn from_file(file: File, specifier: Option<Vec<Specifier>>) -> Result<CD, Error> { pub fn from_file(file: File, specifier: Option<Vec<Specifier>>, unk_sector_behav: UnknownSectorBehavior) -> Result<CD, Error> {
let data_type_ends = { let data_type_ends = {
if let Some(specifier) = specifier { if let Some(specifier) = specifier {
DataTypeEnd::parse_cue_specifier(specifier)? DataTypeEnd::parse_cue_specifier(specifier)?
@ -201,7 +201,7 @@ impl CD {
Vec::new() Vec::new()
} }
}; };
let reader = CDReader::new(file, &data_type_ends)?; let reader = CDReader::new(file, &data_type_ends, unk_sector_behav)?;
let mut sectors = Vec::new(); let mut sectors = Vec::new();
for sector in reader { for sector in reader {

View File

@ -2,17 +2,27 @@ use super::{sector::Sector, types::time::Time};
use super::super::{Error, types::{cue::{DataType, DataTypeEnd}, sector::*}}; use super::super::{Error, types::{cue::{DataType, DataTypeEnd}, sector::*}};
use std::io::Read; use std::io::Read;
#[derive(Copy, Clone)]
pub enum UnknownSectorBehavior {
CauseError,
CauseWarningAddEmpty,
TreatAsAudio,
}
pub struct Reader<'a> { pub struct Reader<'a> {
file: std::fs::File, file: std::fs::File,
data_type_guide: &'a Vec<DataTypeEnd>, data_type_guide: &'a Vec<DataTypeEnd>,
lba: usize, lba: usize,
unk_sector_behav: UnknownSectorBehavior,
active: bool active: bool
} }
impl<'a> Reader<'a> { impl<'a> Reader<'a> {
pub fn new(file: std::fs::File, data_type_guide: &'a Vec<DataTypeEnd>) -> Result<Reader, Error> { const CD_PREGAP_SECTORS:usize = Time::cd_pregap().as_sectors();
pub fn new(file: std::fs::File, data_type_guide: &'a Vec<DataTypeEnd>, unk_sector_behav: UnknownSectorBehavior) -> Result<Reader, Error> {
Ok(Reader{ Ok(Reader{
file, data_type_guide, lba: Time::cd_pregap().as_sectors(), active: true file, data_type_guide, unk_sector_behav, lba: Self::CD_PREGAP_SECTORS, active: true
}) })
} }
@ -23,11 +33,10 @@ impl<'a> Reader<'a> {
return Some(data_type.r#type.clone()); return Some(data_type.r#type.clone());
} }
} }
None None
} }
fn process_audio_sector(&mut self, _force: bool) -> Result<Option<Sector>, Error> { fn process_audio_sector(&mut self, _unk_sector_behav: UnknownSectorBehavior) -> Result<Option<Sector>, Error> {
let mut buffer = [0;std::mem::size_of::<Audio>()]; let mut buffer = [0;std::mem::size_of::<Audio>()];
let bytes = self.file.read(&mut buffer)?; let bytes = self.file.read(&mut buffer)?;
@ -42,18 +51,23 @@ impl<'a> Reader<'a> {
} }
} }
fn process_binary_sector(&mut self, force: bool) -> Result<Option<Sector>, Error> { fn process_binary_sector(&mut self, unk_sector_behav: UnknownSectorBehavior) -> Result<Option<Sector>, Error> {
fn make_ok_some(sector: Sector) -> Result<Option<Sector>, Error> { fn make_ok_some(sector: Sector) -> Result<Option<Sector>, Error> {
Ok(Some(sector)) Ok(Some(sector))
} }
let mut buffer = [0;std::mem::size_of::<Mode2Form1>()]; let mut buffer = [0;SECTOR_SIZE];
let bytes = self.file.read(&mut buffer)?; let bytes = self.file.read(&mut buffer)?;
let sector_id = self.lba - 1 - Self::CD_PREGAP_SECTORS;
if bytes == 0 { if bytes == 0 {
return Ok(None); return Ok(None);
} }
if bytes != SECTOR_SIZE {
return Err(Error::GenericError(format!("Failed to read in a complete sector for sector: {}", sector_id)));
}
unsafe { unsafe {
let sector = &*(buffer.as_ptr() as *const Mode0); let sector = &*(buffer.as_ptr() as *const Mode0);
let mode = sector.header.get_mode(); let mode = sector.header.get_mode();
@ -69,14 +83,18 @@ impl<'a> Reader<'a> {
} }
} }
Err(mode) => { Err(mode) => {
let error_str = format!("Unknown Mode: {} @LBA: {}", mode, self.lba - 1); let error_str = format!("Unknown Mode: {} @Sector: {}", mode, sector_id);
if force { match unk_sector_behav {
println!("Warning: {}", error_str); UnknownSectorBehavior::CauseError => {
return make_ok_some(Sector::Empty(Mode0::new())); return Err(Error::TypeError(error_str));
} },
UnknownSectorBehavior::CauseWarningAddEmpty => {
else { println!("Warning: {}", error_str);
return Err(Error::TypeError(error_str)); return make_ok_some(Sector::Empty(Mode0::new()));
}
UnknownSectorBehavior::TreatAsAudio => {
return make_ok_some(Sector::Audio(std::mem::transmute::<[u8; std::mem::size_of::<Audio>()], Audio>(buffer)));
}
} }
} }
} }
@ -98,7 +116,7 @@ impl<'a> std::iter::Iterator for Reader<'a> {
} }
}; };
match function(self, true) { match function(self, self.unk_sector_behav) {
Ok(sector) => { Ok(sector) => {
if let Some(sector) = sector { if let Some(sector) = sector {
Some(Ok(sector)) Some(Ok(sector))

View File

@ -76,7 +76,7 @@ impl Time {
Time{sector, second, minute} Time{sector, second, minute}
} }
pub fn as_sectors(&self) -> usize { pub const fn as_sectors(&self) -> usize {
self.sector as usize + self.second as usize*Self::MAX_SECTORS + self.minute as usize*Self::MAX_SECONDS*Self::MAX_SECTORS self.sector as usize + self.second as usize*Self::MAX_SECTORS + self.minute as usize*Self::MAX_SECONDS*Self::MAX_SECTORS
} }

View File

@ -1,6 +1,6 @@
[package] [package]
name = "psxcdread" name = "psxcdread"
version = "0.5.0" version = "0.7.0"
edition = "2021" edition = "2021"
[profile.release] [profile.release]

View File

@ -1,5 +1,5 @@
use psxcdread::{*}; use psxcdread::{*};
use cdtypes::{Error, cd::CD, types::{cue, sector::SECTOR_SIZE}}; use cdtypes::{cd::{reader::UnknownSectorBehavior, CD}, types::{cue, sector::SECTOR_SIZE}, Error};
use std::{fs::OpenOptions, io::{stdin, stdout, Write}, path::{Path, PathBuf}}; use std::{fs::OpenOptions, io::{stdin, stdout, Write}, path::{Path, PathBuf}};
fn open_file(path: &Path, write_access: bool) -> Result<std::fs::File, Error> { fn open_file(path: &Path, write_access: bool) -> Result<std::fs::File, Error> {
@ -48,7 +48,7 @@ fn open_cue(file: std::fs::File, cue_path: &Path) -> Result<CD, Error> {
} }
let specifier = cue::read::read(file)?; let specifier = cue::read::read(file)?;
if let Some(bin_path) = get_bin_path(&specifier, cue_path)? { if let Some(bin_path) = get_bin_path(&specifier, cue_path)? {
Ok(CD::from_file(open_file(bin_path.as_path(), false)?, Some(specifier))?) Ok(CD::from_file(open_file(bin_path.as_path(), false)?, Some(specifier), UnknownSectorBehavior::CauseError)?)
} }
else { else {
@ -74,7 +74,7 @@ fn open_cd(path: &str) -> Result<CD, Error> {
} }
else { else {
Ok(CD::from_file(file, None)?) Ok(CD::from_file(file, None, UnknownSectorBehavior::TreatAsAudio)?)
} }
} }