diff options
-rw-r--r-- | atr2xfd.1 | 15 | ||||
-rw-r--r-- | atr2xfd.c | 87 | ||||
-rw-r--r-- | atr2xfd.rst | 13 |
3 files changed, 99 insertions, 16 deletions
@@ -27,7 +27,7 @@ level margin: \\n[rst2man-indent\\n[rst2man-indent-level]] .\" new: \\n[rst2man-indent\\n[rst2man-indent-level]] .in \\n[rst2man-indent\\n[rst2man-indent-level]]u .. -.TH "ATR2XFD" 1 "2024-05-03" "0.2.1" "Urchlay's Atari 8-bit Tools" +.TH "ATR2XFD" 1 "2024-05-05" "0.2.1" "Urchlay's Atari 8-bit Tools" .SH NAME atr2xfd \- Convert an Atari 8-bit ATR disk image to a raw (XFD) image .\" RST source for atr2xfd(1) man page. Convert with: @@ -43,7 +43,7 @@ atr2xfd \- Convert an Atari 8-bit ATR disk image to a raw (XFD) image \fBatrcheck\fP \fIinfile.atr\fP .SH DESCRIPTION .sp -\fBatr2xfd\fP strips the 16\-byte ATR header from an ATR image. While this +\fBatr2xfd\fP strips the 16\-byte ATR header from an ATR image. While this could be done with a command like: .INDENT 0.0 .INDENT 3.5 @@ -56,13 +56,14 @@ dd if=infile.atr outfile.xfd bs=16 skip=1 .UNINDENT .UNINDENT .sp -\&...**atr2xfd** first checks that its input is in fact an ATR file, then +\&...**atr2xfd** first checks that its input is in fact an ATR file, then checks the ATR header and reports any problems it may find. .sp -\fBatrcheck\fP performs the same checks as \fBatr2xfd\fP, but doesn\(aqt actually -write an XFD image. In fact, \fBatrcheck\fP is a symbolic link to \fBatr2xfd\fP, -which changes its behaviour (simply doesn\(aqt write any output) when -called via the link. +\fBatrcheck\fP performs the same checks as \fBatr2xfd\fP, but doesn\(aqt actually +write an XFD image. In fact, \fBatrcheck\fP is a symbolic link to \fBatr2xfd\fP, +which changes its behaviour (simply doesn\(aqt write any output) when +called via the link. \fBatrcheck\fP also examines the boot sector of the ATR, +and attempts to detect which Atari DOS is on the image (if any). .sp Neither \fBatr2xfd\fP nor \fBatrcheck\fP take any options. .SH NOTES @@ -13,9 +13,12 @@ #define SELF "atr2xfd" #define CHECK "atrcheck" +char *self = SELF; + +void classify_boot_sector(FILE *); + int main(int argc, char **argv) { char *type; - char *self = SELF; struct stat st; char infile[4096], outfile[4096]; unsigned char buf[16]; @@ -177,7 +180,9 @@ int main(int argc, char **argv) { fprintf(stderr, "%s: %s is a %s\n", self, infile, type); - fprintf(stderr, "%s: ATR image OK (no fatal errors).\n", self); + if(checkonly) { + classify_boot_sector(in); + } hparas = buf[2] + (buf[3] << 8) + (buf[6] << 16); if(hparas != paras) { @@ -197,8 +202,11 @@ int main(int argc, char **argv) { self); } - if(checkonly) + if(checkonly) { exit(0); + } + + fprintf(stderr, "%s: ATR image OK (no fatal errors).\n", self); /* Only open the output file after the ATR is known to be good */ if(strcmp(outfile, "-") == 0) { @@ -242,3 +250,76 @@ int main(int argc, char **argv) { return i; } + +/* these signatures are for the first N bytes of sector 1. */ +unsigned char dos1_sig[] = "\x00\x01\x00\x07\x00\x13\x4c\x12"; +unsigned char dos2_sig[] = "\x00\x03\x00\x07\x40\x15\x4c\x14"; +unsigned char dos3_sig[] = "\x01\x09\x00\x32\x06\x32"; +unsigned char mydos3_sig[] = "\x00\x03\x00\x07\xe0\x07\x4c\x14"; +unsigned char mydos4_sig[] = "\x4d\x03\x00\x07\xe0\x07\x4c\x14"; +unsigned char topdos11_sig[] = "\xc0\x03\x00\x07\x40\x15\x4c\x24"; +unsigned char topdos15_sig[] = "\x80\x03\x00\x07\x40\x15\x4c\x24"; +unsigned char blank_sig[] = "\x00\x00\x00\x00\x00\x00\x00\x00"; +unsigned char pico_sig[] = "\x00\x03\x00\x10\x10\x4c"; + +/* these signatures are for offset $18 of sector 1. */ +unsigned char dos2_code_sig[] = "\x36\xad\x12\x07"; +unsigned char dos25_code_sig[] = "\x35\x20\x5f\x07"; + +#define SIG_MATCH(x, y) (memcmp(x, y, sizeof(y) - 1) == 0) + +void classify_boot_sector(FILE *f) { + unsigned char buf[128]; + char *dos_type = "Unknown", *boot_text = ""; + int bootable = -1; /* -1 = unknown, 0 = no, 1 = yes */ + int i; + + /* read 1st sector... */ + if( (fread(buf, 1, 128, f) < 128) ) { + fprintf(stderr, "%s: EOF reading sector 1, truncated image.\n", self); + exit(2); + } + +#if 1 + for(i = 0; i < 8; i++) fprintf(stderr, "\\x%02x", buf[i]); + fputc('\n', stderr); +#endif + + /* now figure out what kind of boot sector this is */ + if(SIG_MATCH(buf, dos1_sig)) { + dos_type = "DOS 1.0"; + } else if(SIG_MATCH(buf, dos3_sig)) { + dos_type = "DOS 3.0"; + } else if(SIG_MATCH(buf, dos2_sig)) { + if(SIG_MATCH(buf + 0x18, dos2_code_sig)) + dos_type = "DOS 2.0"; + else if(SIG_MATCH(buf + 0x18, dos25_code_sig)) + dos_type = "DOS 2.5"; + else + dos_type = "DOS 2.0 compatible"; + bootable = (buf[14] != 0); + } else if(buf[0] == 0x00 && buf[1] == 0x03 && + (buf[32] == 0x11 || buf[32] == 0x20) && + buf[6] == 0x4c && buf[7] == 0x80) { + if(buf[32] == 0x11) + dos_type = "SpartaDOS 1.1"; + else + dos_type = "SpartaDOS >= 2"; + } else if(SIG_MATCH(buf, mydos3_sig)) { + dos_type = "MyDOS 3.x"; + } else if(SIG_MATCH(buf, mydos4_sig)) { + dos_type = "MyDOS 4.x"; + } else if(SIG_MATCH(buf, pico_sig)) { + dos_type = "MyPicoDOS 4.x"; + } else if(SIG_MATCH(buf, blank_sig)) { + dos_type = "None (empty boot sector)"; + bootable = 0; + } + + if(bootable == 0) + boot_text = ", not bootable"; + else if(bootable == 1) + boot_text = ", bootable"; + + fprintf(stderr, "%s: DOS type is: %s%s\n", self, dos_type, boot_text); +} diff --git a/atr2xfd.rst b/atr2xfd.rst index fac2ed4..cdf041c 100644 --- a/atr2xfd.rst +++ b/atr2xfd.rst @@ -22,18 +22,19 @@ SYNOPSIS DESCRIPTION =========== -**atr2xfd** strips the 16-byte ATR header from an ATR image. While this +**atr2xfd** strips the 16-byte ATR header from an ATR image. While this could be done with a command like:: dd if=infile.atr outfile.xfd bs=16 skip=1 -...**atr2xfd** first checks that its input is in fact an ATR file, then +...**atr2xfd** first checks that its input is in fact an ATR file, then checks the ATR header and reports any problems it may find. -**atrcheck** performs the same checks as **atr2xfd**, but doesn't actually -write an XFD image. In fact, **atrcheck** is a symbolic link to **atr2xfd**, -which changes its behaviour (simply doesn't write any output) when -called via the link. +**atrcheck** performs the same checks as **atr2xfd**, but doesn't actually +write an XFD image. In fact, **atrcheck** is a symbolic link to **atr2xfd**, +which changes its behaviour (simply doesn't write any output) when +called via the link. **atrcheck** also examines the boot sector of the ATR, +and attempts to detect which Atari DOS is on the image (if any). Neither **atr2xfd** nor **atrcheck** take any options. |