#!/usr/bin/env python3
# Dump the FUT atom name table (atom index -> key string) from CardsDLL.
# Table at VA 0x1802d2760 is an array of char* pointers into .rdata.
import struct, sys

DLL = "/tmp/fut/cardsdll.dll"
data = open(DLL, "rb").read()

# (VA_start, size, file_off) from objdump -h
SECTIONS = [
    (0x180001000, 0x1e3f62, 0x400),    # .text
    (0x1801e5000, 0xa4094, 0x1e4400),  # .rdata
    (0x18028a000, 0x54000, 0x288600),  # .data
]

def va_to_off(va):
    for start, size, off in SECTIONS:
        if start <= va < start + size:
            return off + (va - start)
    return None

def read_cstr(va, maxlen=128):
    off = va_to_off(va)
    if off is None:
        return None
    end = data.find(b"\x00", off, off + maxlen)
    if end < 0:
        return None
    try:
        return data[off:end].decode("ascii")
    except UnicodeDecodeError:
        return None

TABLE_VA = 0x1802d2760
off = va_to_off(TABLE_VA)
atoms = {}
for i in range(0, 1200):
    ptr = struct.unpack_from("<Q", data, off + i * 8)[0]
    if ptr == 0:
        s = None
    else:
        s = read_cstr(ptr)
    if s is None:
        # allow a few gaps then stop if we run off the end
        if i > 40 and all(struct.unpack_from("<Q", data, off + (i + k) * 8)[0] == 0 for k in range(4)):
            break
        continue
    if s.isprintable() and 1 <= len(s) <= 40:
        atoms[i] = s

for i in sorted(atoms):
    print(f"{i}\t0x{i:x}\t{atoms[i]}")
print(f"# total {len(atoms)} atoms", file=sys.stderr)
