diff options
| author | Markus Wick <markus+github@selfnet.de> | 2014-12-10 06:53:11 +0100 |
|---|---|---|
| committer | Markus Wick <markus+github@selfnet.de> | 2014-12-10 06:53:11 +0100 |
| commit | 4c139ca7cc816489feffc0b6ee0a3f1a6d85060e (patch) | |
| tree | e16ae78d1428f5ae62e68541bc8fe46bd3693d34 /Source/Core/VideoCommon/OpcodeDecoding.cpp | |
| parent | 57d2469d93ca6e2d3e0efe7c0efa85dfb95ed9c0 (diff) | |
| parent | e88e63adb36d649903a54740d9580a491cd6bf0d (diff) | |
Merge pull request #1609 from degasus/datareader
VideoCommon: Datareader
Diffstat (limited to 'Source/Core/VideoCommon/OpcodeDecoding.cpp')
| -rw-r--r-- | Source/Core/VideoCommon/OpcodeDecoding.cpp | 353 |
1 files changed, 162 insertions, 191 deletions
diff --git a/Source/Core/VideoCommon/OpcodeDecoding.cpp b/Source/Core/VideoCommon/OpcodeDecoding.cpp index a7dd5b6a85..34b821605f 100644 --- a/Source/Core/VideoCommon/OpcodeDecoding.cpp +++ b/Source/Core/VideoCommon/OpcodeDecoding.cpp @@ -36,7 +36,6 @@ bool g_bRecordFifoData = false; static u32 InterpretDisplayList(u32 address, u32 size) { - u8* old_pVideoData = g_video_buffer_read_ptr; u8* startAddress; if (g_use_deterministic_gpu_thread) @@ -49,41 +48,29 @@ static u32 InterpretDisplayList(u32 address, u32 size) // Avoid the crash if Memory::GetPointer failed .. if (startAddress != nullptr) { - g_video_buffer_read_ptr = startAddress; - // temporarily swap dl and non-dl (small "hack" for the stats) Statistics::SwapDL(); - u8 *end = g_video_buffer_read_ptr + size; - cycles = OpcodeDecoder_Run(end, true); + OpcodeDecoder_Run(DataReader(startAddress, startAddress + size), &cycles, true); INCSTAT(stats.thisFrame.numDListsCalled); // un-swap Statistics::SwapDL(); } - // reset to the old pointer - g_video_buffer_read_ptr = old_pVideoData; - return cycles; } static void InterpretDisplayListPreprocess(u32 address, u32 size) { - u8* old_read_ptr = g_video_buffer_pp_read_ptr; u8* startAddress = Memory::GetPointer(address); PushFifoAuxBuffer(startAddress, size); if (startAddress != nullptr) { - g_video_buffer_pp_read_ptr = startAddress; - - u8 *end = startAddress + size; - OpcodeDecoder_Preprocess(end, true); + OpcodeDecoder_Run<true>(DataReader(startAddress, startAddress + size), nullptr, true); } - - g_video_buffer_pp_read_ptr = old_read_ptr; } static void UnknownOpcode(u8 cmd_byte, void *buffer, bool preprocess) @@ -134,214 +121,198 @@ static void UnknownOpcode(u8 cmd_byte, void *buffer, bool preprocess) } } -template <bool is_preprocess, u8** bufp> -static u32 Decode(u8* end, bool in_display_list) +void OpcodeDecoder_Init() +{ +} + + +void OpcodeDecoder_Shutdown() +{ +} + +template <bool is_preprocess> +u8* OpcodeDecoder_Run(DataReader src, u32* cycles, bool in_display_list) { - u8 *opcodeStart = *bufp; - if (*bufp == end) - return 0; - - u8 cmd_byte = DataRead<u8>(bufp); - u32 cycles; - int refarray; - switch (cmd_byte) + u32 totalCycles = 0; + u8* opcodeStart; + while (true) { - case GX_NOP: - cycles = 6; // Hm, this means that we scan over nop streams pretty slowly... - break; + src.WritePointer(&opcodeStart); - case GX_LOAD_CP_REG: //0x08 - { - if (end - *bufp < 1 + 4) - return 0; - cycles = 12; - u8 sub_cmd = DataRead<u8>(bufp); - u32 value = DataRead<u32>(bufp); - LoadCPReg(sub_cmd, value, is_preprocess); - if (!is_preprocess) - INCSTAT(stats.thisFrame.numCPLoads); - } - break; + if (!src.size()) + goto end; - case GX_LOAD_XF_REG: + u8 cmd_byte = src.Read<u8>(); + int refarray; + switch (cmd_byte) { - if (end - *bufp < 4) - return 0; - u32 Cmd2 = DataRead<u32>(bufp); - int transfer_size = ((Cmd2 >> 16) & 15) + 1; - if ((size_t) (end - *bufp) < transfer_size * sizeof(u32)) - return 0; - cycles = 18 + 6 * transfer_size; - if (!is_preprocess) - { - u32 xf_address = Cmd2 & 0xFFFF; - LoadXFReg(transfer_size, xf_address); + case GX_NOP: + totalCycles += 6; // Hm, this means that we scan over nop streams pretty slowly... + break; - INCSTAT(stats.thisFrame.numXFLoads); - } - else + case GX_LOAD_CP_REG: //0x08 { - *bufp += transfer_size * sizeof(u32); + if (src.size() < 1 + 4) + goto end; + totalCycles += 12; + u8 sub_cmd = src.Read<u8>(); + u32 value = src.Read<u32>(); + LoadCPReg(sub_cmd, value, is_preprocess); + if (!is_preprocess) + INCSTAT(stats.thisFrame.numCPLoads); } - } - break; - - case GX_LOAD_INDX_A: //used for position matrices - refarray = 0xC; - goto load_indx; - case GX_LOAD_INDX_B: //used for normal matrices - refarray = 0xD; - goto load_indx; - case GX_LOAD_INDX_C: //used for postmatrices - refarray = 0xE; - goto load_indx; - case GX_LOAD_INDX_D: //used for lights - refarray = 0xF; - goto load_indx; - load_indx: - if (end - *bufp < 4) - return 0; - cycles = 6; - if (is_preprocess) - PreprocessIndexedXF(DataRead<u32>(bufp), refarray); - else - LoadIndexedXF(DataRead<u32>(bufp), refarray); - break; - - case GX_CMD_CALL_DL: - { - if (end - *bufp < 8) - return 0; - u32 address = DataRead<u32>(bufp); - u32 count = DataRead<u32>(bufp); + break; - if (in_display_list) + case GX_LOAD_XF_REG: { - cycles = 6; - WARN_LOG(VIDEO,"recursive display list detected"); + if (src.size() < 4) + goto end; + u32 Cmd2 = src.Read<u32>(); + int transfer_size = ((Cmd2 >> 16) & 15) + 1; + if (src.size() < transfer_size * sizeof(u32)) + goto end; + totalCycles += 18 + 6 * transfer_size; + if (!is_preprocess) + { + u32 xf_address = Cmd2 & 0xFFFF; + LoadXFReg(transfer_size, xf_address, src); + + INCSTAT(stats.thisFrame.numXFLoads); + } + src.Skip<u32>(transfer_size); } + break; + + case GX_LOAD_INDX_A: //used for position matrices + refarray = 0xC; + goto load_indx; + case GX_LOAD_INDX_B: //used for normal matrices + refarray = 0xD; + goto load_indx; + case GX_LOAD_INDX_C: //used for postmatrices + refarray = 0xE; + goto load_indx; + case GX_LOAD_INDX_D: //used for lights + refarray = 0xF; + goto load_indx; + load_indx: + if (src.size() < 4) + goto end; + totalCycles += 6; + if (is_preprocess) + PreprocessIndexedXF(src.Read<u32>(), refarray); else + LoadIndexedXF(src.Read<u32>(), refarray); + break; + + case GX_CMD_CALL_DL: { - if (is_preprocess) - InterpretDisplayListPreprocess(address, count); + if (src.size() < 8) + goto end; + u32 address = src.Read<u32>(); + u32 count = src.Read<u32>(); + + if (in_display_list) + { + totalCycles += 6; + WARN_LOG(VIDEO,"recursive display list detected"); + } else - cycles = 6 + InterpretDisplayList(address, count); + { + if (is_preprocess) + InterpretDisplayListPreprocess(address, count); + else + totalCycles += 6 + InterpretDisplayList(address, count); + } } - } - break; + break; - case GX_CMD_UNKNOWN_METRICS: // zelda 4 swords calls it and checks the metrics registers after that - cycles = 6; - DEBUG_LOG(VIDEO, "GX 0x44: %08x", cmd_byte); - break; + case GX_CMD_UNKNOWN_METRICS: // zelda 4 swords calls it and checks the metrics registers after that + totalCycles += 6; + DEBUG_LOG(VIDEO, "GX 0x44: %08x", cmd_byte); + break; - case GX_CMD_INVL_VC: // Invalidate Vertex Cache - cycles = 6; - DEBUG_LOG(VIDEO, "Invalidate (vertex cache?)"); - break; + case GX_CMD_INVL_VC: // Invalidate Vertex Cache + totalCycles += 6; + DEBUG_LOG(VIDEO, "Invalidate (vertex cache?)"); + break; - case GX_LOAD_BP_REG: //0x61 - // In skipped_frame case: We have to let BP writes through because they set - // tokens and stuff. TODO: Call a much simplified LoadBPReg instead. - { - if (end - *bufp < 4) - return 0; - cycles = 12; - u32 bp_cmd = DataRead<u32>(bufp); - if (is_preprocess) - { - LoadBPRegPreprocess(bp_cmd); - } - else + case GX_LOAD_BP_REG: //0x61 + // In skipped_frame case: We have to let BP writes through because they set + // tokens and stuff. TODO: Call a much simplified LoadBPReg instead. { - LoadBPReg(bp_cmd); - INCSTAT(stats.thisFrame.numBPLoads); + if (src.size() < 4) + goto end; + totalCycles += 12; + u32 bp_cmd = src.Read<u32>(); + if (is_preprocess) + { + LoadBPRegPreprocess(bp_cmd); + } + else + { + LoadBPReg(bp_cmd); + INCSTAT(stats.thisFrame.numBPLoads); + } } - } - break; - - // draw primitives - default: - if ((cmd_byte & 0xC0) == 0x80) - { - cycles = 1600; - // load vertices - if (end - *bufp < 2) - return 0; - u16 num_vertices = DataRead<u16>(bufp); + break; - if (is_preprocess) + // draw primitives + default: + if ((cmd_byte & 0xC0) == 0x80) { - size_t size = num_vertices * VertexLoaderManager::GetVertexSize(cmd_byte & GX_VAT_MASK, is_preprocess); - if ((size_t) (end - *bufp) < size) - return 0; - *bufp += size; + // load vertices + if (src.size() < 2) + goto end; + u16 num_vertices = src.Read<u16>(); + + if (is_preprocess) + { + size_t size = num_vertices * VertexLoaderManager::GetVertexSize(cmd_byte & GX_VAT_MASK, is_preprocess); + if (src.size() < size) + goto end; + src.Skip(size); + } + else + { + int bytes = VertexLoaderManager::RunVertices( + cmd_byte & GX_VAT_MASK, // Vertex loader index (0 - 7) + (cmd_byte & GX_PRIMITIVE_MASK) >> GX_PRIMITIVE_SHIFT, + num_vertices, + src, + g_bSkipCurrentFrame); + + if (bytes < 0) + goto end; + else + src.Skip(bytes); + } + totalCycles += 1600; } else { - if (!VertexLoaderManager::RunVertices( - cmd_byte & GX_VAT_MASK, // Vertex loader index (0 - 7) - (cmd_byte & GX_PRIMITIVE_MASK) >> GX_PRIMITIVE_SHIFT, - num_vertices, - end - *bufp, - g_bSkipCurrentFrame)) - return 0; + UnknownOpcode(cmd_byte, opcodeStart, is_preprocess); + totalCycles += 1; } + break; } - else - { - UnknownOpcode(cmd_byte, opcodeStart, is_preprocess); - cycles = 1; - } - break; - } - - // Display lists get added directly into the FIFO stream - if (!is_preprocess && g_bRecordFifoData && cmd_byte != GX_CMD_CALL_DL) - FifoRecorder::GetInstance().WriteGPCommand(opcodeStart, u32(*bufp - opcodeStart)); - - // In is_preprocess mode, we don't actually care about cycles, at least for - // now... make sure the compiler realizes that. - return is_preprocess ? 1 : cycles; -} - -void OpcodeDecoder_Init() -{ - g_video_buffer_read_ptr = GetVideoBufferStartPtr(); -} - - -void OpcodeDecoder_Shutdown() -{ -} -u32 OpcodeDecoder_Run(u8* end, bool in_display_list) -{ - u32 totalCycles = 0; - while (true) - { - u8* old = g_video_buffer_read_ptr; - u32 cycles = Decode</*is_preprocess*/ false, &g_video_buffer_read_ptr>(end, in_display_list); - if (cycles == 0) + // Display lists get added directly into the FIFO stream + if (!is_preprocess && g_bRecordFifoData && cmd_byte != GX_CMD_CALL_DL) { - g_video_buffer_read_ptr = old; - break; + u8* opcodeEnd; + src.WritePointer(&opcodeEnd); + FifoRecorder::GetInstance().WriteGPCommand(opcodeStart, u32(opcodeEnd - opcodeStart)); } - totalCycles += cycles; } - return totalCycles; -} -void OpcodeDecoder_Preprocess(u8 *end, bool in_display_list) -{ - while (true) +end: + if (cycles) { - u8* old = g_video_buffer_pp_read_ptr; - u32 cycles = Decode</*is_preprocess*/ true, &g_video_buffer_pp_read_ptr>(end, in_display_list); - if (cycles == 0) - { - g_video_buffer_pp_read_ptr = old; - break; - } + *cycles = totalCycles; } + return opcodeStart; } + +template u8* OpcodeDecoder_Run<true>(DataReader src, u32* cycles, bool in_display_list); +template u8* OpcodeDecoder_Run<false>(DataReader src, u32* cycles, bool in_display_list); |
