Add support to modify BGI scenario strings
This commit is contained in:
76
extract_bgi.py
Normal file
76
extract_bgi.py
Normal file
@@ -0,0 +1,76 @@
|
||||
import struct
|
||||
import json
|
||||
import sys
|
||||
|
||||
|
||||
class BGIScript:
|
||||
def __init__(self, path: str):
|
||||
self.path = path
|
||||
with open(path, 'rb') as f:
|
||||
self.data = bytearray(f.read())
|
||||
self.read_header()
|
||||
self.get_instr_end()
|
||||
|
||||
def read_header(self):
|
||||
self.header_size = struct.unpack('<L', self.data[28:32])[0]
|
||||
self.iPos = 28 + self.header_size
|
||||
|
||||
def get_instr_end(self):
|
||||
finder = self.iPos
|
||||
self.len = len(self.data)
|
||||
self.last_pos = self.len
|
||||
while finder + 4 < self.len:
|
||||
d = struct.unpack('<L', self.data[finder:finder + 4])[0]
|
||||
if d == 0x1b:
|
||||
self.last_pos = finder
|
||||
finder += 4
|
||||
print(self.len)
|
||||
|
||||
def extract_string(self):
|
||||
offset = struct.unpack('<L', self.data[self.iPos:self.iPos + 4])[0]
|
||||
self.iPos += 4
|
||||
start_pos = 28 + self.header_size + offset
|
||||
if start_pos < self.last_pos:
|
||||
return None
|
||||
pos = start_pos
|
||||
while True:
|
||||
if self.data[pos] == 0x00:
|
||||
break
|
||||
pos += 1
|
||||
data = self.data[start_pos:pos]
|
||||
try:
|
||||
data = data.decode('cp932')
|
||||
except UnicodeDecodeError:
|
||||
data = data.decode('utf-8')
|
||||
data = "utf8:" + data
|
||||
return start_pos, data
|
||||
|
||||
def extract_value(self):
|
||||
offset = struct.unpack('<L', self.data[self.iPos:self.iPos + 4])[0]
|
||||
self.iPos += 4
|
||||
return offset
|
||||
|
||||
def extract_values(self):
|
||||
strings = []
|
||||
while self.iPos < self.last_pos:
|
||||
ins = struct.unpack('<L', self.data[self.iPos:self.iPos + 4])[0]
|
||||
self.iPos += 4
|
||||
if ins == 0x03:
|
||||
string = self.extract_string()
|
||||
if string is not None:
|
||||
strings.append(string)
|
||||
elif ins in [0x00, 0x01, 0x02, 0x08, 0x09, 0x0a, 0x19, 0x3f]:
|
||||
val = self.extract_value()
|
||||
return dict(strings)
|
||||
|
||||
|
||||
base = sys.argv[1]
|
||||
json_f = f"{base}.json"
|
||||
if len(sys.argv) > 2:
|
||||
json_f = sys.argv[2]
|
||||
scr = BGIScript(base)
|
||||
print(scr.header_size)
|
||||
print(scr.iPos)
|
||||
print(scr.last_pos)
|
||||
with open(json_f, "w", encoding="utf-8") as f:
|
||||
json.dump(scr.extract_values(), f, ensure_ascii=False, indent=2)
|
||||
Reference in New Issue
Block a user