Skip to content

Commit

Permalink
fixed Call of Duty 4 D3DBsp; lump offsers are now calculated correctly
Browse files Browse the repository at this point in the history
  • Loading branch information
snake-biscuits committed Nov 27, 2021
1 parent d64dd8c commit 60c7ef0
Show file tree
Hide file tree
Showing 3 changed files with 27 additions and 17 deletions.
13 changes: 8 additions & 5 deletions bsp_tool/__init__.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
"""A library for .bsp file analysis & modification"""
__all__ = ["base", "branches", "load_bsp", "lumps", "tools",
"ArkaneBsp", "GoldSrcBsp", "IdTechBsp", "InfinityWardBsp",
"ArkaneBsp", "D3DBsp", "GoldSrcBsp", "IdTechBsp", "InfinityWardBsp",
"QuakeBsp", "RavenBsp", "RespawnBsp", "RitualBsp", "ValveBsp"]

import os
Expand All @@ -21,19 +21,22 @@
BspVariant_from_file_magic = {b"2015": RitualBsp,
b"EF2!": RitualBsp,
b"FAKK": RitualBsp,
b"IBSP": IdTechBsp, # or InfinityWardBsp
b"IBSP": IdTechBsp, # + InfinityWardBsp + D3DBsp
b"rBSP": RespawnBsp,
b"RBSP": RavenBsp,
b"VBSP": ValveBsp} # and ArkaneBsp
# NOTE: if no file_magic is present, options are:
# - GoldSrcBsp
b"VBSP": ValveBsp} # + ArkaneBsp
# NOTE: if no file_magic is present:
# - QuakeBsp
# - GoldSrcBsp
# - 256-bit XOR encoded Tactical Intervention .bsp

# detect GoldSrcBsp
GoldSrc_versions = {*branches.valve.goldsrc.GAME_VERSIONS.values(),
*branches.gearbox.blue_shift.GAME_VERSIONS.values(),
*branches.gearbox.nightfire.GAME_VERSIONS.values()}
# detect InfinityWardBsp / D3DBsp
InfinityWard_versions = {v for s in branches.infinity_ward.scripts for v in s.GAME_VERSIONS.values()}
# detect QuakeBsp
Quake_versions = {*branches.id_software.quake.GAME_VERSIONS.values()}


Expand Down
4 changes: 2 additions & 2 deletions bsp_tool/branches/infinity_ward/call_of_duty4.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ class LUMP(enum.Enum):
NODES = 0x1B
LEAVES = 0x1C
LEAF_BRUSHES = 0x1D
LEAF_SURFACES = 0x1E # unused?
LEAF_SURFACES = 0x1E
COLLISION_VERTICES = 0x1F
COLLISION_TRIANGLES = 0x20
COLLISION_EDGE_WALK = 0x21
Expand Down Expand Up @@ -91,7 +91,7 @@ class LUMP(enum.Enum):

LUMP_CLASSES = {}

SPECIAL_LUMP_CLASSES = {} # "ENTITIES": shared.Entities
SPECIAL_LUMP_CLASSES = {"ENTITIES": shared.Entities}


methods = [shared.worldspawn_volume]
27 changes: 17 additions & 10 deletions bsp_tool/infinity_ward.py
Original file line number Diff line number Diff line change
Expand Up @@ -83,8 +83,9 @@ def _read_header(self, LUMP: enum.Enum) -> LumpHeader:
return header


CoD4LumpHeader = collections.namedtuple("LumpHeader", ["id", "length", "offset"])
CoD4LumpHeader = collections.namedtuple("LumpHeader", ["id", "length", "offset", "name"])
# NOTE: offset is calculated from the sum of preceding lump's lengths (+ padding)
# NOTE: name is calculated from id, just for human-readability


class D3DBsp(base.Bsp):
Expand Down Expand Up @@ -124,24 +125,24 @@ def is_related(f): return f.startswith(os.path.splitext(self.filename)[0])
self.lump_count = int.from_bytes(self.file.read(4), "little")
self.file.seek(0, 2) # move cursor to end of file
self.bsp_file_size = self.file.tell()

# load headers & lumps
self.headers = list() # order matters
self.loading_errors: Dict[str, Exception] = dict()
cursor, offset = 0, 0
cursor = 12 + (self.lump_count * 8) # end of headers; for "reading" lumps
for i in range(self.lump_count):
# read header
self.file.seek(12 + 8 * i)
_id, length = struct.unpack("2i", self.file.read(8))
assert length != 0, "cursed, idk how you got this error"
offset = cursor + (4 - cursor % 4) if cursor % 4 != 0 else cursor
if _id != 0x07: # UNKNOWN_7 is padded to every 2nd byte?
cursor = cursor + (4 - cursor & 3)
offset = cursor
# NOTE: could be wrong
cursor += length
lump_header = CoD4LumpHeader(_id, length, offset)
# NOTE: offset finding could be very incorrect
self.headers.append(lump_header)
# identify lump
LUMP_enum = self.branch.LUMP(lump_header.id)
LUMP_enum = self.branch.LUMP(_id)
LUMP_NAME = LUMP_enum.name
# NOTE: very new to this format, may be collecting the wrong data
lump_header = CoD4LumpHeader(_id, length, offset, LUMP_NAME)
self.headers.append(lump_header)
try:
if LUMP_NAME in self.branch.LUMP_CLASSES:
LumpClass = self.branch.LUMP_CLASSES[LUMP_NAME]
Expand All @@ -164,6 +165,12 @@ def is_related(f): return f.startswith(os.path.splitext(self.filename)[0])
def _read_header(self, LUMP: enum.Enum) -> CoD4LumpHeader:
raise NotImplementedError("CoD4LumpHeaders aren't ordered")

def print_headers(self):
print("LUMP_NAME", " " * 14, "OFFSET", "LENGTH")
print("-" * 38)
for header in self.headers:
print(f"{header.name:<24} {header.offset:06X} {header.length:06X}")


# NOTE: XenonBsp also exists (named after the XBox360 processor)
# -- however we aren't supporting console *.bsp

0 comments on commit 60c7ef0

Please sign in to comment.