aboutsummaryrefslogtreecommitdiff
path: root/crates/fparkan-terrain-format
diff options
context:
space:
mode:
authorValentin Popov <valentin@popov.link>2026-07-18 16:20:37 +0300
committerValentin Popov <valentin@popov.link>2026-07-18 16:20:37 +0300
commit5577a04a4093a529d2c64a24e1ab4c72941b5ff1 (patch)
tree48a647126370ee94aed31ac603f1383511ead536 /crates/fparkan-terrain-format
parent8b211f9a1cdd562488f66ab0be1c9a96291c7944 (diff)
downloadfparkan-5577a04a4093a529d2c64a24e1ab4c72941b5ff1.tar.xz
fparkan-5577a04a4093a529d2c64a24e1ab4c72941b5ff1.zip
feat(terrain): expose slot render dispatch
Diffstat (limited to 'crates/fparkan-terrain-format')
-rw-r--r--crates/fparkan-terrain-format/src/lib.rs47
1 files changed, 47 insertions, 0 deletions
diff --git a/crates/fparkan-terrain-format/src/lib.rs b/crates/fparkan-terrain-format/src/lib.rs
index 6e018c0..0051b82 100644
--- a/crates/fparkan-terrain-format/src/lib.rs
+++ b/crates/fparkan-terrain-format/src/lib.rs
@@ -183,6 +183,33 @@ pub struct TerrainSlotTable {
pub slots_raw: Vec<[u8; SLOT_STRIDE]>,
}
+/// The proven front fields of one 68-byte terrain slot record.
+///
+/// `Terrain.dll!CLandscape` supplies these fields to `GetShade`'s terrain
+/// batch dispatcher: `pair_table_index` selects the pointer-table entry and
+/// `pair_count` is the number of adjacent `u16` pairs to process. The pair
+/// payload and the later material/blend interpretation remain external to the
+/// disk record.
+#[derive(Clone, Copy, Debug, Eq, PartialEq)]
+pub struct TerrainSlotRenderDispatch {
+ /// Index into the runtime pair-pointer table.
+ pub pair_table_index: u16,
+ /// Number of adjacent `u16` pairs in that selected payload.
+ pub pair_count: u16,
+}
+
+impl TerrainSlotTable {
+ /// Returns the render-dispatch header for one decoded slot record.
+ #[must_use]
+ pub fn render_dispatch(&self, slot_index: usize) -> Option<TerrainSlotRenderDispatch> {
+ let raw = self.slots_raw.get(slot_index)?;
+ Some(TerrainSlotRenderDispatch {
+ pair_table_index: u16::from_le_bytes([raw[0], raw[1]]),
+ pair_count: u16::from_le_bytes([raw[2], raw[3]]),
+ })
+ }
+}
+
/// Land mesh document.
#[derive(Clone, Debug, PartialEq)]
pub struct LandMeshDocument {
@@ -1461,6 +1488,26 @@ mod tests {
}
#[test]
+ fn slot_render_dispatch_retains_pair_table_index_and_count() {
+ let mut raw = [0_u8; SLOT_STRIDE];
+ raw[..2].copy_from_slice(&7_u16.to_le_bytes());
+ raw[2..4].copy_from_slice(&3_u16.to_le_bytes());
+ let slots = TerrainSlotTable {
+ header_raw: SLOT_HEADER_ZERO.to_vec(),
+ slots_raw: vec![raw],
+ };
+
+ assert_eq!(
+ slots.render_dispatch(0),
+ Some(TerrainSlotRenderDispatch {
+ pair_table_index: 7,
+ pair_count: 3,
+ })
+ );
+ assert_eq!(slots.render_dispatch(1), None);
+ }
+
+ #[test]
fn terrain_material_tag_decodes_two_sidecar_selectors() {
let mut raw_face = face([0, 1, 2], [None, None, None]);
raw_face[4..6].copy_from_slice(&0x0102_u16.to_le_bytes());