Revised dcb_io::GameFile to use cursors.

This commit is contained in:
Filipe Rodrigues 2021-05-22 22:45:18 +01:00
parent c622af8262
commit eb52ba496d
4 changed files with 189 additions and 61 deletions

View File

@ -8,6 +8,7 @@ use std::{
/// A cursor over a cdrom-xa file.
// TODO: Repair sector headers and edc/ecc after writing
#[derive(PartialEq, Clone, Debug)]
pub struct CdRomCursor<T> {
/// Underlying reader/writer
inner: T,

View File

@ -9,8 +9,8 @@ edition = "2018"
# Dcb
dcb-bytes = { path = "../dcb-bytes" }
dcb-util = { path = "../dcb-util" }
dcb-iso9660 = { path = "../dcb-iso9660" }
dcb-cdrom-xa = { path = "../dcb-cdrom-xa" }
dcb-drv = { path = "../dcb-drv" }
# Log
log = "0.4.13"

View File

@ -1,4 +1,4 @@
//! Abstraction over the game file.
//! Game file.
//!
//! See [`GameFile`] for details
@ -6,59 +6,147 @@
pub mod error;
// Exports
pub use error::{NewError, ReadDrvError};
pub use error::NewError;
// Imports
use dcb_cdrom_xa::CdRomReader;
use dcb_iso9660::entry::FileReader;
use dcb_cdrom_xa::CdRomCursor;
use dcb_drv::cursor::DrvFsCursor;
use dcb_util::IoCursor;
use std::io;
/// Game file reader.
#[derive(PartialEq, Eq, Debug)]
pub struct GameFile<'a, R> {
/// Game file.
#[derive(PartialEq, Clone, Debug)]
pub struct GameFile<T> {
/// CD-Rom
cdrom: &'a mut CdRomReader<R>,
cdrom: CdRomCursor<T>,
/// Iso9660 filesystem
filesystem: dcb_iso9660::FilesystemReader,
/// `A.DRV` cursor
a_drv_cursor: DrvFsCursor,
/// `B.DRV` cursor
b_drv_cursor: DrvFsCursor,
/// `C.DRV` cursor
c_drv_cursor: DrvFsCursor,
/// `E.DRV` cursor
e_drv_cursor: DrvFsCursor,
/// `F.DRV` cursor
f_drv_cursor: DrvFsCursor,
/// `G.DRV` cursor
g_drv_cursor: DrvFsCursor,
/// `P.DRV` cursor
p_drv_cursor: DrvFsCursor,
}
// Constructors
impl<'a, R: io::Read + io::Seek> GameFile<'a, R> {
/// Creates a new game file from the cd reader
pub fn new(cdrom: &'a mut CdRomReader<R>) -> Result<Self, NewError> {
// Read the filesystem
let filesystem = dcb_iso9660::FilesystemReader::new(cdrom).map_err(NewError::ParseFilesystem)?;
impl<T: io::Read + io::Seek> GameFile<T> {
/// `A.DRV` Offset
pub const A_OFFSET: u64 = 0xa1000;
/// `A.DRV` Size
pub const A_SIZE: u64 = 0xa78800;
/// `B.DRV` Offset
pub const B_OFFSET: u64 = 0xb19800;
/// `B.DRV` Size
pub const B_SIZE: u64 = 0x17ea800;
/// `C.DRV` Offset
pub const C_OFFSET: u64 = 0x2304000;
/// `C.DRV` Size
pub const C_SIZE: u64 = 0xb6c000;
/// `E.DRV` Offset
pub const E_OFFSET: u64 = 0x2e70000;
/// `E.DRV` Size
pub const E_SIZE: u64 = 0x1886800;
/// `F.DRV` Offset
pub const F_OFFSET: u64 = 0x46f6800;
/// `F.DRV` Size
pub const F_SIZE: u64 = 0xf2f800;
/// `G.DRV` Offset
pub const G_OFFSET: u64 = 0x5626000;
/// `G.DRV` Size
pub const G_SIZE: u64 = 0x293000;
/// `P.DRV` Offset
pub const P_OFFSET: u64 = 0xc000;
/// `P.DRV` Size
pub const P_SIZE: u64 = 0x95000;
Ok(Self { cdrom, filesystem })
/// Creates a new game file
pub fn new(mut cdrom: CdRomCursor<T>) -> Result<Self, NewError> {
let mut a_drv = IoCursor::new(&mut cdrom, Self::A_OFFSET, Self::A_SIZE).map_err(NewError::OpenA)?;
let a_drv_cursor = DrvFsCursor::new(&mut a_drv).map_err(NewError::CursorA)?;
let mut b_drv = IoCursor::new(&mut cdrom, Self::B_OFFSET, Self::B_SIZE).map_err(NewError::OpenB)?;
let b_drv_cursor = DrvFsCursor::new(&mut b_drv).map_err(NewError::CursorB)?;
let mut c_drv = IoCursor::new(&mut cdrom, Self::C_OFFSET, Self::C_SIZE).map_err(NewError::OpenC)?;
let c_drv_cursor = DrvFsCursor::new(&mut c_drv).map_err(NewError::CursorC)?;
let mut e_drv = IoCursor::new(&mut cdrom, Self::E_OFFSET, Self::E_SIZE).map_err(NewError::OpenE)?;
let e_drv_cursor = DrvFsCursor::new(&mut e_drv).map_err(NewError::CursorE)?;
let mut f_drv = IoCursor::new(&mut cdrom, Self::F_OFFSET, Self::F_SIZE).map_err(NewError::OpenF)?;
let f_drv_cursor = DrvFsCursor::new(&mut f_drv).map_err(NewError::CursorF)?;
let mut g_drv = IoCursor::new(&mut cdrom, Self::G_OFFSET, Self::G_SIZE).map_err(NewError::OpenG)?;
let g_drv_cursor = DrvFsCursor::new(&mut g_drv).map_err(NewError::CursorG)?;
let mut p_drv = IoCursor::new(&mut cdrom, Self::P_OFFSET, Self::P_SIZE).map_err(NewError::OpenP)?;
let p_drv_cursor = DrvFsCursor::new(&mut p_drv).map_err(NewError::CursorP)?;
Ok(Self {
cdrom,
a_drv_cursor,
b_drv_cursor,
c_drv_cursor,
e_drv_cursor,
f_drv_cursor,
g_drv_cursor,
p_drv_cursor,
})
}
/// Returns the `A.DRV` file
pub fn a_drv(cdrom: &mut CdRomCursor<T>) -> Result<IoCursor<&mut CdRomCursor<T>>, io::Error> {
IoCursor::new(cdrom, Self::A_OFFSET, Self::A_SIZE)
}
/// Returns the `B.DRV` file
pub fn b_drv(cdrom: &mut CdRomCursor<T>) -> Result<IoCursor<&mut CdRomCursor<T>>, io::Error> {
IoCursor::new(cdrom, Self::B_OFFSET, Self::B_SIZE)
}
/// Returns the `C.DRV` file
pub fn c_drv(cdrom: &mut CdRomCursor<T>) -> Result<IoCursor<&mut CdRomCursor<T>>, io::Error> {
IoCursor::new(cdrom, Self::C_OFFSET, Self::C_SIZE)
}
/// Returns the `E.DRV` file
pub fn e_drv(cdrom: &mut CdRomCursor<T>) -> Result<IoCursor<&mut CdRomCursor<T>>, io::Error> {
IoCursor::new(cdrom, Self::E_OFFSET, Self::E_SIZE)
}
/// Returns the `F.DRV` file
pub fn f_drv(cdrom: &mut CdRomCursor<T>) -> Result<IoCursor<&mut CdRomCursor<T>>, io::Error> {
IoCursor::new(cdrom, Self::F_OFFSET, Self::F_SIZE)
}
/// Returns the `G.DRV` file
pub fn g_drv(cdrom: &mut CdRomCursor<T>) -> Result<IoCursor<&mut CdRomCursor<T>>, io::Error> {
IoCursor::new(cdrom, Self::G_OFFSET, Self::G_SIZE)
}
/// Returns the `P.DRV` file
pub fn p_drv(cdrom: &mut CdRomCursor<T>) -> Result<IoCursor<&mut CdRomCursor<T>>, io::Error> {
IoCursor::new(cdrom, Self::P_OFFSET, Self::P_SIZE)
}
}
impl<'a, R> GameFile<'a, R> {
impl<T> GameFile<T> {
/// Returns the cdrom associated with this game file
pub fn cdrom(&mut self) -> &mut CdRomReader<R> {
self.cdrom
}
}
impl<'a, R: io::Read + io::Seek> GameFile<'a, R> {
/// Reads a game file
pub fn read_drv<'b>(&'b mut self, name: &str) -> Result<FileReader<'b, R>, ReadDrvError>
where
'a: 'b,
{
// Read the root directory
let root_dir = self
.filesystem
.root_dir()
.read_dir(self.cdrom)
.map_err(ReadDrvError::ReadRoot)?;
// Get the file
let entry = root_dir.find(name).ok_or(ReadDrvError::FindFile)?;
// And read it
entry.read_file(self.cdrom).map_err(ReadDrvError::ReadFile)
pub fn cdrom(&mut self) -> &mut CdRomCursor<T> {
&mut self.cdrom
}
}

View File

@ -1,25 +1,64 @@
//! Errors
// Imports
use std::io;
/// Error for [`GameFile::new`](super::GameFile::new)
#[derive(Debug, thiserror::Error)]
pub enum NewError {
/// Unable to parse filesystem
#[error("Unable to parse filesystem")]
ParseFilesystem(#[source] dcb_iso9660::NewError),
}
/// Error for [`GameFile::read_drv`](super::GameFile::read_drv)
#[derive(Debug, thiserror::Error)]
pub enum ReadDrvError {
/// Unable to read filesystem root
#[error("Unable to read filesystem root")]
ReadRoot(#[source] dcb_iso9660::entry::ReadDirError),
/// Unable to find file
#[error("Unable to find file")]
FindFile,
/// Unable to read file
#[error("Unable to read file")]
ReadFile(#[source] dcb_iso9660::entry::ReadFileError),
/// Unable to open `A.DRV`
#[error("Unable to open `A.DRV` file")]
OpenA(#[source] io::Error),
/// Unable to create `A.DRV` cursor
#[error("Unable to create `A.DRV` cursor")]
CursorA(#[source] dcb_drv::cursor::NewError),
/// Unable to open `B.DRV`
#[error("Unable to open `B.DRV` file")]
OpenB(#[source] io::Error),
/// Unable to create `B.DRV` cursor
#[error("Unable to create `B.DRV` cursor")]
CursorB(#[source] dcb_drv::cursor::NewError),
/// Unable to open `C.DRV`
#[error("Unable to open `C.DRV` file")]
OpenC(#[source] io::Error),
/// Unable to create `C.DRV` cursor
#[error("Unable to create `C.DRV` cursor")]
CursorC(#[source] dcb_drv::cursor::NewError),
/// Unable to open `E.DRV`
#[error("Unable to open `E.DRV` file")]
OpenE(#[source] io::Error),
/// Unable to create `E.DRV` cursor
#[error("Unable to create `E.DRV` cursor")]
CursorE(#[source] dcb_drv::cursor::NewError),
/// Unable to open `F.DRV`
#[error("Unable to open `F.DRV` file")]
OpenF(#[source] io::Error),
/// Unable to create `F.DRV` cursor
#[error("Unable to create `F.DRV` cursor")]
CursorF(#[source] dcb_drv::cursor::NewError),
/// Unable to open `G.DRV`
#[error("Unable to open `G.DRV` file")]
OpenG(#[source] io::Error),
/// Unable to create `G.DRV` cursor
#[error("Unable to create `G.DRV` cursor")]
CursorG(#[source] dcb_drv::cursor::NewError),
/// Unable to open `P.DRV`
#[error("Unable to open `P.DRV` file")]
OpenP(#[source] io::Error),
/// Unable to create `P.DRV` cursor
#[error("Unable to create `P.DRV` cursor")]
CursorP(#[source] dcb_drv::cursor::NewError),
}