Start a debug tool for looking through level data #954
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
This adds a tool to dump data from a level file. For now, it focuses on the drawable trees and the tfrag stuff.
The idea is that we can use this tool to learn about the tfrag format in detail before starting on the tfrag decompilation and porting. So far, I have learned the tree format for tfrag and drawables.
At the highest level is the level file itself, which is a
bsp-header
. It contains adrawable-tree-array
, which contains a small number ofdrawable-tree
s. (~1 to 15?).Each of these
drawable-tree
s is a different kind, distinguished by its type. Different types of trees go to different renderers. For example, there is adrawable-tree-lowres-tfrag
, adrawable-tree-instance-tie
, and even adrawable-tree-actor
. It is possible to have multiple trees of the same type, as some trees seem to have a maximum size - for example adrawable-tree-instance-tie
can have only 43 different prototypes, so it is common to see a few of these. These trees are the thing passed to the appropriate renderers. All the trees for all the levels get put in thebackground-work
structure, which is then read by the renderers.The
drawable-tree-tfrag
contains all the "normal" tfrag data. There are other trees liketrans
,dirt
,ice
,lowres
, andlowres-trans
, which are only present if the level actually has this type of geometry. As far as I can tell, the special ones follow the same format, but I haven't checked this in detail.The
drawable-tree-tfrag
contains a small number (1 to 6?) ofdrawable-inline-array
. They all refer to the same set oftfragment
s (the actual things to draw), but have a different tree structure.The
drawable-inline-array
containsdraw-node
s. Eachdraw-node
contains between 0 and 8 children. The children are represented by a pointer to an inline array of children. The children can be eitherdraw-node
s ortfragment
s. All the children are always the same type.The first
drawable-inline-array
in thedrawable-tree-tfrag
is the full tree structure. It starts with some number of children that is smaller than 8. And from there on, all children aredraw-node
(always 8 or fewer children) or atfragment
directly. So this is the deepest possible tree. I believe the max depth seen is 6?The next
drawable-inline-array
starts with a list of all nodes at with a depth of 1 from one of the top-level nodes of the first. So this has at most 64 entries. Like the previous tree, all the children from here on have 8 or fewer children.This pattern continues. The n-th
drawable-inline-array
is a list of all nodes at depth n in the "real" tree.There are two tricks to this:
First, if the
drawable-inline-array
containsdraw-node
s, the type is actuallydrawable-inline-array-node
. Unlike adraw-node
, which can only contain 8 children, adrawable-inline-array
can contain a huge number of children. The finaldrawable-inline-array
is a list of a all children at the final depth, so it's always an array oftfragment
. In this case, the type of thedrawable-inline-array
is adrawable-inline-array-tfrag
, and it's just a giant list of all thetfragment
s in the level.The second trick is that the
draw-node
s andtfragment
s are stored only once, even if they appear in multipledrawable-inline-array
s. They used the weird "node = length + pointer to inline array of children" format and sorted nodes by depth to enable this.