Last active
June 18, 2021 03:52
-
-
Save bbbradsmith/e74766f1fb36d0f62262f4187fbe7de4 to your computer and use it in GitHub Desktop.
Pasti STX disk image track merge utility (Atari ST)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/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