-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathBasicFileInfo_Decode_V6.py
More file actions
126 lines (99 loc) · 3.22 KB
/
Copy pathBasicFileInfo_Decode_V6.py
File metadata and controls
126 lines (99 loc) · 3.22 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
119
120
121
122
123
124
125
126
import argparse
import json
import pathlib
import re
import sys
STDOUT_ENCODING = sys.stdout.encoding or "utf-8"
def safe_print(text=""):
try:
print(text)
except UnicodeEncodeError:
print(text.encode(STDOUT_ENCODING, "backslashreplace").decode(STDOUT_ENCODING))
def asciiish_from_utf16(blob: bytes, endian: str) -> str:
txt = blob.decode("utf-16-" + endian, errors="ignore")
out = []
for ch in txt:
code = ord(ch)
if ch in "\r\n":
out.append("\n")
elif 32 <= code <= 126:
out.append(ch)
else:
out.append(" ")
s = "".join(out)
s = re.sub(r"[ \t]+", " ", s)
s = re.sub(r"\n+", "\n", s)
return s.strip()
def parse_kv_lines(lines):
meta = {}
leftovers = []
for line in lines:
if ":" in line:
key, value = line.split(":", 1)
key = key.strip()
value = value.strip()
snake = re.sub(r"[^0-9a-zA-Z]+", "_", key).strip("_").lower()
meta[snake] = value
else:
leftovers.append(line)
if "orksharing" in meta and "worksharing" not in meta:
meta["worksharing"] = meta.pop("orksharing")
return meta, leftovers
def main():
parser = argparse.ArgumentParser(
description="Decode and show EVERYTHING from BasicFileInfo.bin"
)
parser.add_argument(
"path",
nargs="?",
default=r"racbasicsamplefamily/BasicFileInfo.bin",
help="Default: racbasicsamplefamily/BasicFileInfo.bin",
)
parser.add_argument(
"--json-out",
action="store_true",
help="Write parsed metadata JSON next to bin",
)
args = parser.parse_args()
path = pathlib.Path(args.path)
blob = path.read_bytes()
safe_print(f"File: {path}")
safe_print(f"Size: {len(blob)} bytes\n")
# --- decode both ---
clean_le = asciiish_from_utf16(blob, "le")
clean_be = asciiish_from_utf16(blob, "be")
# --- split to lines ---
be_lines = [ln for ln in clean_be.split("\n") if ln.strip()]
le_lines = [ln for ln in clean_le.split("\n") if ln.strip()]
# --- parse BE key/values ---
meta, leftovers = parse_kv_lines(be_lines)
# Add fallback format from LE
if "format" not in meta:
m = re.search(r"\b(\d{4})\b", clean_le)
if m:
meta["format"] = m.group(1)
# -------------------------
# PRINT EVERYTHING CLEANLY
# -------------------------
safe_print("=== UTF-16 BE decoded (ASCII-ish) ===")
safe_print(clean_be + "\n")
safe_print("=== UTF-16 LE decoded (ASCII-ish) ===")
safe_print(clean_le + "\n")
safe_print("=== Parsed Key/Value fields ===")
for k in sorted(meta.keys()):
safe_print(f" {k}: {meta[k]}")
safe_print()
safe_print("=== Remaining 'garbage' / unparsed lines ===")
if leftovers:
for ln in leftovers:
safe_print(f" {ln}")
else:
safe_print(" <none>")
safe_print()
# Optional JSON file
if args.json_out:
json_path = path.with_name(path.stem + "_decoded.json")
json_path.write_text(json.dumps(meta, indent=2), encoding="utf-8")
safe_print(f"JSON written: {json_path}")
if __name__ == "__main__":
main()