Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,11 @@
* add: kk49: Support for COTW hp_nepal
* add: kk49: Support for COTW hp_sh
* add: verrasse: Support for COTW the Angler (EGS version)
* add: verrasse: Support for Mad Max (v1.0.3.0 + All DLCs)
* add: verrasse: Support for theHunter Classic (ARC/TAB)
* add: verrasse: Support for theHunter Primal (ARC/TAB)
* add: verrasse: Update for latest COTW the Angler (alpheus, belisama, ceto, doris)
* add: verrasse / r-one: Added more filenames for COTW the Angler
* add: verrasse: Support for Mad Max (v1.0.3.0 + All DLCs)
* add: ash: Added rtpc_v3_flat.ksy
* fix: kk49: ADF5 file determination for COTW save files
* fix: kk49: hack? empty `gdc/global.gdcc` in COTW now?
Expand Down
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,8 @@ Support varies among the games, people are activily using **deca** for GenZero a
|---|---|
|Avalanche Studios / Systemic Reaction|Generation Zero®|
|Avalanche Studios / Expansive Worlds|theHunter™: Call of the Wild|
|Avalanche Studios / Expansive Worlds|theHunter™: Classic|
|Avalanche Studios / Expansive Worlds|theHunter™: Primal|
|Avalanche Studios / Expansive Worlds|Call of the Wild: The Angler™|
|Avalanche Studios|Just Cause 3|
|Avalanche Studios|Just Cause 4|
Expand Down
3 changes: 3 additions & 0 deletions python/deca/deca/db_commands.py
Original file line number Diff line number Diff line change
Expand Up @@ -730,6 +730,9 @@ def process_adf_initial(self, node: VfsNode, db: DbWrap):
except EDecaMissingAdfType as ae:
self._comm.log('DBCmd: Missing ADF Type {:08x} in {} {} {}'.format(
ae.type_id, node.v_hash_to_str(), node.v_path, node.p_path))
except Exception as e:
self._comm.log('DBCmd: Error parsing ADF [{}] in {} {} {}'.format(
repr(e), node.v_hash_to_str(), node.v_path, node.p_path))
return False

def process_rtpc_initial(self, node: VfsNode, db: DbWrap):
Expand Down
2 changes: 1 addition & 1 deletion python/deca/deca/fast_file.py
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ def f(buffer, n_buffer, pos, count):
ff_read_f64s = make_read_many(np.float64)


@njit(**params)
@njit(**params, boundscheck=True)
def ff_read_strz(buffer, n_buffer, pos):
pos0 = pos
while buffer[pos] != 0 and pos < n_buffer:
Expand Down
3 changes: 3 additions & 0 deletions python/deca/deca/ff_adf.py
Original file line number Diff line number Diff line change
Expand Up @@ -1088,6 +1088,9 @@ def process_adf_in_exe(self, exepath, node_uid):
self.type_missing.add((ae.type_id, node_uid))
self._type_map_updated = True

except Exception as e:
print('Error parsing {:08}.adf in EXE-file at position 0x{}: [{}]'.format(poss, hex(poss), repr(e)))

adf_sub_files.append((poss, adf.total_size))

self.typedefs_add(adf.map_typedef)
Expand Down
95 changes: 94 additions & 1 deletion python/deca/deca/ff_arc_tab.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,11 @@ def tab_file_load(filename, ver):

if magic == b'\x00\x08\x00\x00':

if 2 == ver:
if 10 == ver:
tab_file = TabFileV10()
elif 11 == ver:
tab_file = TabFileV11()
elif 2 == ver:
tab_file = TabFileV2()
else:
unknown_version = True
Expand Down Expand Up @@ -69,6 +73,48 @@ def serialize(self, f):
raise NotImplementedError('Interface Class')


class TabFileV10(TabFileBase):
def __init__(self):
TabFileBase.__init__(self)

def deserialize(self, f):
self.magic = f.read(4)

self.file_table = []
self.file_hash_map = {}
entry = TabEntryFileV10()
while entry.deserialize(f):
self.file_table.append(entry)
self.file_hash_map[entry.hashname] = entry
entry = TabEntryFileV10()

return True

def serialize(self, f):
raise NotImplementedError('Interface Class')


class TabFileV11(TabFileBase):
def __init__(self):
TabFileBase.__init__(self)

def deserialize(self, f):
self.magic = f.read(4)

self.file_table = []
self.file_hash_map = {}
entry = TabEntryFileV11()
while entry.deserialize(f):
self.file_table.append(entry)
self.file_hash_map[entry.hashname] = entry
entry = TabEntryFileV11()

return True

def serialize(self, f):
raise NotImplementedError('Interface Class')


class TabFileV2(TabFileBase):
def __init__(self):
TabFileBase.__init__(self)
Expand Down Expand Up @@ -262,6 +308,53 @@ def debug(self):
]


class TabEntryFileV10(TabEntryFileBase):
def __init__(self):
TabEntryFileBase.__init__(self)

def deserialize(self, f):
try:
self.hashname = f.read_u32(raise_on_no_data=True)
self.offset = f.read_u32(raise_on_no_data=True)
self.size_c = f.read_u32(raise_on_no_data=True)
self.size_u = self.size_c
self.compression_type = compression_00_none
self.compression_flags = f.read_u32(raise_on_no_data=True)

if f.debug:
self.debug()
except EDecaOutOfData:
return False

return True

def serialize(self, f):
raise NotImplementedError('TODO')


class TabEntryFileV11(TabEntryFileBase):
def __init__(self):
TabEntryFileBase.__init__(self)

def deserialize(self, f):
try:
self.hashname = f.read_u32(raise_on_no_data=True)
self.offset = f.read_u32(raise_on_no_data=True)
self.size_c = f.read_u32(raise_on_no_data=True)
self.size_u = self.size_c
self.compression_type = compression_00_none

if f.debug:
self.debug()
except EDecaOutOfData:
return False

return True

def serialize(self, f):
raise NotImplementedError('TODO')


class TabEntryFileV2(TabEntryFileBase):
def __init__(self):
TabEntryFileBase.__init__(self)
Expand Down
15 changes: 12 additions & 3 deletions python/deca_gui/deca_gui/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -239,11 +239,19 @@ def update_ui_state(self):
self.ui.bt_mod_build.setEnabled(False)
self.ui.action_external_add.setEnabled(False)
self.ui.action_make_web_map.setEnabled(False)
self.ui.tab_extract.setEnabled(False)
self.ui.tab_modding.setEnabled(False)
self.ui.tab_3d_gltf2.setEnabled(False)
self.ui.tab_utils.setEnabled(False)
else:
self.ui.bt_mod_build_folder_show.setEnabled(True)
self.ui.bt_mod_build.setEnabled(True)
self.ui.action_external_add.setEnabled(True)
self.ui.action_make_web_map.setEnabled(True)
self.ui.tab_extract.setEnabled(True)
self.ui.tab_modding.setEnabled(True)
self.ui.tab_3d_gltf2.setEnabled(True)
self.ui.tab_utils.setEnabled(True)
self.filter_text_changed()

def update_select_state(self, vfs_view):
Expand All @@ -266,10 +274,10 @@ def update_select_state(self, vfs_view):
self.ui.bt_mod_prep.setText('PREP MOD: {}'.format(str_vpaths))

if self.ui.chkbx_mod_build_subset.isChecked():
self.ui.bt_mod_build.setText('Build Mod Subset: {}'.format(str_vpaths))
self.ui.bt_mod_build.setText('BUILD MOD SUBSET: {}'.format(str_vpaths))
self.ui.bt_mod_build.setEnabled(any_selected)
else:
self.ui.bt_mod_build.setText('Build Mod All')
self.ui.bt_mod_build.setText('BUILD MOD ALL')

def vnode_2click_selected(self, uids: List[int]):
self.current_uids = uids
Expand Down Expand Up @@ -371,7 +379,8 @@ def slot_extract_gltf_clicked(self, checked):
texture_format=self.ui.cmbbx_texture_format.currentText())

def slot_mod_build_subset_clicked(self, checked):
self.update_select_state(self.vfs_view_current())
if self.vfs_view_current():
self.update_select_state(self.vfs_view_current())

def slot_mod_prep_clicked(self, checked):
if self.vfs_view_current():
Expand Down
Loading