1use crate::error::{MulReaderError, MulReaderResult};
2use crate::mul::MulReader;
3use byteorder::{LittleEndian, ReadBytesExt};
4use std::io::{Cursor, Read, Seek, SeekFrom};
5
6pub const BLOCK_SIZE: usize = 196;
7
8#[derive(Clone, Copy, PartialEq, Eq, Debug)]
10pub struct Cell {
11 pub graphic: u16,
13 pub altitude: i8,
17}
18
19#[derive(Clone, Copy, PartialEq, Eq, Debug)]
23pub struct Block {
24 pub checksum: u32,
26 pub cells: [Cell; 64],
29}
30
31#[derive(Clone, Copy, PartialEq, Eq, Debug)]
33pub struct StaticLocation {
34 pub object_id: u16,
36 pub x: u8,
38 pub y: u8,
40 pub altitude: i8,
42 pub checksum: u16,
44}
45
46impl StaticLocation {
47 pub fn color_idx(&self) -> u16 {
49 self.object_id + 16384
50 }
51}
52
53pub fn read_block<T: Read + Seek>(data_reader: &mut T, id: u32) -> MulReaderResult<Block> {
55 data_reader.seek(SeekFrom::Start((id * BLOCK_SIZE as u32) as u64))?;
57 let mut block = Block {
59 checksum: data_reader.read_u32::<LittleEndian>()?,
60 cells: [Cell {
61 graphic: 0,
62 altitude: 0,
63 }; 64],
64 };
65 for i in 0..64 {
67 block.cells[i] = Cell {
68 graphic: data_reader.read_u16::<LittleEndian>()?,
69 altitude: data_reader.read_i8()?,
70 };
71 }
72 Ok(block)
73}
74
75pub fn read_block_statics<T: Read + Seek>(
77 mul_reader: &mut MulReader<T>,
78 id: u32,
79) -> MulReaderResult<Vec<StaticLocation>> {
80 let raw = mul_reader.read(id)?;
81 let len = raw.data.len();
82 if len % 7 != 0 {
83 return Err(MulReaderError::UnexpectedSize {
84 expected: (len + (len % 7)) as u32,
85 found: len as u32,
86 });
87 }
88 let mut reader = Cursor::new(raw.data);
89 let mut statics = vec![];
90 for _i in 0..(len / 7) {
91 let object_id = reader.read_u16::<LittleEndian>()?;
92 let x = reader.read_u8()?;
93 let y = reader.read_u8()?;
94 let altitude = reader.read_i8()?;
95 let checksum = reader.read_u16::<LittleEndian>()?;
96 statics.push(StaticLocation {
97 object_id,
98 x,
99 y,
100 altitude,
101 checksum,
102 });
103 }
104 Ok(statics)
105}