diff --git a/rpcs3/Emu/RSX/GCM.h b/rpcs3/Emu/RSX/GCM.h index b0d16bc667..e19e792652 100644 --- a/rpcs3/Emu/RSX/GCM.h +++ b/rpcs3/Emu/RSX/GCM.h @@ -216,12 +216,16 @@ struct CellGcmConfig be_t coreFrequency; }; +struct CellGcmContextData; + +typedef s32(*CellGcmContextCallback)(vm::ptr, u32); + struct CellGcmContextData { be_t begin; be_t end; be_t current; - be_t callback; + vm::bptr callback; }; struct gcmInfo diff --git a/rpcs3/Emu/RSX/RSXThread.cpp b/rpcs3/Emu/RSX/RSXThread.cpp index c3e0f4ff95..7bfc5daa6c 100644 --- a/rpcs3/Emu/RSX/RSXThread.cpp +++ b/rpcs3/Emu/RSX/RSXThread.cpp @@ -2266,7 +2266,7 @@ void RSXThread::Task() if(cmd == 0) { LOG_ERROR(Log::RSX, "null cmd: cmd=0x%x, put=0x%x, get=0x%x (addr=0x%x)", cmd, put, get, (u32)Memory.RSXIOMem.RealAddr(get)); - Emu.Pause(); + //Emu.Pause(); //HACK! We shouldn't be here m_ctrl->get = get + (count + 1) * 4; continue; diff --git a/rpcs3/Emu/SysCalls/Modules/cellGcmSys.cpp b/rpcs3/Emu/SysCalls/Modules/cellGcmSys.cpp index 31eae6d11c..9b61ce5ce3 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellGcmSys.cpp +++ b/rpcs3/Emu/SysCalls/Modules/cellGcmSys.cpp @@ -368,7 +368,7 @@ s32 _cellGcmInitBody(vm::ptr context, u32 cmdSize, u32 ioSiz current_context.begin = ctx_begin; current_context.end = ctx_begin + ctx_size; current_context.current = current_context.begin; - current_context.callback = Emu.GetRSXCallback() - 4; + current_context.callback.set(be_t::make(Emu.GetRSXCallback() - 4)); gcm_info.context_addr = (u32)Memory.MainMem.AllocAlign(0x1000); gcm_info.control_addr = gcm_info.context_addr + 0x40; @@ -502,21 +502,11 @@ s32 cellGcmSetPrepareFlip(vm::ptr ctxt, u32 id) if(current + 8 >= end) { - cellGcmSys->Error("bad flip!"); - //cellGcmCallback(ctxt.addr(), current + 8 - end); - //copied: - - auto& ctrl = vm::get_ref(gcm_info.control_addr); - - const s32 res = ctxt->current - ctxt->begin - ctrl.put; - - memmove(vm::get_ptr(ctxt->begin), vm::get_ptr(ctxt->current - res), res); - - ctxt->current = ctxt->begin + res; - - //InterlockedExchange64((volatile long long*)((u8*)&ctrl + offsetof(CellGcmControl, put)), (u64)(u32)re(res)); - ctrl.put = res; - ctrl.get = 0; + if (s32 res = ctxt->callback(ctxt, 8 /* ??? */)) + { + cellGcmSys->Error("cellGcmSetPrepareFlip : callback failed (0x%08x)", res); + return res; + } } current = ctxt->current; @@ -1163,25 +1153,14 @@ int cellGcmSetTile(u8 index, u8 location, u32 offset, u32 size, u32 pitch, u8 co // TODO: This function was originally located in lv2/SC_GCM and appears in RPCS3 as a lv2 syscall with id 1023, // which according to lv2 dumps isn't the case. So, is this a proper place for this function? -int cellGcmCallback(u32 context_addr, u32 count) +s32 cellGcmCallback(vm::ptr context, u32 count) { - cellGcmSys->Log("cellGcmCallback(context_addr=0x%x, count=0x%x)", context_addr, count); - - GSLockCurrent gslock(GS_LOCK_WAIT_FLUSH); - - auto& ctx = vm::get_ref(context_addr); - auto& ctrl = vm::get_ref(gcm_info.control_addr); - - const s32 res = ctx.current - ctx.begin - ctrl.put; - - memmove(vm::get_ptr(ctx.begin), vm::get_ptr(ctx.current - res), res); - - ctx.current = ctx.begin + res; - - //InterlockedExchange64((volatile long long*)((u8*)&ctrl + offsetof(CellGcmControl, put)), (u64)(u32)re(res)); - ctrl.put = res; - ctrl.get = 0; + cellGcmSys->Log("cellGcmCallback(context_addr=0x%x, count=0x%x)", context.addr(), count); + // TODO: this may be wrong + + vm::write32(context->current, CELL_GCM_METHOD_FLAG_JUMP | CELL_GCM_METHOD_FLAG_NON_INCREMENT | (0)); // set JUMP cmd + context->current = context->begin; // rewind to the beginning return CELL_OK; } diff --git a/rpcs3/Emu/SysCalls/Modules/cellGcmSys.h b/rpcs3/Emu/SysCalls/Modules/cellGcmSys.h index 1473799882..1ee95bdfaf 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellGcmSys.h +++ b/rpcs3/Emu/SysCalls/Modules/cellGcmSys.h @@ -1,4 +1,5 @@ #pragma once +#include "Emu/RSX/GCM.h" enum { @@ -20,8 +21,7 @@ struct CellGcmOffsetTable void InitOffsetTable(); u32 gcmGetLocalMemorySize(); - -// SysCalls +// libgcm functions s32 cellGcmSetPrepareFlip(vm::ptr ctxt, u32 id); s32 cellGcmAddressToOffset(u64 address, vm::ptr> offset); @@ -35,3 +35,6 @@ s32 cellGcmReserveIoMapSize(u32 size); s32 cellGcmUnmapEaIoAddress(u64 ea); s32 cellGcmUnmapIoAddress(u64 io); s32 cellGcmUnreserveIoMapSize(u32 size); + +// Syscall +s32 cellGcmCallback(vm::ptr context, u32 count); diff --git a/rpcs3/Emu/SysCalls/SysCalls.cpp b/rpcs3/Emu/SysCalls/SysCalls.cpp index f055985e88..af6777ecff 100644 --- a/rpcs3/Emu/SysCalls/SysCalls.cpp +++ b/rpcs3/Emu/SysCalls/SysCalls.cpp @@ -26,6 +26,8 @@ #include "lv2/sys_tty.h" #include "lv2/sys_vm.h" +#include "Emu/SysCalls/Modules/cellGcmSys.h" + #include "SysCalls.h" namespace detail{ @@ -40,8 +42,6 @@ static func_caller *null_func = bind_func(default_syscall); static const int kSyscallTableLength = 1024; -extern int cellGcmCallback(u32 context_addr, u32 count); - // UNS = Unused // ROOT = Root // DBG = Debug