From 9bff8e00c86188354363e7b41dfe6f06c781cf5a Mon Sep 17 00:00:00 2001 From: skidau Date: Sat, 16 Feb 2013 12:51:09 +1100 Subject: Added preliminary support to synchronise the timing of the CPU and GPU threads. A new option has been added to the game properties for this purpose. This option may help with random freezes in Dual Core mode. Fixes Gladius and Baten Kaitos: Eternal Wings and the Lost Ocean Fixes issue 5150. --- Source/Core/VideoCommon/Src/OpcodeDecoding.cpp | 85 ++++++++++++++++++++------ 1 file changed, 66 insertions(+), 19 deletions(-) (limited to 'Source/Core/VideoCommon/Src/OpcodeDecoding.cpp') diff --git a/Source/Core/VideoCommon/Src/OpcodeDecoding.cpp b/Source/Core/VideoCommon/Src/OpcodeDecoding.cpp index 4f7f86d655..662dbc66a8 100644 --- a/Source/Core/VideoCommon/Src/OpcodeDecoding.cpp +++ b/Source/Core/VideoCommon/Src/OpcodeDecoding.cpp @@ -136,29 +136,38 @@ void ExecuteDisplayList(u32 address, u32 size) InterpretDisplayList(address, size); } -bool FifoCommandRunnable() +u32 FifoCommandRunnable(u32 &command_size) { + u32 cycleTime = 0; u32 buffer_size = (u32)(GetVideoBufferEndPtr() - g_pVideoData); if (buffer_size == 0) - return false; // can't peek + return 0; // can't peek u8 cmd_byte = DataPeek8(0); - u32 command_size = 0; switch (cmd_byte) { case GX_NOP: // Hm, this means that we scan over nop streams pretty slowly... + command_size = 1; + cycleTime = 6; + break; case GX_CMD_INVL_VC: // Invalidate Vertex Cache - no parameters + command_size = 1; + cycleTime = 6; + break; case GX_CMD_UNKNOWN_METRICS: // zelda 4 swords calls it and checks the metrics registers after that command_size = 1; + cycleTime = 6; break; case GX_LOAD_BP_REG: command_size = 5; + cycleTime = 12; break; case GX_LOAD_CP_REG: command_size = 6; + cycleTime = 12; break; case GX_LOAD_INDX_A: @@ -166,10 +175,39 @@ bool FifoCommandRunnable() case GX_LOAD_INDX_C: case GX_LOAD_INDX_D: command_size = 5; + cycleTime = 6; // TODO break; - case GX_CMD_CALL_DL: - command_size = 9; + case GX_CMD_CALL_DL: + { + // FIXME: Calculate the cycle time of the display list. + //u32 address = DataPeek32(1); + //u32 size = DataPeek32(5); + //u8* old_pVideoData = g_pVideoData; + //u8* startAddress = Memory::GetPointer(address); + + //// Avoid the crash if Memory::GetPointer failed .. + //if (startAddress != 0) + //{ + // g_pVideoData = startAddress; + // u8 *end = g_pVideoData + size; + // u32 step = 0; + // while (g_pVideoData < end) + // { + // cycleTime += FifoCommandRunnable(step); + // g_pVideoData += step; + // } + //} + //else + //{ + // cycleTime = 45; + //} + + //// reset to the old pointer + //g_pVideoData = old_pVideoData; + command_size = 9; + cycleTime = 45; // This is unverified + } break; case GX_LOAD_XF_REG: @@ -180,11 +218,12 @@ bool FifoCommandRunnable() command_size = 1 + 4; u32 Cmd2 = DataPeek32(1); int transfer_size = ((Cmd2 >> 16) & 15) + 1; - command_size += transfer_size * 4; + command_size += transfer_size * 4; + cycleTime = 18 + 6 * transfer_size; } else { - return false; + return 0; } } break; @@ -198,10 +237,11 @@ bool FifoCommandRunnable() command_size = 1 + 2; u16 numVertices = DataPeek16(1); command_size += numVertices * VertexLoaderManager::GetVertexSize(cmd_byte & GX_VAT_MASK); + cycleTime = 12 * numVertices; // This depends on the number of pixels rendered } else { - return false; + return 0; } } else @@ -248,11 +288,19 @@ bool FifoCommandRunnable() } if (command_size > buffer_size) - return false; + return 0; // INFO_LOG("OP detected: cmd_byte 0x%x size %i buffer %i",cmd_byte, command_size, buffer_size); + if (cycleTime == 0) + cycleTime = 6; - return true; + return cycleTime; +} + +u32 FifoCommandRunnable() +{ + u32 command_size = 0; + return FifoCommandRunnable(command_size); } static void Decode() @@ -461,16 +509,15 @@ void OpcodeDecoder_Shutdown() } } -void OpcodeDecoder_Run(bool skipped_frame) +u32 OpcodeDecoder_Run(bool skipped_frame) { - if (!skipped_frame) - { - while (FifoCommandRunnable()) - Decode(); - } - else + u32 totalCycles = 0; + u32 cycles = FifoCommandRunnable(); + while (cycles > 0) { - while (FifoCommandRunnable()) - DecodeSemiNop(); + skipped_frame ? DecodeSemiNop() : Decode(); + totalCycles += cycles; + cycles = FifoCommandRunnable(); } + return totalCycles; } -- cgit v1.2.3 From 0e2c3f3483e230079b5b6107d3cc634f60d92c78 Mon Sep 17 00:00:00 2001 From: skidau Date: Sat, 16 Feb 2013 22:54:10 +1100 Subject: Increased the cycle time of the vertex command. Fixes "Speed Challenge: Jacques Villeneuve's Racing Vision". --- Source/Core/VideoCommon/Src/OpcodeDecoding.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'Source/Core/VideoCommon/Src/OpcodeDecoding.cpp') diff --git a/Source/Core/VideoCommon/Src/OpcodeDecoding.cpp b/Source/Core/VideoCommon/Src/OpcodeDecoding.cpp index 662dbc66a8..c7764dba71 100644 --- a/Source/Core/VideoCommon/Src/OpcodeDecoding.cpp +++ b/Source/Core/VideoCommon/Src/OpcodeDecoding.cpp @@ -237,7 +237,7 @@ u32 FifoCommandRunnable(u32 &command_size) command_size = 1 + 2; u16 numVertices = DataPeek16(1); command_size += numVertices * VertexLoaderManager::GetVertexSize(cmd_byte & GX_VAT_MASK); - cycleTime = 12 * numVertices; // This depends on the number of pixels rendered + cycleTime = 393 * numVertices; // This depends on the number of pixels rendered } else { -- cgit v1.2.3 From 36f2082a5f50da83035c1f6a3be059f018d3299b Mon Sep 17 00:00:00 2001 From: skidau Date: Wed, 20 Feb 2013 23:38:25 +1100 Subject: Made vertex loading take constant time. Fixes a hang in Gladius. --- Source/Core/VideoCommon/Src/OpcodeDecoding.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'Source/Core/VideoCommon/Src/OpcodeDecoding.cpp') diff --git a/Source/Core/VideoCommon/Src/OpcodeDecoding.cpp b/Source/Core/VideoCommon/Src/OpcodeDecoding.cpp index c7764dba71..bb6c555c07 100644 --- a/Source/Core/VideoCommon/Src/OpcodeDecoding.cpp +++ b/Source/Core/VideoCommon/Src/OpcodeDecoding.cpp @@ -237,7 +237,7 @@ u32 FifoCommandRunnable(u32 &command_size) command_size = 1 + 2; u16 numVertices = DataPeek16(1); command_size += numVertices * VertexLoaderManager::GetVertexSize(cmd_byte & GX_VAT_MASK); - cycleTime = 393 * numVertices; // This depends on the number of pixels rendered + cycleTime = 1600; // This depends on the number of pixels rendered } else { -- cgit v1.2.3