2002-02-04 16:58:13 +00:00
|
|
|
/*
|
|
|
|
* emul_op.cpp - 68k opcodes for ROM patches
|
|
|
|
*
|
|
|
|
* SheepShaver (C) 1997-2002 Christian Bauer and Marc Hellwig
|
|
|
|
*
|
|
|
|
* This program is free software; you can redistribute it and/or modify
|
|
|
|
* it under the terms of the GNU General Public License as published by
|
|
|
|
* the Free Software Foundation; either version 2 of the License, or
|
|
|
|
* (at your option) any later version.
|
|
|
|
*
|
|
|
|
* This program is distributed in the hope that it will be useful,
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
* GNU General Public License for more details.
|
|
|
|
*
|
|
|
|
* You should have received a copy of the GNU General Public License
|
|
|
|
* along with this program; if not, write to the Free Software
|
|
|
|
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include <stdio.h>
|
|
|
|
|
|
|
|
#include "sysdeps.h"
|
|
|
|
#include "main.h"
|
|
|
|
#include "version.h"
|
|
|
|
#include "prefs.h"
|
|
|
|
#include "cpu_emulation.h"
|
|
|
|
#include "xlowmem.h"
|
|
|
|
#include "xpram.h"
|
|
|
|
#include "timer.h"
|
|
|
|
#include "adb.h"
|
|
|
|
#include "sony.h"
|
|
|
|
#include "disk.h"
|
|
|
|
#include "cdrom.h"
|
|
|
|
#include "scsi.h"
|
|
|
|
#include "video.h"
|
|
|
|
#include "audio.h"
|
|
|
|
#include "ether.h"
|
|
|
|
#include "serial.h"
|
|
|
|
#include "clip.h"
|
|
|
|
#include "extfs.h"
|
|
|
|
#include "macos_util.h"
|
|
|
|
#include "rom_patches.h"
|
|
|
|
#include "rsrc_patches.h"
|
|
|
|
#include "name_registry.h"
|
|
|
|
#include "user_strings.h"
|
|
|
|
#include "emul_op.h"
|
2003-12-04 17:26:38 +00:00
|
|
|
#include "thunks.h"
|
2002-02-04 16:58:13 +00:00
|
|
|
|
|
|
|
#define DEBUG 0
|
|
|
|
#include "debug.h"
|
|
|
|
|
|
|
|
|
|
|
|
#if __BEOS__
|
|
|
|
#define PRECISE_TIMING 1
|
|
|
|
#else
|
|
|
|
#define PRECISE_TIMING 0
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
|
|
// TVector of MakeExecutable
|
|
|
|
static uint32 *MakeExecutableTvec;
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Execute EMUL_OP opcode (called by 68k emulator)
|
|
|
|
*/
|
|
|
|
|
|
|
|
void EmulOp(M68kRegisters *r, uint32 pc, int selector)
|
|
|
|
{
|
|
|
|
D(bug("EmulOp %04x at %08x\n", selector, pc));
|
|
|
|
switch (selector) {
|
|
|
|
case OP_BREAK: // Breakpoint
|
|
|
|
printf("*** Breakpoint\n");
|
|
|
|
Dump68kRegs(r);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case OP_XPRAM1: { // Read/write from/to XPRam
|
|
|
|
uint32 len = r->d[3];
|
|
|
|
uint8 *adr = Mac2HostAddr(r->a[3]);
|
|
|
|
D(bug("XPRAMReadWrite d3: %08lx, a3: %p\n", len, adr));
|
|
|
|
int ofs = len & 0xffff;
|
|
|
|
len >>= 16;
|
|
|
|
if (len & 0x8000) {
|
|
|
|
len &= 0x7fff;
|
|
|
|
for (uint32 i=0; i<len; i++)
|
|
|
|
XPRAM[((ofs + i) & 0xff) + 0x1300] = *adr++;
|
|
|
|
} else {
|
|
|
|
for (uint32 i=0; i<len; i++)
|
|
|
|
*adr++ = XPRAM[((ofs + i) & 0xff) + 0x1300];
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
case OP_XPRAM2: // Read from XPRam
|
|
|
|
r->d[1] = XPRAM[(r->d[1] & 0xff) + 0x1300];
|
|
|
|
break;
|
|
|
|
|
|
|
|
case OP_XPRAM3: // Write to XPRam
|
|
|
|
XPRAM[(r->d[1] & 0xff) + 0x1300] = r->d[2];
|
|
|
|
break;
|
|
|
|
|
|
|
|
case OP_NVRAM1: { // Read from NVRAM
|
|
|
|
int ofs = r->d[0];
|
|
|
|
r->d[0] = XPRAM[ofs & 0x1fff];
|
|
|
|
bool localtalk = !(XPRAM[0x13e0] || XPRAM[0x13e1]); // LocalTalk enabled?
|
|
|
|
switch (ofs) {
|
|
|
|
case 0x13e0: // Disable LocalTalk (use EtherTalk instead)
|
|
|
|
if (localtalk)
|
|
|
|
r->d[0] = 0x00;
|
|
|
|
break;
|
|
|
|
case 0x13e1:
|
|
|
|
if (localtalk)
|
|
|
|
r->d[0] = 0x01;
|
|
|
|
break;
|
|
|
|
case 0x13e2:
|
|
|
|
if (localtalk)
|
|
|
|
r->d[0] = 0x00;
|
|
|
|
break;
|
|
|
|
case 0x13e3:
|
|
|
|
if (localtalk)
|
|
|
|
r->d[0] = 0x0a;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
case OP_NVRAM2: // Write to NVRAM
|
|
|
|
XPRAM[r->d[0] & 0x1fff] = r->d[1];
|
|
|
|
break;
|
|
|
|
|
|
|
|
case OP_NVRAM3: // Read/write from/to NVRAM
|
|
|
|
if (r->d[3]) {
|
|
|
|
r->d[0] = XPRAM[(r->d[4] + 0x1300) & 0x1fff];
|
|
|
|
} else {
|
|
|
|
XPRAM[(r->d[4] + 0x1300) & 0x1fff] = r->d[5];
|
|
|
|
r->d[0] = 0;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case OP_FIX_MEMTOP: // Fixes MemTop in BootGlobs during startup
|
|
|
|
D(bug("Fix MemTop\n"));
|
|
|
|
WriteMacInt32(BootGlobsAddr - 20, RAMBase + RAMSize); // MemTop
|
|
|
|
r->a[6] = RAMBase + RAMSize;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case OP_FIX_MEMSIZE: { // Fixes physical/logical RAM size during startup
|
|
|
|
D(bug("Fix MemSize\n"));
|
|
|
|
uint32 diff = ReadMacInt32(0x1ef8) - ReadMacInt32(0x1ef4);
|
|
|
|
WriteMacInt32(0x1ef8, RAMSize); // Physical RAM size
|
|
|
|
WriteMacInt32(0x1ef4, RAMSize - diff); // Logical RAM size
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
case OP_FIX_BOOTSTACK: // Fixes boot stack pointer in boot 3 resource
|
|
|
|
D(bug("Fix BootStack\n"));
|
|
|
|
r->a[1] = r->a[7] = RAMBase + RAMSize * 3 / 4;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case OP_SONY_OPEN: // Floppy driver functions
|
|
|
|
r->d[0] = SonyOpen(r->a[0], r->a[1]);
|
|
|
|
break;
|
|
|
|
case OP_SONY_PRIME:
|
|
|
|
r->d[0] = SonyPrime(r->a[0], r->a[1]);
|
|
|
|
break;
|
|
|
|
case OP_SONY_CONTROL:
|
|
|
|
r->d[0] = SonyControl(r->a[0], r->a[1]);
|
|
|
|
break;
|
|
|
|
case OP_SONY_STATUS:
|
|
|
|
r->d[0] = SonyStatus(r->a[0], r->a[1]);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case OP_DISK_OPEN: // Disk driver functions
|
|
|
|
r->d[0] = DiskOpen(r->a[0], r->a[1]);
|
|
|
|
break;
|
|
|
|
case OP_DISK_PRIME:
|
|
|
|
r->d[0] = DiskPrime(r->a[0], r->a[1]);
|
|
|
|
break;
|
|
|
|
case OP_DISK_CONTROL:
|
|
|
|
r->d[0] = DiskControl(r->a[0], r->a[1]);
|
|
|
|
break;
|
|
|
|
case OP_DISK_STATUS:
|
|
|
|
r->d[0] = DiskStatus(r->a[0], r->a[1]);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case OP_CDROM_OPEN: // CD-ROM driver functions
|
|
|
|
r->d[0] = CDROMOpen(r->a[0], r->a[1]);
|
|
|
|
break;
|
|
|
|
case OP_CDROM_PRIME:
|
|
|
|
r->d[0] = CDROMPrime(r->a[0], r->a[1]);
|
|
|
|
break;
|
|
|
|
case OP_CDROM_CONTROL:
|
|
|
|
r->d[0] = CDROMControl(r->a[0], r->a[1]);
|
|
|
|
break;
|
|
|
|
case OP_CDROM_STATUS:
|
|
|
|
r->d[0] = CDROMStatus(r->a[0], r->a[1]);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case OP_AUDIO_DISPATCH: // Audio component functions
|
|
|
|
r->d[0] = AudioDispatch(r->a[3], r->a[4]);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case OP_SOUNDIN_OPEN: // Sound input driver functions
|
|
|
|
r->d[0] = SoundInOpen(r->a[0], r->a[1]);
|
|
|
|
break;
|
|
|
|
case OP_SOUNDIN_PRIME:
|
|
|
|
r->d[0] = SoundInPrime(r->a[0], r->a[1]);
|
|
|
|
break;
|
|
|
|
case OP_SOUNDIN_CONTROL:
|
|
|
|
r->d[0] = SoundInControl(r->a[0], r->a[1]);
|
|
|
|
break;
|
|
|
|
case OP_SOUNDIN_STATUS:
|
|
|
|
r->d[0] = SoundInStatus(r->a[0], r->a[1]);
|
|
|
|
break;
|
|
|
|
case OP_SOUNDIN_CLOSE:
|
|
|
|
r->d[0] = SoundInClose(r->a[0], r->a[1]);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case OP_ADBOP: // ADBOp() replacement
|
|
|
|
ADBOp(r->d[0], Mac2HostAddr(ReadMacInt32(r->a[0])));
|
|
|
|
break;
|
|
|
|
|
|
|
|
case OP_INSTIME: // InsTime() replacement
|
|
|
|
r->d[0] = InsTime(r->a[0], r->d[1]);
|
|
|
|
break;
|
|
|
|
case OP_RMVTIME: // RmvTime() replacement
|
|
|
|
r->d[0] = RmvTime(r->a[0]);
|
|
|
|
break;
|
|
|
|
case OP_PRIMETIME: // PrimeTime() replacement
|
|
|
|
r->d[0] = PrimeTime(r->a[0], r->d[0]);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case OP_MICROSECONDS: // Microseconds() replacement
|
|
|
|
Microseconds(r->a[0], r->d[0]);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case OP_PUT_SCRAP: // PutScrap() patch
|
|
|
|
PutScrap(ReadMacInt32(r->a[7] + 8), Mac2HostAddr(ReadMacInt32(r->a[7] + 4)), ReadMacInt32(r->a[7] + 12));
|
|
|
|
break;
|
|
|
|
|
|
|
|
case OP_GET_SCRAP: // GetScrap() patch
|
|
|
|
GetScrap((void **)Mac2HostAddr(ReadMacInt32(r->a[7] + 4)), ReadMacInt32(r->a[7] + 8), ReadMacInt32(r->a[7] + 12));
|
|
|
|
break;
|
|
|
|
|
|
|
|
case OP_DEBUG_STR: // DebugStr() shows warning message
|
|
|
|
if (PrefsFindBool("nogui")) {
|
|
|
|
uint8 *pstr = Mac2HostAddr(ReadMacInt32(r->a[7] + 4));
|
|
|
|
char str[256];
|
|
|
|
int i;
|
|
|
|
for (i=0; i<pstr[0]; i++)
|
|
|
|
str[i] = pstr[i+1];
|
|
|
|
str[i] = 0;
|
|
|
|
WarningAlert(str);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case OP_INSTALL_DRIVERS: { // Patch to install our own drivers during startup
|
|
|
|
// Install drivers
|
|
|
|
InstallDrivers();
|
|
|
|
|
|
|
|
// Patch MakeExecutable()
|
|
|
|
MakeExecutableTvec = (uint32 *)FindLibSymbol("\023PrivateInterfaceLib", "\016MakeExecutable");
|
|
|
|
D(bug("MakeExecutable TVECT at %p\n", MakeExecutableTvec));
|
2003-12-04 17:26:38 +00:00
|
|
|
MakeExecutableTvec[0] = htonl(NativeFunction(NATIVE_MAKE_EXECUTABLE));
|
|
|
|
#if !EMULATED_PPC
|
2002-02-04 16:58:13 +00:00
|
|
|
MakeExecutableTvec[1] = (uint32)TOC;
|
|
|
|
#endif
|
|
|
|
|
|
|
|
// Patch DebugStr()
|
2004-01-10 08:46:57 +00:00
|
|
|
static const uint16 proc[] = {
|
|
|
|
PW(M68K_EMUL_OP_DEBUG_STR),
|
|
|
|
PW(0x4e74), // rtd #4
|
|
|
|
PW(0x0004)
|
2002-02-04 16:58:13 +00:00
|
|
|
};
|
|
|
|
WriteMacInt32(0x1dfc, (uint32)proc);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
case OP_NAME_REGISTRY: // Patch Name Registry and initialize CallUniversalProc
|
|
|
|
r->d[0] = (uint32)-1;
|
|
|
|
PatchNameRegistry();
|
|
|
|
InitCallUniversalProc();
|
|
|
|
break;
|
|
|
|
|
|
|
|
case OP_RESET: // Early in MacOS reset
|
|
|
|
D(bug("*** RESET ***\n"));
|
|
|
|
TimerReset();
|
|
|
|
MacOSUtilReset();
|
|
|
|
AudioReset();
|
|
|
|
#if 0
|
|
|
|
printf("DR activated\n");
|
|
|
|
WriteMacInt32(KernelDataAddr + 0x17a0, 3); // Prepare for DR emulator activation
|
|
|
|
WriteMacInt32(KernelDataAddr + 0x17c0, DR_CACHE_BASE);
|
|
|
|
WriteMacInt32(KernelDataAddr + 0x17c4, DR_CACHE_SIZE);
|
|
|
|
WriteMacInt32(KernelDataAddr + 0x1b00, DR_CACHE_BASE + 0x10000);
|
|
|
|
memcpy((void *)(DR_CACHE_BASE + 0x10000), (void *)(ROM_BASE + 0x370000), 0x10000);
|
|
|
|
clear_caches((void *)(DR_CACHE_BASE + 0x10000), 0x10000, B_INVALIDATE_ICACHE | B_FLUSH_DCACHE);
|
|
|
|
#endif
|
|
|
|
break;
|
|
|
|
|
|
|
|
case OP_IRQ: // Level 1 interrupt
|
|
|
|
WriteMacInt16(ReadMacInt32(KernelDataAddr + 0x67c), 0); // Clear interrupt
|
|
|
|
r->d[0] = 0;
|
|
|
|
if (HasMacStarted()) {
|
|
|
|
if (InterruptFlags & INTFLAG_VIA) {
|
|
|
|
ClearInterruptFlag(INTFLAG_VIA);
|
|
|
|
#if !PRECISE_TIMING
|
|
|
|
TimerInterrupt();
|
|
|
|
#endif
|
2003-09-07 14:33:54 +00:00
|
|
|
ExecuteNative(NATIVE_VIDEO_VBL);
|
2002-02-04 16:58:13 +00:00
|
|
|
|
|
|
|
static int tick_counter = 0;
|
|
|
|
if (++tick_counter >= 60) {
|
|
|
|
tick_counter = 0;
|
|
|
|
SonyInterrupt();
|
|
|
|
DiskInterrupt();
|
|
|
|
CDROMInterrupt();
|
|
|
|
}
|
|
|
|
|
|
|
|
r->d[0] = 1; // Flag: 68k interrupt routine executes VBLTasks etc.
|
|
|
|
}
|
|
|
|
if (InterruptFlags & INTFLAG_SERIAL) {
|
|
|
|
ClearInterruptFlag(INTFLAG_SERIAL);
|
|
|
|
SerialInterrupt();
|
|
|
|
}
|
|
|
|
if (InterruptFlags & INTFLAG_ETHER) {
|
|
|
|
ClearInterruptFlag(INTFLAG_ETHER);
|
2003-09-07 14:33:54 +00:00
|
|
|
ExecuteNative(NATIVE_ETHER_IRQ);
|
2002-02-04 16:58:13 +00:00
|
|
|
}
|
|
|
|
if (InterruptFlags & INTFLAG_TIMER) {
|
|
|
|
ClearInterruptFlag(INTFLAG_TIMER);
|
|
|
|
TimerInterrupt();
|
|
|
|
}
|
|
|
|
if (InterruptFlags & INTFLAG_AUDIO) {
|
|
|
|
ClearInterruptFlag(INTFLAG_AUDIO);
|
|
|
|
AudioInterrupt();
|
|
|
|
}
|
|
|
|
if (InterruptFlags & INTFLAG_ADB) {
|
|
|
|
ClearInterruptFlag(INTFLAG_ADB);
|
|
|
|
ADBInterrupt();
|
|
|
|
}
|
|
|
|
} else
|
|
|
|
r->d[0] = 1;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case OP_SCSI_DISPATCH: { // SCSIDispatch() replacement
|
|
|
|
uint32 ret = ReadMacInt32(r->a[7]);
|
|
|
|
uint16 sel = ReadMacInt16(r->a[7] + 4);
|
|
|
|
r->a[7] += 6;
|
|
|
|
// D(bug("SCSIDispatch(%d)\n", sel));
|
|
|
|
int stack;
|
|
|
|
switch (sel) {
|
|
|
|
case 0: // SCSIReset
|
|
|
|
WriteMacInt16(r->a[7], SCSIReset());
|
|
|
|
stack = 0;
|
|
|
|
break;
|
|
|
|
case 1: // SCSIGet
|
|
|
|
WriteMacInt16(r->a[7], SCSIGet());
|
|
|
|
stack = 0;
|
|
|
|
break;
|
|
|
|
case 2: // SCSISelect
|
|
|
|
case 11: // SCSISelAtn
|
|
|
|
WriteMacInt16(r->a[7] + 2, SCSISelect(ReadMacInt8(r->a[7] + 1)));
|
|
|
|
stack = 2;
|
|
|
|
break;
|
|
|
|
case 3: // SCSICmd
|
|
|
|
WriteMacInt16(r->a[7] + 6, SCSICmd(ReadMacInt16(r->a[7]), Mac2HostAddr(ReadMacInt32(r->a[7] + 2))));
|
|
|
|
stack = 6;
|
|
|
|
break;
|
|
|
|
case 4: // SCSIComplete
|
|
|
|
WriteMacInt16(r->a[7] + 12, SCSIComplete(ReadMacInt32(r->a[7]), ReadMacInt32(r->a[7] + 4), ReadMacInt32(r->a[7] + 8)));
|
|
|
|
stack = 12;
|
|
|
|
break;
|
|
|
|
case 5: // SCSIRead
|
|
|
|
case 8: // SCSIRBlind
|
|
|
|
WriteMacInt16(r->a[7] + 4, SCSIRead(ReadMacInt32(r->a[7])));
|
|
|
|
stack = 4;
|
|
|
|
break;
|
|
|
|
case 6: // SCSIWrite
|
|
|
|
case 9: // SCSIWBlind
|
|
|
|
WriteMacInt16(r->a[7] + 4, SCSIWrite(ReadMacInt32(r->a[7])));
|
|
|
|
stack = 4;
|
|
|
|
break;
|
|
|
|
case 10: // SCSIStat
|
|
|
|
WriteMacInt16(r->a[7], SCSIStat());
|
|
|
|
stack = 0;
|
|
|
|
break;
|
|
|
|
case 12: // SCSIMsgIn
|
|
|
|
WriteMacInt16(r->a[7] + 4, 0);
|
|
|
|
stack = 4;
|
|
|
|
break;
|
|
|
|
case 13: // SCSIMsgOut
|
|
|
|
WriteMacInt16(r->a[7] + 2, 0);
|
|
|
|
stack = 2;
|
|
|
|
break;
|
|
|
|
case 14: // SCSIMgrBusy
|
|
|
|
WriteMacInt16(r->a[7], SCSIMgrBusy());
|
|
|
|
stack = 0;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
printf("FATAL: SCSIDispatch: illegal selector\n");
|
|
|
|
stack = 0;
|
|
|
|
//!! SysError(12)
|
|
|
|
}
|
|
|
|
r->a[0] = ret;
|
|
|
|
r->a[7] += stack;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
case OP_SCSI_ATOMIC: // SCSIAtomic() replacement
|
|
|
|
D(bug("SCSIAtomic\n"));
|
|
|
|
r->d[0] = (uint32)-7887;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case OP_NTRB_17_PATCH:
|
|
|
|
r->a[2] = ReadMacInt32(r->a[7]);
|
|
|
|
r->a[7] += 4;
|
|
|
|
if (ReadMacInt16(r->a[2] + 6) == 17)
|
|
|
|
PatchNativeResourceManager();
|
|
|
|
break;
|
|
|
|
|
|
|
|
case OP_NTRB_17_PATCH2:
|
|
|
|
r->a[7] += 8;
|
|
|
|
PatchNativeResourceManager();
|
|
|
|
break;
|
|
|
|
|
|
|
|
case OP_NTRB_17_PATCH3:
|
|
|
|
r->a[2] = ReadMacInt32(r->a[7]);
|
|
|
|
r->a[7] += 4;
|
|
|
|
D(bug("%d %d\n", ReadMacInt16(r->a[2]), ReadMacInt16(r->a[2] + 6)));
|
|
|
|
if (ReadMacInt16(r->a[2]) == 11 && ReadMacInt16(r->a[2] + 6) == 17)
|
|
|
|
PatchNativeResourceManager();
|
|
|
|
break;
|
|
|
|
|
|
|
|
case OP_CHECKLOAD: { // vCheckLoad() patch
|
|
|
|
uint32 type = ReadMacInt32(r->a[7]);
|
|
|
|
r->a[7] += 4;
|
|
|
|
int16 id = ReadMacInt16(r->a[2]);
|
|
|
|
if (r->a[0] == 0)
|
|
|
|
break;
|
|
|
|
uint32 adr = ReadMacInt32(r->a[0]);
|
|
|
|
if (adr == 0)
|
|
|
|
break;
|
|
|
|
uint16 *p = (uint16 *)Mac2HostAddr(adr);
|
|
|
|
uint32 size = ReadMacInt32(adr - 8) & 0xffffff;
|
|
|
|
CheckLoad(type, id, p, size);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
case OP_EXTFS_COMM: // External file system routines
|
|
|
|
WriteMacInt16(r->a[7] + 14, ExtFSComm(ReadMacInt16(r->a[7] + 12), ReadMacInt32(r->a[7] + 8), ReadMacInt32(r->a[7] + 4)));
|
|
|
|
break;
|
|
|
|
|
|
|
|
case OP_EXTFS_HFS:
|
|
|
|
WriteMacInt16(r->a[7] + 20, ExtFSHFS(ReadMacInt32(r->a[7] + 16), ReadMacInt16(r->a[7] + 14), ReadMacInt32(r->a[7] + 10), ReadMacInt32(r->a[7] + 6), ReadMacInt16(r->a[7] + 4)));
|
|
|
|
break;
|
|
|
|
|
|
|
|
case OP_IDLE_TIME:
|
|
|
|
#if __BEOS__
|
|
|
|
// Sleep if no events pending
|
|
|
|
if (ReadMacInt32(0x14c) == 0) {
|
|
|
|
sleep(16667);
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
r->a[0] = ReadMacInt32(0x2b6);
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
printf("FATAL: EMUL_OP called with bogus selector %08x\n", selector);
|
|
|
|
QuitEmulator();
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|