mirror of
https://git.k-space.ee/arti/vt1200.git
synced 2026-10-30 12:03:54 +02:00
Andrew Morton's Unix-hosted assembler/linker for the TMS34010, fetched from the gsptools archive and patched to build on x86-64. The K&R sources silently truncate pointers there: implicit int parameter declarations and fixed-argument printf wrappers. The patch fixes those and the flex 2.6 yy_init mismatch. hello.as34.g is harness/hello-world/hello.asm in as34 syntax. as34/ld34 reproduce the GSPA-built payload byte-for-byte (82 bytes, md5 db91788991ebba476b55a11127a36475), and the MAME hello.lua run reports the same markers, the same 1024-word VRAM block and a byte-identical frame. build.sh downloads the upstream tarball at build time (sha256 pinned); the tree is not vendored.
75 lines
2.4 KiB
Python
Executable File
75 lines
2.4 KiB
Python
Executable File
#!/usr/bin/env python3
|
|
"""Extract the loadable .text bytes from an as34/ld34 g.out file.
|
|
|
|
g.out is not COFF. It uses the .go/linkhdr format from binutils/link.h
|
|
(LINKMAGIC 0x3abf782e), packed with #pragma pack(2).
|
|
|
|
IMPORTANT: link.h declares the header fields that hold addresses and sizes
|
|
as `long`. On the original 32-bit Unix hosts that is 4 bytes; on x86-64 it
|
|
is 8, so the written header is 156 bytes here instead of the historical 80.
|
|
as34 and ld34 are both rebuilt with the same compiler, so they agree with
|
|
each other and with this parser. A stable on-disk format would need `long`
|
|
changed to int32_t in link.h.
|
|
|
|
Layout as written by this 64-bit build (offsets in bytes):
|
|
|
|
off field
|
|
0 short swapped
|
|
2 long magic
|
|
10 short flags
|
|
12 long time
|
|
20 long textstart file position of text
|
|
28 long textsize size in BYTES
|
|
36 long datastart
|
|
44 long datasize
|
|
52 long bsssize
|
|
60 long relocstart
|
|
68 long nrelocs
|
|
76 long symtabstart
|
|
84 long nsyms
|
|
92 long stabstart
|
|
100 long nstabs
|
|
108 long stringstart
|
|
116 long stringSize
|
|
124 long textLoadAddress BIT address
|
|
132 long dataLoadAddress
|
|
140 long bssLoadAddress
|
|
148 long entrypoint BIT address
|
|
"""
|
|
import hashlib
|
|
import struct
|
|
import sys
|
|
|
|
LINKMAGIC = 0x3ABF782E
|
|
|
|
|
|
def main(out_path, bin_path):
|
|
d = open(out_path, "rb").read()
|
|
fields = struct.unpack_from("<hqh" + "q" * 18, d, 0)
|
|
(swapped, magic, flags, _time, textstart, textsize,
|
|
_datastart, _datasize, _bsssize, _relocstart, _nrelocs,
|
|
_symtabstart, _nsyms, _stabstart, _nstabs,
|
|
_stringstart, _stringsize,
|
|
textload, _dataload, _bssload, entry) = fields
|
|
|
|
if magic != LINKMAGIC:
|
|
sys.exit("extract: bad magic %#010x" % magic)
|
|
if swapped:
|
|
sys.exit("extract: byte-swapped header not handled")
|
|
|
|
payload = d[textstart:textstart + textsize]
|
|
if len(payload) != textsize:
|
|
sys.exit("extract: truncated text (%d of %d bytes)"
|
|
% (len(payload), textsize))
|
|
|
|
open(bin_path, "wb").write(payload)
|
|
print("origin=%08X (bits) size=%d bytes entry=%08X file_offset=%#x md5=%s"
|
|
% (textload, textsize, entry, textstart,
|
|
hashlib.md5(payload).hexdigest()))
|
|
|
|
|
|
if __name__ == "__main__":
|
|
if len(sys.argv) != 3:
|
|
sys.exit("usage: extract.py hello.out payload.bin")
|
|
main(sys.argv[1], sys.argv[2])
|