Skip to content

Instantly share code, notes, and snippets.

@mariomadproductions
Last active October 12, 2021 20:37
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save mariomadproductions/9a649f43cbf3960cbdc4699c2ee97c66 to your computer and use it in GitHub Desktop.
Save mariomadproductions/9a649f43cbf3960cbdc4699c2ee97c66 to your computer and use it in GitHub Desktop.
tmd-printer by ihaveamac
#!/usr/bin/env python3
from argparse import ArgumentParser
from glob import iglob
from os.path import join
from sys import argv, exit, stderr
parser = ArgumentParser(description='Prints Content IDs and Title Versions.')
parser.add_argument('items', help='Path to TMDs or a folder containing TMDs.', nargs='*')
parser.add_argument('-verbose', help='Extra output.', action='store_true')
group = parser.add_mutually_exclusive_group(required=True)
group.add_argument('-id', help='Print Title ID', action='store_true')
group.add_argument('-version', help='Print Title Versions', action='store_true')
group.add_argument('-content', help='Print Content IDs', action='store_true')
a = parser.parse_args()
def debug(*args, **kwargs):
if a.verbose:
print('DEBUG:', *args, file=stderr, **kwargs)
items = set()
def parse_tmd(fn):
with open(fn, 'rb') as f:
debug('Reading', fn)
f.seek(0x18C)
title_id = f.read(8)
if a.id:
items.add(title_id.hex())
return # all we need then
if a.version:
f.seek(0x1DC)
title_version = int.from_bytes(f.read(2), 'big')
debug(f'Adding title version', title_version)
items.add(title_version)
elif a.content:
f.seek(0x1DE)
content_count = int.from_bytes(f.read(2), 'big')
debug('Content count:', content_count)
if title_id[1] in {4, 5}: # not 3DS or Wii U
seek_to = 0xB04
read_size = 0x30
else:
seek_to = 0x1E4
read_size = 0x24
f.seek(seek_to)
for _ in range(content_count):
chunk = f.read(read_size)
c_id = chunk[0:4].hex()
debug('Adding', c_id)
items.add(c_id)
if title_id[1] == 5 and int.from_bytes(chunk[6:8], 'big') & 2: # check type if Wii U for h3 file
debug('Adding h3 for', c_id)
items.add(c_id + '.h3')
for arg in a.items:
try:
parse_tmd(arg)
except IsADirectoryError:
for p in iglob(join(arg, 'tmd.*')):
parse_tmd(p)
def sorter(x):
if a.id:
return int(x, 16)
elif a.version:
return x
elif a.content:
return int(x[0:8], 16)
debug('Sorting')
for t in sorted(items, key=sorter):
print(t)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment