From cb1dd6dac57d1a0b461d62191202119df4f16d20 Mon Sep 17 00:00:00 2001 From: gbeauche <> Date: Sun, 7 Sep 2003 14:33:54 +0000 Subject: [PATCH] - Integrate new NativeOp instructions to be used as trampolines to call native functions from ppc code. - Little endian fixes in emul_op.cpp - Add new 'gpch' 750 patch to workaround crash with MacOS 8.6 - Don't crash in Process Manager on reset/shutdown with MacOS 8.6 - We also have an experimental interrupt thread in emulation mode --- SheepShaver/src/Unix/acconfig.h | 3 ++ SheepShaver/src/Unix/main_unix.cpp | 43 +++++++++------ SheepShaver/src/emul_op.cpp | 17 ++++-- SheepShaver/src/include/cpu_emulation.h | 7 ++- SheepShaver/src/include/emul_op.h | 32 ++++++++++- SheepShaver/src/include/name_registry.h | 1 + SheepShaver/src/name_registry.cpp | 9 +++- SheepShaver/src/rom_patches.cpp | 70 ++++++++++++++++--------- SheepShaver/src/rsrc_patches.cpp | 43 ++++++++++++++- 9 files changed, 174 insertions(+), 51 deletions(-) diff --git a/SheepShaver/src/Unix/acconfig.h b/SheepShaver/src/Unix/acconfig.h index 9ba67fda..c1e36681 100644 --- a/SheepShaver/src/Unix/acconfig.h +++ b/SheepShaver/src/Unix/acconfig.h @@ -32,6 +32,9 @@ /* Define if using XFree86 VidMode extension. */ #undef ENABLE_XF86_VIDMODE +/* Define is using PowerPC emulator. */ +#undef EMULATED_PPC + /* Leave that blank line there!! Autoheader needs it. If you're adding to this file, keep in mind: diff --git a/SheepShaver/src/Unix/main_unix.cpp b/SheepShaver/src/Unix/main_unix.cpp index f4b13cc5..8fcbd0bf 100644 --- a/SheepShaver/src/Unix/main_unix.cpp +++ b/SheepShaver/src/Unix/main_unix.cpp @@ -222,8 +222,8 @@ static pthread_t emul_thread; // MacOS thread static bool ready_for_signals = false; // Handler installed, signals can be sent static int64 num_segv = 0; // Number of handled SEGV signals -#if !EMULATED_PPC static struct sigaction sigusr2_action; // Interrupt signal (of emulator thread) +#if !EMULATED_PPC static struct sigaction sigsegv_action; // Data access exception signal (of emulator thread) static struct sigaction sigill_action; // Illegal instruction signal (of emulator thread) static void *sig_stack = NULL; // Stack for signal handlers @@ -238,8 +238,8 @@ static void Quit(void); static void *emul_func(void *arg); static void *nvram_func(void *arg); static void *tick_func(void *arg); -#if !EMULATED_PPC static void sigusr2_handler(int sig, sigcontext_struct *sc); +#if !EMULATED_PPC static void sigsegv_handler(int sig, sigcontext_struct *sc); static void sigill_handler(int sig, sigcontext_struct *sc); #endif @@ -457,7 +457,7 @@ int main(int argc, char **argv) ErrorAlert(str); goto quit; } -#if !EMULATED_PPC +#if !EMULATED_PPC || defined(__powerpc__) if (vm_protect((char *)ROM_BASE, ROM_AREA_SIZE, VM_PAGE_READ | VM_PAGE_WRITE | VM_PAGE_EXECUTE) < 0) { sprintf(str, GetString(STR_ROM_MMAP_ERR), strerror(errno)); ErrorAlert(str); @@ -637,7 +637,15 @@ int main(int argc, char **argv) WriteMacInt32(XLM_PVR, PVR); // Theoretical PVR WriteMacInt32(XLM_BUS_CLOCK, BusClockSpeed); // For DriverServicesLib patch WriteMacInt16(XLM_EXEC_RETURN_OPCODE, M68K_EXEC_RETURN); // For Execute68k() (RTS from the executed 68k code will jump here and end 68k mode) -#if !EMULATED_PPC +#if EMULATED_PPC + WriteMacInt32(XLM_ETHER_INIT, POWERPC_NATIVE_OP_FUNC(NATIVE_ETHER_INIT)); + WriteMacInt32(XLM_ETHER_TERM, POWERPC_NATIVE_OP_FUNC(NATIVE_ETHER_TERM)); + WriteMacInt32(XLM_ETHER_OPEN, POWERPC_NATIVE_OP_FUNC(NATIVE_ETHER_OPEN)); + WriteMacInt32(XLM_ETHER_CLOSE, POWERPC_NATIVE_OP_FUNC(NATIVE_ETHER_CLOSE)); + WriteMacInt32(XLM_ETHER_WPUT, POWERPC_NATIVE_OP_FUNC(NATIVE_ETHER_WPUT)); + WriteMacInt32(XLM_ETHER_RSRV, POWERPC_NATIVE_OP_FUNC(NATIVE_ETHER_RSRV)); + WriteMacInt32(XLM_VIDEO_DOIO, POWERPC_NATIVE_OP_FUNC(NATIVE_VIDEO_DO_DRIVER_IO)); +#else WriteMacInt32(XLM_TOC, (uint32)TOC); // TOC pointer of emulator WriteMacInt32(XLM_ETHER_INIT, (uint32)InitStreamModule); // DLPI ethernet driver functions WriteMacInt32(XLM_ETHER_TERM, (uint32)TerminateStreamModule); @@ -707,18 +715,21 @@ int main(int argc, char **argv) ErrorAlert(str); goto quit; } +#endif // Install interrupt signal handler sigemptyset(&sigusr2_action.sa_mask); sigusr2_action.sa_handler = (__sighandler_t)sigusr2_handler; + sigusr2_action.sa_flags = 0; +#if !EMULATED_PPC sigusr2_action.sa_flags = SA_ONSTACK | SA_RESTART; +#endif sigusr2_action.sa_restorer = NULL; if (sigaction(SIGUSR2, &sigusr2_action, NULL) < 0) { sprintf(str, GetString(STR_SIGUSR2_INSTALL_ERR), strerror(errno)); ErrorAlert(str); goto quit; } -#endif // Get my thread ID and execute MacOS thread function emul_thread = pthread_self(); @@ -995,7 +1006,11 @@ void MakeExecutable(int dummy, void *start, uint32 length) void PatchAfterStartup(void) { +#if EMULATED_PPC + ExecuteNative(NATIVE_VIDEO_INSTALL_ACCEL); +#else ExecutePPC(VideoInstallAccel); +#endif InstallExtFS(); } @@ -1135,16 +1150,8 @@ void B2_delete_mutex(B2_mutex *mutex) void TriggerInterrupt(void) { -#if EMULATED_PPC - WriteMacInt32(0x16a, ReadMacInt32(0x16a) + 1); -#else -#if 0 - WriteMacInt32(0x16a, ReadMacInt32(0x16a) + 1); -#else if (ready_for_signals) pthread_kill(emul_thread, SIGUSR2); -#endif -#endif } @@ -1171,7 +1178,7 @@ void ClearInterruptFlag(uint32 flag) void DisableInterrupt(void) { - atomic_add((int *)XLM_IRQ_NEST, 1); + atomic_add((int *)XLM_IRQ_NEST, tswap32(1)); } @@ -1181,17 +1188,19 @@ void DisableInterrupt(void) void EnableInterrupt(void) { - atomic_add((int *)XLM_IRQ_NEST, -1); + atomic_add((int *)XLM_IRQ_NEST, tswap32((uint32)-1)); } -#if !EMULATED_PPC /* * USR2 handler */ static void sigusr2_handler(int sig, sigcontext_struct *sc) { +#if EMULATED_PPC + HandleInterrupt(); +#else pt_regs *r = sc->regs; // Do nothing if interrupts are disabled @@ -1273,9 +1282,11 @@ static void sigusr2_handler(int sig, sigcontext_struct *sc) #endif } +#endif } +#if !EMULATED_PPC /* * SIGSEGV handler */ diff --git a/SheepShaver/src/emul_op.cpp b/SheepShaver/src/emul_op.cpp index bada48e8..a6c815ec 100644 --- a/SheepShaver/src/emul_op.cpp +++ b/SheepShaver/src/emul_op.cpp @@ -67,7 +67,6 @@ static uint32 *MakeExecutableTvec; void EmulOp(M68kRegisters *r, uint32 pc, int selector) { - D(bug("EmulOp %04x at %08x\n", selector, pc)); switch (selector) { case OP_BREAK: // Breakpoint @@ -271,10 +270,10 @@ void EmulOp(M68kRegisters *r, uint32 pc, int selector) #endif // Patch DebugStr() - static const uint16 proc[] = { - M68K_EMUL_OP_DEBUG_STR, - 0x4e74, // rtd #4 - 0x0004 + static const uint8 proc[] = { + M68K_EMUL_OP_DEBUG_STR >> 8, M68K_EMUL_OP_DEBUG_STR & 0xff, + 0x4e, 0x74, // rtd #4 + 0x00, 0x04 }; WriteMacInt32(0x1dfc, (uint32)proc); break; @@ -311,7 +310,11 @@ void EmulOp(M68kRegisters *r, uint32 pc, int selector) #if !PRECISE_TIMING TimerInterrupt(); #endif +#if EMULATED_PPC + ExecuteNative(NATIVE_VIDEO_VBL); +#else ExecutePPC(VideoVBL); +#endif static int tick_counter = 0; if (++tick_counter >= 60) { @@ -329,7 +332,11 @@ void EmulOp(M68kRegisters *r, uint32 pc, int selector) } if (InterruptFlags & INTFLAG_ETHER) { ClearInterruptFlag(INTFLAG_ETHER); +#if EMULATED_PPC + ExecuteNative(NATIVE_ETHER_IRQ); +#else ExecutePPC(EtherIRQ); +#endif } if (InterruptFlags & INTFLAG_TIMER) { ClearInterruptFlag(INTFLAG_TIMER); diff --git a/SheepShaver/src/include/cpu_emulation.h b/SheepShaver/src/include/cpu_emulation.h index 88442767..1cd5143f 100644 --- a/SheepShaver/src/include/cpu_emulation.h +++ b/SheepShaver/src/include/cpu_emulation.h @@ -68,6 +68,11 @@ static inline void *Mac2Mac_memcpy(uint32 dest, uint32 src, size_t n) {return me struct M68kRegisters; extern void Execute68k(uint32, M68kRegisters *r); // Execute 68k subroutine from EMUL_OP routine, must be ended with RTS extern void Execute68kTrap(uint16 trap, M68kRegisters *r); // Execute 68k A-Trap from EMUL_OP routine -extern void ExecutePPC(void (*func)()); // Execute PPC code from EMUL_OP routine (real mode switch) +#if EMULATED_PPC +extern void HandleInterrupt(void); +extern void ExecuteNative(int selector); // Execute native code from EMUL_OP routine (real mode switch) +#else +extern void ExecutePPC(void (*func)(void)); // Execute PPC code from EMUL_OP routine (real mode switch) +#endif #endif diff --git a/SheepShaver/src/include/emul_op.h b/SheepShaver/src/include/emul_op.h index e93481ac..4a428d6a 100644 --- a/SheepShaver/src/include/emul_op.h +++ b/SheepShaver/src/include/emul_op.h @@ -28,6 +28,35 @@ const uint32 POWERPC_BLR = 0x4e800020; const uint32 POWERPC_BCTR = 0x4e800420; const uint32 POWERPC_EMUL_OP = 0x18000000; // Base opcode for EMUL_OP opcodes (only used with PPC emulation) +enum { // Selectors for NATIVE_EXEC callbacks (only used with PPC emulation) + NATIVE_PATCH_NAME_REGISTRY, + NATIVE_VIDEO_INSTALL_ACCEL, + NATIVE_VIDEO_VBL, + NATIVE_VIDEO_DO_DRIVER_IO, + NATIVE_ETHER_IRQ, + NATIVE_ETHER_INIT, + NATIVE_ETHER_TERM, + NATIVE_ETHER_OPEN, + NATIVE_ETHER_CLOSE, + NATIVE_ETHER_WPUT, + NATIVE_ETHER_RSRV, + NATIVE_SERIAL_NOTHING, + NATIVE_SERIAL_OPEN, + NATIVE_SERIAL_PRIME_IN, + NATIVE_SERIAL_PRIME_OUT, + NATIVE_SERIAL_CONTROL, + NATIVE_SERIAL_STATUS, + NATIVE_SERIAL_CLOSE, + NATIVE_GET_RESOURCE, + NATIVE_GET_1_RESOURCE, + NATIVE_GET_IND_RESOURCE, + NATIVE_GET_1_IND_RESOURCE, + NATIVE_R_GET_RESOURCE, + NATIVE_OP_MAX +}; +#define POWERPC_NATIVE_OP_FUNC(SELECTOR) ((uint32)(uintptr)&NativeOpTable[SELECTOR]) +extern const uint32 NativeOpTable[NATIVE_OP_MAX]; + // 68k opcodes const uint16 M68K_ILLEGAL = 0x4afc; const uint16 M68K_NOP = 0x4e71; @@ -53,7 +82,8 @@ enum { // Selectors for EMUL_OP opcodes }; const uint16 M68K_EMUL_RETURN = 0xfe40; // Extended opcodes const uint16 M68K_EXEC_RETURN = 0xfe41; -const uint16 M68K_EMUL_BREAK = 0xfe42; +const uint16 M68K_EXEC_NATIVE = 0xfe42; +const uint16 M68K_EMUL_BREAK = 0xfe43; const uint16 M68K_EMUL_OP_XPRAM1 = M68K_EMUL_BREAK + OP_XPRAM1; const uint16 M68K_EMUL_OP_XPRAM2 = M68K_EMUL_BREAK + OP_XPRAM2; const uint16 M68K_EMUL_OP_XPRAM3 = M68K_EMUL_BREAK + OP_XPRAM3; diff --git a/SheepShaver/src/include/name_registry.h b/SheepShaver/src/include/name_registry.h index a417e31e..c282abf1 100644 --- a/SheepShaver/src/include/name_registry.h +++ b/SheepShaver/src/include/name_registry.h @@ -21,6 +21,7 @@ #ifndef NAME_REGISTRY_H #define NAME_REGISTRY_H +extern void DoPatchNameRegistry(void); extern void PatchNameRegistry(void); #endif diff --git a/SheepShaver/src/name_registry.cpp b/SheepShaver/src/name_registry.cpp index 9660e4a6..53c6600b 100644 --- a/SheepShaver/src/name_registry.cpp +++ b/SheepShaver/src/name_registry.cpp @@ -25,6 +25,7 @@ #include "main.h" #include "macos_util.h" #include "user_strings.h" +#include "emul_op.h" #define DEBUG 0 #include "debug.h" @@ -60,7 +61,7 @@ static const uint8 ethernet_driver[] = { * Patch Name Registry during startup */ -static void patch_name_registry(void) +void DoPatchNameRegistry(void) { uint32 u32; D(bug("Patching Name Registry...")); @@ -286,5 +287,9 @@ void PatchNameRegistry(void) } // Main routine must be executed in PPC mode - ExecutePPC(patch_name_registry); +#if EMULATED_PPC + ExecuteNative(NATIVE_PATCH_NAME_REGISTRY); +#else + ExecutePPC(DoPatchNameRegistry); +#endif } diff --git a/SheepShaver/src/rom_patches.cpp b/SheepShaver/src/rom_patches.cpp index 0d6e36ee..5fbca399 100644 --- a/SheepShaver/src/rom_patches.cpp +++ b/SheepShaver/src/rom_patches.cpp @@ -447,7 +447,17 @@ static const uint8 cdrom_driver[] = { // CD-ROM driver 0x4e, 0x75 // rts }; -#ifdef __linux__ +#if EMULATED_PPC +#define SERIAL_TRAMPOLINES 1 +static uint32 serial_nothing_tvect[2] = {POWERPC_NATIVE_OP_FUNC(NATIVE_SERIAL_NOTHING), 0}; +static uint32 serial_open_tvect[2] = {POWERPC_NATIVE_OP_FUNC(NATIVE_SERIAL_OPEN), 0}; +static uint32 serial_prime_in_tvect[2] = {POWERPC_NATIVE_OP_FUNC(NATIVE_SERIAL_PRIME_IN), 0}; +static uint32 serial_prime_out_tvect[2] = {POWERPC_NATIVE_OP_FUNC(NATIVE_SERIAL_PRIME_OUT), 0}; +static uint32 serial_control_tvect[2] = {POWERPC_NATIVE_OP_FUNC(NATIVE_SERIAL_CONTROL), 0}; +static uint32 serial_status_tvect[2] = {POWERPC_NATIVE_OP_FUNC(NATIVE_SERIAL_STATUS), 0}; +static uint32 serial_close_tvect[2] = {POWERPC_NATIVE_OP_FUNC(NATIVE_SERIAL_CLOSE), 0}; +#elif defined(__linux__) +#define SERIAL_TRAMPOLINES 1 static uint32 serial_nothing_tvect[2] = {(uint32)SerialNothing, 0}; static uint32 serial_open_tvect[2] = {(uint32)SerialOpen, 0}; static uint32 serial_prime_in_tvect[2] = {(uint32)SerialPrimeIn, 0}; @@ -464,7 +474,7 @@ static const uint32 ain_driver[] = { // .AIn driver header 0x00000000, 0x00000000, 0xaafe0700, 0x00000000, 0x00000000, 0x00179822, -#ifdef __linux__ +#ifdef SERIAL_TRAMPOLINES 0x00010004, (uint32)serial_nothing_tvect, #else 0x00010004, (uint32)SerialNothing, @@ -472,7 +482,7 @@ static const uint32 ain_driver[] = { // .AIn driver header 0x00000000, 0x00000000, 0xaafe0700, 0x00000000, 0x00000000, 0x00179822, -#ifdef __linux__ +#ifdef SERIAL_TRAMPOLINES 0x00010004, (uint32)serial_prime_in_tvect, #else 0x00010004, (uint32)SerialPrimeIn, @@ -480,7 +490,7 @@ static const uint32 ain_driver[] = { // .AIn driver header 0x00000000, 0x00000000, 0xaafe0700, 0x00000000, 0x00000000, 0x00179822, -#ifdef __linux__ +#ifdef SERIAL_TRAMPOLINES 0x00010004, (uint32)serial_control_tvect, #else 0x00010004, (uint32)SerialControl, @@ -488,7 +498,7 @@ static const uint32 ain_driver[] = { // .AIn driver header 0x00000000, 0x00000000, 0xaafe0700, 0x00000000, 0x00000000, 0x00179822, -#ifdef __linux__ +#ifdef SERIAL_TRAMPOLINES 0x00010004, (uint32)serial_status_tvect, #else 0x00010004, (uint32)SerialStatus, @@ -496,7 +506,7 @@ static const uint32 ain_driver[] = { // .AIn driver header 0x00000000, 0x00000000, 0xaafe0700, 0x00000000, 0x00000000, 0x00179822, -#ifdef __linux__ +#ifdef SERIAL_TRAMPOLINES 0x00010004, (uint32)serial_nothing_tvect, #else 0x00010004, (uint32)SerialNothing, @@ -511,7 +521,7 @@ static const uint32 aout_driver[] = { // .AOut driver header 0x00000000, 0x00000000, 0xaafe0700, 0x00000000, 0x00000000, 0x00179822, -#ifdef __linux__ +#ifdef SERIAL_TRAMPOLINES 0x00010004, (uint32)serial_open_tvect, #else 0x00010004, (uint32)SerialOpen, @@ -519,7 +529,7 @@ static const uint32 aout_driver[] = { // .AOut driver header 0x00000000, 0x00000000, 0xaafe0700, 0x00000000, 0x00000000, 0x00179822, -#ifdef __linux__ +#ifdef SERIAL_TRAMPOLINES 0x00010004, (uint32)serial_prime_out_tvect, #else 0x00010004, (uint32)SerialPrimeOut, @@ -527,7 +537,7 @@ static const uint32 aout_driver[] = { // .AOut driver header 0x00000000, 0x00000000, 0xaafe0700, 0x00000000, 0x00000000, 0x00179822, -#ifdef __linux__ +#ifdef SERIAL_TRAMPOLINES 0x00010004, (uint32)serial_control_tvect, #else 0x00010004, (uint32)SerialControl, @@ -535,7 +545,7 @@ static const uint32 aout_driver[] = { // .AOut driver header 0x00000000, 0x00000000, 0xaafe0700, 0x00000000, 0x00000000, 0x00179822, -#ifdef __linux__ +#ifdef SERIAL_TRAMPOLINES 0x00010004, (uint32)serial_status_tvect, #else 0x00010004, (uint32)SerialStatus, @@ -543,7 +553,7 @@ static const uint32 aout_driver[] = { // .AOut driver header 0x00000000, 0x00000000, 0xaafe0700, 0x00000000, 0x00000000, 0x00179822, -#ifdef __linux__ +#ifdef SERIAL_TRAMPOLINES 0x00010004, (uint32)serial_close_tvect, #else 0x00010004, (uint32)SerialClose, @@ -558,7 +568,7 @@ static const uint32 bin_driver[] = { // .BIn driver header 0x00000000, 0x00000000, 0xaafe0700, 0x00000000, 0x00000000, 0x00179822, -#ifdef __linux__ +#ifdef SERIAL_TRAMPOLINES 0x00010004, (uint32)serial_nothing_tvect, #else 0x00010004, (uint32)SerialNothing, @@ -566,7 +576,7 @@ static const uint32 bin_driver[] = { // .BIn driver header 0x00000000, 0x00000000, 0xaafe0700, 0x00000000, 0x00000000, 0x00179822, -#ifdef __linux__ +#ifdef SERIAL_TRAMPOLINES 0x00010004, (uint32)serial_prime_in_tvect, #else 0x00010004, (uint32)SerialPrimeIn, @@ -574,7 +584,7 @@ static const uint32 bin_driver[] = { // .BIn driver header 0x00000000, 0x00000000, 0xaafe0700, 0x00000000, 0x00000000, 0x00179822, -#ifdef __linux__ +#ifdef SERIAL_TRAMPOLINES 0x00010004, (uint32)serial_control_tvect, #else 0x00010004, (uint32)SerialControl, @@ -582,7 +592,7 @@ static const uint32 bin_driver[] = { // .BIn driver header 0x00000000, 0x00000000, 0xaafe0700, 0x00000000, 0x00000000, 0x00179822, -#ifdef __linux__ +#ifdef SERIAL_TRAMPOLINES 0x00010004, (uint32)serial_status_tvect, #else 0x00010004, (uint32)SerialStatus, @@ -590,7 +600,7 @@ static const uint32 bin_driver[] = { // .BIn driver header 0x00000000, 0x00000000, 0xaafe0700, 0x00000000, 0x00000000, 0x00179822, -#ifdef __linux__ +#ifdef SERIAL_TRAMPOLINES 0x00010004, (uint32)serial_nothing_tvect, #else 0x00010004, (uint32)SerialNothing, @@ -605,7 +615,7 @@ static const uint32 bout_driver[] = { // .BOut driver header 0x00000000, 0x00000000, 0xaafe0700, 0x00000000, 0x00000000, 0x00179822, -#ifdef __linux__ +#ifdef SERIAL_TRAMPOLINES 0x00010004, (uint32)serial_open_tvect, #else 0x00010004, (uint32)SerialOpen, @@ -613,7 +623,7 @@ static const uint32 bout_driver[] = { // .BOut driver header 0x00000000, 0x00000000, 0xaafe0700, 0x00000000, 0x00000000, 0x00179822, -#ifdef __linux__ +#ifdef SERIAL_TRAMPOLINES 0x00010004, (uint32)serial_prime_out_tvect, #else 0x00010004, (uint32)SerialPrimeOut, @@ -621,7 +631,7 @@ static const uint32 bout_driver[] = { // .BOut driver header 0x00000000, 0x00000000, 0xaafe0700, 0x00000000, 0x00000000, 0x00179822, -#ifdef __linux__ +#ifdef SERIAL_TRAMPOLINES 0x00010004, (uint32)serial_control_tvect, #else 0x00010004, (uint32)SerialControl, @@ -629,7 +639,7 @@ static const uint32 bout_driver[] = { // .BOut driver header 0x00000000, 0x00000000, 0xaafe0700, 0x00000000, 0x00000000, 0x00179822, -#ifdef __linux__ +#ifdef SERIAL_TRAMPOLINES 0x00010004, (uint32)serial_status_tvect, #else 0x00010004, (uint32)SerialStatus, @@ -637,7 +647,7 @@ static const uint32 bout_driver[] = { // .BOut driver header 0x00000000, 0x00000000, 0xaafe0700, 0x00000000, 0x00000000, 0x00179822, -#ifdef __linux__ +#ifdef SERIAL_TRAMPOLINES 0x00010004, (uint32)serial_close_tvect, #else 0x00010004, (uint32)SerialClose, @@ -1030,15 +1040,17 @@ static bool patch_68k_emul(void) *lp = htonl(POWERPC_ILLEGAL); #if EMULATED_PPC - // Install EMUL_RETURN, EXEC_RETURN and EMUL_OP opcodes + // Install EMUL_RETURN, EXEC_RETURN, EXEC_NATIVE and EMUL_OP opcodes lp = (uint32 *)(ROM_BASE + 0x380000 + (M68K_EMUL_RETURN << 3)); *lp++ = htonl(POWERPC_EMUL_OP); *lp++ = htonl(0x4bf66e80); // b 0x366084 *lp++ = htonl(POWERPC_EMUL_OP | 1); *lp++ = htonl(0x4bf66e78); // b 0x366084 + *lp++ = htonl(POWERPC_EMUL_OP | 2); + *lp++ = htonl(0x4bf66e70); // b 0x366084 for (int i=0; i