flic/codec/
codec001.rs

1//! Codec for chunk type 1 = FLI_WRUN.
2
3use std::io::{Cursor,Read};
4use byteorder::LittleEndian as LE;
5use byteorder::ReadBytesExt;
6
7use ::{FlicError,FlicResult,RasterMut};
8
9/// Magic for a FLI_WRUN chunk.
10///
11/// This is likely to be used by very old development FLICs only.
12pub const FLI_WRUN: u16 = 1;
13
14/// Decode a FLI_WRUN chunk.
15///
16/// The following logic only makes sense for 320x200 FLICs.
17pub fn decode_fli_wrun(src: &[u8], dst: &mut RasterMut)
18        -> FlicResult<()> {
19    if dst.x != 0 || dst.y != 0
20            || dst.w != 320 || dst.h != 200 || dst.stride != 320 {
21        return Err(FlicError::WrongResolution);
22    }
23
24    let mut r = Cursor::new(src);
25    let mut idx0 = 0;
26
27    let count = r.read_u16::<LE>()?;
28    for _ in 0..count {
29        // Read a short, but cast to a signed byte.
30        let signed_length = (r.read_u16::<LE>()? as i8) as i32;
31
32        if signed_length >= 0 {
33            let start = idx0;
34            let end = start + 2 * signed_length as usize;
35            if end > dst.buf.len() {
36                return Err(FlicError::Corrupted);
37            }
38
39            let c0 = r.read_u8()?;
40            let c1 = r.read_u8()?;
41            for e in &mut dst.buf[start..end].chunks_mut(2) {
42                e[0] = c0;
43                e[1] = c1;
44            }
45
46            idx0 = end;
47        } else {
48            let start = idx0;
49            let end = start + 2 * (-signed_length) as usize;
50            if end > dst.buf.len() {
51                return Err(FlicError::Corrupted);
52            }
53
54            r.read_exact(&mut dst.buf[start..end])?;
55
56            idx0 = end;
57        }
58    }
59
60    Ok(())
61}
62
63#[cfg(test)]
64mod tests {
65    use ::RasterMut;
66    use super::decode_fli_wrun;
67
68    #[test]
69    fn test_decode_fli_wrun() {
70        let src = [
71            0x02, 0x00, // count 2
72            0x03, 0xFF, // length = 0xFF03 = +3 (and some garbage)
73            0xCD, 0xAB, // data
74            0xFC, 0xFF, // length = 0xFFFC = -4 (and some garbage)
75            0x23, 0x01, 0x67, 0x45, 0xAB, 0x89, 0xEF, 0xCD ];
76
77        let expected = [
78            0xCD, 0xAB, 0xCD, 0xAB, 0xCD, 0xAB,
79            0x23, 0x01, 0x67, 0x45, 0xAB, 0x89, 0xEF, 0xCD,
80            0x00, 0x00 ];
81
82        const SCREEN_W: usize = 320;
83        const SCREEN_H: usize = 200;
84        let mut buf = [0; SCREEN_W * SCREEN_H];
85        let mut pal = [0; 3 * 256];
86
87        let res = decode_fli_wrun(&src,
88                &mut RasterMut::new(SCREEN_W, SCREEN_H, &mut buf, &mut pal));
89        assert!(res.is_ok());
90        assert_eq!(&buf[0..16], &expected[..]);
91    }
92}