1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
use std::io::Read;
use byteorder::{BigEndian, ReadBytesExt};
use flate2::read::ZlibDecoder;
use super::{ChunkInfo, CompressedSizes, CompressionParameters, DcxHeader};
use crate::sprj::formats::read::ReadFormatsExt;
pub enum DcxDecoder<R: Read> {
Deflate(ZlibDecoder<R>),
}
pub fn read_compression_params<R: Read>(
mut reader: R,
) -> Result<CompressionParameters, std::io::Error> {
let mut algo = [0u8; 4];
reader.read_exact(&mut algo)?;
let algo_settings_len = reader.read_u32::<BigEndian>()?;
let mut algo_settings = vec![0; algo_settings_len as usize - 12];
reader.read_exact(&mut algo_settings[..])?;
let compression_level = algo_settings[0];
match &algo {
b"DFLT" => Ok(CompressionParameters::Deflate { compression_level }),
_ => unimplemented!(),
}
}
impl<R: Read> DcxDecoder<R> {
pub fn new(mut reader: R) -> Result<(DcxHeader, DcxDecoder<R>), std::io::Error> {
reader.read_magic(b"DCX\0")?;
let version = reader.read_u32::<BigEndian>()?;
let _size_offset = reader.read_u32::<BigEndian>()?;
let _params_offset = reader.read_u32::<BigEndian>()?;
let _chunk_info_offset = reader.read_u32::<BigEndian>()?;
let _data_offset = reader.read_u32::<BigEndian>()?;
reader.read_magic(b"DCS\0")?;
let uncompressed_size = reader.read_u32::<BigEndian>()?;
let compressed_size = reader.read_u32::<BigEndian>()?;
let compressed_sizes = CompressedSizes {
uncompressed_size,
compressed_size,
};
reader.read_magic(b"DCP\0")?;
let compression_parameters = read_compression_params(&mut reader)?;
reader.read_magic(b"DCA\0")?;
let _chunk_info_len = reader.read_u32::<BigEndian>()?;
let chunk_info = ChunkInfo {};
let decoder = compression_parameters.create_decoder(reader);
let header = DcxHeader {
version,
compression_parameters,
compressed_sizes,
chunk_info,
};
Ok((header, decoder))
}
}
impl<R: Read> Read for DcxDecoder<R> {
fn read(&mut self, buf: &mut [u8]) -> std::io::Result<usize> {
match self {
DcxDecoder::Deflate(compressor) => compressor.read(buf),
}
}
}