From 08fe7fe4b6dd9c2a4cb9326f211dd336a19b71d0 Mon Sep 17 00:00:00 2001 From: Stephen Heumann Date: Wed, 17 Oct 2018 20:14:40 -0500 Subject: [PATCH] Add support for DiskCopy 4.2 image format. --- Makefile | 2 +- README.md | 2 +- cdev.c | 4 ++++ cdev.rez | 13 ++++++++++++- diskcopy42.h | 21 ++++++++++++++++++++ driver.c | 54 ++++++++++++++++++++++++++++++++++++++++++++++++++++ endian.asm | 32 +++++++++++++++++++++++++++++++ endian.h | 20 +++++++++++++++++++ mounturl.h | 3 ++- session.h | 4 +++- 10 files changed, 150 insertions(+), 5 deletions(-) create mode 100644 diskcopy42.h create mode 100644 endian.asm create mode 100644 endian.h diff --git a/Makefile b/Makefile index 9c2d6c4..411a144 100644 --- a/Makefile +++ b/Makefile @@ -7,7 +7,7 @@ HTTPTEST_PROG = httptest MOUNTURL_OBJS = mounturl.a netdiskerror.a MOUNTURL_PROG = mounturl -NETDISKINIT_OBJS = initstart.a netdiskinit.a hostname.a http.a readtcp.a seturl.a strcasecmp.a tcpconnection.a urlparser.a driver.a installdriver.a asmglue.a driverwrapper.a session.a systemservices.a +NETDISKINIT_OBJS = initstart.a netdiskinit.a hostname.a http.a readtcp.a seturl.a strcasecmp.a tcpconnection.a urlparser.a driver.a installdriver.a asmglue.a driverwrapper.a session.a systemservices.a endian.a # NETDISKINIT_RSRC = NETDISKINIT_PROG = NetDiskInit diff --git a/README.md b/README.md index f0d8ef3..4cf26ac 100644 --- a/README.md +++ b/README.md @@ -21,7 +21,7 @@ Compatibility ------------- NetDisk can access disk image files on most servers that allow unencrypted HTTP access. The server must also support HTTP range requests. Most modern servers support these, but some may not, in which case an error message will be shown. -NetDisk supports raw (aka ProDOS-order and various other names), 2MG, and DOS-order disk images. The images may use any filesystem for which you have an FST installed, except that DOS 3.3 filesystems are not supported due to a limitation in that FST. You can use images of any size (subject to the limitations of the relevant FST), from floppy disks to large hard drive partitions or CD-ROMS. +NetDisk supports raw (aka ProDOS-order and various other names), 2MG, DOS-order, and DiskCopy 4.2 disk images. The images may use any filesystem for which you have an FST installed, except that DOS 3.3 filesystems are not supported due to a limitation in that FST. You can use images of any size (subject to the limitations of the relevant FST), from floppy disks to large hard drive partitions or CD-ROMS. Usage diff --git a/cdev.c b/cdev.c index 7951774..5a87b70 100644 --- a/cdev.c +++ b/cdev.c @@ -41,6 +41,7 @@ #define format2mgItem 302 #define formatRawItem 303 #define formatDOSOrderItem 304 +#define formatDiskCopy42Item 305 #define netDiskMissingError 3000 #define mountURLError 3001 @@ -147,6 +148,9 @@ void DoHit(long ctlID, CtlRecHndl ctlHandle) case formatDOSOrderItem: format = formatDOSOrder; break; + case formatDiskCopy42Item: + format = formatDiskCopy42; + break; } } diff --git a/cdev.rez b/cdev.rez index 1d69542..1e6e1c1 100644 --- a/cdev.rez +++ b/cdev.rez @@ -96,6 +96,7 @@ resource rIcon (1) { #define format2mgItem 302 #define formatRawItem 303 #define formatDOSOrderItem 304 +#define formatDiskCopy42Item 305 /* * Controls in the control panel window (for 640 mode or 320 mode) @@ -202,7 +203,8 @@ resource rMenu (imageFormatMenu) { formatAutoDetectItem, format2mgItem, formatRawItem, - formatDOSOrderItem + formatDOSOrderItem, + formatDiskCopy42Item, }; }; resource rPString(imageFormatMenu,noCrossBank) { "Format: " }; @@ -243,6 +245,15 @@ resource rMenuItem (formatDOSOrderItem) { }; resource rPString(formatDOSOrderItem,noCrossBank) { "DOS Order" }; +resource rMenuItem (formatDiskCopy42Item) { + formatDiskCopy42Item, /* menu item ID */ + "","", + 0, + refIsResource*itemTitleRefShift, + formatDiskCopy42Item /* menu item title ref */ +}; +resource rPString(formatDiskCopy42Item,noCrossBank) { "DiskCopy 4.2" }; + /* * Controls in the help window */ diff --git a/diskcopy42.h b/diskcopy42.h new file mode 100644 index 0000000..35239b6 --- /dev/null +++ b/diskcopy42.h @@ -0,0 +1,21 @@ +#ifndef DISKCOPY42_H +#define DISKCOPY42_H + +#define DC42_DISK_NAME_LEN 64 +#define DC42_DATA_OFFSET 84 + +/* Expected magic value in "private" header field (taken as little-endian) */ +#define DC42_MAGIC 0x0001 + +struct DiskCopy42Header { + char diskName[DC42_DISK_NAME_LEN]; /* p-string */ + LongWord dataSize; /* big-endian */ + LongWord tagSize; /* big-endian */ + LongWord dataChecksum; + LongWord tagChecksum; + Byte diskFormat; + Byte formatByte; + Word private; +}; + +#endif diff --git a/driver.c b/driver.c index a16280f..f343b2c 100644 --- a/driver.c +++ b/driver.c @@ -15,6 +15,7 @@ #include "mounturl.h" #include "systemservices.h" #include "version.h" +#include "endian.h" #define BLOCK_SIZE 512 @@ -26,6 +27,8 @@ static const int sectorMap[2][8] = {{ 0, 13, 11, 9, 7, 5, 3, 1}, {14, 12, 10, 8, 6, 4, 2, 15}}; +#define APPLE_35_DISK_SIZE (800L * 1024) + struct DIB dibs[NDIBS] = {0}; struct DIBList dibList = {NDIBS}; @@ -210,6 +213,38 @@ Word DriverDispatch(Word callNum, struct GSOSDP *dp) { } #pragma databank 0 +/* + * Check for a valid DiskCopy 4.2 header, and process it if found. + * Returns a non-zero error code for an invalid or unsupported DC42 file, + * OPERATION_SUCCESSFUL otherwise (whether it's a DC42 file or not). + */ +static enum NetDiskError CheckDiskCopy42(Session *sess) { + struct DiskCopy42Header *hdr = &sess->fileHeader.diskCopy42Header; + + if (sess->totalLength == DISK_II_DISK_SIZE) + return OPERATION_SUCCESSFUL; + if (sess->totalLength == APPLE_35_DISK_SIZE) + return OPERATION_SUCCESSFUL; + + if (hdr->private != DC42_MAGIC) + return OPERATION_SUCCESSFUL; + + if (hdr->dataSize == 0 || ntohl(hdr->dataSize) % BLOCK_SIZE != 0) + return OPERATION_SUCCESSFUL; + + if ((unsigned char)hdr->diskName[0] >= DC42_DISK_NAME_LEN) + return OPERATION_SUCCESSFUL; + + if (ntohl(hdr->dataSize) + ntohl(hdr->tagSize) + DC42_DATA_OFFSET + != sess->totalLength) + return OPERATION_SUCCESSFUL; + + sess->dataOffset = DC42_DATA_OFFSET; + sess->dataLength = ntohl(hdr->dataSize); + + return OPERATION_SUCCESSFUL; +} + /* * Check for a 2IMG file, and process its header if one is found. * Returns a non-zero error code for an invalid or unsupported 2IMG file, @@ -318,6 +353,25 @@ static Word DoMountURL(struct GSOSDP *dp) { } } + if (mountURLRec->format == formatAutoDetect + || mountURLRec->format == formatDiskCopy42) + { + err = CheckDiskCopy42(sess); + if (err != OPERATION_SUCCESSFUL) { + EndNetDiskSession(sess); + dp->transferCount = 0; + mountURLRec->result = err; + return drvrIOError; + } + if (sess->dataOffset == DC42_DATA_OFFSET) { + mountURLRec->format = formatDiskCopy42; + } else if (mountURLRec->format == formatDiskCopy42) { + dp->transferCount = 0; + mountURLRec->result = NOT_SPECIFIED_IMAGE_TYPE; + return drvrIOError; + } + } + if (sess->dataOffset == 0) { /* No encapsulating disk image - treat this as raw blocks */ sess->dataLength = sess->totalLength; diff --git a/endian.asm b/endian.asm new file mode 100644 index 0000000..fed061b --- /dev/null +++ b/endian.asm @@ -0,0 +1,32 @@ + case on + +htons start +ntohs entry + ply + phb + plx + pla + xba + phx + plb + phy + rtl + end + +htonl start +ntohl entry + lda 4,s + xba + tax + lda 6,s + xba + tay + phb + pla + sta 3,s + pla + sta 3,s + plb + tya + rtl + end diff --git a/endian.h b/endian.h new file mode 100644 index 0000000..7008ac1 --- /dev/null +++ b/endian.h @@ -0,0 +1,20 @@ +#ifndef ENDIAN_H +#define ENDIAN_H + +#include + +/* + * Undefine these in case they're defined as macros. + * (In particular, GNO has broken macro definitions for these.) + */ +#undef htons +#undef ntohs +#undef htonl +#undef ntohl + +Word htons(Word); +Word ntohs(Word); +LongWord htonl(LongWord); +LongWord ntohl(LongWord); + +#endif diff --git a/mounturl.h b/mounturl.h index 708b464..53b7bce 100644 --- a/mounturl.h +++ b/mounturl.h @@ -15,7 +15,8 @@ enum DiskImageFormat { formatAutoDetect = 0, format2mg, formatRaw, - formatDOSOrder + formatDOSOrder, + formatDiskCopy42 }; struct MountURLRec { diff --git a/session.h b/session.h index 1791ad2..ff38f04 100644 --- a/session.h +++ b/session.h @@ -3,6 +3,7 @@ #include #include "twoimg.h" +#include "diskcopy42.h" typedef struct Session { /* Marinetti TCP connection status */ @@ -63,8 +64,9 @@ typedef struct Session { /* Buffer for initial bytes of file (which may be a disk image header) */ union { - unsigned char buf[32]; + unsigned char buf[84]; struct TwoImgHeader twoImgHeader; + struct DiskCopy42Header diskCopy42Header; } fileHeader; } Session;