Invoke on something like dump/*.cst. Needs regex postprocessing, as is common.
1 #!python
2
3 import os, sys, zlib
4 from struct import unpack
5
6 for fname in sys.argv[1:]:
7 with open(fname, "rb") as f:
8 print(f"decompressing {fname}")
9 fdata = f.read()
10
11 header = fdata[:8].decode("utf-8")
12 if header != "CatScene":
13 continue
14
15 compressed_len = unpack("<I", bytes(fdata[0x08:0x0C]))[0]
16 decompressed_len = unpack("<I", bytes(fdata[0x0C:0x10]))[0]
17
18 decompressed = zlib.decompress(bytes(fdata[0x10:compressed_len+0x10]))
19 fdata = decompressed
20
21 with open(fname.replace(".cst", "")+".bin", "wb") as f2:
22 f2.write(fdata)
23
24 flen = unpack("<I", bytes(fdata[0x00:0x04]))[0]
25 ranges = unpack("<I", bytes(fdata[0x04:0x08]))[0]
26 ranges_bytes = unpack("<I", bytes(fdata[0x08:0x0C]))[0]
27 headerlen = unpack("<I", bytes(fdata[0x0C:0x10]))[0]
28
29 # header structure is something like
30 # uint32 filelen
31 # uint32 num_ranges
32 # uint32 len_ranges_bytes
33 # uint32 len_header_bytes (excluding these first four words)
34
35 # struct[num_ranges] {uint32, uint32} // where first is length of range, second is index of range
36 # uint32[entries] // indexed into by ranges
37 # with this part (the two arrays together) being len_header_bytes bytes long
38
39 # we don't actually need any of that for just script ripping
40
41 code = fdata[headerlen+0x10:]
42
43 i = 0
44 while len(code[i:]) > 0:
45 # guess
46 oplen = code[i]
47 if oplen != 1:
48 print("oplen error")
49 exit()
50 i += 1
51
52 op = code[i]
53 i += 1
54 if op in [0x20, 0x21, 0x30]:
55 string = []
56 char = code[i]
57 while char != 0:
58 string += [char]
59 i += 1
60 char = code[i]
61 i += 1
62 string = bytes(string).decode("cp932")
63
64 if op == 0x20:
65 print(string.replace("\n", "").replace("\\n",""), end="")
66 elif op in [0x02]: # linefeed
67 print("")
68 i += 1
69 elif op in [0x03]: # some other kind of linefeed (grisaia)
70 print("")
71 i += 1
72 else:
73 print(f"\n\nunknown op {op:02X} at {i+headerlen+0x10:08X} in {fname}\n")
74 exit()
75 print("")