mirror of
https://github.com/elliotnunn/NetBoot.git
synced 2024-12-22 01:30:18 +00:00
1 line
30 KiB
C
1 line
30 KiB
C
#include <Memory.h>
|
|
#include <Devices.h>
|
|
#include <Files.h>
|
|
#include <Disks.h>
|
|
#include <Errors.h>
|
|
#include <Events.h>
|
|
#include <OSUtils.h>
|
|
#include <QuickDraw.h>
|
|
#include "fc8-decompress-68000.h"
|
|
|
|
#define NUM_CACHE_BLOCKS 16
|
|
#define CACHE_BLOCK_SIZE (64L*1024)
|
|
|
|
#define NEED_DRVSTAT 1
|
|
#define NEED_ACCRUN 0
|
|
|
|
/* If NEED_ACCRUN is set, the dNeedTime (0x60) flag should be set in the header, and the
|
|
* delayticks field in the header should be set to something sensible.
|
|
*/
|
|
|
|
unsigned long kRomDrvSize = 0x00380000L;
|
|
Ptr kRomDrvLocation = (Ptr)0x40880000;
|
|
|
|
// Macintosh low-memory globals
|
|
unsigned long* BufPtr = (unsigned long*)0x010C;
|
|
unsigned long* MemTop = (unsigned long*)0x0108;
|
|
unsigned char* MMU32Bit = (unsigned char*)0x0CB2;
|
|
unsigned char* LLKeyMap = (unsigned char*)0x0174;
|
|
|
|
#pragma parameter __D0 ReadXPRam(__D0, __D1, __A0)
|
|
short ReadXPRam(short size, short offset, char *where) = {0x4840, 0x3001, _ReadXPRam};
|
|
|
|
typedef void (*RomDrvCopyFunc)(unsigned char *, unsigned char *, unsigned long);
|
|
|
|
struct CacheRecord {
|
|
unsigned int isValid : 1;
|
|
unsigned int isModified : 1;
|
|
unsigned short hitCount;
|
|
unsigned long timestamp;
|
|
unsigned long diskOffset;
|
|
unsigned char* pData;
|
|
};
|
|
typedef struct CacheRecord CacheRecord;
|
|
|
|
struct RomDrvContext {
|
|
DrvSts2 drvsts;
|
|
Ptr origcopyfunc;
|
|
Ptr ramdisk;
|
|
RomDrvCopyFunc copyfunc;
|
|
unsigned char * disk;
|
|
char initialized;
|
|
char useram;
|
|
char ram24at8mb;
|
|
char usecache;
|
|
char showedFullError;
|
|
unsigned short numModifiedBlocks;
|
|
unsigned long marker;
|
|
unsigned long ioCount;
|
|
unsigned long blocksLoaded;
|
|
unsigned long blocksFlushed;
|
|
CacheRecord cacheRecords[NUM_CACHE_BLOCKS];
|
|
};
|
|
typedef struct RomDrvContext RomDrvContext;
|
|
|
|
#define ICON_NONE 0
|
|
#define ICON_DISK 1
|
|
#define ICON_TITLE 2
|
|
|
|
const unsigned char DiskIcon[258] = {
|
|
0xf, 0xff, 0xff, 0xe0, 0x10, 0x00, 0x00, 0x10, 0x10,
|
|
0x00, 0x00, 0x10, 0x11, 0xff, 0xff, 0x10, 0x12, 0x1, 0x00,
|
|
0x90, 0x12, 0x00, 0x81, 0x90, 0x12, 0x00, 0x7e, 0x90, 0x12,
|
|
0x11, 0x3c, 0x90, 0x12, 0x11, 0x3c, 0x90, 0x12, 0x1, 0x18,
|
|
0x90, 0x12, 0x1, 0x00, 0x90, 0x12, 0x3, 0x00, 0x90, 0x12,
|
|
0x00, 0x00, 0x90, 0x12, 0x8, 0x40, 0x90, 0x12, 0x7, 0x80,
|
|
0x90, 0x12, 0x00, 0x00, 0x90, 0x12, 0x00, 0x00, 0x90, 0x11,
|
|
0xff, 0xff, 0x10, 0x10, 0x00, 0x00, 0x10, 0x8, 0x00, 0x00,
|
|
0x20, 0x3f, 0xff, 0xff, 0xf8, 0x20, 0x00, 0x00, 0x8, 0x2f,
|
|
0xff, 0xff, 0xe8, 0x20, 0x00, 0x00, 0x8, 0x2f, 0xff, 0xff,
|
|
0xe8, 0x20, 0x00, 0x00, 0x8, 0x20, 0x00, 0x00, 0x8, 0x20,
|
|
0x00, 0xf, 0xe8, 0x2c, 0x00, 0x00, 0x8, 0x20, 0x00, 0x00,
|
|
0x68, 0x20, 0x00, 0x00, 0x8, 0x3f, 0xff, 0xff, 0xf8,
|
|
// mask
|
|
0xf, 0xff, 0xff, 0xe0, 0x1f, 0xff, 0xff,
|
|
0xf0, 0x1f, 0xff, 0xff, 0xf0, 0x1f, 0xff, 0xff, 0xf0, 0x1f,
|
|
0xff, 0xff, 0xf0, 0x1f, 0xff, 0xff, 0xf0, 0x1f, 0xff, 0xff,
|
|
0xf0, 0x1f, 0xff, 0xff, 0xf0, 0x1f, 0xff, 0xff, 0xf0, 0x1f,
|
|
0xff, 0xff, 0xf0, 0x1f, 0xff, 0xff, 0xf0, 0x1f, 0xff, 0xff,
|
|
0xf0, 0x1f, 0xff, 0xff, 0xf0, 0x1f, 0xff, 0xff, 0xf0, 0x1f,
|
|
0xff, 0xff, 0xf0, 0x1f, 0xff, 0xff, 0xf0, 0x1f, 0xff, 0xff,
|
|
0xf0, 0x1f, 0xff, 0xff, 0xf0, 0x1f, 0xff, 0xff, 0xf0, 0xf,
|
|
0xff, 0xff, 0xe0, 0x3f, 0xff, 0xff, 0xf8, 0x3f, 0xff, 0xff,
|
|
0xf8, 0x3f, 0xff, 0xff, 0xf8, 0x3f, 0xff, 0xff, 0xf8, 0x3f,
|
|
0xff, 0xff, 0xf8, 0x3f, 0xff, 0xff, 0xf8, 0x3f, 0xff, 0xff,
|
|
0xf8, 0x3f, 0xff, 0xff, 0xf8, 0x3f, 0xff, 0xff, 0xf8, 0x3f,
|
|
0xff, 0xff, 0xf8, 0x3f, 0xff, 0xff, 0xf8, 0x3f, 0xff, 0xff,
|
|
0xf8, 0, 0};
|
|
|
|
const unsigned char bmow_title [] = {
|
|
0x7F, 0xFF, 0xFC, 0x00, 0x7F, 0x80, 0x00, 0x3F, 0x80, 0x07, 0xFF, 0xE0, 0x01, 0xFF, 0x80, 0x03, 0xFE,
|
|
0x7F, 0xFF, 0xFE, 0x00, 0x7F, 0xC0, 0x00, 0x7F, 0x80, 0x0F, 0xFF, 0xF0, 0x01, 0xFF, 0x80, 0x03, 0xFE,
|
|
0x7F, 0xFF, 0xFF, 0x00, 0x7F, 0xE0, 0x00, 0xFF, 0x80, 0x1F, 0xFF, 0xF8, 0x01, 0xFF, 0x80, 0x03, 0xFE,
|
|
0x7F, 0xFF, 0xFF, 0x80, 0x7F, 0xF0, 0x01, 0xFF, 0x80, 0x3F, 0xFF, 0xFC, 0x01, 0xFF, 0x80, 0x03, 0xFE,
|
|
0x7F, 0xE0, 0x1F, 0xC0, 0x7F, 0xF8, 0x03, 0xFF, 0x80, 0x7F, 0x00, 0xFE, 0x01, 0xFF, 0x80, 0x03, 0xFE,
|
|
0x7F, 0xE0, 0x1F, 0xE0, 0x7F, 0xFC, 0x07, 0xFF, 0x80, 0xFF, 0x00, 0xFF, 0x01, 0xFF, 0x80, 0x03, 0xFE,
|
|
0x7F, 0xE0, 0x1F, 0xF0, 0x7F, 0xFE, 0x0F, 0xFF, 0x81, 0xFF, 0x00, 0xFF, 0x81, 0xFF, 0x80, 0x03, 0xFE,
|
|
0x7F, 0xE0, 0x1F, 0xF0, 0x7F, 0xFF, 0x1F, 0xFF, 0x83, 0xFF, 0x00, 0xFF, 0xC1, 0xFF, 0x80, 0x03, 0xFE,
|
|
0x7F, 0xE0, 0x1F, 0xE0, 0x7F, 0xFF, 0xBF, 0xFF, 0x83, 0xFF, 0x00, 0xFF, 0xC1, 0xFF, 0x80, 0x03, 0xFE,
|
|
0x7F, 0xFF, 0xFF, 0xC0, 0x7F, 0xFF, 0xFF, 0xFF, 0x83, 0xFF, 0x00, 0xFF, 0xC1, 0xFF, 0x81, 0x03, 0xFE,
|
|
0x7F, 0xFF, 0xFF, 0x80, 0x7F, 0xFF, 0xFF, 0xFF, 0x83, 0xFF, 0x00, 0xFF, 0xC1, 0xFF, 0x83, 0x83, 0xFE,
|
|
0x7F, 0xFF, 0xFF, 0x00, 0x7F, 0xFF, 0xFF, 0xFF, 0x83, 0xFF, 0x00, 0xFF, 0xC1, 0xFF, 0x87, 0xC3, 0xFE,
|
|
0x7F, 0xFF, 0xFF, 0x80, 0x7F, 0xEF, 0xFE, 0xFF, 0x83, 0xFF, 0x00, 0xFF, 0xC1, 0xFF, 0x8F, 0xE3, 0xFE,
|
|
0x7F, 0xE0, 0x1F, 0xC0, 0x7F, 0xE7, 0xFC, 0xFF, 0x83, 0xFF, 0x00, 0xFF, 0xC1, 0xFF, 0x9F, 0xF3, 0xFE,
|
|
0x7F, 0xE0, 0x1F, 0xE0, 0x7F, 0xE3, 0xF8, 0xFF, 0x83, 0xFF, 0x00, 0xFF, 0xC1, 0xFF, 0xBF, 0xFB, 0xFE,
|
|
0x7F, 0xE0, 0x1F, 0xF0, 0x7F, 0xE1, 0xF0, 0xFF, 0x83, 0xFF, 0x00, 0xFF, 0xC1, 0xFF, 0xFF, 0xFF, 0xFE,
|
|
0x7F, 0xE0, 0x1F, 0xF0, 0x7F, 0xE0, 0xE0, 0xFF, 0x83, 0xFF, 0x00, 0xFF, 0xC1, 0xFF, 0xFF, 0xFF, 0xFE,
|
|
0x7F, 0xE0, 0x1F, 0xF0, 0x7F, 0xE0, 0x40, 0xFF, 0x83, 0xFF, 0x00, 0xFF, 0xC1, 0xFF, 0xFF, 0xFF, 0xFE,
|
|
0x7F, 0xE0, 0x1F, 0xF0, 0x7F, 0xE0, 0x00, 0xFF, 0x83, 0xFF, 0x00, 0xFF, 0xC1, 0xFF, 0xFE, 0xFF, 0xFE,
|
|
0x7F, 0xE0, 0x1F, 0xF0, 0x7F, 0xE0, 0x00, 0xFF, 0x83, 0xFF, 0x00, 0xFF, 0xC1, 0xFF, 0xFC, 0x7F, 0xFE,
|
|
0x7F, 0xE0, 0x1F, 0xF0, 0x7F, 0xE0, 0x00, 0xFF, 0x81, 0xFF, 0x00, 0xFF, 0x81, 0xFF, 0xF8, 0x3F, 0xFE,
|
|
0x7F, 0xE0, 0x1F, 0xE0, 0x7F, 0xE0, 0x00, 0xFF, 0x80, 0xFF, 0x00, 0xFF, 0x01, 0xFF, 0xF0, 0x1F, 0xFE,
|
|
0x7F, 0xE0, 0x1F, 0xC0, 0x7F, 0xE0, 0x00, 0xFF, 0x80, 0x7F, 0x00, 0xFE, 0x01, 0xFF, 0xE0, 0x0F, 0xFE,
|
|
0x7F, 0xFF, 0xFF, 0x80, 0x7F, 0xE0, 0x00, 0xFF, 0x80, 0x3F, 0xFF, 0xFC, 0x01, 0xFF, 0xC0, 0x07, 0xFE,
|
|
0x7F, 0xFF, 0xFF, 0x00, 0x7F, 0xE0, 0x00, 0xFF, 0x80, 0x1F, 0xFF, 0xF8, 0x01, 0xFF, 0x80, 0x03, 0xFE,
|
|
0x7F, 0xFF, 0xFE, 0x00, 0x7F, 0xE0, 0x00, 0xFF, 0x80, 0x0F, 0xFF, 0xF0, 0x01, 0xFF, 0x00, 0x01, 0xFE,
|
|
0x7F, 0xFF, 0xFC, 0x00, 0x7F, 0xE0, 0x00, 0xFF, 0x80, 0x07, 0xFF, 0xE0, 0x01, 0xFE, 0x00, 0x00, 0xFE,
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
};
|
|
|
|
/* AddDrive is declared in Files.h, but it's defined in MacOS.lib, which we don't want,
|
|
* so just shortcut the whole thing here.
|
|
*/
|
|
asm void RomDrvAddDrive(short drvrRefNum, short drvNum, DrvQElPtr dq)
|
|
{
|
|
fralloc +
|
|
CLR.L D0
|
|
MOVE.W drvNum, D0
|
|
SWAP D0
|
|
MOVE.W drvrRefNum, D0
|
|
MOVEA.L dq, A0
|
|
0xA04E
|
|
frfree
|
|
RTS
|
|
}
|
|
|
|
#pragma parameter __D0 RomDrvStripAddress(__D0)
|
|
pascal Ptr RomDrvStripAddress(void *addr) = 0xA055;
|
|
|
|
char DiskIsCompressed()
|
|
{
|
|
unsigned long signature = *(unsigned long*)kRomDrvLocation;
|
|
return (signature & 0xFFFFFF00) == 0x46433800; // 'FC8'
|
|
}
|
|
|
|
char DiskIsWholeCompressed()
|
|
{
|
|
unsigned long signature = *(unsigned long*)kRomDrvLocation;
|
|
return signature == 0x4643385F; // 'FC8_'
|
|
}
|
|
|
|
char DiskIsBlockCompressed()
|
|
{
|
|
unsigned long signature = *(unsigned long*)kRomDrvLocation;
|
|
return signature == 0x46433862; // 'FC8b'
|
|
}
|
|
|
|
unsigned long UncompressedDiskSize()
|
|
{
|
|
if (DiskIsCompressed())
|
|
return *(unsigned long*)(kRomDrvLocation+4);
|
|
else
|
|
return kRomDrvSize;
|
|
}
|
|
|
|
void RomDrvCopy(unsigned char *source, unsigned char *dest, unsigned long count)
|
|
{
|
|
signed char mode = true32b;
|
|
SwapMMUMode(&mode);
|
|
BlockMoveData(source, dest, count);
|
|
SwapMMUMode(&mode);
|
|
}
|
|
|
|
void PStrCpy(unsigned char* str, const unsigned char* str2)
|
|
{
|
|
unsigned char len = str2[0];
|
|
|
|
str[0] = len;
|
|
|
|
for (; len>0; len--)
|
|
str[len] = str2[len];
|
|
}
|
|
|
|
void PStrCat(unsigned char* str, const unsigned char* extra)
|
|
{
|
|
unsigned char baseLen = str[0];
|
|
unsigned char extraLen = extra[0];
|
|
|
|
str[0] += extraLen;
|
|
|
|
for (; extraLen>0; extraLen--)
|
|
str[baseLen+extraLen] = extra[extraLen];
|
|
}
|
|
|
|
void PUShortToStr(unsigned char* str, unsigned short num)
|
|
{
|
|
unsigned short temp = num;
|
|
unsigned char power = 1;
|
|
unsigned char len = 0;
|
|
|
|
while (temp >= 10)
|
|
{
|
|
temp /= 10;
|
|
power *= 10;
|
|
}
|
|
|
|
while (power > 0)
|
|
{
|
|
str[1+len] = '0' + num/power;
|
|
num -= ((num/power)*power);
|
|
power /= 10;
|
|
len++;
|
|
}
|
|
|
|
str[0] = len;
|
|
}
|
|
|
|
short RomDrvOpen(IOParamPtr /*p*/, DCtlPtr d)
|
|
{
|
|
DrvSts2 *dsptr;
|
|
DrvQElPtr dq;
|
|
int i, drvnum = 1;
|
|
RomDrvContext *ctx;
|
|
unsigned long driveSize;
|
|
|
|
if (d->dCtlStorage == NULL)
|
|
{
|
|
// alloc some memory for driver context
|
|
d->dCtlStorage = NewHandleSysClear(sizeof(RomDrvContext));
|
|
HLock(d->dCtlStorage);
|
|
ctx = *(RomDrvContext**)d->dCtlStorage;
|
|
|
|
// init the cache records
|
|
for (i=0; i<NUM_CACHE_BLOCKS; i++)
|
|
{
|
|
ctx->cacheRecords[i].isValid = 0;
|
|
ctx->cacheRecords[i].pData = NULL;
|
|
}
|
|
|
|
ctx->marker = 0xBEEFBABE;
|
|
ctx->usecache = 0;
|
|
ctx->showedFullError = 0;
|
|
ctx->numModifiedBlocks = 0;
|
|
ctx->ioCount = 1;
|
|
ctx->blocksLoaded = 0;
|
|
ctx->blocksFlushed = 0;
|
|
|
|
// copy the copy function into RAM, for 32-bit safeness
|
|
ctx->origcopyfunc = NewPtrSys(64);
|
|
if (!ctx->origcopyfunc)
|
|
{
|
|
SysBeep(8);
|
|
return openErr;
|
|
}
|
|
BlockMove(&RomDrvCopy, ctx->origcopyfunc, 64);
|
|
ctx->copyfunc = (RomDrvCopyFunc)RomDrvStripAddress(ctx->origcopyfunc);
|
|
|
|
// find an available drive number
|
|
for (dq = (DrvQElPtr)(GetDrvQHdr())->qHead; dq; dq = (DrvQElPtr)dq->qLink)
|
|
{
|
|
if(dq->dQDrive >= drvnum) drvnum = dq->dQDrive+1;
|
|
}
|
|
|
|
// set drive parameters, and add it to the drive queue
|
|
ctx->ramdisk = NULL;
|
|
ctx->disk = (unsigned char *)kRomDrvLocation;
|
|
dsptr = &ctx->drvsts;
|
|
dsptr->writeProt = 0xFF;
|
|
dsptr->diskInPlace = 8;
|
|
dsptr->dQDrive = drvnum;
|
|
dsptr->dQRefNum = d->dCtlRefNum;
|
|
driveSize = UncompressedDiskSize();
|
|
dsptr->driveSize = (driveSize/512L) & 0xFFFF;
|
|
dsptr->driveS1 = ((driveSize/512L) & 0xFFFF0000) >> 16;
|
|
RomDrvAddDrive(dsptr->dQRefNum, drvnum, (DrvQElPtr)&dsptr->qLink);
|
|
}
|
|
|
|
return noErr;
|
|
}
|
|
|
|
char CanAllocAbove8MB(unsigned long bytesNeeded)
|
|
{
|
|
// 24-bit can alloc above 8MB?
|
|
if (GetMMUMode() == false32b && 0x00800000 + bytesNeeded <= *MemTop)
|
|
return 1;
|
|
|
|
return 0;
|
|
}
|
|
|
|
char CanAllocWithBufPtr(unsigned long bytesNeeded)
|
|
{
|
|
// top of system startup blocks is the lowest point to which BufPtr can safely be lowered
|
|
// BufPtr = address of the highest byte of allocatable memory
|
|
// See explanation in Apple's Memory Manager documentation
|
|
// https://developer.apple.com/legacy/library/documentation/mac/pdf/Memory/Memory_Manager.pdf
|
|
unsigned long systemStartupBlocksTop = (*MemTop) / 2 + 1024;
|
|
|
|
// 4/24/2016 - The systemStartupBlocksTop formula doesn't seem to work reliably
|
|
// 1.5MB alloc on a 4MB system passes this test, but then System 7 reports out of memory
|
|
// same with 3.5MB alloc on an 8MB system
|
|
// use a more conservative formula instead
|
|
//if (*BufPtr - bytesNeeded >= systemStartupBlocksTop)
|
|
if (*BufPtr - (bytesNeeded + 0x80000) >= systemStartupBlocksTop)
|
|
return 1;
|
|
|
|
return 0;
|
|
}
|
|
|
|
void EraseBox()
|
|
{
|
|
struct QDStorage
|
|
{
|
|
QDGlobals qd;
|
|
long qdGlobalsPtr;
|
|
} qds;
|
|
GrafPort gp;
|
|
GrafPtr oldport;
|
|
long olda5;
|
|
Rect r;
|
|
short cx, cy, extraHeight = 20;
|
|
const short boxWidth = 300;
|
|
|
|
// setup Quickdraw
|
|
GetPort(&oldport);
|
|
olda5 = SetA5((long)&qds.qdGlobalsPtr);
|
|
|
|
InitGraf(&qds.qd.thePort);
|
|
OpenPort(&gp);
|
|
|
|
cx = gp.portBits.bounds.right / 2;
|
|
cy = gp.portBits.bounds.bottom / 2;
|
|
|
|
SetRect(&r, cx - boxWidth/2 - 10, cy - 16 - 10, cx + boxWidth/2 + 10, cy + 16 + 40 + extraHeight);
|
|
|
|
FillRect(&r, &qds.qd.gray);
|
|
|
|
ClosePort(&gp);
|
|
SetA5(olda5);
|
|
}
|
|
|
|
short DisplayBoxedStrings(char iconType, const unsigned char* str, const unsigned char* str2)
|
|
{
|
|
struct QDStorage
|
|
{
|
|
QDGlobals qd;
|
|
long qdGlobalsPtr;
|
|
} qds;
|
|
GrafPort gp;
|
|
GrafPtr oldport;
|
|
long olda5;
|
|
Rect r;
|
|
BitMap sourceBits, destBits;
|
|
short cx, cy, width, width2 = 0, extraHeight = 20;
|
|
const short boxWidth = 300;
|
|
|
|
// setup Quickdraw
|
|
GetPort(&oldport);
|
|
olda5 = SetA5((long)&qds.qdGlobalsPtr);
|
|
|
|
InitGraf(&qds.qd.thePort);
|
|
OpenPort(&gp);
|
|
|
|
destBits = gp.portBits;
|
|
cx = gp.portBits.bounds.right / 2;
|
|
cy = gp.portBits.bounds.bottom / 2;
|
|
|
|
width = StringWidth(str);
|
|
|
|
if (str2)
|
|
{
|
|
width2 = StringWidth(str2);
|
|
}
|
|
|
|
if (iconType != ICON_NONE)
|
|
{
|
|
// draw a centered box, scaled to the text
|
|
SetRect(&r, cx - boxWidth/2 - 10, cy - 16 - 10, cx + boxWidth/2 + 10, cy + 16 + 40 + extraHeight);
|
|
EraseRect(&r);
|
|
FrameRect(&r);
|
|
|
|
if (iconType == ICON_DISK)
|
|
{
|
|
SetRect(&r, cx - 16, cy - 16, cx + 16, cy + 16);
|
|
sourceBits.rowBytes = 4;
|
|
SetRect(&sourceBits.bounds, 0, 0, 32, 32);
|
|
sourceBits.baseAddr = (char*)DiskIcon;
|
|
}
|
|
else if (iconType == ICON_TITLE)
|
|
{
|
|
SetRect(&r, cx - 68, cy - 14, cx + 68, cy + 14);
|
|
sourceBits.rowBytes = 17;
|
|
SetRect(&sourceBits.bounds, 0, 0, 136, 28);
|
|
sourceBits.baseAddr = (char*)bmow_title;
|
|
}
|
|
|
|
CopyBits(&sourceBits, &destBits, &sourceBits.bounds, &r, srcCopy, NULL);
|
|
}
|
|
else
|
|
{
|
|
// erase the old text area
|
|
SetRect(&r, cx - boxWidth/2 - 10, cy + 16 + 30 - 12, cx + boxWidth/2 + 10, cy + 16 + 40 + extraHeight);
|
|
InsetRect(&r, 1, 1);
|
|
EraseRect(&r);
|
|
}
|
|
|
|
MoveTo(cx - width/2, cy + 16 + 30);
|
|
DrawString(str);
|
|
if (str2)
|
|
{
|
|
MoveTo(cx - width2/2, cy + 16 + 30 + extraHeight);
|
|
DrawString(str2);
|
|
}
|
|
|
|
ClosePort(&gp);
|
|
SetA5(olda5);
|
|
|
|
return boxWidth;
|
|
}
|
|
|
|
void DisplayErrorString(const unsigned char* str)
|
|
{
|
|
DisplayBoxedStrings(ICON_DISK, str, "\pPress RETURN to continue");
|
|
|
|
// wait for Enter/Return key, keymap bit 36 or 42 (international keyboard)
|
|
while(1)
|
|
{
|
|
if((LLKeyMap[4] & 0x10) || (LLKeyMap[5] & 0x04))
|
|
break;
|
|
}
|
|
|
|
EraseBox();
|
|
}
|
|
|
|
void DisplayDiskError(short err)
|
|
{
|
|
// draw a centered box, scaled to the prompt text
|
|
if (err == 1)
|
|
DisplayErrorString("\pDisk decompression error");
|
|
else if (err == 2)
|
|
DisplayErrorString("\pNot enough RAM");
|
|
}
|
|
|
|
asm void MakeSafeRomPC()
|
|
{
|
|
// modify the return address on the stack
|
|
andi.l #0x00FFFFFF, (sp)
|
|
ori.l #0x40000000, (sp)
|
|
rts
|
|
}
|
|
|
|
void CopyDiskDataToIObuf(RomDrvContext *ctx, unsigned char* src, char* dest, unsigned long count)
|
|
{
|
|
if (GetMMUMode() == false32b && (!ctx->ramdisk || ctx->ram24at8mb))
|
|
{
|
|
// 24-bit mode with rom disk, or 24-bit mode with 32-bit ram disk
|
|
// must switch to 32-bit mode and perform the read using a stripped address
|
|
ctx->copyfunc((unsigned char *)(src), (unsigned char*)RomDrvStripAddress(dest), count);
|
|
}
|
|
else
|
|
{
|
|
// already in 32-bit mode, or in 24-bit mode with a 24-bit ram disk
|
|
// ok to just perform the read
|
|
BlockMoveData(src, dest, count);
|
|
}
|
|
}
|
|
|
|
void CopyDiskDataFromIObuf(RomDrvContext *ctx, char* src, unsigned char* dest, unsigned long count)
|
|
{
|
|
if (ctx->ram24at8mb)
|
|
{
|
|
// 24-bit mode with 32-bit ram disk
|
|
// must switch to 32-bit mode and perform the write using a stripped address
|
|
ctx->copyfunc((unsigned char *)RomDrvStripAddress(src), (unsigned char *)(dest), count);
|
|
}
|
|
else
|
|
{
|
|
// already in 32-bit mode, or in 24-bit mode with a 24-bit ram disk
|
|
// ok to just perform the write
|
|
BlockMoveData(src, dest, count);
|
|
}
|
|
}
|
|
|
|
unsigned long GetBlockOffset(unsigned char* pCompressedData, unsigned long blockNumber)
|
|
{
|
|
const unsigned long kFC8bBlockOffsets = 12;
|
|
unsigned char* pBlockOffset = pCompressedData + kFC8bBlockOffsets + blockNumber * 4;
|
|
//signed char addressMode = true32b;
|
|
unsigned long blockOffset;
|
|
|
|
// ensure the PC's high byte is 0x40 (ROM), so we can safely switch to 32-bit addressing mode
|
|
//MakeSafeRomPC();
|
|
//SwapMMUMode(&addressMode);
|
|
|
|
blockOffset =
|
|
((unsigned long)pBlockOffset[0]) << 24 |
|
|
((unsigned long)pBlockOffset[1]) << 16 |
|
|
((unsigned long)pBlockOffset[2]) << 8 |
|
|
((unsigned long)pBlockOffset[3]);
|
|
|
|
// restore the old addressing mode
|
|
//SwapMMUMode(&addressMode);
|
|
|
|
return blockOffset;
|
|
}
|
|
|
|
short GetDiskDataFromROMToRamdisk(RomDrvContext *ctx, unsigned char* src, unsigned char* dest, unsigned long count)
|
|
{
|
|
short result = 0;
|
|
|
|
// don't need to strip address on dest, because it was already done when dest RAM was allocated
|
|
if (DiskIsCompressed())
|
|
{
|
|
unsigned short decompressStatus;
|
|
signed char addressMode = true32b;
|
|
char isBlockCompressed = DiskIsBlockCompressed();
|
|
unsigned char* pCompressedData = (unsigned char*)kRomDrvLocation;
|
|
|
|
// ensure the PC's high byte is 0x40 (ROM), so we can safely switch to 32-bit addressing mode
|
|
MakeSafeRomPC();
|
|
SwapMMUMode(&addressMode);
|
|
|
|
// decompress ROM disk data into the RAM disk.
|
|
// is this a decompression of the entire disk image, for an image that's block compressed?
|
|
if (count > CACHE_BLOCK_SIZE && isBlockCompressed)
|
|
{
|
|
unsigned long i, numBlocks = count / CACHE_BLOCK_SIZE;
|
|
|
|
for (i=0; i<numBlocks; i++)
|
|
{
|
|
unsigned long blockOffset = GetBlockOffset(pCompressedData, i);
|
|
|
|
decompressStatus = fc8_decode(pCompressedData + blockOffset, dest + i * CACHE_BLOCK_SIZE, CACHE_BLOCK_SIZE);
|
|
|
|
// error?
|
|
if (!decompressStatus)
|
|
break;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
decompressStatus = fc8_decode(src, dest, count);
|
|
}
|
|
|
|
// restore the old addressing mode
|
|
SwapMMUMode(&addressMode);
|
|
|
|
if (!decompressStatus)
|
|
{
|
|
result = 1; // decompression error
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// fill the RAM disk with the ROM disk image
|
|
if (GetMMUMode() == false32b)
|
|
ctx->copyfunc(src, dest, count);
|
|
else
|
|
BlockMoveData(src, dest, count);
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
void FillCacheBlock(RomDrvContext *ctx, unsigned long entry, long offset)
|
|
{
|
|
short result = 0;
|
|
|
|
if (!DiskIsBlockCompressed())
|
|
{
|
|
result = GetDiskDataFromROMToRamdisk(ctx, (unsigned char*)kRomDrvLocation + offset, ctx->cacheRecords[entry].pData, CACHE_BLOCK_SIZE);
|
|
}
|
|
else
|
|
{
|
|
unsigned long blockNumber = offset / CACHE_BLOCK_SIZE, blockOffset;
|
|
|
|
blockOffset = GetBlockOffset((unsigned char*)kRomDrvLocation, blockNumber);
|
|
|
|
if (ctx->cacheRecords[entry].isValid)
|
|
ctx->blocksFlushed++;
|
|
|
|
result = GetDiskDataFromROMToRamdisk(ctx, (unsigned char*)kRomDrvLocation + blockOffset, ctx->cacheRecords[entry].pData, CACHE_BLOCK_SIZE);
|
|
|
|
ctx->blocksLoaded++;
|
|
}
|
|
|
|
if (result)
|
|
DisplayDiskError(result);
|
|
}
|
|
|
|
char SetupRAMDisk(RomDrvContext *ctx, char useCache)
|
|
{
|
|
char result = 0;
|
|
unsigned long bytesNeeded = useCache ? (CACHE_BLOCK_SIZE * NUM_CACHE_BLOCKS) : UncompressedDiskSize();
|
|
|
|
ctx->useram = 1;
|
|
|
|
// In 24-bit mode, first try to use normally inaccessable RAM beyond 8MB for the RAM disk
|
|
if (CanAllocAbove8MB(bytesNeeded))
|
|
{
|
|
ctx->ram24at8mb = 1;
|
|
ctx->ramdisk = NewPtrSys(1); // just a dummy pointer to make rest of code work
|
|
ctx->disk = (unsigned char *)(0x00800000);
|
|
}
|
|
|
|
// Both 24 and 32-bit mode try to allocate RAM by directly lowering BufPtr
|
|
else if (CanAllocWithBufPtr(bytesNeeded))
|
|
{
|
|
// carve out space for the RAM disk by lowering BufPtr
|
|
*BufPtr -= bytesNeeded;
|
|
ctx->ramdisk = (char*)*BufPtr;
|
|
ctx->disk = (unsigned char *)RomDrvStripAddress((Ptr)ctx->ramdisk);
|
|
}
|
|
else
|
|
{
|
|
// allocation attempts failed.
|
|
result = 2; // not enough RAM for decompression
|
|
ctx->useram = 0;
|
|
ctx->drvsts.writeProt = 0xFF;
|
|
}
|
|
|
|
if (ctx->ramdisk)
|
|
{
|
|
if (useCache)
|
|
{
|
|
// setup pointers to cache block storage in RAM. Data will be loaded on demand
|
|
int i;
|
|
for (i=0; i<NUM_CACHE_BLOCKS; i++)
|
|
ctx->cacheRecords[i].pData = ctx->disk + CACHE_BLOCK_SIZE * i;
|
|
|
|
ctx->usecache = 1;
|
|
}
|
|
else
|
|
{
|
|
// copy/decompress the whole disk image into RAM
|
|
long startTime, totalTime;
|
|
|
|
if (DiskIsCompressed())
|
|
DisplayBoxedStrings(ICON_NONE, "\pDecompressing disk image...", NULL);
|
|
else
|
|
DisplayBoxedStrings(ICON_NONE, "\pPreparing disk image...", NULL);
|
|
|
|
startTime = TickCount();
|
|
result = GetDiskDataFromROMToRamdisk(ctx, (unsigned char*)kRomDrvLocation, ctx->disk, UncompressedDiskSize());
|
|
totalTime = TickCount() - startTime;
|
|
|
|
if (result == 0)
|
|
{
|
|
// show the copy/decompression time, then wait for key
|
|
/*Str255 s;
|
|
Str32 s2;
|
|
|
|
PStrCpy(s, "\pDecompression time: ");
|
|
PUShortToStr(s2, (unsigned short)totalTime);
|
|
PStrCat(s,s2);
|
|
DisplayErrorString(s);
|
|
*/
|
|
}
|
|
}
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
char DrawIntroScreen()
|
|
{
|
|
long wait;
|
|
long diagWait;
|
|
char diskmode = 0;
|
|
Str255 s,sd;
|
|
Str32 s2;
|
|
unsigned short megs;
|
|
unsigned char drewPrompt;
|
|
|
|
// find megabytes of installed RAM
|
|
PStrCpy(s, "\p Detected ");
|
|
megs = (*MemTop) >> 20;
|
|
PUShortToStr(s2, megs);
|
|
PStrCat(s, s2);
|
|
PStrCat(s, "\p MB RAM, ");
|
|
|
|
// set the diagnostic info
|
|
if (GetMMUMode() == true32b)
|
|
PStrCat(s, "\p32-bit mode ");
|
|
else
|
|
PStrCat(s, "\p24-bit mode ");
|
|
|
|
if (DiskIsCompressed())
|
|
{
|
|
unsigned long diskBytes = UncompressedDiskSize();
|
|
megs = (diskBytes + 512L * 1024) / (1024L * 1024L);
|
|
PUShortToStr(sd, megs);
|
|
|
|
if (DiskIsBlockCompressed())
|
|
PStrCat(sd, "\p MB block-compressed disk image");
|
|
else
|
|
PStrCat(sd, "\p MB whole-compressed disk image");
|
|
}
|
|
else
|
|
{
|
|
megs = (kRomDrvSize + 512L * 1024) / (1024L * 1024L);
|
|
PUShortToStr(sd, megs);
|
|
|
|
if (DiskIsBlockCompressed())
|
|
PStrCat(sd, "\p MB uncompressed disk image");
|
|
}
|
|
|
|
DisplayBoxedStrings(ICON_TITLE, s, sd);
|
|
|
|
wait = TickCount() + 360;
|
|
diagWait = TickCount() + 120;
|
|
drewPrompt = 0;
|
|
while (TickCount() < wait)
|
|
{
|
|
// overwrite diagnotic info after 1 second
|
|
if (TickCount() > diagWait && drewPrompt == 0)
|
|
{
|
|
DisplayBoxedStrings(ICON_DISK, "\pPress R for rom disk, A for ram disk", NULL);
|
|
drewPrompt = 1;
|
|
}
|
|
|
|
// check for 'r' key
|
|
if(LLKeyMap[1] & 0x80)
|
|
{
|
|
diskmode = 1;
|
|
break;
|
|
}
|
|
// check for 'a' key
|
|
else if(LLKeyMap[0] & 0x01)
|
|
{
|
|
diskmode = 2;
|
|
break;
|
|
}
|
|
// check for 'x' key
|
|
else if(LLKeyMap[0] & 0x80)
|
|
{
|
|
diskmode = 3;
|
|
break;
|
|
}
|
|
}
|
|
|
|
return diskmode;
|
|
}
|
|
|
|
unsigned long GetCacheEntryForOffset(RomDrvContext *ctx, long offset)
|
|
{
|
|
unsigned long lowestTimestamp = 0xFFFFFFFF;
|
|
unsigned long entry, replaceableEntry = NUM_CACHE_BLOCKS;
|
|
unsigned long desiredBlockOffset = offset & (~(CACHE_BLOCK_SIZE-1));
|
|
|
|
for (entry=0; entry<NUM_CACHE_BLOCKS; entry++)
|
|
{
|
|
CacheRecord* pCacheRecord = &ctx->cacheRecords[entry];
|
|
|
|
if (pCacheRecord->isValid)
|
|
{
|
|
// is the desired data in this cache block?
|
|
if (pCacheRecord->diskOffset == desiredBlockOffset)
|
|
{
|
|
break;
|
|
}
|
|
|
|
// could this entry be used to load a new cache block?
|
|
if (!pCacheRecord->isModified && lowestTimestamp != 0 && pCacheRecord->timestamp < lowestTimestamp)
|
|
{
|
|
// old, unmodified entry can be replaced if necessary
|
|
replaceableEntry = entry;
|
|
lowestTimestamp = pCacheRecord->timestamp;
|
|
}
|
|
|
|
}
|
|
else if (lowestTimestamp != 0)
|
|
{
|
|
// unused/invalid entry can be replaced if necessary
|
|
replaceableEntry = entry;
|
|
lowestTimestamp = 0;
|
|
}
|
|
}
|
|
|
|
// didn't find the necessary block in the cache? load it into the cache
|
|
if (entry == NUM_CACHE_BLOCKS)
|
|
{
|
|
// is there a replaceable entry?
|
|
if (replaceableEntry != NUM_CACHE_BLOCKS)
|
|
{
|
|
CacheRecord* pCacheRecord = &ctx->cacheRecords[replaceableEntry];
|
|
|
|
FillCacheBlock(ctx, replaceableEntry, offset);
|
|
|
|
pCacheRecord->isValid = 1;
|
|
pCacheRecord->isModified = 0;
|
|
pCacheRecord->hitCount = 0;
|
|
pCacheRecord->diskOffset = desiredBlockOffset;
|
|
|
|
entry = replaceableEntry;
|
|
}
|
|
}
|
|
|
|
return entry;
|
|
}
|
|
|
|
short HandleDiskRead(RomDrvContext *ctx, IOParamPtr p, DCtlPtr d, long off)
|
|
{
|
|
if (!ctx->usecache)
|
|
{
|
|
CopyDiskDataToIObuf(ctx, ctx->disk + off, p->ioBuffer, p->ioReqCount);
|
|
}
|
|
else
|
|
{
|
|
long subOff = off;
|
|
long subCount = p->ioReqCount;
|
|
unsigned long entry;
|
|
|
|
// get data from the necessary cache block(s)
|
|
while (subCount != 0)
|
|
{
|
|
entry = GetCacheEntryForOffset(ctx, subOff);
|
|
|
|
// copy the data from the cache block
|
|
if (entry == NUM_CACHE_BLOCKS)
|
|
{
|
|
// cache block isn't loaded, and nothing could be unloaded to make room for it!
|
|
// TODO: prevent this from happening
|
|
return offLinErr;
|
|
}
|
|
else
|
|
{
|
|
CacheRecord* pCacheRecord = &ctx->cacheRecords[entry];
|
|
unsigned long copySize = subCount;
|
|
if (copySize > (pCacheRecord->diskOffset + CACHE_BLOCK_SIZE) - subOff)
|
|
copySize = (pCacheRecord->diskOffset + CACHE_BLOCK_SIZE) - subOff;
|
|
|
|
CopyDiskDataToIObuf(ctx, pCacheRecord->pData + subOff - pCacheRecord->diskOffset, p->ioBuffer + subOff - off, copySize);
|
|
|
|
subOff += copySize;
|
|
subCount -= copySize;
|
|
|
|
pCacheRecord->timestamp = ctx->ioCount;
|
|
pCacheRecord->hitCount++;
|
|
}
|
|
}
|
|
}
|
|
|
|
p->ioActCount = p->ioReqCount;
|
|
d->dCtlPosition = off + p->ioReqCount;
|
|
p->ioPosOffset = d->dCtlPosition;
|
|
|
|
return noErr;
|
|
}
|
|
|
|
short HandleDiskWrite(RomDrvContext *ctx, IOParamPtr p, DCtlPtr d, long off)
|
|
{
|
|
if (!ctx->usecache)
|
|
{
|
|
CopyDiskDataFromIObuf(ctx, p->ioBuffer, ctx->disk + off, p->ioReqCount);
|
|
}
|
|
else
|
|
{
|
|
long subOff = off;
|
|
long subCount = p->ioReqCount;
|
|
unsigned long entry;
|
|
|
|
// write data to the necessary cache block(s)
|
|
while (subCount != 0)
|
|
{
|
|
entry = GetCacheEntryForOffset(ctx, subOff);
|
|
|
|
// copy the data from the cache block
|
|
if (entry == NUM_CACHE_BLOCKS)
|
|
{
|
|
// cache block isn't loaded, and nothing could be unloaded to make room for it!
|
|
// this should never happen
|
|
return verErr;
|
|
}
|
|
else
|
|
{
|
|
CacheRecord* pCacheRecord = &ctx->cacheRecords[entry];
|
|
unsigned long copySize = subCount;
|
|
|
|
// if this block would be newly modified, and would leave fewer than 2 unmodified blocks
|
|
// remaining, report an error and fail
|
|
if (!ctx->showedFullError && !pCacheRecord->isModified && ctx->numModifiedBlocks >= NUM_CACHE_BLOCKS - 2)
|
|
{
|
|
DisplayErrorString("\pWrite cache is full. Try rom disk X option.");
|
|
|
|
subOff += copySize;
|
|
subCount -= copySize;
|
|
pCacheRecord->timestamp = ctx->ioCount;
|
|
ctx->drvsts.writeProt = 0xFF;
|
|
ctx->showedFullError = 1;
|
|
|
|
return verErr;
|
|
}
|
|
else
|
|
{
|
|
if (copySize > (pCacheRecord->diskOffset + CACHE_BLOCK_SIZE) - subOff)
|
|
copySize = (pCacheRecord->diskOffset + CACHE_BLOCK_SIZE) - subOff;
|
|
|
|
CopyDiskDataFromIObuf(ctx, p->ioBuffer + subOff - off, pCacheRecord->pData + subOff - pCacheRecord->diskOffset, copySize);
|
|
|
|
subOff += copySize;
|
|
subCount -= copySize;
|
|
|
|
pCacheRecord->timestamp = ctx->ioCount;
|
|
pCacheRecord->hitCount++;
|
|
if (!pCacheRecord->isModified)
|
|
ctx->numModifiedBlocks++;
|
|
pCacheRecord->isModified = 1;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
p->ioActCount = p->ioReqCount;
|
|
d->dCtlPosition = off + p->ioReqCount;
|
|
p->ioPosOffset = d->dCtlPosition;
|
|
|
|
return noErr;
|
|
}
|
|
|
|
short RomDrvPrime(IOParamPtr p, DCtlPtr d)
|
|
{
|
|
long off;
|
|
RomDrvContext *ctx;
|
|
char startup;
|
|
char ram;
|
|
|
|
if (!d->dCtlStorage)
|
|
{
|
|
p->ioResult = offLinErr;
|
|
return offLinErr;
|
|
}
|
|
|
|
ctx = *(RomDrvContext**)d->dCtlStorage;
|
|
|
|
if (!ctx->drvsts.diskInPlace)
|
|
{
|
|
return offLinErr;
|
|
}
|
|
|
|
// on first call to Prime, setup the disk
|
|
if (!ctx->initialized)
|
|
{
|
|
// initialize as a ready-only disk
|
|
ctx->initialized = 1;
|
|
|
|
|
|
// check the startup and ram disk preferences from the control panel
|
|
// TBD: how do we know something else isn't using this area of PRAM?
|
|
ReadXPRam(1, 4, &startup);
|
|
ReadXPRam(1, 5, &ram);
|
|
|
|
if (startup && 0)
|
|
{
|
|
if(ram)
|
|
SetupRAMDisk(ctx, 1);
|
|
// else continue as a read-only ROM disk
|
|
}
|
|
else
|
|
{
|
|
char diskmode = DrawIntroScreen(ctx);
|
|
|
|
// confirm the block size
|
|
if (diskmode > 0 && DiskIsBlockCompressed())
|
|
{
|
|
unsigned long blockSize =
|
|
((unsigned long)kRomDrvLocation[8]) << 24 |
|
|
((unsigned long)kRomDrvLocation[9]) << 16 |
|
|
((unsigned long)kRomDrvLocation[10]) << 8 |
|
|
((unsigned long)kRomDrvLocation[11]);
|
|
|
|
if (blockSize != CACHE_BLOCK_SIZE)
|
|
{
|
|
Str255 s;
|
|
Str32 sd;
|
|
PStrCpy(s, "\pCompressed image block size is not ");
|
|
PUShortToStr(sd, CACHE_BLOCK_SIZE / 1024);
|
|
PStrCat(s, sd);
|
|
PStrCat(s, "\pK");
|
|
DisplayErrorString(s);
|
|
}
|
|
}
|
|
|
|
// check which mode was selected
|
|
if (diskmode == 0)
|
|
{
|
|
// disable the disk, by flagging it as not in place
|
|
ctx->drvsts.diskInPlace = 0;
|
|
EraseBox();
|
|
return offLinErr;
|
|
}
|
|
else if ((diskmode == 1 && DiskIsBlockCompressed()) ||
|
|
(diskmode == 2 && !DiskIsWholeCompressed()))
|
|
{
|
|
// R: create read-only disk directly from ROM, when disk image is compressed
|
|
// A: create read/write disk with a small RAM cache
|
|
char result = SetupRAMDisk(ctx, 1);
|
|
if (result)
|
|
DisplayDiskError(result);
|
|
else if (diskmode == 2)
|
|
ctx->drvsts.writeProt = 0;
|
|
}
|
|
else if (DiskIsWholeCompressed() || diskmode == 3)
|
|
{
|
|
// X: create read/write disk as a fully-RAM resident disk
|
|
char result = SetupRAMDisk(ctx, 0);
|
|
if (result)
|
|
DisplayDiskError(result);
|
|
else if (diskmode == 2 || diskmode == 3)
|
|
ctx->drvsts.writeProt = 0;
|
|
}
|
|
|
|
EraseBox();
|
|
}
|
|
}
|
|
|
|
// now process the I/O request
|
|
switch (p->ioPosMode & 0x000F)
|
|
{
|
|
case fsAtMark: off = d->dCtlPosition; break;
|
|
case fsFromStart: off = p->ioPosOffset; break;
|
|
case fsFromMark: off = d->dCtlPosition + p->ioPosOffset; break;
|
|
default: break;
|
|
}
|
|
|
|
ctx->ioCount++;
|
|
|
|
if ((p->ioTrap & 0x00ff) == aRdCmd)
|
|
{
|
|
short result = noErr;
|
|
|
|
/* bit 6 indicates this should be a verify operation */
|
|
if (!(p->ioPosMode & 0x40))
|
|
{
|
|
result = HandleDiskRead(ctx, p, d, off);
|
|
}
|
|
return result;
|
|
}
|
|
else if((p->ioTrap & 0x00ff) == aWrCmd && ctx->ramdisk)
|
|
{
|
|
return HandleDiskWrite(ctx, p, d, off);
|
|
}
|
|
|
|
SysBeep(0);
|
|
return wPrErr;
|
|
}
|
|
|
|
short RomDrvClose(IOParamPtr /*p*/, DCtlPtr d)
|
|
{
|
|
RomDrvContext *ctx;
|
|
|
|
if (!d->dCtlStorage) return noErr;
|
|
ctx = *(RomDrvContext**)d->dCtlStorage;
|
|
if (ctx->ramdisk) DisposePtr(ctx->ramdisk);
|
|
DisposePtr(ctx->origcopyfunc);
|
|
HUnlock(d->dCtlStorage);
|
|
DisposeHandle(d->dCtlStorage);
|
|
d->dCtlStorage = NULL;
|
|
|
|
return noErr;
|
|
}
|
|
|
|
short main(IOParamPtr p, DCtlPtr d, short cmd)
|
|
{
|
|
switch(cmd) {
|
|
case 0: return RomDrvOpen(p, d);
|
|
case 1: return RomDrvPrime(p, d);
|
|
case 2:
|
|
if (((CntrlParamPtr)p)->csCode == 21)
|
|
{
|
|
*(Ptr*)&((CntrlParamPtr)p)->csParam = (Ptr)&DiskIcon;
|
|
return noErr;
|
|
}
|
|
else if (((CntrlParamPtr)p)->csCode == 22)
|
|
{
|
|
*(Ptr*)&((CntrlParamPtr)p)->csParam = (Ptr)&DiskIcon;
|
|
return noErr;
|
|
}
|
|
#if NEED_ACCRUN
|
|
if (((CntrlParamPtr)p)->csCode == accRun)
|
|
{
|
|
RomDrvContext *ctx;
|
|
if (!d->dCtlStorage) return noErr;
|
|
ctx = *(RomDrvContext**)d->dCtlStorage;
|
|
|
|
// if we want a ram disk, but haven't allocated one yet, do it now
|
|
if (ctx->useram && !ctx->ramdisk)
|
|
{
|
|
// create a buffer for the RAM disk in the system heap
|
|
// this doesn't seem to work reliabily - OK in System 7.0.1, but hangs at Finder in 7.1
|
|
ctx->ramdisk = NewPtrSys(UncompressedDiskSize());
|
|
if(ctx->ramdisk)
|
|
{
|
|
ctx->disk = (unsigned char *)ctx->ramdisk;
|
|
|
|
FillRAMDisk(ctx);
|
|
}
|
|
else
|
|
{
|
|
ctx->useram = 0;
|
|
}
|
|
}
|
|
d->dCtlDelay = 0;
|
|
d->dCtlFlags &= ~dNeedTimeMask;
|
|
return noErr;
|
|
}
|
|
#endif
|
|
return controlErr;
|
|
case 3:
|
|
#if NEED_DRVSTAT
|
|
if (!d->dCtlStorage) return statusErr;
|
|
|
|
if(((CntrlParamPtr)p)->csCode == drvStsCode) {
|
|
BlockMove(*d->dCtlStorage, &((CntrlParamPtr)p)->csParam, sizeof(DrvSts2));
|
|
return noErr;
|
|
}
|
|
#endif
|
|
return statusErr;
|
|
case 4: return RomDrvClose(p, d);
|
|
default: return noErr;
|
|
}
|
|
} |