Last active
September 3, 2023 14:43
-
-
Save txmutt/86fbdae347cad173f58c306ee3d28a9b to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import struct | |
import sys | |
import os | |
""" | |
extract opus files from Muse Sounds STS containers. | |
the STS format is very simple. no reverse-engineering required, just about | |
half an hour spent gazing at it in a hex editor. | |
it is as follows: | |
uint32 STS name length | |
char[nLen] STS name | |
uint32 Number of files | |
Entry[nEntries] File entries | |
File Entry: | |
uint32 Filename length | |
char[nLen] Filename | |
uint32 File start offset | |
uint32 Reserved | |
uint32 File end offset | |
uint32 Reserved | |
all offsets are absolute, and the data is located right after the file entry table with no padding before or betweem. | |
""" | |
basename = os.path.basename(sys.argv[1]).rsplit(".", maxsplit=1)[0] | |
if not os.path.exists(basename): | |
os.mkdir(basename) | |
def readString(f): | |
sLen = struct.unpack("<I", fi.read(4))[0] | |
sVal = fi.read(sLen).decode() | |
return sVal | |
with open(sys.argv[1], "rb") as fi: | |
title = readString(fi) | |
nEntries = struct.unpack("<I", fi.read(4))[0] | |
print(title) | |
print(f"{nEntries} entries\n") | |
for _ in range(nEntries): | |
name = readString(fi) | |
start, end = struct.unpack("<I4xI4x", fi.read(16)) | |
print(name) | |
seek = fi.tell() | |
fi.seek(start) | |
data = fi.read(end - start) | |
with open(f"{basename}/{name}", "wb") as fo: | |
fo.write(data) | |
fi.seek(seek) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment