Add support for image format selection and detection.

At the moment, the auto-detection of DOS vs. ProDOS order is just based on the size of the image (i.e. 5.25" images are DOS-order, anything else is ProDOS-order).
This commit is contained in:
Stephen Heumann 2018-10-07 22:22:09 -05:00
parent d2f7ec3b64
commit dcc069d5b8
6 changed files with 155 additions and 69 deletions

25
cdev.c
View File

@ -36,6 +36,12 @@
//#define trianglePic 7 //#define trianglePic 7
#define useCacheChk 8 #define useCacheChk 8
#define imageFormatMenu 300
#define formatAutoDetectItem 301
#define format2mgItem 302
#define formatRawItem 303
#define formatDOSOrderItem 304
#define netDiskMissingError 3000 #define netDiskMissingError 3000
#define mountURLError 3001 #define mountURLError 3001
#define unsupportedProtocolAlert 3002 #define unsupportedProtocolAlert 3002
@ -49,6 +55,8 @@ WindowPtr wPtr = NULL;
Boolean useCache; Boolean useCache;
enum DiskImageFormat format;
struct MountURLRec mountURLRec = {sizeof(struct MountURLRec)}; struct MountURLRec mountURLRec = {sizeof(struct MountURLRec)};
void DoMount(void) void DoMount(void)
@ -91,6 +99,8 @@ void DoMount(void)
if (useCache) { if (useCache) {
mountURLRec.flags |= flgUseCache; mountURLRec.flags |= flgUseCache;
} }
mountURLRec.format = format;
SendRequest(MountURL, sendToName|stopAfterOne, (Long)NETDISK_REQUEST_NAME, SendRequest(MountURL, sendToName|stopAfterOne, (Long)NETDISK_REQUEST_NAME,
(Long)&mountURLRec, NULL); (Long)&mountURLRec, NULL);
@ -123,6 +133,21 @@ void DoHit(long ctlID, CtlRecHndl ctlHandle)
DoMount(); DoMount();
} else if (ctlID == useCacheChk) { } else if (ctlID == useCacheChk) {
useCache = !useCache; useCache = !useCache;
} else if (ctlID == imageFormatMenu) {
switch (GetCtlValue(ctlHandle)) {
case formatAutoDetectItem:
format = formatAutoDetect;
break;
case format2mgItem:
format = format2mg;
break;
case formatRawItem:
format = formatRaw;
break;
case formatDOSOrderItem:
format = formatDOSOrder;
break;
}
} }
return; return;

133
cdev.rez
View File

