@@ -141,6 +141,40 @@ impl Display for Entry {
141141 }
142142}
143143
144+ #[ derive( IntoBytes , FromBytes , Serialize , Deserialize , Clone , Copy , Debug ) ]
145+ #[ repr( C , packed) ]
146+ pub struct HuffmanHeader {
147+ magic : [ u8 ; 4 ] ,
148+ chunk_count : u32 ,
149+ chunk_base : u32 ,
150+ _unk0 : u32 ,
151+ hs0 : u32 ,
152+ hs1 : u32 ,
153+ _unk1 : u32 ,
154+ _unk2 : u32 ,
155+ _r : [ u8 ; 16 ] , // all 0 in sample
156+ chunk_size : u32 ,
157+ _unk3 : u32 ,
158+ name : [ u8 ; 8 ] ,
159+ }
160+
161+ const HUFFMAN_HEADER_SIZE : usize = size_of :: < HuffmanHeader > ( ) ;
162+
163+ #[ derive( Serialize , Deserialize , Clone , Debug ) ]
164+ #[ repr( C ) ]
165+ pub struct Huffman {
166+ header : HuffmanHeader ,
167+ chunks : Vec < u32 > ,
168+ }
169+
170+ #[ derive( Serialize , Deserialize , Clone , Debug ) ]
171+ pub enum Module {
172+ Uncompressed ( Entry ) ,
173+ Huffman ( Result < ( Entry , Huffman ) , String > ) ,
174+ Lzma ( Result < Entry , String > ) ,
175+ Unknown ( Entry ) ,
176+ }
177+
144178#[ derive( IntoBytes , FromBytes , Serialize , Deserialize , Clone , Copy , Debug ) ]
145179#[ repr( C , packed) ]
146180pub struct Header {
@@ -153,7 +187,7 @@ pub struct Header {
153187pub struct Directory {
154188 pub manifest : Manifest ,
155189 pub header : Header ,
156- pub entries : Vec < Entry > ,
190+ pub modules : Vec < Module > ,
157191 pub offset : usize ,
158192 pub size : usize ,
159193 pub name : String ,
@@ -202,10 +236,50 @@ impl Directory {
202236 Ok ( n) => n. trim_end_matches ( '\0' ) . to_string ( ) ,
203237 Err ( _) => format ! ( "{:02x?}" , header. name) ,
204238 } ;
239+
240+ // Check for consistency and wrap entries with additional information.
241+ let modules = entries
242+ . iter ( )
243+ . map ( |e| {
244+ let c = e. flags . compression ( ) ;
245+ let o = e. offset as usize ;
246+ let sig = & data[ o..o + 4 ] ;
247+ match c {
248+ Compression :: Huffman => {
249+ if sig != SIG_LUT_BYTES {
250+ return Module :: Huffman ( Err ( format ! (
251+ "Expected {SIG_LUT_BYTES:02x?} @ {o:08x}, got {sig:02x?}"
252+ ) ) ) ;
253+ }
254+ let ( header, _) = HuffmanHeader :: read_from_prefix ( & data[ o..] ) . unwrap ( ) ;
255+ let count = header. chunk_count as usize ;
256+ let co = o + HUFFMAN_HEADER_SIZE ;
257+ let ( chunks, _) =
258+ Ref :: < _ , [ u32 ] > :: from_prefix_with_elems ( & data[ co..] , count) . unwrap ( ) ;
259+ let huff = Huffman {
260+ header,
261+ chunks : chunks. to_vec ( ) ,
262+ } ;
263+ Module :: Huffman ( Ok ( ( * e, huff) ) )
264+ }
265+ Compression :: Lzma => {
266+ if sig != SIG_LZMA_BYTES {
267+ return Module :: Lzma ( Err ( format ! (
268+ "Expected {SIG_LZMA_BYTES:02x?} @ {o:08x}, got {sig:02x?}"
269+ ) ) ) ;
270+ }
271+ Module :: Lzma ( Ok ( * e) )
272+ }
273+ Compression :: Uncompressed => Module :: Uncompressed ( * e) ,
274+ Compression :: Unknown => Module :: Unknown ( * e) ,
275+ }
276+ } )
277+ . collect ( ) ;
278+
205279 Ok ( Self {
206280 manifest,
207281 header,
208- entries ,
282+ modules ,
209283 offset,
210284 size,
211285 name,
0 commit comments