Skip to content

Instantly share code, notes, and snippets.

@bbbradsmith
Last active June 18, 2021 03:52
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 bbbradsmith/e74766f1fb36d0f62262f4187fbe7de4 to your computer and use it in GitHub Desktop.
Save bbbradsmith/e74766f1fb36d0f62262f4187fbe7de4 to your computer and use it in GitHub Desktop.
Pasti STX disk image track merge utility (Atari ST)
#!/usr/bin/env python3
#
# Pasti .STX Atari ST disk image merger
# Allows combining of tracks from separate STX files,
# for cases where we can only dump part of a disk at a time.
#
# Usage:
# stx_main("a.stx")
# stx_add("b.stx")
# stx_add("c.stx")
# stx_out("merged.stx")
#
# Based on Pasti reverse engineering:
# http://info-coach.fr/atari/documents/_mydoc/Pasti-documentation.pdf
#
# See also: stx_dump.py
# https://gist.github.com/bbbradsmith/a0fb690f366c902e96f25a8351a5c46c
#
# Brad Smith, 2021
# http://rainwarrior.ca
#
import struct
header = None
tracks = [{},{}]
def stx_print_header(d):
h = struct.unpack("<BBBBHHHBBL",d[0:16])
print("id: $%02X $%02X $%02X $%02X \"%c%c%c\"+$%02X" % (h[0:4]+h[0:4]))
print("version: %d" % h[4])
print("tool: $%04X" % h[5])
print("reserved: $%04X" % h[6])
print("tracks: %d" % h[7])
print("revision: %d" % h[8])
print("reserved: $%08X" % h[9])
def stx_print_track_header(d):
t = struct.unpack("<LLHHHBB",d[0:16])
tside = t[5]>>7
tnum = t[5]&0x7F
print("Track: %d:%02d %2d sectors, %d bytes" % (tside,tnum,t[2],t[0]))
def stx_main(filename):
global header, tracks
print("Main Pasti: " + filename)
d = open(filename,"rb").read()
stx_print_header(d)
header = struct.unpack("<BBBBHHHBBL",d[0:16])
p = 16
for t in range(0,header[7]):
thead = struct.unpack("<LLHHHBB",d[p:p+16])
stx_print_track_header(d[p:p+16])
tlen = thead[0]
tside = thead[5]>>7
tnum = thead[5]&0x7F
if tnum in tracks[tside]:
print("Warning: duplicate track %d:%02d" % (tside,tnum))
tracks[tside][tnum] = d[p:p+tlen]
p += tlen
print(".")
def stx_add(filename):
global tracks
print("Add Pasti: " + filename)
d = open(filename,"rb").read()
h = struct.unpack("<BBBBHHHBBL",d[0:16])
stx_print_header(d)
p = 16
for t in range(0,h[7]):
thead = struct.unpack("<LLHHHBB",d[p:p+16])
stx_print_track_header(d[p:p+16])
tlen = thead[0]
tside = thead[5]>>7
tnum = thead[5]&0x7F
if tnum in tracks[tside]:
print("Warning: duplicate track %d:%02d" % (tside,tnum))
tracks[tside][tnum] = d[p:p+tlen]
p += tlen
print(".")
def stx_out(filename):
global header, tracks
assert header,"No main loaded? Use stx_main first."
print("Out Pasti: " + filename)
f = open(filename,"wb")
tcount = len(tracks[0]) + len(tracks[1])
header = list(header)
header[7] = tcount
header = tuple(header)
dh = struct.pack("<BBBBHHHBBL",*header)
stx_print_header(dh)
f.write(dh)
for i in range(256):
if i in tracks[0]:
stx_print_track_header(tracks[0][i])
f.write(tracks[0][i])
if i in tracks[1]:
stx_print_track_header(tracks[1][i])
f.write(tracks[1][i])
print(".")
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment