Improve psxcdread
This commit is contained in:
parent
27287773b7
commit
5ec7acb803
|
@ -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]
|
||||||
|
|
|
@ -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 {
|
||||||
|
|
|
@ -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))
|
||||||
|
|
|
@ -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
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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]
|
||||||
|
|
|
@ -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)?)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue