mirror of
https://github.com/hrydgard/ppsspp.git
synced 2025-02-03 12:12:06 +00:00
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:
parent
2ed0902ae2
commit
97bdaf5dd2
@ -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);
|
||||
|
@ -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"},
|
||||
|
@ -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);
|
||||
|
@ -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,
|
||||
|
@ -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:
|
||||
|
@ -81,6 +81,7 @@ private:
|
||||
struct CmdProcessorState {
|
||||
u32 pc;
|
||||
u32 stallAddr;
|
||||
int subIntrBase;
|
||||
};
|
||||
|
||||
struct VirtualFramebuffer {
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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:
|
||||
|
Loading…
x
Reference in New Issue
Block a user