diff --git a/src/xenia/cpu/ppc/ppc_emit_control.cc b/src/xenia/cpu/ppc/ppc_emit_control.cc index 15c990339..4452c55ea 100644 --- a/src/xenia/cpu/ppc/ppc_emit_control.cc +++ b/src/xenia/cpu/ppc/ppc_emit_control.cc @@ -423,8 +423,15 @@ int InstrEmit_mcrf(PPCHIRBuilder& f, const InstrData& i) { // System linkage (A-24) int InstrEmit_sc(PPCHIRBuilder& f, const InstrData& i) { - f.CallExtern(f.function()); - return 0; + // Game code should only ever use LEV=0. + // LEV=2 is to signify 'call import' from Xenia. + // TODO(gibbed): syscalls! + if (i.SC.LEV == 2) { + f.CallExtern(f.function()); + return 0; + } + XEINSTRNOTIMPLEMENTED(); + return 1; } // Trap (A-25) diff --git a/src/xenia/cpu/xex_module.cc b/src/xenia/cpu/xex_module.cc index 09cea5143..7208b55b9 100644 --- a/src/xenia/cpu/xex_module.cc +++ b/src/xenia/cpu/xex_module.cc @@ -1225,15 +1225,17 @@ bool XexModule::SetupLibraryImports(const char* name, // bctr // Real consoles rewrite this with some code that sets r11. // If we did that we'd still have to put a thunk somewhere and do the - // dynamic lookup. Instead, we rewrite it to use syscalls, as they - // aren't used on the 360. CPU backends can either take the syscall - // or do something smarter. - // sc + // dynamic lookup. Instead, we rewrite it to use syscalls. + // We use sc with a LEV operand of 2, which is reserved usage and + // should never see actual usage outside of our rewrite. + // CPU backends can either take the special form syscall or do + // something smarter. + // sc 2 // blr // nop // nop uint8_t* p = memory()->TranslateVirtual(record_addr); - xe::store_and_swap(p + 0x0, 0x44000002); + xe::store_and_swap(p + 0x0, 0x44000042); xe::store_and_swap(p + 0x4, 0x4E800020); xe::store_and_swap(p + 0x8, 0x60000000); xe::store_and_swap(p + 0xC, 0x60000000);