-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
MipTex doesn't require Seek
- Loading branch information
Showing
5 changed files
with
146 additions
and
91 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,82 +1,57 @@ | ||
use std::{ | ||
collections::HashMap, | ||
io::{self, Read, Seek, SeekFrom}, | ||
sync::{Arc, Mutex}, | ||
}; | ||
|
||
use byteorder::{LittleEndian, ReadBytesExt}; | ||
|
||
use crate::{ | ||
wad::{Archive, Content}, | ||
CStr16, | ||
}; | ||
|
||
use super::{ | ||
chunk, cstr16, | ||
texture::{font, miptex, qpic}, | ||
}; | ||
use crate::wad::{ContentType, RawArchive, RawEntry, ReadSeek}; | ||
|
||
#[allow(dead_code)] | ||
struct Entry { | ||
offset: u32, | ||
full_size: u32, | ||
size: u32, | ||
ty: u8, | ||
compression: u8, | ||
name: CStr16, | ||
} | ||
use super::cstr16; | ||
|
||
pub fn archive<R: Read + Seek>(mut reader: R) -> io::Result<Archive> { | ||
pub fn raw_archive<R: Read + Seek + 'static>(reader: R) -> io::Result<RawArchive> { | ||
const MAGIC: &[u8; 4] = b"WAD3"; | ||
|
||
let reader: Arc<Mutex<dyn ReadSeek>> = Arc::new(Mutex::new(reader)); | ||
let mut reader_ref = reader.lock().unwrap(); | ||
|
||
let mut header = [0u8; 4]; | ||
reader.read_exact(&mut header)?; | ||
reader_ref.read_exact(&mut header)?; | ||
if &header != MAGIC { | ||
return Err(io::Error::new(io::ErrorKind::Unsupported, "invalid magic")); | ||
} | ||
let size = reader.read_u32::<LittleEndian>()?; | ||
let offset = reader.read_u32::<LittleEndian>()?; | ||
let size = reader_ref.read_u32::<LittleEndian>()?; | ||
let offset = reader_ref.read_u32::<LittleEndian>()?; | ||
|
||
reader.seek(SeekFrom::Start(offset as u64))?; | ||
let mut entries = Vec::with_capacity(size as usize); | ||
reader_ref.seek(SeekFrom::Start(offset as u64))?; | ||
let mut entries = HashMap::with_capacity(size as usize); | ||
for _ in 0..size { | ||
let offset = reader.read_u32::<LittleEndian>()?; | ||
let size = reader.read_u32::<LittleEndian>()?; | ||
let full_size = reader.read_u32::<LittleEndian>()?; // full_size, not used | ||
let ty = reader.read_u8()?; | ||
let compression = reader.read_u8()?; | ||
let _ = reader.read_u16::<LittleEndian>(); // dummy | ||
let name = cstr16(&mut reader)?; | ||
let offset = reader_ref.read_u32::<LittleEndian>()?; | ||
let size = reader_ref.read_u32::<LittleEndian>()?; | ||
let full_size = reader_ref.read_u32::<LittleEndian>()?; // full_size, not used | ||
let ty = match reader_ref.read_u8()? { | ||
0x42 => ContentType::Picture, | ||
0x43 => ContentType::MipTexture, | ||
0x46 => ContentType::Font, | ||
unknown => ContentType::Other(unknown), | ||
}; | ||
let compression = reader_ref.read_u8()?; | ||
let _ = reader_ref.read_u16::<LittleEndian>(); // dummy | ||
let name = cstr16(&mut *reader_ref)?; | ||
|
||
entries.push(Entry { | ||
offset, | ||
full_size, | ||
size, | ||
ty, | ||
compression, | ||
entries.insert( | ||
name, | ||
}) | ||
} | ||
|
||
let mut archive = HashMap::with_capacity(entries.len()); | ||
for entry in entries { | ||
reader.seek(SeekFrom::Start(entry.offset as u64))?; | ||
|
||
if entry.compression != 0 { | ||
unimplemented!("compression not supported by goldsrc") | ||
} | ||
|
||
let content = match entry.ty { | ||
0x42 => Content::Picture(qpic(&mut reader)?), | ||
0x43 => Content::MipTexture(miptex(&mut reader)?), | ||
0x46 => Content::Font(font(&mut reader)?), | ||
ty => Content::Other { | ||
RawEntry { | ||
source: Arc::clone(&reader), | ||
offset, | ||
full_size, | ||
size, | ||
ty, | ||
data: chunk(&mut reader, entry.size as usize)?, | ||
compression, | ||
}, | ||
}; | ||
|
||
archive.insert(entry.name, content); | ||
); | ||
} | ||
|
||
Ok(archive) | ||
Ok(RawArchive { entries }) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,15 +1,68 @@ | ||
use std::collections::HashMap; | ||
use std::{ | ||
collections::HashMap, | ||
io::{self, Read, Seek, SeekFrom}, | ||
sync::{Arc, Mutex}, | ||
}; | ||
|
||
use crate::CStr16; | ||
|
||
use super::texture::{Font, MipTexture, Picture}; | ||
#[non_exhaustive] | ||
#[repr(u8)] | ||
#[derive(Debug, Clone, Copy)] | ||
pub enum ContentType { | ||
Picture, | ||
MipTexture, | ||
Font, | ||
Other(u8), | ||
} | ||
|
||
pub type Archive = HashMap<CStr16, Content>; | ||
/// Helpful trait for Read and Seek dyn Trait | ||
pub(crate) trait ReadSeek: Read + Seek {} | ||
impl<T: Read + Seek> ReadSeek for T {} | ||
|
||
#[non_exhaustive] | ||
pub enum Content { | ||
Picture(Picture), | ||
MipTexture(MipTexture), | ||
Font(Font), | ||
Other { ty: u8, data: Vec<u8> }, | ||
struct SharedChunkReader { | ||
source: Arc<Mutex<dyn ReadSeek>>, | ||
begin: usize, | ||
end: usize, | ||
} | ||
|
||
impl Read for SharedChunkReader { | ||
fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> { | ||
if self.begin == self.end { | ||
return Ok(0); | ||
} | ||
|
||
let mut source = self.source.lock().unwrap(); | ||
source.seek(SeekFrom::Start(self.begin as u64))?; | ||
let remaining = self.end - self.begin; | ||
let readlen = buf.len().min(remaining); | ||
source.read_exact(&mut buf[..readlen])?; | ||
self.begin += readlen; | ||
|
||
Ok(readlen) | ||
} | ||
} | ||
|
||
// TODO : Debug? | ||
pub struct RawEntry { | ||
pub(crate) source: Arc<Mutex<dyn ReadSeek>>, | ||
pub offset: u32, | ||
pub full_size: u32, | ||
pub size: u32, | ||
pub ty: ContentType, | ||
pub compression: u8, | ||
} | ||
|
||
impl RawEntry { | ||
pub fn reader(&self) -> impl Read { | ||
SharedChunkReader { | ||
source: Arc::clone(&self.source), | ||
begin: self.offset as usize, | ||
end: (self.offset + self.size) as usize, | ||
} | ||
} | ||
} | ||
|
||
pub struct RawArchive { | ||
pub entries: HashMap<CStr16, RawEntry>, | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters