Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,17 +6,17 @@ Physis is a [Rust](https://www.rust-lang.org/learn/get-started) library for read

```rust,no_run
use physis::{
Error,
Result,
resource::{SqPackResource, Resource},
model::MDL,
};

fn main() -> Result<(), Error> {
fn main() -> Result<()> {
// Construct a resource to read from SqPack:
let mut resource = SqPackResource::from_existing("game");

// Read the raw data of this file, our resource takes care of decompressing it:
let bytes = resource.read(".mdl").ok_or(Error::Unknown)?;
let bytes = resource.read(".mdl")?;

// Or read and parse it:
let mdl = resource.parsed::<MDL>("test.mdl")?;
Expand Down
2 changes: 1 addition & 1 deletion examples/extractor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ fn main() {
let mut game_data = SqPackResource::from_existing(game_dir);

// Extract said file:
let Some(game_file) = game_data.read(file_path) else {
let Ok(game_file) = game_data.read(file_path) else {
println!("File {} not found!", file_path);
return;
};
Expand Down
11 changes: 5 additions & 6 deletions src/amb.rs
Original file line number Diff line number Diff line change
Expand Up @@ -77,25 +77,24 @@ pub struct AmbEntry {
}

impl ReadableFile for Amb {
fn from_existing(platform: Platform, buffer: ByteSpan) -> Option<Self> {
fn from_existing(platform: Platform, buffer: ByteSpan) -> crate::Result<Self> {
let endianness = platform.endianness();
let mut cursor = Cursor::new(buffer);

Amb::read_options(&mut cursor, endianness, ()).ok()
Ok(Amb::read_options(&mut cursor, endianness, ())?)
}
}

impl WritableFile for Amb {
fn write_to_buffer(&self, platform: Platform) -> Option<ByteBuffer> {
fn write_to_buffer(&self, platform: Platform) -> crate::Result<ByteBuffer> {
let mut buffer = ByteBuffer::new();

{
let mut cursor = Cursor::new(&mut buffer);
self.write_options(&mut cursor, platform.endianness(), ())
.ok()?;
self.write_options(&mut cursor, platform.endianness(), ())?;
}

Some(buffer)
Ok(buffer)
}
}

Expand Down
11 changes: 5 additions & 6 deletions src/atch.rs
Original file line number Diff line number Diff line change
Expand Up @@ -40,25 +40,24 @@ impl Atch {
}

impl ReadableFile for Atch {
fn from_existing(platform: Platform, buffer: ByteSpan) -> Option<Self> {
fn from_existing(platform: Platform, buffer: ByteSpan) -> crate::Result<Self> {
let endianness = platform.endianness();
let mut cursor = Cursor::new(buffer);

Self::read_options(&mut cursor, endianness, ()).ok()
Ok(Self::read_options(&mut cursor, endianness, ())?)
}
}

impl WritableFile for Atch {
fn write_to_buffer(&self, platform: Platform) -> Option<ByteBuffer> {
fn write_to_buffer(&self, platform: Platform) -> crate::Result<ByteBuffer> {
let mut buffer = ByteBuffer::new();

{
let mut cursor = Cursor::new(&mut buffer);
self.write_options(&mut cursor, platform.endianness(), ())
.ok()?;
self.write_options(&mut cursor, platform.endianness(), ())?;
}

Some(buffer)
Ok(buffer)
}
}

Expand Down
15 changes: 6 additions & 9 deletions src/avfx.rs
Original file line number Diff line number Diff line change
Expand Up @@ -403,16 +403,15 @@ where
}

impl ReadableFile for Avfx {
fn from_existing(platform: Platform, buffer: ByteSpan) -> Option<Self> {
fn from_existing(platform: Platform, buffer: ByteSpan) -> crate::Result<Self> {
let mut cursor = Cursor::new(buffer);
let header =
AvfxBlock::<Avfx>::read_options(&mut cursor, platform.endianness(), ()).ok()?;
Some(header.data)
let header = AvfxBlock::<Avfx>::read_options(&mut cursor, platform.endianness(), ())?;
Ok(header.data)
}
}

impl WritableFile for Avfx {
fn write_to_buffer(&self, platform: Platform) -> Option<ByteBuffer> {
fn write_to_buffer(&self, platform: Platform) -> crate::Result<ByteBuffer> {
let mut buffer = ByteBuffer::new();

{
Expand All @@ -422,12 +421,10 @@ impl WritableFile for Avfx {
size: 0,
data: self.clone(),
};
block
.write_options(&mut cursor, platform.endianness(), ())
.ok()?;
block.write_options(&mut cursor, platform.endianness(), ())?;
}

Some(buffer)
Ok(buffer)
}
}

Expand Down
15 changes: 8 additions & 7 deletions src/cmp.rs
Original file line number Diff line number Diff line change
Expand Up @@ -59,24 +59,25 @@ pub struct CMP {
}

impl ReadableFile for CMP {
fn from_existing(platform: Platform, buffer: ByteSpan) -> Option<Self> {
fn from_existing(platform: Platform, buffer: ByteSpan) -> crate::Result<Self> {
let mut cursor = Cursor::new(buffer);

cursor.seek(SeekFrom::Start(0x2a800)).ok()?;
cursor.seek(SeekFrom::Start(0x2a800))?;

let rem = buffer.len() - cursor.position() as usize;
let entries = rem / std::mem::size_of::<RacialScalingParameters>();

let mut parameters = vec![];

for _ in 0..entries {
parameters.push(
RacialScalingParameters::read_options(&mut cursor, platform.endianness(), ())
.ok()?,
);
parameters.push(RacialScalingParameters::read_options(
&mut cursor,
platform.endianness(),
(),
)?);
}

Some(CMP { parameters })
Ok(CMP { parameters })
}
}

Expand Down
6 changes: 3 additions & 3 deletions src/common.rs
Original file line number Diff line number Diff line change
Expand Up @@ -168,15 +168,15 @@ impl Ord for Version<'_> {
/// This should be implemented for all types readable from SqPack.
pub trait ReadableFile: Sized {
/// Read an existing file.
fn from_existing(platform: Platform, buffer: ByteSpan) -> Option<Self>;
fn from_existing(platform: Platform, buffer: ByteSpan) -> crate::Result<Self>;
}

/// A file that can be written back to its serialized byte form.
///
/// This should be implemented for all types readable from SqPack, on a best-effort basis.
pub trait WritableFile: Sized {
/// Writes data back to a buffer.
fn write_to_buffer(&self, platform: Platform) -> Option<ByteBuffer>;
fn write_to_buffer(&self, platform: Platform) -> crate::Result<ByteBuffer>;
}

/// Used for basic sanity checking tests in other modules.
Expand All @@ -188,7 +188,7 @@ pub fn pass_random_invalid<T: ReadableFile>() {

// Feeding it invalid data should not panic
// Note that we don't check the Option currently, because some types like Hwc return Some regardless.
T::from_existing(
let _ = T::from_existing(
Platform::Win32,
&std::fs::read(d).expect("Could not read random test file"),
);
Expand Down
16 changes: 8 additions & 8 deletions src/compression.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ use std::ptr::null_mut;
use libz_rs_sys::*;

/// Decompress ZLib data that has no header.
pub fn no_header_decompress(in_data: &mut [u8], out_data: &mut [u8]) -> bool {
pub fn no_header_decompress(in_data: &mut [u8], out_data: &mut [u8]) -> crate::Result<()> {
unsafe {
let mut strm = z_stream {
next_in: null_mut(),
Expand All @@ -32,7 +32,7 @@ pub fn no_header_decompress(in_data: &mut [u8], out_data: &mut [u8]) -> bool {
core::mem::size_of::<z_stream>() as i32,
);
if ret != Z_OK {
return false;
return Err(crate::Error::Zlib(ret));
}

strm.next_in = in_data.as_mut_ptr();
Expand All @@ -41,17 +41,17 @@ pub fn no_header_decompress(in_data: &mut [u8], out_data: &mut [u8]) -> bool {

let ret = inflate(&mut strm, Z_NO_FLUSH);
if ret != Z_STREAM_END {
return false;
return Err(crate::Error::Zlib(ret));
}

inflateEnd(&mut strm);

true
Ok(())
}
}

/// Decompress zlib data that has a header.
pub fn header_decompress(in_data: &mut [u8], out_data: &mut [u8]) -> Option<usize> {
pub fn header_decompress(in_data: &mut [u8], out_data: &mut [u8]) -> crate::Result<usize> {
unsafe {
let mut strm = z_stream {
next_in: null_mut(),
Expand All @@ -76,7 +76,7 @@ pub fn header_decompress(in_data: &mut [u8], out_data: &mut [u8]) -> Option<usiz
core::mem::size_of::<z_stream>() as i32,
);
if ret != Z_OK {
return None;
return Err(crate::Error::Zlib(ret));
}

strm.next_in = in_data.as_mut_ptr();
Expand All @@ -85,11 +85,11 @@ pub fn header_decompress(in_data: &mut [u8], out_data: &mut [u8]) -> Option<usiz

let ret = inflate(&mut strm, Z_NO_FLUSH);
if ret != Z_STREAM_END && ret != Z_OK {
return None;
return Err(crate::Error::Zlib(ret));
}

inflateEnd(&mut strm);

Some(out_data.len() - strm.avail_out as usize)
Ok(out_data.len() - strm.avail_out as usize)
}
}
15 changes: 9 additions & 6 deletions src/cutb.rs
Original file line number Diff line number Diff line change
Expand Up @@ -159,25 +159,28 @@ pub struct CTTLNode {
}

impl ReadableFile for Cutscene {
fn from_existing(platform: Platform, buffer: ByteSpan) -> Option<Cutscene> {
fn from_existing(platform: Platform, buffer: ByteSpan) -> crate::Result<Cutscene> {
let mut cursor = Cursor::new(buffer);
let string_heap = StringHeap::from(0);
Cutscene::read_options(&mut cursor, platform.endianness(), (&string_heap,)).ok()
Ok(Cutscene::read_options(
&mut cursor,
platform.endianness(),
(&string_heap,),
)?)
}
}

impl WritableFile for Cutscene {
fn write_to_buffer(&self, platform: Platform) -> Option<ByteBuffer> {
fn write_to_buffer(&self, platform: Platform) -> crate::Result<ByteBuffer> {
let mut buffer = ByteBuffer::new();

{
let mut cursor = Cursor::new(&mut buffer);
let mut string_heap = StringHeap::from(0);
self.write_options(&mut cursor, platform.endianness(), (&mut string_heap,))
.ok()?;
self.write_options(&mut cursor, platform.endianness(), (&mut string_heap,))?;
}

Some(buffer)
Ok(buffer)
}
}

Expand Down
33 changes: 16 additions & 17 deletions src/dic.rs
Original file line number Diff line number Diff line change
Expand Up @@ -72,10 +72,9 @@ pub struct Dictionary {
}

impl ReadableFile for Dictionary {
fn from_existing(platform: Platform, buffer: ByteSpan) -> Option<Self> {
fn from_existing(platform: Platform, buffer: ByteSpan) -> crate::Result<Self> {
let mut cursor = Cursor::new(buffer);
let mut dict =
DictionaryHeader::read_options(&mut cursor, platform.endianness(), ()).unwrap();
let mut dict = DictionaryHeader::read_options(&mut cursor, platform.endianness(), ())?;

let map_start = 0x8750u32;
let map_size = 0x200u32;
Expand All @@ -87,32 +86,32 @@ impl ReadableFile for Dictionary {

for i in 0..dict.block_lengths[0] / 2 {
let offset = dict.block_offsets[0] + i * 2;
cursor.seek(SeekFrom::Start(offset as u64)).ok()?;
dict.begin_node.push(cursor.read_le::<u16>().ok()?);
cursor.seek(SeekFrom::Start(offset as u64))?;
dict.begin_node.push(cursor.read_le::<u16>()?);
}

for i in 0..dict.block_lengths[1] / 2 {
let offset = dict.block_offsets[1] + i * 2;
cursor.seek(SeekFrom::Start(offset as u64)).ok()?;
dict.inner_node.push(cursor.read_le::<u16>().ok()?);
cursor.seek(SeekFrom::Start(offset as u64))?;
dict.inner_node.push(cursor.read_le::<u16>()?);
}

for i in 0..dict.block_lengths[2] / 2 {
let offset = dict.block_offsets[2] + i * 2;
cursor.seek(SeekFrom::Start(offset as u64)).ok()?;
dict.chara.push(cursor.read_le::<u16>().ok()?);
cursor.seek(SeekFrom::Start(offset as u64))?;
dict.chara.push(cursor.read_le::<u16>()?);
}

for i in 0..dict.block_lengths[3] / 2 {
let offset = dict.block_offsets[3] + i * 2;
cursor.seek(SeekFrom::Start(offset as u64)).ok()?;
dict.word.push(cursor.read_le::<u16>().ok()?);
cursor.seek(SeekFrom::Start(offset as u64))?;
dict.word.push(cursor.read_le::<u16>()?);
}

for i in 0..dict.block_lengths[4] / 16 {
let offset = dict.block_offsets[4] + i * 16;
cursor.seek(SeekFrom::Start(offset as u64)).ok()?;
dict.entries.push(cursor.read_le::<EntryItem>().ok()?);
cursor.seek(SeekFrom::Start(offset as u64))?;
dict.entries.push(cursor.read_le::<EntryItem>()?);
}

let mut dict = Dictionary {
Expand All @@ -121,14 +120,14 @@ impl ReadableFile for Dictionary {
};

// TODO: lol
dict.words = dict.list_words()?;
dict.words = dict.list_words();

Some(dict)
Ok(dict)
}
}

impl Dictionary {
fn list_words(&self) -> Option<Vec<String>> {
fn list_words(&self) -> Vec<String> {
let mut result = Vec::new();
let lut = self.generate_index_rune_lookup_table();
for (id, v) in self.header.begin_node.iter().enumerate() {
Expand All @@ -142,7 +141,7 @@ impl Dictionary {
}
}

Some(result)
result
}

fn generate_index_rune_lookup_table(&self) -> HashMap<u16, u16> {
Expand Down
11 changes: 5 additions & 6 deletions src/eid.rs
Original file line number Diff line number Diff line change
Expand Up @@ -57,25 +57,24 @@ pub struct Eid {
}

impl ReadableFile for Eid {
fn from_existing(platform: Platform, buffer: ByteSpan) -> Option<Self> {
fn from_existing(platform: Platform, buffer: ByteSpan) -> crate::Result<Self> {
let endianness = platform.endianness();
let mut cursor = Cursor::new(buffer);

Self::read_options(&mut cursor, endianness, ()).ok()
Ok(Self::read_options(&mut cursor, endianness, ())?)
}
}

impl WritableFile for Eid {
fn write_to_buffer(&self, platform: Platform) -> Option<ByteBuffer> {
fn write_to_buffer(&self, platform: Platform) -> crate::Result<ByteBuffer> {
let mut buffer = ByteBuffer::new();

{
let mut cursor = Cursor::new(&mut buffer);
self.write_options(&mut cursor, platform.endianness(), ())
.ok()?;
self.write_options(&mut cursor, platform.endianness(), ())?;
}

Some(buffer)
Ok(buffer)
}
}

Expand Down
Loading