summaryrefslogtreecommitdiff
path: root/Source/Core/VideoCommon/Src/OpcodeDecoding.cpp
diff options
context:
space:
mode:
authorskidau <skidau@gmail.com>2013-03-27 13:19:23 +1100
committerskidau <skidau@gmail.com>2013-03-27 13:19:23 +1100
commit7784fa4c67cc8d2545f45694d83805e7e89cd583 (patch)
tree7724133aabe971ec417d1dea0977a525bb8debfb /Source/Core/VideoCommon/Src/OpcodeDecoding.cpp
parentd33c19b0cd2bae982c8d35e86a9d3551f9e5c72f (diff)
parent5cea0d9defeaa23e7af94adf7615a44fb2c9c173 (diff)
Merge branch 'master' into wii-network
# By Ryan Houdek (185) and others # Via degasus (12) and others * master: (625 commits) Revert "Don't open/close file for every file operation." as it was crashing PokePark in Windows builds. Array overrun fixed in VertexShaderCache for the DX11 plugin. Fixed DSPTool build. Windows build fix Go back to assuming every HID device is a wiimote on Windows. Fixed issue 6117. Unfixed issue 6031. VideoSoftware: Improve fog range adjustment by using less magic and more comments. revert RasterFont for VideoSoftware ogl: fix virtual xfb Windows build fix from web interface... Adjusted the audio loop criteria, using >= on the Wii and == on GC. This fixes the audio static that occurred in Wii games after hours of play. Forced the exception check only for ARAM DMA transfers. Removed the Eternal Darkness boot hack and replaced it with an exception check. VideoSoftware: Implement fog range adjustment, fixing issue 6147. implement 4xSSAA for OGL move ogl-only settings into backend Fix description of disable fog, and move it to enhancements tab. Reverted rd76ca5783743 as it was made obsolete by r1d550f4496e4. Removed the tracking of the FIFO Writes as it was made obsolete by r1d550f4496e4. Forced the external exception check to occur sooner by changing the downcount. Mark the Direct3D9 backend deprecated. Prefer D3D11 and OpenGL over D3D9 by default. ... Conflicts: CMakeLists.txt Source/Core/Common/Common.vcxproj.filters Source/Core/Common/Src/CommonPaths.h Source/Core/Core/Core.vcxproj.filters Source/Core/Core/Src/Core.cpp Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device_FileIO.cpp Source/VSProps/Dolphin.Win32.props Source/VSProps/Dolphin.x64.props
Diffstat (limited to 'Source/Core/VideoCommon/Src/OpcodeDecoding.cpp')
-rw-r--r--Source/Core/VideoCommon/Src/OpcodeDecoding.cpp473
1 files changed, 260 insertions, 213 deletions
diff --git a/Source/Core/VideoCommon/Src/OpcodeDecoding.cpp b/Source/Core/VideoCommon/Src/OpcodeDecoding.cpp
index 4f7f86d655..92d596b774 100644
--- a/Source/Core/VideoCommon/Src/OpcodeDecoding.cpp
+++ b/Source/Core/VideoCommon/Src/OpcodeDecoding.cpp
@@ -123,7 +123,7 @@ void InterpretDisplayList(u32 address, u32 size)
Statistics::SwapDL();
}
- // reset to the old pointer
+ // reset to the old pointer
g_pVideoData = old_pVideoData;
}
@@ -136,74 +136,114 @@ 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
+ if (buffer_size == 0)
+ 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...
+ 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
- case GX_CMD_UNKNOWN_METRICS: // zelda 4 swords calls it and checks the metrics registers after that
- command_size = 1;
- break;
-
- case GX_LOAD_BP_REG:
- command_size = 5;
- break;
-
- case GX_LOAD_CP_REG:
- command_size = 6;
- break;
-
- case GX_LOAD_INDX_A:
- case GX_LOAD_INDX_B:
- case GX_LOAD_INDX_C:
- case GX_LOAD_INDX_D:
- command_size = 5;
- break;
-
- case GX_CMD_CALL_DL:
- command_size = 9;
- break;
-
- case GX_LOAD_XF_REG:
- {
- // check if we can read the header
- if (buffer_size >= 5)
- {
- command_size = 1 + 4;
- u32 Cmd2 = DataPeek32(1);
- int transfer_size = ((Cmd2 >> 16) & 15) + 1;
- command_size += transfer_size * 4;
- }
- else
+ 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:
+ case GX_LOAD_INDX_B:
+ case GX_LOAD_INDX_C:
+ case GX_LOAD_INDX_D:
+ command_size = 5;
+ cycleTime = 6; // TODO
+ break;
+
+ 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:
+ {
+ // check if we can read the header
+ if (buffer_size >= 5)
{
- return false;
- }
- }
- break;
-
- default:
- if (cmd_byte & 0x80)
- {
- // check if we can read the header
- if (buffer_size >= 3)
+ command_size = 1 + 4;
+ u32 Cmd2 = DataPeek32(1);
+ int transfer_size = ((Cmd2 >> 16) & 15) + 1;
+ command_size += transfer_size * 4;
+ cycleTime = 18 + 6 * transfer_size;
+ }
+ else
{
- command_size = 1 + 2;
- u16 numVertices = DataPeek16(1);
+ return 0;
+ }
+ }
+ break;
+
+ default:
+ if (cmd_byte & 0x80)
+ {
+ // check if we can read the header
+ if (buffer_size >= 3)
+ {
+ command_size = 1 + 2;
+ u16 numVertices = DataPeek16(1);
command_size += numVertices * VertexLoaderManager::GetVertexSize(cmd_byte & GX_VAT_MASK);
- }
+ cycleTime = 1600; // This depends on the number of pixels rendered
+ }
else
- {
- return false;
- }
- }
+ {
+ return 0;
+ }
+ }
else
{
// TODO(Omega): Maybe dump FIFO to file on this error
@@ -218,7 +258,7 @@ bool FifoCommandRunnable()
Host_SysMessage(szTemp);
INFO_LOG(VIDEO, "%s", szTemp);
{
- SCPFifoStruct &fifo = CommandProcessor::fifo;
+ SCPFifoStruct &fifo = CommandProcessor::fifo;
char szTmp[512];
// sprintf(szTmp, "Illegal command %02x (at %08x)",cmd_byte,g_pDataReader->GetPtr());
@@ -243,197 +283,205 @@ bool FifoCommandRunnable()
Host_SysMessage(szTmp);
INFO_LOG(VIDEO, "%s", szTmp);
}
- }
- break;
- }
-
- if (command_size > buffer_size)
- return false;
+ }
+ break;
+ }
+
+ if (command_size > buffer_size)
+ return 0;
- // INFO_LOG("OP detected: cmd_byte 0x%x size %i buffer %i",cmd_byte, command_size, buffer_size);
+ // 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()
{
- u8 *opcodeStart = g_pVideoData;
-
- int cmd_byte = DataReadU8();
- switch (cmd_byte)
- {
- case GX_NOP:
- break;
-
- case GX_LOAD_CP_REG: //0x08
- {
- u8 sub_cmd = DataReadU8();
- u32 value = DataReadU32();
- LoadCPReg(sub_cmd, value);
+ u8 *opcodeStart = g_pVideoData;
+
+ int cmd_byte = DataReadU8();
+ switch (cmd_byte)
+ {
+ case GX_NOP:
+ break;
+
+ case GX_LOAD_CP_REG: //0x08
+ {
+ u8 sub_cmd = DataReadU8();
+ u32 value = DataReadU32();
+ LoadCPReg(sub_cmd, value);
INCSTAT(stats.thisFrame.numCPLoads);
- }
- break;
+ }
+ break;
- case GX_LOAD_XF_REG:
- {
- u32 Cmd2 = DataReadU32();
- int transfer_size = ((Cmd2 >> 16) & 15) + 1;
+ case GX_LOAD_XF_REG:
+ {
+ u32 Cmd2 = DataReadU32();
+ int transfer_size = ((Cmd2 >> 16) & 15) + 1;
u32 xf_address = Cmd2 & 0xFFFF;
GC_ALIGNED128(u32 data_buffer[16]);
DataReadU32xFuncs[transfer_size-1](data_buffer);
- LoadXFReg(transfer_size, xf_address, data_buffer);
+ LoadXFReg(transfer_size, xf_address, data_buffer);
INCSTAT(stats.thisFrame.numXFLoads);
- }
- break;
-
- case GX_LOAD_INDX_A: //used for position matrices
- LoadIndexedXF(DataReadU32(), 0xC);
- break;
- case GX_LOAD_INDX_B: //used for normal matrices
- LoadIndexedXF(DataReadU32(), 0xD);
- break;
- case GX_LOAD_INDX_C: //used for postmatrices
- LoadIndexedXF(DataReadU32(), 0xE);
- break;
- case GX_LOAD_INDX_D: //used for lights
- LoadIndexedXF(DataReadU32(), 0xF);
- break;
-
- case GX_CMD_CALL_DL:
- {
- u32 address = DataReadU32();
- u32 count = DataReadU32();
- ExecuteDisplayList(address, count);
- }
- break;
-
- case GX_CMD_UNKNOWN_METRICS: // zelda 4 swords calls it and checks the metrics registers after that
+ }
+ break;
+
+ case GX_LOAD_INDX_A: //used for position matrices
+ LoadIndexedXF(DataReadU32(), 0xC);
+ break;
+ case GX_LOAD_INDX_B: //used for normal matrices
+ LoadIndexedXF(DataReadU32(), 0xD);
+ break;
+ case GX_LOAD_INDX_C: //used for postmatrices
+ LoadIndexedXF(DataReadU32(), 0xE);
+ break;
+ case GX_LOAD_INDX_D: //used for lights
+ LoadIndexedXF(DataReadU32(), 0xF);
+ break;
+
+ case GX_CMD_CALL_DL:
+ {
+ u32 address = DataReadU32();
+ u32 count = DataReadU32();
+ ExecuteDisplayList(address, count);
+ }
+ break;
+
+ case GX_CMD_UNKNOWN_METRICS: // zelda 4 swords calls it and checks the metrics registers after that
DEBUG_LOG(VIDEO, "GX 0x44: %08x", cmd_byte);
- break;
+ break;
- case GX_CMD_INVL_VC: // Invalidate Vertex Cache
- DEBUG_LOG(VIDEO, "Invalidate (vertex cache?)");
- break;
+ case GX_CMD_INVL_VC: // Invalidate Vertex Cache
+ DEBUG_LOG(VIDEO, "Invalidate (vertex cache?)");
+ break;
- case GX_LOAD_BP_REG: //0x61
- {
+ case GX_LOAD_BP_REG: //0x61
+ {
u32 bp_cmd = DataReadU32();
- LoadBPReg(bp_cmd);
+ LoadBPReg(bp_cmd);
INCSTAT(stats.thisFrame.numBPLoads);
- }
- break;
-
- // draw primitives
- default:
- if (cmd_byte & 0x80)
- {
- // load vertices (use computed vertex size from FifoCommandRunnable above)
+ }
+ break;
+
+ // draw primitives
+ default:
+ if (cmd_byte & 0x80)
+ {
+ // load vertices (use computed vertex size from FifoCommandRunnable above)
u16 numVertices = DataReadU16();
VertexLoaderManager::RunVertices(
cmd_byte & GX_VAT_MASK, // Vertex loader index (0 - 7)
(cmd_byte & GX_PRIMITIVE_MASK) >> GX_PRIMITIVE_SHIFT,
numVertices);
- }
- else
- {
+ }
+ else
+ {
ERROR_LOG(VIDEO, "OpcodeDecoding::Decode: Illegal command %02x", cmd_byte);
- break;
- }
- break;
- }
+ break;
+ }
+ break;
+ }
// Display lists get added directly into the FIFO stream
if (g_bRecordFifoData && cmd_byte != GX_CMD_CALL_DL)
- FifoRecorder::GetInstance().WriteGPCommand(opcodeStart, g_pVideoData - opcodeStart);
+ FifoRecorder::GetInstance().WriteGPCommand(opcodeStart, u32(g_pVideoData - opcodeStart));
}
static void DecodeSemiNop()
{
- u8 *opcodeStart = g_pVideoData;
-
- int cmd_byte = DataReadU8();
- switch (cmd_byte)
- {
- case GX_CMD_UNKNOWN_METRICS: // zelda 4 swords calls it and checks the metrics registers after that
- case GX_CMD_INVL_VC: // Invalidate Vertex Cache
- case GX_NOP:
+ u8 *opcodeStart = g_pVideoData;
+
+ int cmd_byte = DataReadU8();
+ switch (cmd_byte)
+ {
+ case GX_CMD_UNKNOWN_METRICS: // zelda 4 swords calls it and checks the metrics registers after that
+ case GX_CMD_INVL_VC: // Invalidate Vertex Cache
+ case GX_NOP:
break;
case GX_LOAD_CP_REG: //0x08
// We have to let CP writes through because they determine the size of vertices.
- {
- u8 sub_cmd = DataReadU8();
- u32 value = DataReadU32();
- LoadCPReg(sub_cmd, value);
- INCSTAT(stats.thisFrame.numCPLoads);
- }
- break;
-
- case GX_LOAD_XF_REG:
- {
- u32 Cmd2 = DataReadU32();
- int transfer_size = ((Cmd2 >> 16) & 15) + 1;
- u32 address = Cmd2 & 0xFFFF;
- GC_ALIGNED128(u32 data_buffer[16]);
- DataReadU32xFuncs[transfer_size-1](data_buffer);
- LoadXFReg(transfer_size, address, data_buffer);
- INCSTAT(stats.thisFrame.numXFLoads);
- }
- break;
-
- case GX_LOAD_INDX_A: //used for position matrices
- LoadIndexedXF(DataReadU32(), 0xC);
- break;
- case GX_LOAD_INDX_B: //used for normal matrices
- LoadIndexedXF(DataReadU32(), 0xD);
- break;
- case GX_LOAD_INDX_C: //used for postmatrices
- LoadIndexedXF(DataReadU32(), 0xE);
- break;
- case GX_LOAD_INDX_D: //used for lights
- LoadIndexedXF(DataReadU32(), 0xF);
- break;
-
- case GX_CMD_CALL_DL:
+ {
+ u8 sub_cmd = DataReadU8();
+ u32 value = DataReadU32();
+ LoadCPReg(sub_cmd, value);
+ INCSTAT(stats.thisFrame.numCPLoads);
+ }
+ break;
+
+ case GX_LOAD_XF_REG:
+ {
+ u32 Cmd2 = DataReadU32();
+ int transfer_size = ((Cmd2 >> 16) & 15) + 1;
+ u32 address = Cmd2 & 0xFFFF;
+ GC_ALIGNED128(u32 data_buffer[16]);
+ DataReadU32xFuncs[transfer_size-1](data_buffer);
+ LoadXFReg(transfer_size, address, data_buffer);
+ INCSTAT(stats.thisFrame.numXFLoads);
+ }
+ break;
+
+ case GX_LOAD_INDX_A: //used for position matrices
+ LoadIndexedXF(DataReadU32(), 0xC);
+ break;
+ case GX_LOAD_INDX_B: //used for normal matrices
+ LoadIndexedXF(DataReadU32(), 0xD);
+ break;
+ case GX_LOAD_INDX_C: //used for postmatrices
+ LoadIndexedXF(DataReadU32(), 0xE);
+ break;
+ case GX_LOAD_INDX_D: //used for lights
+ LoadIndexedXF(DataReadU32(), 0xF);
+ break;
+
+ case GX_CMD_CALL_DL:
// Hm, wonder if any games put tokens in display lists - in that case,
// we'll have to parse them too.
- DataSkip(8);
- break;
+ DataSkip(8);
+ break;
- case GX_LOAD_BP_REG: //0x61
+ case GX_LOAD_BP_REG: //0x61
// We have to let BP writes through because they set tokens and stuff.
// TODO: Call a much simplified LoadBPReg instead.
- {
+ {
u32 bp_cmd = DataReadU32();
- LoadBPReg(bp_cmd);
+ LoadBPReg(bp_cmd);
INCSTAT(stats.thisFrame.numBPLoads);
- }
- break;
-
- // draw primitives
- default:
- if (cmd_byte & 0x80)
- {
- // load vertices (use computed vertex size from FifoCommandRunnable above)
+ }
+ break;
+
+ // draw primitives
+ default:
+ if (cmd_byte & 0x80)
+ {
+ // load vertices (use computed vertex size from FifoCommandRunnable above)
u16 numVertices = DataReadU16();
DataSkip(numVertices * VertexLoaderManager::GetVertexSize(cmd_byte & GX_VAT_MASK));
- }
- else
- {
+ }
+ else
+ {
ERROR_LOG(VIDEO, "OpcodeDecoding::Decode: Illegal command %02x", cmd_byte);
- break;
- }
- break;
- }
+ break;
+ }
+ break;
+ }
if (g_bRecordFifoData && cmd_byte != GX_CMD_CALL_DL)
- FifoRecorder::GetInstance().WriteGPCommand(opcodeStart, g_pVideoData - opcodeStart);
+ FifoRecorder::GetInstance().WriteGPCommand(opcodeStart, u32(g_pVideoData - opcodeStart));
}
void OpcodeDecoder_Init()
-{
+{
g_pVideoData = GetVideoBufferStartPtr();
#if _M_SSE >= 0x301
@@ -446,8 +494,8 @@ void OpcodeDecoder_Init()
if (g_Config.bEnableOpenCL)
{
- OpenCL::Initialize();
- TexDecoder_OpenCL_Initialize();
+ OpenCL::Initialize();
+ TexDecoder_OpenCL_Initialize();
}
}
@@ -456,21 +504,20 @@ void OpcodeDecoder_Shutdown()
{
if (g_Config.bEnableOpenCL)
{
- TexDecoder_OpenCL_Shutdown();
- OpenCL::Destroy();
+ TexDecoder_OpenCL_Shutdown();
+ OpenCL::Destroy();
}
}
-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;
}