I think I finally understood how origin-relative GE jumps are supposed to work.

This commit is contained in:
Henrik Rydgard 2013-02-02 13:38:34 +01:00
parent 78906531f9
commit 0769a1d3e8
7 changed files with 31 additions and 18 deletions

View File

@ -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;

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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;

View File

@ -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

@ -1 +1 @@
Subproject commit c21e1ee2cced55bb68edefbb58ba4b30bde807ba
Subproject commit f22ad17d40c00d9a60bd21f53820012b302d7559

@ -1 +1 @@
Subproject commit 31e3915d4e4302e5e7dc2f6c2a4f191c420f38f9
Subproject commit 4f047eb8c76c6388a63a87ec72e98c64670152d5