Add support for selecting the GE callback per list.

Not sure if interrupts are right, but this should be more right.
This commit is contained in:
Unknown W. Brackets 2012-12-21 22:50:35 -08:00
parent 2ed0902ae2
commit 97bdaf5dd2
10 changed files with 90 additions and 30 deletions

View File

@ -410,6 +410,11 @@ template<u32 func(u32, u32, u32, int)> void WrapU_UUUI() {
RETURN(retval);
}
template<u32 func(u32, u32, int, u32)> void WrapU_UUIU() {
u32 retval = func(PARAM(0), PARAM(1), PARAM(2), PARAM(3));
RETURN(retval);
}
template<u32 func(u32, int, int, int)> void WrapU_UIII() {
u32 retval = func(PARAM(0), PARAM(1), PARAM(2), PARAM(3));
RETURN(retval);

View File

@ -25,13 +25,19 @@
#include "../GPU/GPUState.h"
#include "../GPU/GPUInterface.h"
static PspGeCallbackData ge_callback_data[16];
static bool ge_used_callbacks[16] = {0};
void __GeInit()
{
memset(&ge_used_callbacks, 0, sizeof(ge_used_callbacks));
}
void __GeDoState(PointerWrap &p)
{
// Everything is done in sceDisplay.
p.DoArray(ge_callback_data, ARRAY_SIZE(ge_callback_data));
p.DoArray(ge_used_callbacks, ARRAY_SIZE(ge_used_callbacks));
// Everything else is done in sceDisplay.
p.DoMarker("sceGe");
}
@ -57,7 +63,29 @@ u32 sceGeEdramGetSize()
return retVal;
}
u32 sceGeListEnQueue(u32 listAddress, u32 stallAddress, u32 callbackId,
// TODO: Probably shouldn't use an interrupt?
int __GeSubIntrBase(int callbackId)
{
// Negative means don't use.
if (callbackId < 0)
return 0;
if (callbackId >= ARRAY_SIZE(ge_used_callbacks))
{
WARN_LOG(HLE, "Unexpected (too high) GE callback id %d, ignoring", callbackId);
return 0;
}
if (!ge_used_callbacks[callbackId])
{
WARN_LOG(HLE, "Unregistered GE callback id %d, ignoring", callbackId);
return 0;
}
return (callbackId + 1) << 16;
}
u32 sceGeListEnQueue(u32 listAddress, u32 stallAddress, int callbackId,
u32 optParamAddr)
{
DEBUG_LOG(HLE,
@ -65,14 +93,14 @@ u32 sceGeListEnQueue(u32 listAddress, u32 stallAddress, u32 callbackId,
listAddress, stallAddress, callbackId, optParamAddr);
//if (!stallAddress)
// stallAddress = listAddress;
u32 listID = gpu->EnqueueList(listAddress, stallAddress, false);
u32 listID = gpu->EnqueueList(listAddress, stallAddress, __GeSubIntrBase(callbackId), false);
DEBUG_LOG(HLE, "List %i enqueued.", listID);
//return display list ID
return listID;
}
u32 sceGeListEnQueueHead(u32 listAddress, u32 stallAddress, u32 callbackId,
u32 sceGeListEnQueueHead(u32 listAddress, u32 stallAddress, int callbackId,
u32 optParamAddr)
{
DEBUG_LOG(HLE,
@ -80,7 +108,7 @@ u32 sceGeListEnQueueHead(u32 listAddress, u32 stallAddress, u32 callbackId,
listAddress, stallAddress, callbackId, optParamAddr);
//if (!stallAddress)
// stallAddress = listAddress;
u32 listID = gpu->EnqueueList(listAddress, stallAddress, true);
u32 listID = gpu->EnqueueList(listAddress, stallAddress, __GeSubIntrBase(callbackId), true);
DEBUG_LOG(HLE, "List %i enqueued.", listID);
//return display list ID
@ -138,32 +166,54 @@ u32 sceGeSetCallback(u32 structAddr)
{
DEBUG_LOG(HLE, "sceGeSetCallback(struct=%08x)", structAddr);
PspGeCallbackData ge_callback_data;
Memory::ReadStruct(structAddr, &ge_callback_data);
int cbID = -1;
for (int i = 0; i < ARRAY_SIZE(ge_used_callbacks); ++i)
if (!ge_used_callbacks[i])
{
cbID = i;
break;
}
if (ge_callback_data.finish_func)
if (cbID == -1)
return SCE_KERNEL_ERROR_OUT_OF_MEMORY;
ge_used_callbacks[cbID] = true;
Memory::ReadStruct(structAddr, &ge_callback_data[cbID]);
int subIntrBase = __GeSubIntrBase(cbID);
if (ge_callback_data[cbID].finish_func)
{
sceKernelRegisterSubIntrHandler(PSP_GE_INTR, PSP_GE_SUBINTR_FINISH,
ge_callback_data.finish_func, ge_callback_data.finish_arg);
sceKernelEnableSubIntr(PSP_GE_INTR, PSP_GE_SUBINTR_FINISH);
sceKernelRegisterSubIntrHandler(PSP_GE_INTR, subIntrBase | PSP_GE_SUBINTR_FINISH,
ge_callback_data[cbID].finish_func, ge_callback_data[cbID].finish_arg);
sceKernelEnableSubIntr(PSP_GE_INTR, subIntrBase | PSP_GE_SUBINTR_FINISH);
}
if (ge_callback_data.signal_func)
if (ge_callback_data[cbID].signal_func)
{
sceKernelRegisterSubIntrHandler(PSP_GE_INTR, PSP_GE_SUBINTR_SIGNAL,
ge_callback_data.signal_func, ge_callback_data.signal_arg);
sceKernelEnableSubIntr(PSP_GE_INTR, PSP_GE_SUBINTR_SIGNAL);
sceKernelRegisterSubIntrHandler(PSP_GE_INTR, subIntrBase | PSP_GE_SUBINTR_SIGNAL,
ge_callback_data[cbID].signal_func, ge_callback_data[cbID].signal_arg);
sceKernelEnableSubIntr(PSP_GE_INTR, subIntrBase | PSP_GE_SUBINTR_SIGNAL);
}
// TODO: This should return a callback ID
return 0;
return cbID;
}
int sceGeUnsetCallback(u32 cbID)
{
DEBUG_LOG(HLE, "sceGeUnsetCallback(cbid=%08x)", cbID);
sceKernelReleaseSubIntrHandler(PSP_GE_INTR, PSP_GE_SUBINTR_FINISH);
sceKernelReleaseSubIntrHandler(PSP_GE_INTR, PSP_GE_SUBINTR_SIGNAL);
if (cbID >= ARRAY_SIZE(ge_used_callbacks))
return SCE_KERNEL_ERROR_INVALID_ID;
if (ge_used_callbacks[cbID])
{
int subIntrBase = __GeSubIntrBase(cbID);
sceKernelReleaseSubIntrHandler(PSP_GE_INTR, subIntrBase | PSP_GE_SUBINTR_FINISH);
sceKernelReleaseSubIntrHandler(PSP_GE_INTR, subIntrBase | PSP_GE_SUBINTR_SIGNAL);
}
ge_used_callbacks[cbID] = false;
return 0;
}
@ -235,8 +285,8 @@ u32 sceGeEdramSetAddrTranslation(int new_size)
const HLEFunction sceGe_user[] =
{
{0xE47E40E4, WrapU_V<sceGeEdramGetAddr>, "sceGeEdramGetAddr"},
{0xAB49E76A, WrapU_UUUU<sceGeListEnQueue>, "sceGeListEnQueue"},
{0x1C0D95A6, WrapU_UUUU<sceGeListEnQueueHead>, "sceGeListEnQueueHead"},
{0xAB49E76A, WrapU_UUIU<sceGeListEnQueue>, "sceGeListEnQueue"},
{0x1C0D95A6, WrapU_UUIU<sceGeListEnQueueHead>, "sceGeListEnQueueHead"},
{0xE0D68148, WrapI_UU<sceGeListUpdateStallAddr>, "sceGeListUpdateStallAddr"},
{0x03444EB4, WrapI_UU<sceGeListSync>, "sceGeListSync"},
{0xB287BD61, WrapU_U<sceGeDrawSync>, "sceGeDrawSync"},

View File

@ -45,4 +45,4 @@ void __GeShutdown();
u32 sceGeRestoreContext(u32 ctxAddr);
u32 sceGeSaveContext(u32 ctxAddr);
u32 sceGeListEnQueue(u32 listAddress, u32 stallAddress, u32 callbackId, u32 optParamAddr);
u32 sceGeListEnQueue(u32 listAddress, u32 stallAddress, int callbackId, u32 optParamAddr);

View File

@ -23,7 +23,9 @@
enum
{
SCE_KERNEL_ERROR_OK = 0,
SCE_KERNEL_ERROR_OK = 0,
SCE_KERNEL_ERROR_OUT_OF_MEMORY = 0x80000022,
SCE_KERNEL_ERROR_INVALID_ID = 0x80000100,
SCE_KERNEL_ERROR_INVALID_VALUE = 0x800001fe,
SCE_KERNEL_ERROR_INVALID_ARGUMENT = 0x800001ff,
SCE_KERNEL_ERROR_ERROR = 0x80020001,

View File

@ -543,7 +543,7 @@ void GLES_GPU::ExecuteOp(u32 op, u32 diff) {
case GE_CMD_FINISH:
// TODO: Should this run while interrupts are suspended?
if (interruptsEnabled_)
__TriggerInterruptWithArg(PSP_INTR_HLE, PSP_GE_INTR, PSP_GE_SUBINTR_FINISH, 0);
__TriggerInterruptWithArg(PSP_INTR_HLE, PSP_GE_INTR, currentList->subIntrBase | PSP_GE_SUBINTR_FINISH, 0);
break;
case GE_CMD_END:
@ -581,7 +581,7 @@ void GLES_GPU::ExecuteOp(u32 op, u32 diff) {
}
// TODO: Should this run while interrupts are suspended?
if (interruptsEnabled_)
__TriggerInterruptWithArg(PSP_INTR_HLE, PSP_GE_INTR, PSP_GE_SUBINTR_SIGNAL, signal);
__TriggerInterruptWithArg(PSP_INTR_HLE, PSP_GE_INTR, currentList->subIntrBase | PSP_GE_SUBINTR_SIGNAL, signal);
}
break;
case GE_CMD_FINISH:

View File

@ -81,6 +81,7 @@ private:
struct CmdProcessorState {
u32 pc;
u32 stallAddr;
int subIntrBase;
};
struct VirtualFramebuffer {

View File

@ -23,13 +23,14 @@ int GPUCommon::listStatus(int listid)
return 0x80000100; // INVALID_ID
}
u32 GPUCommon::EnqueueList(u32 listpc, u32 stall, bool head)
u32 GPUCommon::EnqueueList(u32 listpc, u32 stall, int subIntrBase, bool head)
{
DisplayList dl;
dl.id = dlIdGenerator++;
dl.pc = listpc & 0xFFFFFFF;
dl.stall = stall & 0xFFFFFFF;
dl.status = PSP_GE_LIST_QUEUED;
dl.subIntrBase = subIntrBase;
if(head)
dlQueue.push_front(dl);
else

View File

@ -17,7 +17,7 @@ public:
virtual bool InterpretList(DisplayList &list);
virtual bool ProcessDLQueue();
virtual void UpdateStall(int listid, u32 newstall);
virtual u32 EnqueueList(u32 listpc, u32 stall, bool head);
virtual u32 EnqueueList(u32 listpc, u32 stall, int subIntrBase, bool head);
virtual int listStatus(int listid);
virtual void DoState(PointerWrap &p);

View File

@ -37,6 +37,7 @@ struct DisplayList
u32 pc;
u32 stall;
DisplayListStatus status;
int subIntrBase;
};
class GPUInterface
@ -49,7 +50,7 @@ public:
// Draw queue management
// TODO: Much of this should probably be shared between the different GPU implementations.
virtual u32 EnqueueList(u32 listpc, u32 stall, bool head) = 0;
virtual u32 EnqueueList(u32 listpc, u32 stall, int subIntrBase, bool head) = 0;
virtual void UpdateStall(int listid, u32 newstall) = 0;
virtual void DrawSync(int mode) = 0;
virtual void Continue() = 0;

View File

@ -138,7 +138,7 @@ void NullGPU::ExecuteOp(u32 op, u32 diff)
// TODO: Should this run while interrupts are suspended?
if (interruptsEnabled_)
__TriggerInterruptWithArg(PSP_INTR_HLE, PSP_GE_INTR, PSP_GE_SUBINTR_SIGNAL, signal);
__TriggerInterruptWithArg(PSP_INTR_HLE, PSP_GE_INTR, currentList->subIntrBase | PSP_GE_SUBINTR_SIGNAL, signal);
}
break;
@ -170,7 +170,7 @@ void NullGPU::ExecuteOp(u32 op, u32 diff)
DEBUG_LOG(G3D,"DL CMD FINISH");
// TODO: Should this run while interrupts are suspended?
if (interruptsEnabled_)
__TriggerInterruptWithArg(PSP_INTR_HLE, PSP_GE_INTR, PSP_GE_SUBINTR_FINISH, 0);
__TriggerInterruptWithArg(PSP_INTR_HLE, PSP_GE_INTR, currentList->subIntrBase | PSP_GE_SUBINTR_FINISH, 0);
break;
case GE_CMD_END: