-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathcollmismatch.py
More file actions
executable file
·118 lines (99 loc) · 4.93 KB
/
Copy pathcollmismatch.py
File metadata and controls
executable file
·118 lines (99 loc) · 4.93 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
#!/usr/bin/env python3
import sys
import os
import struct
import codec
import myth_collection
import mesh_tag
import mesh2info
import mono2tag
import mons_tag
import loadtags
DEBUG = (os.environ.get('DEBUG') == '1')
def main(game_directory, level, plugin_names):
"""
Load Myth game tags and plugins and output markers for a mesh
"""
(game_version, tags, entrypoint_map, data_map, cutscenes) = loadtags.load_tags(game_directory, plugin_names)
try:
if level:
for mesh_id in mesh2info.mesh_entries(game_version, level, entrypoint_map, tags, plugin_names):
parse_mesh_markers(game_version, tags, data_map, mesh_id)
else:
mono2tag.print_entrypoint_map(entrypoint_map, plugin_names=plugin_names)
except (struct.error, UnicodeDecodeError) as e:
raise ValueError(f"Error processing binary data: {e}")
def parse_mesh_markers(game_version, tags, data_map, mesh_id):
(mesh_tag_location, mesh_tag_header, mesh_tag_data) = loadtags.get_tag_info(tags, data_map, 'mesh', mesh_id)
mesh_header = mesh_tag.parse_header(mesh_tag_data)
(palette, orphans) = mesh_tag.parse_markers(mesh_header, mesh_tag_data)
log_mismatches(game_version, mesh_tag_location, mesh_tag_header, tags, data_map, palette, orphans)
def check_unit_collection_mismatch(game_version, tags, data_map, tag_type, tag_id):
if tag_type == 'unit':
(unit_location, unit_header, unit_data) = loadtags.get_tag_info(tags, data_map, tag_type, tag_id)
if unit_data:
unit = mons_tag.parse_unit(unit_data)
mons_tag_id = codec.decode_string(unit.mons)
(mons_location, mons_header, mons_data) = loadtags.get_tag_info(tags, data_map, 'mons', mons_tag_id)
mons_coll = None
if mons_data:
mons = mons_tag.parse_tag(game_version, mons_data)
mons_coll = codec.decode_string(mons.collection_tag)
core_tag_id = codec.decode_string(unit.core)
(core_location, core_header, core_data) = loadtags.get_tag_info(tags, data_map, 'core', core_tag_id)
core_coll = None
if core_data:
core_tag = myth_collection.parse_collection_ref(core_data)
core_coll = codec.decode_string(core_tag.collection_tag)
if mons_coll and core_coll and mons_coll != core_coll:
(mons_coll_location, mons_coll_header) = loadtags.lookup_tag_header(tags, '.256', mons_coll)
(core_coll_location, core_coll_header) = loadtags.lookup_tag_header(tags, '.256', core_coll)
return (tag_type, unit_header, unit_location, tag_id, [
('mons', mons_header, mons_location, mons_tag_id, [
('.256', mons_coll_header, mons_coll_location, mons_coll, [])
]),
('core', core_header, core_location, core_tag_id, [
('.256', core_coll_header, core_coll_location, core_coll, [])
])
])
def log_mismatches(game_version, mesh_tag_location, mesh_tag_header, tags, data_map, palette, orphans):
mismatched_unit_collections = {}
for palette_type, p_list in palette.items():
for palette_index, p_val in enumerate(p_list):
tag_id = p_val['tag']
tag_type = mesh_tag.Marker2Tag.get(palette_type)
(location, tag_header) = loadtags.lookup_tag_header(tags, tag_type, tag_id)
mismatch_tree = check_unit_collection_mismatch(game_version, tags, data_map, tag_type, tag_id)
if mismatch_tree:
mismatched_unit_collections[tag_id] = mismatch_tree
print_mismatches(mismatched_unit_collections, mesh_tag_header, mesh_tag_location)
def print_mismatches(mismatched_unit_collections, mesh_tag_header, mesh_tag_location):
if len(mismatched_unit_collections):
print(
f'Mismatched collections: {mesh_tag_header.tag_id} {mesh_tag_header.name} {mesh_tag_location}',
mismatched_unit_collections.keys()
)
for unit_tag, mismatch_tree in mismatched_unit_collections.items():
traverse_mismatch_tree(*mismatch_tree)
def traverse_mismatch_tree(tag_type, tag_header, location, tag_id, children, depth=0):
print(f'{' '*depth}- {tag_type}.{tag_id} [{tag_header.name if tag_header else None}] ({location})')
for child in children:
traverse_mismatch_tree(*child, depth=depth+1)
if __name__ == "__main__":
if len(sys.argv) < 2:
print(f"Usage: python3 {sys.argv[0]} <game_directory> [<level> [<plugin_names> ...]]")
sys.exit(1)
game_directory = sys.argv[1]
level = None
plugin_names = []
if len(sys.argv) > 2:
level = sys.argv[2]
if len(sys.argv) > 3:
plugin_names = sys.argv[3:]
try:
main(game_directory, level, plugin_names)
except KeyboardInterrupt:
sys.exit(130)
except BrokenPipeError:
sys.stdout = None
sys.exit(1)