Improve psxcdread

This commit is contained in:
Jaby 2024-07-28 13:22:39 -05:00
parent 7dd98d5762
commit 4cb6e05e62
6 changed files with 43 additions and 25 deletions

View File

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

View File

@ -2,7 +2,7 @@ pub mod reader;
pub mod sector;
use sector::*;
use reader::Reader as CDReader;
use reader::{UnknownSectorBehavior, Reader as CDReader};
use super::{Error, types as types};
use types::{cue::{Specifier, DataType, DataTypeEnd}, lsb_msb::ReadWriteEndian, pvd::PrimaryVolumeDescriptor, sector::{Mode2Form1, SubHeaderForm}};
use std::fs::File;
@ -191,7 +191,7 @@ pub struct 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 = {
if let Some(specifier) = specifier {
DataTypeEnd::parse_cue_specifier(specifier)?
@ -201,7 +201,7 @@ impl CD {
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();
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 std::io::Read;
#[derive(Copy, Clone)]
pub enum UnknownSectorBehavior {
CauseError,
CauseWarningAddEmpty,
TreatAsAudio,
}
pub struct Reader<'a> {
file: std::fs::File,
data_type_guide: &'a Vec<DataTypeEnd>,
lba: usize,
unk_sector_behav: UnknownSectorBehavior,
active: bool
}
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{
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());
}
}
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 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> {
Ok(Some(sector))
}
let mut buffer = [0;std::mem::size_of::<Mode2Form1>()];
let bytes = self.file.read(&mut buffer)?;
let mut buffer = [0;SECTOR_SIZE];
let bytes = self.file.read(&mut buffer)?;
let sector_id = self.lba - 1 - Self::CD_PREGAP_SECTORS;
if bytes == 0 {
return Ok(None);
}
if bytes != SECTOR_SIZE {
return Err(Error::GenericError(format!("Failed to read in a complete sector for sector: {}", sector_id)));
}
unsafe {
let sector = &*(buffer.as_ptr() as *const Mode0);
let mode = sector.header.get_mode();
@ -69,14 +83,18 @@ impl<'a> Reader<'a> {
}
}
Err(mode) => {
let error_str = format!("Unknown Mode: {} @LBA: {}", mode, self.lba - 1);
if force {
println!("Warning: {}", error_str);
return make_ok_some(Sector::Empty(Mode0::new()));
}
else {
return Err(Error::TypeError(error_str));
let error_str = format!("Unknown Mode: {} @Sector: {}", mode, sector_id);
match unk_sector_behav {
UnknownSectorBehavior::CauseError => {
return Err(Error::TypeError(error_str));
},
UnknownSectorBehavior::CauseWarningAddEmpty => {
println!("Warning: {}", 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) => {
if let Some(sector) = sector {
Some(Ok(sector))

View File

@ -76,7 +76,7 @@ impl Time {
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
}

View File

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

View File

@ -1,5 +1,5 @@
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}};
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)?;
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 {
@ -74,7 +74,7 @@ fn open_cd(path: &str) -> Result<CD, Error> {
}
else {
Ok(CD::from_file(file, None)?)
Ok(CD::from_file(file, None, UnknownSectorBehavior::TreatAsAudio)?)
}
}