aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--atr2xfd.115
-rw-r--r--atr2xfd.c87
-rw-r--r--atr2xfd.rst13
3 files changed, 99 insertions, 16 deletions
diff --git a/atr2xfd.1 b/atr2xfd.1
index 1eca729..a192c2c 100644
--- a/atr2xfd.1
+++ b/atr2xfd.1
@@ -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
diff --git a/atr2xfd.c b/atr2xfd.c
index c941266..bed24fe 100644
--- a/atr2xfd.c
+++ b/atr2xfd.c
@@ -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.