@ -23,7 +23,7 @@ resource rCDEVFlags (1) {
1, /* version */ 1, /* version */
1, /* min ROM version */ 1, /* min ROM version */
0, /* reserved */ 0, /* reserved */
{0, 0, 55, 320}, /* rectangle */ {0, 0, 71, 320}, /* rectangle */
"NetDisk", /* name */ "NetDisk", /* name */
"Stephen Heumann", /* author */ "Stephen Heumann", /* author */
"v1.0b1" /* version string */ "v1.0b1" /* version string */
@ -91,6 +91,11 @@ resource rIcon (1) {
#define helpTxt 5 #define helpTxt 5
#define imageFormatMenu 300
#define formatAutoDetectItem 301
#define format2mgItem 302
#define formatRawItem 303
#define formatDOSOrderItem 304
/* /*
* Controls in the control panel window (for 640 mode or 320 mode) * Controls in the control panel window (for 640 mode or 320 mode)
@ -101,8 +106,7 @@ resource rControlList (640) {
cdevWindow+urlLine, cdevWindow+urlLine,
cdevWindow+useCacheChk, cdevWindow+useCacheChk,
cdevWindow+mountBtn, cdevWindow+mountBtn,
//cdevWindow+trianglePic, cdevWindow+imageFormatMenu
//cdevWindow+optionsPopUp
}; };
}; };
@ -112,14 +116,13 @@ resource rControlList (320) {
cdevWindow+urlLine, cdevWindow+urlLine,
cdevWindow+useCacheChk, cdevWindow+useCacheChk,
cdevWindow+mountBtn, cdevWindow+mountBtn,
//cdevWindow+trianglePic+320, cdevWindow+imageFormatMenu+320
//cdevWindow+optionsPopUp+320
}; };
}; };
resource rControlTemplate (cdevWindow+imageURLTxt) { resource rControlTemplate (cdevWindow+imageURLTxt) {
imageURLTxt, /* control ID */ imageURLTxt, /* control ID */
{4, 10, 15, 270}, /* control rect */ {4, 9, 15, 270}, /* control rect */
statTextControl {{ statTextControl {{
fBlastText, /* flags */ fBlastText, /* flags */
$1000+RefIsResource, /* moreFlags */ $1000+RefIsResource, /* moreFlags */
@ -148,7 +151,7 @@ resource rPString (cdevWindow+urlLine) { "http://" };
resource rControlTemplate (cdevWindow+mountBtn) { resource rControlTemplate (cdevWindow+mountBtn) {
mountBtn, mountBtn,
{35, 156, 0, 0}, {50, 156, 0, 0},
SimpleButtonControl {{ SimpleButtonControl {{
DefaultButton, DefaultButton,
$3000+RefIsResource, $3000+RefIsResource,
@ -163,7 +166,7 @@ resource rPString(cdevWindow+mountBtn) { "Mount Disk Image" };
resource rControlTemplate (cdevWindow+useCacheChk) { resource rControlTemplate (cdevWindow+useCacheChk) {
useCacheChk, useCacheChk,
{37,10,0,0}, {52,10,0,0},
CheckControl {{ CheckControl {{
$0000, $0000,
$1002, $1002,
@ -174,77 +177,85 @@ resource rControlTemplate (cdevWindow+useCacheChk) {
}; };
resource rPString (cdevWindow+useCacheChk) {"Use Disk Cache"}; resource rPString (cdevWindow+useCacheChk) {"Use Disk Cache"};
#if 0
/* Options menu pop-up -- separate versions for 640 mode and 320 mode */ /* Disk image format pop-up menu */
resource rControlTemplate (cdevWindow+optionsPopUp) {
optionsPopUp, resource rControlTemplate (cdevWindow+imageFormatMenu) {
{5, 282, 13, 310 }, imageFormatMenu,
{31, 8, 43, 314},
PopUpControl {{ PopUpControl {{
fDontDrawTitle+fDontDrawResult,
fCtlProcNotPtr+RefIsResource/*+fDrawPopDownIcon*/,
0, 0,
fCtlProcNotPtr+RefIsResource+fDrawPopDownIcon,
0, 0,
optionsMenu, /* menu ref */ 93, /* title width */
optionsItem, /* initial value */ imageFormatMenu, /* menu ref */
formatAutoDetectItem, /* initial value */
0 0
}}; }};
}; };
resource rControlTemplate (cdevWindow+optionsPopUp+ 320) { resource rControlTemplate (cdevWindow+imageFormatMenu+320) {
optionsPopUp, imageFormatMenu,
{5, 296, 13, 310 }, {31, 8, 43, 312},
PopUpControl {{ PopUpControl {{
fDontDrawTitle+fDontDrawResult,
fCtlProcNotPtr+RefIsResource/*+fDrawPopDownIcon*/,
0, 0,
fCtlProcNotPtr+RefIsResource+fDrawPopDownIcon,
0, 0,
optionsMenu, /* menu ref */ 95, /* title width */
optionsItem, /* initial value */ imageFormatMenu, /* menu ref */
formatAutoDetectItem, /* initial value */
0 0
}}; }};
}; };
/* Triangle to draw on options pop-up */ resource rMenu (imageFormatMenu) {
resource rControlTemplate (cdevWindow+trianglePic) { imageFormatMenu, /* menu ID */
trianglePic,
{7, 286, 11, 302},
PictureControl {{
CtlInactive,
fCtlProcNotPtr+RefIsResource,
0,
trianglePic /* picture reference */
}};
};
resource rControlTemplate (cdevWindow+trianglePic+320) {
trianglePic,
{7, 298, 0, 0},
PictureControl {{
CtlInactive,
fCtlProcNotPtr+RefIsResource,
0,
trianglePic /* picture reference */
}};
};
data rPicture (trianglePic) {
$"8000 0000 0000 0400 1000 1182 0100 0A00"
$"01C0 01C0 FF3F FF3F 9000 8000 0000 0400"
$"0000 0000 0400 1000 0000 0000 0400 1000"
$"0000 0000 0400 1000 0000 0000 0000 F000"
$"000F FF00 00FF FFF0 0FFF"
};
resource rMenu (optionsMenu) {
optionsMenu, /* menu ID */
refIsResource*menuTitleRefShift + refIsResource*itemRefShift, refIsResource*menuTitleRefShift + refIsResource*itemRefShift,
optionsMenu, /* menu title ref (not drawn) */ imageFormatMenu, /* menu title ref (not drawn) */
{ {
//items go here formatAutoDetectItem,
format2mgItem,
formatRawItem,
formatDOSOrderItem
}; };
}; };
resource rPString(optionsMenu,noCrossBank) { "" }; resource rPString(imageFormatMenu,noCrossBank) { "Image Format" };
#endif
resource rMenuItem (formatAutoDetectItem) {
formatAutoDetectItem, /* menu item ID */
"","",
0,
refIsResource*itemTitleRefShift,
formatAutoDetectItem /* menu item title ref */
};
resource rPString(formatAutoDetectItem,noCrossBank) { "Auto-Detect" };
resource rMenuItem (format2mgItem) {
format2mgItem, /* menu item ID */
"","",
0,
refIsResource*itemTitleRefShift,
format2mgItem /* menu item title ref */
};
resource rPString(format2mgItem,noCrossBank) { "Universal Disk Image (2MG)" };
resource rMenuItem (formatRawItem) {
formatRawItem, /* menu item ID */
"","",
0,
refIsResource*itemTitleRefShift,
formatRawItem /* menu item title ref */
};
resource rPString(formatRawItem,noCrossBank) { "ProDOS Order/Raw/ISO" };
resource rMenuItem (formatDOSOrderItem) {
formatDOSOrderItem, /* menu item ID */
"","",
0,
refIsResource*itemTitleRefShift,
formatDOSOrderItem /* menu item title ref */
};
resource rPString(formatDOSOrderItem,noCrossBank) { "DOS Order" };
/* /*
* Controls in the help window * Controls in the help window

View File

@ -21,6 +21,7 @@
/* Disk II-style track/sector layout (relevant to DOS-order images) */ /* Disk II-style track/sector layout (relevant to DOS-order images) */
#define TRACK_SIZE (BLOCK_SIZE * 8) #define TRACK_SIZE (BLOCK_SIZE * 8)
#define SECTOR_SIZE 256 #define SECTOR_SIZE 256
#define DISK_II_DISK_SIZE (TRACK_SIZE * 35L)
/* The sectors making up each block within a track (using DOS 3.3 numbering) */ /* The sectors making up each block within a track (using DOS 3.3 numbering) */
static const int sectorMap[2][8] = {{ 0, 13, 11, 9, 7, 5, 3, 1}, static const int sectorMap[2][8] = {{ 0, 13, 11, 9, 7, 5, 3, 1},
{14, 12, 10, 8, 6, 4, 2, 15}}; {14, 12, 10, 8, 6, 4, 2, 15}};
@ -293,12 +294,23 @@ static Word DoMountURL(struct GSOSDP *dp) {
return drvrIOError; return drvrIOError;
} }
err = CheckTwoImg(sess); if (mountURLRec->format == formatAutoDetect
if (err != OPERATION_SUCCESSFUL) { || mountURLRec->format == format2mg)
EndNetDiskSession(sess); {
dp->transferCount = 0; err = CheckTwoImg(sess);
mountURLRec->result = err; if (err != OPERATION_SUCCESSFUL) {
return drvrIOError; EndNetDiskSession(sess);
dp->transferCount = 0;
mountURLRec->result = err;
return drvrIOError;
}
if (sess->dataOffset != 0) {
mountURLRec->format = format2mg;
} else if (mountURLRec->format == format2mg) {
dp->transferCount = 0;
mountURLRec->result = NOT_SPECIFIED_IMAGE_TYPE;
return drvrIOError;
}
} }
if (sess->dataOffset == 0) { if (sess->dataOffset == 0) {
@ -306,11 +318,38 @@ static Word DoMountURL(struct GSOSDP *dp) {
sess->dataLength = sess->totalLength; sess->dataLength = sess->totalLength;
} }
// TODO remove this hack in favor of better format detection
if (mountURLRec->format == formatAutoDetect) {
if (sess->dataLength == DISK_II_DISK_SIZE) {
mountURLRec->format = formatDOSOrder;
}
}
if (mountURLRec->format == formatDOSOrder) {
if (sess->dataLength % TRACK_SIZE != 0) {
dp->transferCount = 0;
mountURLRec->result = NOT_SPECIFIED_IMAGE_TYPE;
return drvrIOError;
}
sess->dosOrder = TRUE;
}
if (sess->dataLength % BLOCK_SIZE != 0) { if (sess->dataLength % BLOCK_SIZE != 0) {
dp->transferCount = 0; dp->transferCount = 0;
mountURLRec->result = NOT_MULTIPLE_OF_BLOCK_SIZE; if (mountURLRec->format == formatAutoDetect) {
mountURLRec->result = NOT_MULTIPLE_OF_BLOCK_SIZE;
} else {
mountURLRec->result = NOT_SPECIFIED_IMAGE_TYPE;
}
return drvrIOError; return drvrIOError;
} }
if (mountURLRec->format == formatAutoDetect) {
if (sess->dataLength != DISK_II_DISK_SIZE) {
mountURLRec->format = formatRaw;
}
}
dp->dibPointer->blockCount = sess->dataLength / BLOCK_SIZE; dp->dibPointer->blockCount = sess->dataLength / BLOCK_SIZE;
dp->dibPointer->extendedDIBPtr = sess; dp->dibPointer->extendedDIBPtr = sess;

View File

@ -11,11 +11,19 @@
/* Bits in flags */ /* Bits in flags */
#define flgUseCache 0x0001 #define flgUseCache 0x0001
enum DiskImageFormat {
formatAutoDetect = 0,
format2mg,
formatRaw,
formatDOSOrder
};
struct MountURLRec { struct MountURLRec {
Word byteCount; Word byteCount;
enum NetDiskError result; /* output value */ enum NetDiskError result; /* output value */
char *url; /* C-string; will be modified */ char *url; /* C-string; will be modified */
Word flags; Word flags;
enum DiskImageFormat format; /* input/output value */
Word devNum; /* output value: device number */ Word devNum; /* output value: device number */
}; };

View File

@ -67,6 +67,8 @@ char *ErrorString(enum NetDiskError err) {
case NOT_MULTIPLE_OF_BLOCK_SIZE: case NOT_MULTIPLE_OF_BLOCK_SIZE:
return "The file is not a multiple of 512 bytes. It may not be a disk " return "The file is not a multiple of 512 bytes. It may not be a disk "
"image file, or is not in a supported format."; "image file, or is not in a supported format.";
case NOT_SPECIFIED_IMAGE_TYPE:
return "The file is not a valid disk image of the specified type.";
/* HTTP errors */ /* HTTP errors */
case 400: case 400:

View File

@ -38,7 +38,8 @@ enum NetDiskError {
/* File format errors */ /* File format errors */
UNSUPPORTED_2IMG_FILE = 600, UNSUPPORTED_2IMG_FILE = 600,
NOT_MULTIPLE_OF_BLOCK_SIZE NOT_MULTIPLE_OF_BLOCK_SIZE,
NOT_SPECIFIED_IMAGE_TYPE
}; };