diff --git a/BasiliskII/src/cdrom.cpp b/BasiliskII/src/cdrom.cpp index ce2a398a..964f116d 100644 --- a/BasiliskII/src/cdrom.cpp +++ b/BasiliskII/src/cdrom.cpp @@ -448,6 +448,9 @@ int16 CDROMOpen(uint32 pb, uint32 dce) Execute68kTrap(0xa04e, &r); // AddDrive() } } + + CDROMOpenDone(); + return noErr; } diff --git a/BasiliskII/src/include/cdrom.h b/BasiliskII/src/include/cdrom.h index 0ab114a5..bf899e61 100644 --- a/BasiliskII/src/include/cdrom.h +++ b/BasiliskII/src/include/cdrom.h @@ -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 diff --git a/BasiliskII/src/main.cpp b/BasiliskII/src/main.cpp index dcb86e9c..e010a19c 100644 --- a/BasiliskII/src/main.cpp +++ b/BasiliskII/src/main.cpp @@ -202,6 +202,8 @@ bool InitAll(const char *vmdir) return true; } +void CDROMOpenDone() { +} /* * Deinitialize everything diff --git a/SheepShaver/src/include/macos_util.h b/SheepShaver/src/include/macos_util.h index aec13cff..50bcee3b 100644 --- a/SheepShaver/src/include/macos_util.h +++ b/SheepShaver/src/include/macos_util.h @@ -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() diff --git a/SheepShaver/src/macos_util.cpp b/SheepShaver/src/macos_util.cpp index 6a3f9644..62a83f30 100644 --- a/SheepShaver/src/macos_util.cpp +++ b/SheepShaver/src/macos_util.cpp @@ -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 diff --git a/SheepShaver/src/main.cpp b/SheepShaver/src/main.cpp index e34b24be..b725e08f 100755 --- a/SheepShaver/src/main.cpp +++ b/SheepShaver/src/main.cpp @@ -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