115 lines
3.4 KiB
Python
115 lines
3.4 KiB
Python
import struct
|
|
import sys
|
|
import json
|
|
|
|
|
|
class BPScript:
|
|
def __init__(self, path: str):
|
|
self.path = path
|
|
with open(path, 'rb') as f:
|
|
self.data = bytearray(f.read())
|
|
self.len = len(self.data)
|
|
self.read_header()
|
|
self.iPos = self.header_size
|
|
|
|
def read_header(self):
|
|
self.header_size = struct.unpack('<L', self.data[0:4])[0]
|
|
self.instr_size = struct.unpack('<L', self.data[4:8])[0]
|
|
if self.len != self.header_size + self.instr_size:
|
|
raise ValueError("Invalid BPScript file size")
|
|
self.iPos = self.header_size
|
|
self.last_pos = 0
|
|
while self.iPos < self.len - 4:
|
|
d = struct.unpack('<L', self.data[self.iPos:self.iPos + 4])[0]
|
|
if d == 0x17:
|
|
self.last_pos = self.iPos
|
|
self.iPos += 4
|
|
else:
|
|
self.iPos += 1
|
|
|
|
def extract_string(self):
|
|
offset = struct.unpack('<h', self.data[self.iPos:self.iPos + 2])[0]
|
|
start_pos = self.iPos + offset - 1
|
|
self.iPos += 2
|
|
if start_pos < self.last_pos or start_pos >= self.len or ((start_pos > self.last_pos + 1) and self.data[start_pos-1] != 0):
|
|
self.iPos -= 2
|
|
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
|
|
if not data:
|
|
return None
|
|
return start_pos, data
|
|
|
|
def extract_values(self):
|
|
strings = []
|
|
self.iPos = self.header_size
|
|
while self.iPos < self.last_pos:
|
|
ins = self.data[self.iPos]
|
|
self.iPos += 1
|
|
if ins == 0x5:
|
|
try:
|
|
t = self.extract_string()
|
|
if t is not None:
|
|
strings.append(t)
|
|
except UnicodeDecodeError:
|
|
self.iPos -= 2
|
|
return dict(strings)
|
|
|
|
def extract_strings(self):
|
|
self.iPos = self.last_pos + 1
|
|
while self.data[self.iPos] == 0:
|
|
self.iPos += 1
|
|
strings = []
|
|
start_pos = self.iPos
|
|
while self.iPos < self.len:
|
|
if self.data[self.iPos] == 0:
|
|
data = self.data[start_pos:self.iPos]
|
|
try:
|
|
data = data.decode('cp932')
|
|
except UnicodeDecodeError:
|
|
data = data.decode('utf-8')
|
|
data = "utf8:" + data
|
|
if data:
|
|
strings.append((start_pos, data))
|
|
start_pos = self.iPos + 1
|
|
self.iPos += 1
|
|
return dict(strings)
|
|
|
|
|
|
base = sys.argv[1]
|
|
json_f = f"{base}.json"
|
|
if len(sys.argv) > 2:
|
|
json_f = sys.argv[2]
|
|
scr = BPScript(base)
|
|
print(scr.header_size)
|
|
print(scr.last_pos)
|
|
a = scr.extract_values()
|
|
print(a)
|
|
b = None
|
|
try:
|
|
b = scr.extract_strings()
|
|
print(b)
|
|
print(len(a), len(b))
|
|
missing = {}
|
|
for key in b.keys():
|
|
if key not in a:
|
|
missing[key] = b[key]
|
|
for key in a.keys():
|
|
if key not in b:
|
|
missing[key] = a[key]
|
|
print(missing)
|
|
print(len(missing))
|
|
except UnicodeDecodeError:
|
|
pass
|
|
with open(json_f, "w", encoding="utf-8") as f:
|
|
json.dump(b if b else a, f, ensure_ascii=False, indent=2)
|