Skip to content

Instantly share code, notes, and snippets.

@txmutt
Last active September 3, 2023 14:43
Show Gist options
  • Save txmutt/86fbdae347cad173f58c306ee3d28a9b to your computer and use it in GitHub Desktop.
Save txmutt/86fbdae347cad173f58c306ee3d28a9b to your computer and use it in GitHub Desktop.
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