For NewWorld ROM, implement the bootdriver setting by reordering the drive queue once CD-ROM drives are added

This commit is contained in:
rakslice 2020-09-24 19:09:54 -07:00
parent 9708089c1e
commit 561f1dfcde
6 changed files with 76 additions and 0 deletions

View File

@ -448,6 +448,9 @@ int16 CDROMOpen(uint32 pb, uint32 dce)
Execute68kTrap(0xa04e, &r); // AddDrive()
}
}
CDROMOpenDone();
return noErr;
}

View File

@ -40,4 +40,6 @@ extern int16 CDROMPrime(uint32 pb, uint32 dce);
extern int16 CDROMControl(uint32 pb, uint32 dce);
extern int16 CDROMStatus(uint32 pb, uint32 dce);
extern void CDROMOpenDone(void); // Called by CDROMOpen() once drives have been to the drive queue
#endif

View File

@ -202,6 +202,8 @@ bool InitAll(const char *vmdir)
return true;
}
void CDROMOpenDone() {
}
/*
* Deinitialize everything

View File

@ -353,6 +353,7 @@ extern void Enqueue(uint32 elem, uint32 list); // Enqueue QElem to list
extern int FindFreeDriveNumber(int num); // Find first free drive number, starting at "num"
extern void MountVolume(void *fh); // Mount volume with given file handle (see sys.h)
extern void FileDiskLayout(loff_t size, uint8 *data, loff_t &start_byte, loff_t &real_size); // Calculate disk image file layout given file size and first 256 data bytes
extern void MoveDrivesFromDriverToFront(uint32 driverRefNum); // Move drives from the given driver to the head of the drive queue
extern uint32 FindLibSymbol(const char *lib, const char *sym); // Find symbol in shared library
extern void InitCallUniversalProc(void); // Init CallUniversalProc()
extern long CallUniversalProc(void *upp, uint32 info); // CallUniversalProc()

View File

@ -103,6 +103,32 @@ void Enqueue(uint32 elem, uint32 list)
}
}
static void InsertQueueEntry(uint32 elem, uint32 at, uint32 list) {
uint32 next = ReadMacInt32(at);
WriteMacInt32(at, elem);
WriteMacInt32(elem + qLink, next);
if (next == 0) {
// inserted at end
WriteMacInt32(list + qTail, elem);
}
}
static void RemoveQueueEntry(uint32 at, uint32 list) {
uint32 e = ReadMacInt32(at);
uint32 next = ReadMacInt32(e + qLink);
if (next == 0) {
// removing from end
if (at == list + qHead) {
WriteMacInt32(list + qTail, 0);
} else {
WriteMacInt32(list + qTail, at - qLink);
}
}
WriteMacInt32(at, next);
WriteMacInt32(e + qLink, 0);
}
/*
* Find first free drive number, starting at num
@ -127,6 +153,37 @@ int FindFreeDriveNumber(int num)
return num;
}
/*
* Move drives of the given driver to the front of the drive queue
*/
void MoveDrivesFromDriverToFront(uint32 driverRefNum) {
const uint32 DrvQHdr = 0x308; // drive queue address
uint32 nextInsertPos = DrvQHdr + qHead;
uint32 ptrToElem = DrvQHdr + qHead;
uint32 e = ReadMacInt32(ptrToElem);
while (e) {
uint32 next = ReadMacInt32(e + qLink);
uint32 d = e - dsQLink;
uint32 curRefNum = ReadMacInt16(d + dsQRefNum);
if ((curRefNum & 0xffff) == (driverRefNum & 0xffff)) {
RemoveQueueEntry(ptrToElem, DrvQHdr);
InsertQueueEntry(e, nextInsertPos, DrvQHdr);
nextInsertPos = e + qLink;
// after the removal, ptrToElem already points to next
} else {
ptrToElem = e + qLink;
}
e = next;
}
}
/*
* Mount volume with given file handle (call this function when you are unable to

View File

@ -264,6 +264,17 @@ bool InitAll(const char *vmdir)
return true;
}
void CDROMOpenDone() {
// At this point, any initial CD-ROM drives have been added to the drive queue.
if (ROMType == ROMTYPE_NEWWORLD) {
// The PRAM boot device setting has no apparent effect,
// but we can achieve a boot with the specified device by reordering the drive queue ourselves.
int bootdriver = PrefsFindInt32("bootdriver");
if (bootdriver) {
MoveDrivesFromDriverToFront(bootdriver);
}
}
}
/*
* Deinitialize everything