Added ability to read linedef lumps. Also added all the test functionality to make sure we are reading the linedefs correctly.
115 lines
3.9 KiB
Rust
115 lines
3.9 KiB
Rust
use std::{fs::File, io::Read, path::Path};
|
|
|
|
use super::header::Header;
|
|
use crate::lumps::{LinedefLump, Lump, LumpType, VertexLump};
|
|
use crate::types::{Linedef, Vertex};
|
|
use crate::utils::{read_ascii, read_i16_le, read_u32_le, validate_wad};
|
|
|
|
pub struct WADFile {
|
|
pub path: String,
|
|
pub wad_id: String,
|
|
pub num_lumps: u32,
|
|
pub dir_offset: u32,
|
|
pub directory: Vec<Lump>,
|
|
pub data: Vec<u8>,
|
|
}
|
|
|
|
impl WADFile {
|
|
pub fn new(path: String) -> Self {
|
|
if !(validate_wad(path.as_str()).unwrap()) {
|
|
panic!();
|
|
}
|
|
|
|
let file_path = Path::new(path.as_str());
|
|
let mut wad_file = File::open(file_path).unwrap();
|
|
let file_size = wad_file.metadata().unwrap().len() as usize;
|
|
let mut file_buffer: Vec<u8> = Vec::with_capacity(file_size);
|
|
|
|
wad_file.read_to_end(&mut file_buffer).unwrap();
|
|
|
|
let wad_header = Header::read_data(&file_buffer[0..12]);
|
|
|
|
let mut lump_dir: Vec<Lump> = Vec::with_capacity(wad_header.num_lumps as usize);
|
|
let offset = wad_header.dir_offset;
|
|
|
|
for entry in 0..wad_header.num_lumps {
|
|
let startpos = (offset + 16 * entry) as usize;
|
|
let lump_offset = read_u32_le(&file_buffer[startpos..startpos + 4]);
|
|
let size = read_u32_le(&file_buffer[startpos + 4..startpos + 8]);
|
|
let name = read_ascii(&file_buffer[startpos + 8..startpos + 16]);
|
|
let lump_type = match name.as_str() {
|
|
"VERTEXES" => LumpType::Vertex,
|
|
"LINEDEFS" => LumpType::Linedef,
|
|
_ => LumpType::Unknown,
|
|
};
|
|
lump_dir.push(Lump {
|
|
name,
|
|
offset: lump_offset,
|
|
lump_type,
|
|
size,
|
|
});
|
|
}
|
|
|
|
Self {
|
|
path,
|
|
wad_id: wad_header.wad_id,
|
|
num_lumps: wad_header.num_lumps,
|
|
dir_offset: wad_header.dir_offset,
|
|
directory: lump_dir,
|
|
data: file_buffer,
|
|
}
|
|
}
|
|
|
|
pub fn get_vertex_lump(&self, lump: &Lump) -> VertexLump {
|
|
let lump_offset = lump.offset as usize;
|
|
let lump_size = lump.size as usize;
|
|
let lump_data = &self.data[lump_offset..lump_offset + lump_size];
|
|
let lump_entries: usize = lump_size / 4;
|
|
let mut vertexes: Vec<Vertex> = Vec::with_capacity(lump_entries);
|
|
|
|
for entry in 0..lump_entries {
|
|
let startpos = entry * 4;
|
|
let vertex_x = read_i16_le(&lump_data[startpos..startpos + 2]);
|
|
let vertex_y = read_i16_le(&lump_data[startpos + 2..startpos + 4]);
|
|
|
|
vertexes.push(Vertex {
|
|
x: vertex_x,
|
|
y: vertex_y,
|
|
});
|
|
}
|
|
|
|
VertexLump { vertexes }
|
|
}
|
|
|
|
pub fn get_linedef_lump(&self, lump: &Lump) -> LinedefLump {
|
|
let lump_offset = lump.offset as usize;
|
|
let lump_size = lump.size as usize;
|
|
let lump_data = &self.data[lump_offset..lump_offset + lump_size];
|
|
let lump_entries = lump_size / 14;
|
|
let mut linedefs: Vec<Linedef> = Vec::with_capacity(lump_entries);
|
|
|
|
for entry in 0..lump_entries {
|
|
let startpos = entry * 14;
|
|
let vertex1 = read_i16_le(&lump_data[startpos..startpos + 2]);
|
|
let vertex2 = read_i16_le(&lump_data[startpos + 2..startpos + 4]);
|
|
let flags = read_i16_le(&lump_data[startpos + 4..startpos + 6]);
|
|
let special = read_i16_le(&lump_data[startpos + 6..startpos + 8]);
|
|
let tag = read_i16_le(&lump_data[startpos + 8..startpos + 10]);
|
|
let front_sidedef = read_i16_le(&lump_data[startpos + 10..startpos + 12]);
|
|
let back_sidedef = read_i16_le(&lump_data[startpos + 12..startpos + 14]);
|
|
|
|
linedefs.push(Linedef {
|
|
vertex1,
|
|
vertex2,
|
|
flags,
|
|
special,
|
|
tag,
|
|
front_sidedef,
|
|
back_sidedef,
|
|
});
|
|
}
|
|
|
|
LinedefLump { linedefs }
|
|
}
|
|
}
|