Files
BT411/context/asset-formats.md
T
arcattackandClaude Fable 5 2e9c78d604 Gait: the AUTHENTIC walk lean -- interior/exterior clip sets, level cockpit + leaning mechs (task #59)
The MadCat (and every leg-mech) leans -8deg into a walk / -11deg into a run --
an authored jointhip (hingex) pose in the EXTERIOR gait clips that the walk/run
CYCLE clips never rebind, so it HOLDS.  The 1995 game keeps a separate INTERIOR
('i'-suffix) clip set for the mech you PILOT: those shake jointshakey (cockpit
rattle) and OMIT jointhip, so your own view stays level while everyone else sees
you lean.  The port had this entirely dead -- the local cockpit mech pitched
-8deg into the ground (user-reported "staring at the ground").

ROOT CAUSE (two stacked bugs):
- The authentic ctor clip-set gate (@part_012.c:10308-10320) was reconstructed
  as no-op stubs: LoadLowDetailBody/LoadHighDetailBody MISLABELED the
  FUN_004a80d4/86c8 GAIT-CLIP loader addresses as a "body LOD" pair, so the gate
  did nothing and a separate unconditional LoadLocomotionClips always loaded
  EXTERIOR clips.
- LoadLocomotionClipsExt (the interior loader) was a stub aliased to the
  exterior loader.

FIX:
- Reconstructed the real 4-char INTERIOR loader (byte-exact vs @004a86c8; the
  'i'-suffix table dumped from the exe @0x10d74d: swri/wwri/wwli/...; all 18
  base clips confirmed present in BTL4.RES for mad/blh/ava).
- Fixed the ctor gate: getenv("L4VIEWEXT") || (instanceFlags&0xC)==4 -> exterior
  (replicant / forced external view); else -> interior (local cockpit master).
  Removed the mislabeling no-op stubs.
- PORT ADAPTATION (MaintainViewClipSet, per-frame in PerformAndWatch): the port
  never sets the replicant COPY bit (all MP mechs build as local masters --
  heat-sim/scoring/torso-watcher-connect all run on both, by design), so the
  ctor gate lands everyone on interior.  Pick the set by VIEWPOINT instead: the
  mech you pilot keeps interior (level cockpit), every other mech flips once to
  exterior (the lean).  Reloads only on a viewpoint-status change; the sets
  share stride data so the swap is seamless.  Model pointers stashed at ctor.

VERIFIED live (BT_HIP_LOG probe): your walking mech writes jointhip=0 (level);
the peer's replica in the other pod's view leans at exactly -8.0/-11.1deg --
the authored clip values.  A/B control: L4VIEWEXT=1 forces the walking master
back to 74 sustained -8/-11 writes.

KB: locomotion.md ("NO walk lean" audit conclusion CORRECTED -- the lean is
authored + sustained + clip-set-specific), asset-formats.md (.ANI parses
pitch/yaw/roll for all joint types; KeyJointPos translation; cycle clips carry
no pitch), open-questions.md (item closed).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-13 14:46:22 -05:00

62 lines
4.0 KiB
Markdown

---
id: asset-formats
title: "Asset Formats — MOD/SKL/ANI/BMF/BSL/textures/gauges/collision"
status: established
source_sections: "PROGRESS_LOG.md §5; docs/ASSET_PIPELINE.md; docs/BGF_FORMAT.md"
related_topics: [bgf-format, rendering, locomotion, combat-damage, gauges-hud]
key_terms: [MOD, SKL, ANI, BMF, BSL, VTX, SLD, DZM, PCC, GIM, material-ramp]
---
# Asset Formats
All reverse-engineered. Geometry (BGF) has its own topic ([[bgf-format]]); the full pixel/material
spec is `docs/ASSET_PIPELINE.md`. Full list: `docs/PROGRESS_LOG.md §5`.
## Definition / skeleton / animation
- **`.MOD`** — INI mech/object definition: skeleton, skins, collision, gauges, physics, animations,
class. The `.MOD` physics (MoverMass/drag/MaxAcceleration) governed thrust VEHICLES + collisions,
NOT walk gait ([[locomotion]]). [T1]
- **`.SKL`** — INI joint skeleton. `[joint] parent=, Type=(hingex/y/z|ball|balltranslate),
Object=part.bgf, dzone=, tranx/y/z, pitch/yaw/roll`. Build a **DCS tree**; neutral pose ≈
translations (pyr≈0). [T1]
- **`.ANI`** — INI keyframe animation. `[HEADER] framecount/framerate(30)/skeletonfile`; `[frameN]`
joint→**`pitch yaw roll` radians for EVERY joint type** (ANIMTOOL.cpp:140-142 parses the triple as
EulerAngles unconditionally — the old "balltranslate→translate" note was wrong [T0]); a
balltranslate joint ADDITIONALLY gets a per-frame translation from the separate **`[KeyJointPos]`**
section (ANIMTOOL.cpp:478-483 packs EulerAngles+Vector3D; JMOVER/seqctl apply SetRotation +
SetTranslation). For the root `jointlocal`, KeyJointPos.y = the gait vertical bob;
`[RootTranslation]` per-keyframe `x y z` where **`.z` = forward root SPEED** (units/s). Walk anims
have no baked root translation — forward motion is animation-driven from `.z` ([[locomotion]]).
Walk/run CYCLE clips author NO body pitch — root keys are a ≤1.5° roll sway only; the authored
LEAN lives in the transition (`rwl/rwr/wrl/wrr` jointhip ~7-12°) + `bmp` stagger (~25°) clips
(2026-07-13 sweep of all 331 source ANIs). [T1]
## Materials / textures
- **`.BMF`** — `DIV-BIZ2` (FILETYPE=1) material+texture LIBRARY (no pixels). Material → DIFFUSE color
+ `MATERIAL_TEXTURE`→texture→`TEXTURE_MAP` image basename. Tags: `0x18 BITSLICE` (BSL slice select),
`0x28` ramp ref, `0x26` emissive, `0x30/0x31` ramp def. [T1]
- **Texture pixels:** `.tga` (Truevision), `.vtx` (`DIV-VTX2`, trailing RGB), and **`.bsl`**
(`DIV-BSL2` — a BIT-SLICED container: w*h 32-bit texel words holding SIX independent 4-bit
GRAYSCALE sub-images (nibble pair-swapped, byte 0 pad) OR RGB444/RGBA4444 (sliceType 7/8). The BMF
`0x18 BITSLICE` tag picks the slice, absent=0). Decoding BSL as RGB = the "rainbow/graffiti mech"
bug. Reference reader: `DivLoader/VGCDivLoader.cpp:323-410`; archive-only — in-repo reimplementation: `engine/MUNGA_L4/image.cpp`. [T2]
- **`.VMF`** — `DIV-VIZ2` material SOURCE. Carries the `SCROLL` animation + `MAP{}` image binding for
effects (beams/muzzle/smoke/sky). THE key effects asset ([[rendering]]). [T2]
- **[[material-ramp]]** — the IG board colours no-normal geometry by a 2-endpoint RAMP; details in
[[bgf-format]] + [[rendering]]. [T2]
## Collision / damage / subsystems
- **`.SLD`** collision solids (Block/YCyl/Cone/Ramp/Wedge). Terrain is modeled AS collision volumes;
see [[locomotion]] ground model + [[combat-damage]]. [T1]
- **`.DZM`** = INI damage-zone→material map (mech skin damage states). **`.DMG`/`.TBL`** damage
zones/tables, **`.SUB`** subsystems (weapon params — DischargeTime/RechargeRate/WeaponRange),
**`.CTL`** control maps. [T1]
## Cockpit HUD assets ([[gauges-hud]])
- **`.GIM`** vector MFD/radar line maps + **`.GAT`** color table; **`.PCC`** ZSoft PCX 8-bit gauge
rasters (fonts helv15/helv42, label strips, dials). [T1]
## Key Relationships
- Geometry detail: [[bgf-format]]; pixel/material spec: `docs/ASSET_PIPELINE.md`.
- Consumed by: [[rendering]], [[locomotion]] (SKL/ANI), [[combat-damage]] (SLD/DZM/SUB), [[gauges-hud]] (GIM/PCC).