1
0
Fork 0
mirror of https://codeberg.org/icewind/vbsp.git synced 2026-06-03 18:54:05 +02:00

valve bsp wip

This commit is contained in:
Robin Appelman 2020-06-25 00:25:48 +02:00
commit 08a1c53535
6 changed files with 568 additions and 712 deletions

149
src/bspfile.rs Normal file
View file

@ -0,0 +1,149 @@
use crate::*;
use binread::io::Cursor;
use binread::BinReaderExt;
use std::borrow::Cow;
pub struct BspFile<'a> {
data: &'a [u8],
directories: Directories,
header: Header,
}
impl<'a> BspFile<'a> {
pub fn new(data: &'a [u8]) -> BspResult<Self> {
const EXPECTED_HEADER: Header = Header {
v: b'V',
b: b'B',
s: b'S',
p: b'P',
};
// TODO: Use this to decide on the version to parse it as
const EXPECTED_VERSION: u32 = 0x14;
let mut cursor = Cursor::new(data);
let header: Header = cursor.read_le()?;
let version: u32 = cursor.read_le()?;
if header != EXPECTED_HEADER || version != EXPECTED_VERSION {
return Err(BspError::UnexpectedHeader(header));
}
let directories = cursor.read_le()?;
let map_version: u32 = cursor.read_le()?;
dbg!(map_version);
Ok(BspFile {
data,
directories,
header,
})
}
pub fn directories(&self) -> &Directories {
&self.directories
}
pub fn header(&self) -> &Header {
&self.header
}
pub fn lump_reader(&self, lump: LumpType) -> BspResult<LumpReader<Cursor<Cow<[u8]>>>> {
let data = self.get_lump(lump)?;
Ok(LumpReader::new(data))
}
fn get_lump(&self, lump: LumpType) -> BspResult<Cow<[u8]>> {
let lump = &self.directories[lump];
let raw_data = self
.data
.get(lump.offset as usize..lump.offset as usize + lump.length as usize)
.ok_or_else(|| BspError::LumpOutOfBounds(lump.clone()))?;
Ok(match lump.ident {
0 => Cow::Borrowed(raw_data),
_ => {
let mut data: Vec<u8> = Vec::with_capacity(lump.ident as usize);
let mut cursor = Cursor::new(raw_data);
lzma_rs::lzma_decompress(&mut cursor, &mut data)
.map_err(BspError::LumpDecompressError)?;
if data.len() != lump.ident as usize {
return Err(BspError::UnexpectedUncompressedLumpSize {
got: data.len() as u32,
expected: lump.ident,
});
}
Cow::Owned(data)
}
})
}
}
#[derive(Clone, Copy, Debug, Eq, PartialEq, Hash)]
pub enum LumpType {
Entities,
Planes,
TextureData,
Vertices,
Visibility,
Nodes,
TextureInfo,
Faces,
Lighting,
Occlusion,
Leaves,
FaceIds,
Edges,
SurfaceEdges,
Models,
WorldLights,
LeafFaces,
LeafBrushes,
Brushes,
BrushSides,
Areas,
AreaPortals,
Unused0,
Unused1,
Unused2,
Unused3,
DisplayInfo,
OriginalFaces,
PhysDisplay,
PhysCollide,
VertNormals,
VertNormalIndices,
DisplayLightMapAlphas,
DisplayVertices,
DisplayLightMapSamplePositions,
GameLump,
LeafWaterData,
Primitives,
PrimVertices,
PrimIndices,
PakFile,
ClipPortalVertices,
CubeMaps,
TextureDataStringData,
TextureDataStringTable,
Overlays,
LeafMinimumDistanceToWater,
FaceMacroTextureInfo,
DisplayTris,
PhysicsCollideSurface,
WaterOverlays,
LeafAmbientIndexHdr,
LeafAmbientIndex,
LightingHdr,
WorldLightsHdr,
LeafAmbientLightingHdr,
LeafAmbientLighting,
XZipPakFile,
FacesHdr,
MapFlags,
OverlayFades,
OverlaySystemLevels,
PhysLevel,
DisplayMultiBlend,
}

1021
src/lib.rs

File diff suppressed because it is too large Load diff

83
src/reader.rs Normal file
View file

@ -0,0 +1,83 @@
use crate::*;
use binread::BinReaderExt;
use bv::BitVec;
use std::borrow::Cow;
use std::mem::size_of;
pub struct LumpReader<R> {
inner: R,
length: usize,
}
impl<'a> LumpReader<Cursor<Cow<'a, [u8]>>> {
pub fn new(data: Cow<'a, [u8]>) -> Self {
let length = data.len();
let reader = Cursor::new(data);
LumpReader {
inner: reader,
length,
}
}
}
impl<R: BinReaderExt + Read> LumpReader<R> {
pub fn read_entities(&mut self) -> BspResult<Entities> {
let mut entities = String::with_capacity(self.length);
self.inner.read_to_string(&mut entities)?;
Ok(Entities { entities })
}
pub fn read_vec<F, T>(&mut self, mut f: F) -> BspResult<Vec<T>>
where
F: FnMut(&mut LumpReader<R>) -> BspResult<T>,
{
let num_entries = self.length / size_of::<T>();
let mut entries = Vec::with_capacity(num_entries);
for _ in 0..num_entries {
entries.push(f(self)?);
}
Ok(entries)
}
pub fn read<T: BinRead>(&mut self) -> BspResult<T> {
Ok(self.inner.read_le()?)
}
pub fn read_visdata(&mut self) -> BspResult<VisData> {
if (self.length as usize) < std::mem::size_of::<u32>() * 2 {
return Ok(VisData::default());
}
let n_vecs = self.inner.read_le()?;
let sz_vecs = self.inner.read_le()?;
let vecs_size = n_vecs as u64 * sz_vecs as u64;
let mut vecs = Vec::with_capacity(
vecs_size
.try_into()
.map_err(|e| io::Error::new(io::ErrorKind::InvalidData, e))?,
);
self.inner
.by_ref()
.take(vecs_size as u64)
.read_to_end(&mut vecs)?;
if (vecs.len() as u64) < vecs_size {
return Err(BspError::UnexpectedEOF);
}
if (vecs.len() as u64) > vecs_size {
return Err(BspError::UnexpectedExtraData);
}
let vecs = BitVec::from_bits(vecs);
let vis_data = VisData {
n_vecs,
sz_vecs,
vecs,
};
Ok(vis_data)
}
}