Merge pull request #3873 from unknownbrackets/ge-minor

Improve sceGeBreak and offsetAddr handling
This commit is contained in:
Henrik Rydgård 2013-09-22 00:18:59 -07:00
commit c69852444b
5 changed files with 47 additions and 18 deletions

View File

@ -403,11 +403,28 @@ int sceGeContinue()
return gpu->Continue();
}
int sceGeBreak(u32 mode)
int sceGeBreak(u32 mode, u32 unknownPtr)
{
if (mode > 1)
{
WARN_LOG(SCEGE, "sceGeBreak(mode=%d, unknown=%08x): invalid mode", mode, unknownPtr);
return SCE_KERNEL_ERROR_INVALID_MODE;
}
// Not sure what this is supposed to be for...
if ((int)unknownPtr < 0 || (int)unknownPtr + 16 < 0)
{
WARN_LOG_REPORT(SCEGE, "sceGeBreak(mode=%d, unknown=%08x): invalid ptr", mode, unknownPtr);
return 0x80000023;
}
else if (unknownPtr != 0)
WARN_LOG_REPORT(SCEGE, "sceGeBreak(mode=%d, unknown=%08x): unknown ptr (%s)", mode, unknownPtr, Memory::IsValidAddress(unknownPtr) ? "valid" : "invalid");
//mode => 0 : current dlist 1: all drawing
DEBUG_LOG(SCEGE, "sceGeBreak(mode=%d)", mode);
return gpu->Break(mode);
DEBUG_LOG(SCEGE, "sceGeBreak(mode=%d, unknown=%08x)", mode, unknownPtr);
int result = gpu->Break(mode);
if (result >= 0 && mode == 0)
return 0x35000000 ^ result;
return result;
}
u32 sceGeSetCallback(u32 structAddr)
@ -481,7 +498,7 @@ u32 sceGeSaveContext(u32 ctxAddr)
DEBUG_LOG(SCEGE, "sceGeSaveContext(%08x)", ctxAddr);
gpu->SyncThread();
if (gpu->DrawSync(1) != PSP_GE_LIST_COMPLETED)
if (gpu->BusyDrawing())
{
WARN_LOG(SCEGE, "sceGeSaveContext(%08x): lists in process, aborting", ctxAddr);
// Real error code.
@ -504,7 +521,7 @@ u32 sceGeRestoreContext(u32 ctxAddr)
DEBUG_LOG(SCEGE, "sceGeRestoreContext(%08x)", ctxAddr);
gpu->SyncThread();
if (gpu->DrawSync(1) != PSP_GE_LIST_COMPLETED)
if (gpu->BusyDrawing())
{
WARN_LOG(SCEGE, "sceGeRestoreContext(%08x): lists in process, aborting", ctxAddr);
return SCE_KERNEL_ERROR_BUSY;
@ -601,7 +618,7 @@ const HLEFunction sceGe_user[] =
{0xE0D68148, WrapI_UU<sceGeListUpdateStallAddr>, "sceGeListUpdateStallAddr"},
{0x03444EB4, WrapI_UU<sceGeListSync>, "sceGeListSync"},
{0xB287BD61, WrapU_U<sceGeDrawSync>, "sceGeDrawSync"},
{0xB448EC0D, WrapI_U<sceGeBreak>, "sceGeBreak"},
{0xB448EC0D, WrapI_UU<sceGeBreak>, "sceGeBreak"},
{0x4C06E472, WrapI_V<sceGeContinue>, "sceGeContinue"},
{0xA4FC06A4, WrapU_U<sceGeSetCallback>, "sceGeSetCallback"},
{0x05DB22CE, WrapI_U<sceGeUnsetCallback>, "sceGeUnsetCallback"},

View File

@ -48,6 +48,17 @@ void GPUCommon::PopDLQueue() {
}
}
bool GPUCommon::BusyDrawing() {
u32 state = DrawSync(1);
if (state == PSP_GE_LIST_DRAWING || state == PSP_GE_LIST_STALLING) {
lock_guard guard(listLock);
if (currentList && currentList->state != PSP_GE_DL_STATE_PAUSED) {
return true;
}
}
return false;
}
u32 GPUCommon::DrawSync(int mode) {
// FIXME: Workaround for displaylists sometimes hanging unprocessed. Not yet sure of the cause.
if (g_Config.bSeparateCPUThread) {
@ -252,6 +263,7 @@ u32 GPUCommon::EnqueueList(u32 listpc, u32 stall, int subIntrBase, PSPPointer<Ps
dl.waitTicks = (u64)-1;
dl.interruptsEnabled = interruptsEnabled_;
dl.started = false;
dl.offsetAddr = 0;
if (args.IsValid() && args->context.IsValid())
dl.context = args->context;
else
@ -377,7 +389,7 @@ u32 GPUCommon::Break(int mode) {
return SCE_KERNEL_ERROR_INVALID_MODE;
if (!currentList)
return 0x80000020;
return SCE_KERNEL_ERROR_ALREADY;
if (mode == 1)
{
@ -410,9 +422,9 @@ u32 GPUCommon::Break(int mode) {
ERROR_LOG_REPORT(G3D, "sceGeBreak: can't break signal-pausing list");
}
else
return 0x80000020;
return SCE_KERNEL_ERROR_ALREADY;
}
return 0x80000021;
return SCE_KERNEL_ERROR_BUSY;
}
if (currentList->state == PSP_GE_DL_STATE_QUEUED)
@ -456,10 +468,7 @@ bool GPUCommon::InterpretList(DisplayList &list) {
}
list.started = true;
// I don't know if this is the correct place to zero this, but something
// need to do it. See Sol Trigger title screen.
// TODO: Maybe this is per list? Should a stalled list remember the old value?
gstate_c.offsetAddr = 0;
gstate_c.offsetAddr = list.offsetAddr;
if (!Memory::IsValidAddress(list.pc)) {
ERROR_LOG_REPORT(G3D, "DL PC = %08x WTF!!!!", list.pc);
@ -514,6 +523,8 @@ bool GPUCommon::InterpretList(DisplayList &list) {
UpdatePC(list.pc - 4, list.pc);
}
list.offsetAddr = gstate_c.offsetAddr;
if (g_Config.bShowDebugStats) {
time_update();
gpuStats.msProcessingDisplayLists += time_now_d() - start;

View File

@ -44,6 +44,7 @@ public:
SyncThread();
return true;
}
virtual bool BusyDrawing();
virtual u32 Continue();
virtual u32 Break(int mode);
virtual void ReapplyGfxState();

View File

@ -134,6 +134,7 @@ struct DisplayList
bool pendingInterrupt;
bool started;
u32_le *context;
u32 offsetAddr;
};
enum GPUInvalidationType {
@ -237,6 +238,7 @@ public:
virtual void Resized() = 0;
virtual bool FramebufferDirty() = 0;
virtual bool FramebufferReallyDirty() = 0;
virtual bool BusyDrawing() = 0;
// Debugging
virtual void DumpNextFrame() = 0;

View File

@ -56,14 +56,12 @@ void NullGPU::ExecuteOp(u32 op, u32 diff)
DEBUG_LOG(G3D,"DL BASE: %06x", data);
break;
case GE_CMD_VADDR: /// <<8????
gstate_c.vertexAddr = ((gstate.base & 0x00FF0000) << 8)|data;
DEBUG_LOG(G3D,"DL VADDR: %06x", gstate_c.vertexAddr);
case GE_CMD_VADDR:
gstate_c.vertexAddr = gstate_c.getRelativeAddress(data);
break;
case GE_CMD_IADDR:
gstate_c.indexAddr = ((gstate.base & 0x00FF0000) << 8)|data;
DEBUG_LOG(G3D,"DL IADDR: %06x", gstate_c.indexAddr);
gstate_c.indexAddr = gstate_c.getRelativeAddress(data);
break;
case GE_CMD_PRIM: