mirror of
https://github.com/libretro/ppsspp.git
synced 2024-11-24 08:39:51 +00:00
I think I finally understood how origin-relative GE jumps are supposed to work.
This commit is contained in:
parent
78906531f9
commit
0769a1d3e8
@ -314,17 +314,14 @@ void GLES_GPU::ExecuteOp(u32 op, u32 diff) {
|
||||
// Handle control and drawing commands here directly. The others we delegate.
|
||||
switch (cmd) {
|
||||
case GE_CMD_BASE:
|
||||
//DEBUG_LOG(G3D,"DL BASE: %06x", data & 0xFFFFFF);
|
||||
break;
|
||||
|
||||
case GE_CMD_VADDR: /// <<8????
|
||||
gstate_c.vertexAddr = ((gstate.base & 0x00FF0000) << 8)|data;
|
||||
//DEBUG_LOG(G3D,"DL VADDR: %06x", gstate_c.vertexAddr);
|
||||
break;
|
||||
|
||||
case GE_CMD_IADDR:
|
||||
gstate_c.indexAddr = ((gstate.base & 0x00FF0000) << 8)|data;
|
||||
//DEBUG_LOG(G3D,"DL IADDR: %06x", gstate_c.indexAddr);
|
||||
break;
|
||||
|
||||
case GE_CMD_PRIM:
|
||||
@ -388,23 +385,24 @@ void GLES_GPU::ExecuteOp(u32 op, u32 diff) {
|
||||
|
||||
case GE_CMD_JUMP:
|
||||
{
|
||||
u32 target = (((gstate.base & 0x00FF0000) << 8) | (op & 0xFFFFFC)) & 0x0FFFFFFF;
|
||||
u32 target = gstate_c.getJumpAddress(data);
|
||||
if (Memory::IsValidAddress(target)) {
|
||||
currentList->pc = target - 4; // pc will be increased after we return, counteract that
|
||||
} else {
|
||||
ERROR_LOG(G3D, "JUMP to illegal address %08x - ignoring??", target);
|
||||
ERROR_LOG(G3D, "JUMP to illegal address %08x - ignoring! data=%06x", target, data);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case GE_CMD_CALL:
|
||||
{
|
||||
// Saint Seiya needs correct support for relative calls.
|
||||
u32 retval = currentList->pc + 4;
|
||||
u32 target = (((gstate.base & 0x00FF0000) << 8) | (op & 0xFFFFFC)) & 0xFFFFFFF;
|
||||
u32 target = gstate_c.getJumpAddress(data);
|
||||
if (stackptr == ARRAY_SIZE(stack)) {
|
||||
ERROR_LOG(G3D, "CALL: Stack full!");
|
||||
} else if (!Memory::IsValidAddress(target)) {
|
||||
ERROR_LOG(G3D, "CALL to illegal address %08x - ignoring??", target);
|
||||
ERROR_LOG(G3D, "CALL to illegal address %08x - ignoring! data=%06x", target, data);
|
||||
} else {
|
||||
stack[stackptr++] = retval;
|
||||
currentList->pc = target - 4; // pc will be increased after we return, counteract that
|
||||
@ -418,6 +416,7 @@ void GLES_GPU::ExecuteOp(u32 op, u32 diff) {
|
||||
ERROR_LOG(G3D, "RET: Stack empty!");
|
||||
} else {
|
||||
u32 target = (currentList->pc & 0xF0000000) | (stack[--stackptr] & 0x0FFFFFFF);
|
||||
//target = (target + gstate_c.originAddr) & 0xFFFFFFF;
|
||||
currentList->pc = target - 4;
|
||||
if (!Memory::IsValidAddress(currentList->pc)) {
|
||||
ERROR_LOG(G3D, "Invalid DL PC %08x on return", currentList->pc);
|
||||
@ -427,6 +426,16 @@ void GLES_GPU::ExecuteOp(u32 op, u32 diff) {
|
||||
}
|
||||
break;
|
||||
|
||||
case GE_CMD_OFFSETADDR:
|
||||
gstate_c.offsetAddr = data << 8;
|
||||
// ???
|
||||
break;
|
||||
|
||||
case GE_CMD_ORIGIN:
|
||||
gstate_c.offsetAddr = currentList->pc;
|
||||
break;
|
||||
|
||||
|
||||
case GE_CMD_SIGNAL:
|
||||
{
|
||||
// Processed in GE_END. Has data.
|
||||
@ -495,10 +504,6 @@ void GLES_GPU::ExecuteOp(u32 op, u32 diff) {
|
||||
// bounding box test. Let's do nothing.
|
||||
break;
|
||||
|
||||
case GE_CMD_ORIGIN:
|
||||
gstate.offsetAddr = currentList->pc & 0xFFFFFF;
|
||||
break;
|
||||
|
||||
case GE_CMD_VERTEXTYPE:
|
||||
if (diff & GE_VTYPE_THROUGH) {
|
||||
// Throughmode changed, let's make the proj matrix dirty.
|
||||
@ -507,10 +512,6 @@ void GLES_GPU::ExecuteOp(u32 op, u32 diff) {
|
||||
// This sets through-mode or not, as well.
|
||||
break;
|
||||
|
||||
case GE_CMD_OFFSETADDR:
|
||||
// offsetAddr = data<<8;
|
||||
break;
|
||||
|
||||
case GE_CMD_REGION1:
|
||||
{
|
||||
int x1 = data & 0x3ff;
|
||||
|
@ -31,6 +31,7 @@ GPUStatistics gpuStats;
|
||||
void InitGfxState()
|
||||
{
|
||||
memset(&gstate, 0, sizeof(gstate));
|
||||
memset(&gstate_c, 0, sizeof(gstate_c));
|
||||
for (int i = 0; i < 256; i++) {
|
||||
gstate.cmdmem[i] = i << 24;
|
||||
}
|
||||
|
@ -231,6 +231,8 @@ struct GPUStateCache
|
||||
u32 vertexAddr;
|
||||
u32 indexAddr;
|
||||
|
||||
u32 offsetAddr;
|
||||
|
||||
bool textureChanged;
|
||||
|
||||
float uScale,vScale,zScale;
|
||||
@ -247,6 +249,9 @@ struct GPUStateCache
|
||||
|
||||
float vpWidth;
|
||||
float vpHeight;
|
||||
|
||||
|
||||
u32 getJumpAddress(u32 data) const;
|
||||
};
|
||||
|
||||
// TODO: Implement support for these.
|
||||
@ -322,3 +327,8 @@ extern GPUgstate gstate;
|
||||
extern GPUStateCache gstate_c;
|
||||
extern GPUInterface *gpu;
|
||||
extern GPUStatistics gpuStats;
|
||||
|
||||
inline u32 GPUStateCache::getJumpAddress(u32 data) const {
|
||||
u32 baseExtended = ((gstate.base & 0x0F0000) << 8) | (data & 0xFFFFFF);
|
||||
return (gstate_c.offsetAddr + baseExtended) & 0x0FFFFFFF;
|
||||
}
|
||||
|
@ -85,7 +85,7 @@ void GeDisassembleOp(u32 pc, u32 op, u32 prev, char *buffer) {
|
||||
case GE_CMD_CALL:
|
||||
{
|
||||
u32 retval = pc + 4;
|
||||
u32 target = (((gstate.base & 0x00FF0000) << 8) | (op & 0xFFFFFC)) & 0xFFFFFFF;
|
||||
u32 target = gstate_c.getJumpAddress(op & 0xFFFFFF);
|
||||
sprintf(buffer, "CMD CALL - %08x to %08x, ret=%08x", pc, target, retval);
|
||||
}
|
||||
break;
|
||||
|
@ -169,6 +169,7 @@ void NullGPU::ExecuteOp(u32 op, u32 diff)
|
||||
|
||||
case GE_CMD_ORIGIN:
|
||||
gstate.offsetAddr = currentList->pc & 0xFFFFFF;
|
||||
gstate_c.offsetAddr = currentList->pc;
|
||||
break;
|
||||
|
||||
case GE_CMD_VERTEXTYPE:
|
||||
|
2
native
2
native
@ -1 +1 @@
|
||||
Subproject commit c21e1ee2cced55bb68edefbb58ba4b30bde807ba
|
||||
Subproject commit f22ad17d40c00d9a60bd21f53820012b302d7559
|
@ -1 +1 @@
|
||||
Subproject commit 31e3915d4e4302e5e7dc2f6c2a4f191c420f38f9
|
||||
Subproject commit 4f047eb8c76c6388a63a87ec72e98c64670152d5
|
Loading…
Reference in New Issue
Block a user