-
Notifications
You must be signed in to change notification settings - Fork 1
/
cob_file.py
105 lines (74 loc) · 2.87 KB
/
cob_file.py
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
# written by ashdnazg https://github.com/ashdnazg/bos2cob
# released under the GNU GPL v3 license
import struct
PACK_FORMAT = "<%dL"
COB_HEADER_FIELDS = (
"VersionSignature",
"NumberOfScripts",
"NumberOfPieces",
"TotalScriptLen",
"NumberOfStaticVars",
"Unknown_2",
"OffsetToScriptCodeIndexArray",
"OffsetToScriptNameOffsetArray",
"OffsetToPieceNameOffsetArray",
"OffsetToScriptCode",
"OffsetToNamesArray",
)
class COB(object):
def write_strings(self, strings):
offsets = []
content = b""
for s in strings:
offsets.append(self._offset)
s += '\0'
content += s.encode('utf-8')
self._offset += len(s)
return offsets, content
def write_functions_code_array(self, functions_code_array):
code_offsets = []
code_offset = 0
for code in functions_code_array:
self._content += code
code_offsets.append(code_offset)
code_offset += len(code) // 4
self._offset += len(code)
return code_offsets
def write_array(self, array, is_header = False):
if is_header:
self._content = struct.pack(PACK_FORMAT % (len(array),), *array) + self._content
else:
self._content += struct.pack(PACK_FORMAT % (len(array),), *array)
self._offset += len(array) * 4
def __init__(self, function_names, functions_code, piece_names, static_vars, sound_names, cobVersion = 4):
self._content = b""
header = {
"VersionSignature" : cobVersion,
"NumberOfScripts" : len(function_names),
"NumberOfPieces" : len(piece_names),
"TotalScriptLen" : sum(len(c) for c in functions_code.values()) // 4,
"NumberOfStaticVars" : len(static_vars),
"Unknown_2" : 0,
"NumberOfSounds" : len(sound_names)
}
self._offset = len(COB_HEADER_FIELDS) * 4
header['OffsetToScriptCode'] = self._offset
code_offsets = self.write_functions_code_array(functions_code[n] for n in function_names)
header['OffsetToScriptCodeIndexArray'] = self._offset
self.write_array(code_offsets)
#reserving space for later
header['OffsetToScriptNameOffsetArray'] = self._offset
self._offset += len(function_names) * 4
header['OffsetToPieceNameOffsetArray'] = self._offset
self._offset += len(piece_names) * 4
header['OffsetToNamesArray'] = self._offset
script_name_offsets, script_name_content = self.write_strings(function_names)
piece_name_offsets, piece_name_content = self.write_strings(piece_names)
self._offset = header['OffsetToScriptNameOffsetArray']
self.write_array(script_name_offsets)
self.write_array(piece_name_offsets)
self.write_array(tuple(header[n] for n in COB_HEADER_FIELDS), True)
self._content += script_name_content + piece_name_content
self._header = header
def get_content(self):
return self._content