From 99e4a500dcd051277fe24705539ad1f4948b82ec Mon Sep 17 00:00:00 2001 From: Soren Jorvang Date: Sun, 27 Mar 2011 09:28:51 +0000 Subject: [PATCH] Fix scons build. git-svn-id: https://dolphin-emu.googlecode.com/svn/trunk@7415 8ced0084-cf51-0410-be5f-012b33b47a6e --- Source/Core/Core/SConscript | 6 + .../Core/Core/Src/FifoPlayer/FifoAnalyzer.cpp | 468 ++++++------ .../Core/Core/Src/FifoPlayer/FifoAnalyzer.h | 106 +-- .../Src/FifoPlayer/FifoPlaybackAnalyzer.cpp | 690 +++++++++--------- .../Src/FifoPlayer/FifoPlaybackAnalyzer.h | 126 ++-- .../Src/FifoPlayer/FifoRecordAnalyzer.cpp | 608 +++++++-------- .../Core/Src/FifoPlayer/FifoRecordAnalyzer.h | 110 +-- Source/Core/DolphinWX/SConscript | 1 + 8 files changed, 1061 insertions(+), 1054 deletions(-) diff --git a/Source/Core/Core/SConscript b/Source/Core/Core/SConscript index 2f1cf50041..3dc39b0644 100644 --- a/Source/Core/Core/SConscript +++ b/Source/Core/Core/SConscript @@ -52,6 +52,12 @@ files = [ 'Src/Debugger/Debugger_SymbolMap.cpp', 'Src/Debugger/Dump.cpp', 'Src/Debugger/PPCDebugInterface.cpp', + 'Src/FifoPlayer/FifoAnalyzer.cpp', + 'Src/FifoPlayer/FifoDataFile.cpp', + 'Src/FifoPlayer/FifoPlaybackAnalyzer.cpp', + 'Src/FifoPlayer/FifoPlayer.cpp', + 'Src/FifoPlayer/FifoRecordAnalyzer.cpp', + 'Src/FifoPlayer/FifoRecorder.cpp', 'Src/GeckoCode.cpp', 'Src/GeckoCodeConfig.cpp', 'Src/HLE/HLE.cpp', diff --git a/Source/Core/Core/Src/FifoPlayer/FifoAnalyzer.cpp b/Source/Core/Core/Src/FifoPlayer/FifoAnalyzer.cpp index dd975ef82a..e18f26fe43 100644 --- a/Source/Core/Core/Src/FifoPlayer/FifoAnalyzer.cpp +++ b/Source/Core/Core/Src/FifoPlayer/FifoAnalyzer.cpp @@ -1,235 +1,235 @@ -// Copyright (C) 2003 Dolphin Project. - -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, version 2.0. - -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License 2.0 for more details. - -// A copy of the GPL 2.0 should have been included with the program. -// If not, see http://www.gnu.org/licenses/ - -// Official SVN repository and contact information can be found at -// http://code.google.com/p/dolphin-emu/ - -#include "FifoAnalyzer.h" - -#include "Core.h" - -#include "VertexLoader.h" -#include "VertexLoader_Position.h" -#include "VertexLoader_Normal.h" -#include "VertexLoader_TextCoord.h" - -namespace FifoAnalyzer -{ - -void Init() -{ - VertexLoader_Normal::Init(); - VertexLoader_Position::Init(); - VertexLoader_TextCoord::Init(); -} - -u8 ReadFifo8(u8 *&data) -{ - u8 value = data[0]; - data += 1; - return value; -} - -u16 ReadFifo16(u8 *&data) -{ - u16 value = Common::swap16(data); - data += 2; - return value; -} - -u32 ReadFifo32(u8 *&data) -{ - u32 value = Common::swap32(data); - data += 4; - return value; -} - -void InitBPMemory(BPMemory *bpMem) -{ - memset(bpMem, 0, sizeof(BPMemory)); - bpMem->bpMask = 0x00FFFFFF; -} - -BPCmd DecodeBPCmd(u32 value, const BPMemory &bpMem) -{ - //handle the mask register - int opcode = value >> 24; - int oldval = ((u32*)&bpMem)[opcode]; - int newval = (oldval & ~bpMem.bpMask) | (value & bpMem.bpMask); - int changes = (oldval ^ newval) & 0xFFFFFF; - - BPCmd bp = {opcode, changes, newval}; - - return bp; -} - -void LoadBPReg(const BPCmd &bp, BPMemory &bpMem) -{ - ((u32*)&bpMem)[bp.address] = bp.newvalue; - - //reset the mask register - if (bp.address != 0xFE) - bpMem.bpMask = 0xFFFFFF; -} - -void GetTlutLoadData(u32 &tlutAddr, u32 &memAddr, u32 &tlutXferCount, BPMemory &bpMem) -{ - tlutAddr = (bpMem.tlutXferDest & 0x3FF) << 9; - tlutXferCount = (bpMem.tlutXferDest & 0x1FFC00) >> 5; - - // TODO - figure out a cleaner way. - if (Core::g_CoreStartupParameter.bWii) - memAddr = bpmem.tlutXferSrc << 5; - else - memAddr = (bpmem.tlutXferSrc & 0xFFFFF) << 5; -} - -void LoadCPReg(u32 subCmd, u32 value, CPMemory &cpMem) -{ - switch (subCmd & 0xF0) - { - case 0x50: - cpMem.vtxDesc.Hex &= ~0x1FFFF; // keep the Upper bits - cpMem.vtxDesc.Hex |= value; - break; - - case 0x60: - cpMem.vtxDesc.Hex &= 0x1FFFF; // keep the lower 17Bits - cpMem.vtxDesc.Hex |= (u64)value << 17; - break; - - case 0x70: - _assert_((subCmd & 0x0F) < 8); - cpMem.vtxAttr[subCmd & 7].g0.Hex = value; - break; - - case 0x80: - _assert_((subCmd & 0x0F) < 8); - cpMem.vtxAttr[subCmd & 7].g1.Hex = value; - break; - - case 0x90: - _assert_((subCmd & 0x0F) < 8); - cpMem.vtxAttr[subCmd & 7].g2.Hex = value; - break; - - case 0xA0: - cpMem.arrayBases[subCmd & 0xF] = value; - break; - - case 0xB0: - cpMem.arrayStrides[subCmd & 0xF] = value & 0xFF; - break; - } -} - -u32 CalculateVertexSize(int vatIndex, const CPMemory &cpMem) -{ - u32 vertexSize = 0; - - int sizes[21]; - CalculateVertexElementSizes(sizes, vatIndex, cpMem); - - for (int i = 0; i < 21; ++i) - vertexSize += sizes[i]; - - return vertexSize; -} - -void CalculateVertexElementSizes(int sizes[], int vatIndex, const CPMemory &cpMem) -{ - const TVtxDesc &vtxDesc = cpMem.vtxDesc; - const VAT &vtxAttr = cpMem.vtxAttr[vatIndex]; - - // Colors - const int colDesc[2] = {vtxDesc.Color0, vtxDesc.Color1}; - const int colComp[2] = {vtxAttr.g0.Color0Comp, vtxAttr.g0.Color1Comp}; - - const int tcElements[8] = - { - vtxAttr.g0.Tex0CoordElements, vtxAttr.g1.Tex1CoordElements, vtxAttr.g1.Tex2CoordElements, - vtxAttr.g1.Tex3CoordElements, vtxAttr.g1.Tex4CoordElements, vtxAttr.g2.Tex5CoordElements, - vtxAttr.g2.Tex6CoordElements, vtxAttr.g2.Tex7CoordElements - }; - - const int tcFormat[8] = - { - vtxAttr.g0.Tex0CoordFormat, vtxAttr.g1.Tex1CoordFormat, vtxAttr.g1.Tex2CoordFormat, - vtxAttr.g1.Tex3CoordFormat, vtxAttr.g1.Tex4CoordFormat, vtxAttr.g2.Tex5CoordFormat, - vtxAttr.g2.Tex6CoordFormat, vtxAttr.g2.Tex7CoordFormat - }; - - // Add position and texture matrix indices - u64 vtxDescHex = cpMem.vtxDesc.Hex; - for (int i = 0; i < 9; ++i) - { - sizes[i] = vtxDescHex & 1; - vtxDescHex >>= 1; - } - - // Position - sizes[9] = VertexLoader_Position::GetSize(vtxDesc.Position, vtxAttr.g0.PosFormat, vtxAttr.g0.PosElements); - - // Normals - if (vtxDesc.Normal != NOT_PRESENT) - { - sizes[10] = VertexLoader_Normal::GetSize(vtxDesc.Normal, vtxAttr.g0.NormalFormat, vtxAttr.g0.NormalElements, vtxAttr.g0.NormalIndex3); - } - else - { - sizes[10] = 0; - } - - // Colors - for (int i = 0; i < 2; i++) - { - int size = 0; - - switch (colDesc[i]) - { - case NOT_PRESENT: - break; - case DIRECT: - switch (colComp[i]) - { - case FORMAT_16B_565: size = 2; break; - case FORMAT_24B_888: size = 3; break; - case FORMAT_32B_888x: size = 4; break; - case FORMAT_16B_4444: size = 2; break; - case FORMAT_24B_6666: size = 3; break; - case FORMAT_32B_8888: size = 4; break; - default: _assert_(0); break; - } - break; - case INDEX8: - size = 1; - break; - case INDEX16: - size = 2; - break; - } - - sizes[11 + i] = size; - } - - // Texture coordinates - vtxDescHex = vtxDesc.Hex >> 17; - for (int i = 0; i < 8; i++) - { - sizes[13 + i] = VertexLoader_TextCoord::GetSize(vtxDescHex & 3, tcFormat[i], tcElements[i]); - vtxDescHex >>= 2; - } -} - +// Copyright (C) 2003 Dolphin Project. + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, version 2.0. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License 2.0 for more details. + +// A copy of the GPL 2.0 should have been included with the program. +// If not, see http://www.gnu.org/licenses/ + +// Official SVN repository and contact information can be found at +// http://code.google.com/p/dolphin-emu/ + +#include "FifoAnalyzer.h" + +#include "Core.h" + +#include "VertexLoader.h" +#include "VertexLoader_Position.h" +#include "VertexLoader_Normal.h" +#include "VertexLoader_TextCoord.h" + +namespace FifoAnalyzer +{ + +void Init() +{ + VertexLoader_Normal::Init(); + VertexLoader_Position::Init(); + VertexLoader_TextCoord::Init(); +} + +u8 ReadFifo8(u8 *&data) +{ + u8 value = data[0]; + data += 1; + return value; +} + +u16 ReadFifo16(u8 *&data) +{ + u16 value = Common::swap16(data); + data += 2; + return value; +} + +u32 ReadFifo32(u8 *&data) +{ + u32 value = Common::swap32(data); + data += 4; + return value; +} + +void InitBPMemory(BPMemory *bpMem) +{ + memset(bpMem, 0, sizeof(BPMemory)); + bpMem->bpMask = 0x00FFFFFF; +} + +BPCmd DecodeBPCmd(u32 value, const BPMemory &bpMem) +{ + //handle the mask register + int opcode = value >> 24; + int oldval = ((u32*)&bpMem)[opcode]; + int newval = (oldval & ~bpMem.bpMask) | (value & bpMem.bpMask); + int changes = (oldval ^ newval) & 0xFFFFFF; + + BPCmd bp = {opcode, changes, newval}; + + return bp; +} + +void LoadBPReg(const BPCmd &bp, BPMemory &bpMem) +{ + ((u32*)&bpMem)[bp.address] = bp.newvalue; + + //reset the mask register + if (bp.address != 0xFE) + bpMem.bpMask = 0xFFFFFF; +} + +void GetTlutLoadData(u32 &tlutAddr, u32 &memAddr, u32 &tlutXferCount, BPMemory &bpMem) +{ + tlutAddr = (bpMem.tlutXferDest & 0x3FF) << 9; + tlutXferCount = (bpMem.tlutXferDest & 0x1FFC00) >> 5; + + // TODO - figure out a cleaner way. + if (Core::g_CoreStartupParameter.bWii) + memAddr = bpmem.tlutXferSrc << 5; + else + memAddr = (bpmem.tlutXferSrc & 0xFFFFF) << 5; +} + +void LoadCPReg(u32 subCmd, u32 value, CPMemory &cpMem) +{ + switch (subCmd & 0xF0) + { + case 0x50: + cpMem.vtxDesc.Hex &= ~0x1FFFF; // keep the Upper bits + cpMem.vtxDesc.Hex |= value; + break; + + case 0x60: + cpMem.vtxDesc.Hex &= 0x1FFFF; // keep the lower 17Bits + cpMem.vtxDesc.Hex |= (u64)value << 17; + break; + + case 0x70: + _assert_((subCmd & 0x0F) < 8); + cpMem.vtxAttr[subCmd & 7].g0.Hex = value; + break; + + case 0x80: + _assert_((subCmd & 0x0F) < 8); + cpMem.vtxAttr[subCmd & 7].g1.Hex = value; + break; + + case 0x90: + _assert_((subCmd & 0x0F) < 8); + cpMem.vtxAttr[subCmd & 7].g2.Hex = value; + break; + + case 0xA0: + cpMem.arrayBases[subCmd & 0xF] = value; + break; + + case 0xB0: + cpMem.arrayStrides[subCmd & 0xF] = value & 0xFF; + break; + } +} + +u32 CalculateVertexSize(int vatIndex, const CPMemory &cpMem) +{ + u32 vertexSize = 0; + + int sizes[21]; + CalculateVertexElementSizes(sizes, vatIndex, cpMem); + + for (int i = 0; i < 21; ++i) + vertexSize += sizes[i]; + + return vertexSize; +} + +void CalculateVertexElementSizes(int sizes[], int vatIndex, const CPMemory &cpMem) +{ + const TVtxDesc &vtxDesc = cpMem.vtxDesc; + const VAT &vtxAttr = cpMem.vtxAttr[vatIndex]; + + // Colors + const int colDesc[2] = {vtxDesc.Color0, vtxDesc.Color1}; + const int colComp[2] = {vtxAttr.g0.Color0Comp, vtxAttr.g0.Color1Comp}; + + const int tcElements[8] = + { + vtxAttr.g0.Tex0CoordElements, vtxAttr.g1.Tex1CoordElements, vtxAttr.g1.Tex2CoordElements, + vtxAttr.g1.Tex3CoordElements, vtxAttr.g1.Tex4CoordElements, vtxAttr.g2.Tex5CoordElements, + vtxAttr.g2.Tex6CoordElements, vtxAttr.g2.Tex7CoordElements + }; + + const int tcFormat[8] = + { + vtxAttr.g0.Tex0CoordFormat, vtxAttr.g1.Tex1CoordFormat, vtxAttr.g1.Tex2CoordFormat, + vtxAttr.g1.Tex3CoordFormat, vtxAttr.g1.Tex4CoordFormat, vtxAttr.g2.Tex5CoordFormat, + vtxAttr.g2.Tex6CoordFormat, vtxAttr.g2.Tex7CoordFormat + }; + + // Add position and texture matrix indices + u64 vtxDescHex = cpMem.vtxDesc.Hex; + for (int i = 0; i < 9; ++i) + { + sizes[i] = vtxDescHex & 1; + vtxDescHex >>= 1; + } + + // Position + sizes[9] = VertexLoader_Position::GetSize(vtxDesc.Position, vtxAttr.g0.PosFormat, vtxAttr.g0.PosElements); + + // Normals + if (vtxDesc.Normal != NOT_PRESENT) + { + sizes[10] = VertexLoader_Normal::GetSize(vtxDesc.Normal, vtxAttr.g0.NormalFormat, vtxAttr.g0.NormalElements, vtxAttr.g0.NormalIndex3); + } + else + { + sizes[10] = 0; + } + + // Colors + for (int i = 0; i < 2; i++) + { + int size = 0; + + switch (colDesc[i]) + { + case NOT_PRESENT: + break; + case DIRECT: + switch (colComp[i]) + { + case FORMAT_16B_565: size = 2; break; + case FORMAT_24B_888: size = 3; break; + case FORMAT_32B_888x: size = 4; break; + case FORMAT_16B_4444: size = 2; break; + case FORMAT_24B_6666: size = 3; break; + case FORMAT_32B_8888: size = 4; break; + default: _assert_(0); break; + } + break; + case INDEX8: + size = 1; + break; + case INDEX16: + size = 2; + break; + } + + sizes[11 + i] = size; + } + + // Texture coordinates + vtxDescHex = vtxDesc.Hex >> 17; + for (int i = 0; i < 8; i++) + { + sizes[13 + i] = VertexLoader_TextCoord::GetSize(vtxDescHex & 3, tcFormat[i], tcElements[i]); + vtxDescHex >>= 2; + } +} + } \ No newline at end of file diff --git a/Source/Core/Core/Src/FifoPlayer/FifoAnalyzer.h b/Source/Core/Core/Src/FifoPlayer/FifoAnalyzer.h index 55f1917e57..eb9a978aca 100644 --- a/Source/Core/Core/Src/FifoPlayer/FifoAnalyzer.h +++ b/Source/Core/Core/Src/FifoPlayer/FifoAnalyzer.h @@ -1,54 +1,54 @@ -// Copyright (C) 2003 Dolphin Project. - -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, version 2.0. - -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License 2.0 for more details. - -// A copy of the GPL 2.0 should have been included with the program. -// If not, see http://www.gnu.org/licenses/ - -// Official SVN repository and contact information can be found at -// http://code.google.com/p/dolphin-emu/ - -#ifndef _FIFOANALYZER_H -#define _FIFOANALYZER_H - -#include "Common.h" - -#include "BPMemory.h" -#include "CPMemory.h" - -namespace FifoAnalyzer -{ - void Init(); - - u8 ReadFifo8(u8 *&data); - u16 ReadFifo16(u8 *&data); - u32 ReadFifo32(u8 *&data); - - // TODO- move to video common - void InitBPMemory(BPMemory *bpMem); - BPCmd DecodeBPCmd(u32 value, const BPMemory &bpMem); - void LoadBPReg(const BPCmd &bp, BPMemory &bpMem); - void GetTlutLoadData(u32 &tlutAddr, u32 &memAddr, u32 &tlutXferCount, BPMemory &bpMem); - - struct CPMemory - { - TVtxDesc vtxDesc; - VAT vtxAttr[8]; - u32 arrayBases[16]; - u32 arrayStrides[16]; - }; - - void LoadCPReg(u32 subCmd, u32 value, CPMemory &cpMem); - - u32 CalculateVertexSize(int vatIndex, const CPMemory &cpMem); - void CalculateVertexElementSizes(int sizes[], int vatIndex, const CPMemory &cpMem); -} - +// Copyright (C) 2003 Dolphin Project. + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, version 2.0. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License 2.0 for more details. + +// A copy of the GPL 2.0 should have been included with the program. +// If not, see http://www.gnu.org/licenses/ + +// Official SVN repository and contact information can be found at +// http://code.google.com/p/dolphin-emu/ + +#ifndef _FIFOANALYZER_H +#define _FIFOANALYZER_H + +#include "Common.h" + +#include "BPMemory.h" +#include "CPMemory.h" + +namespace FifoAnalyzer +{ + void Init(); + + u8 ReadFifo8(u8 *&data); + u16 ReadFifo16(u8 *&data); + u32 ReadFifo32(u8 *&data); + + // TODO- move to video common + void InitBPMemory(BPMemory *bpMem); + BPCmd DecodeBPCmd(u32 value, const BPMemory &bpMem); + void LoadBPReg(const BPCmd &bp, BPMemory &bpMem); + void GetTlutLoadData(u32 &tlutAddr, u32 &memAddr, u32 &tlutXferCount, BPMemory &bpMem); + + struct CPMemory + { + TVtxDesc vtxDesc; + VAT vtxAttr[8]; + u32 arrayBases[16]; + u32 arrayStrides[16]; + }; + + void LoadCPReg(u32 subCmd, u32 value, CPMemory &cpMem); + + u32 CalculateVertexSize(int vatIndex, const CPMemory &cpMem); + void CalculateVertexElementSizes(int sizes[], int vatIndex, const CPMemory &cpMem); +} + #endif \ No newline at end of file diff --git a/Source/Core/Core/Src/FifoPlayer/FifoPlaybackAnalyzer.cpp b/Source/Core/Core/Src/FifoPlayer/FifoPlaybackAnalyzer.cpp index ccec508cdb..060ff4078b 100644 --- a/Source/Core/Core/Src/FifoPlayer/FifoPlaybackAnalyzer.cpp +++ b/Source/Core/Core/Src/FifoPlayer/FifoPlaybackAnalyzer.cpp @@ -1,346 +1,346 @@ -// Copyright (C) 2003 Dolphin Project. - -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, version 2.0. - -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License 2.0 for more details. - -// A copy of the GPL 2.0 should have been included with the program. -// If not, see http://www.gnu.org/licenses/ - -// Official SVN repository and contact information can be found at -// http://code.google.com/p/dolphin-emu/ - -#include "FifoAnalyzer.h" -#include "FifoDataFile.h" -#include "FifoPlaybackAnalyzer.h" - -#include "Common.h" - -#include "OpcodeDecoding.h" -#include "TextureDecoder.h" -#include "VertexLoader.h" - -using namespace std; -using namespace FifoAnalyzer; - -// For debugging -#define LOG_FIFO_CMDS 0 -struct CmdData -{ - u32 size; - u32 offset; - u8 *ptr; -}; - -FifoPlaybackAnalyzer::FifoPlaybackAnalyzer() -{ - FifoAnalyzer::Init(); -} - -void FifoPlaybackAnalyzer::AnalyzeFrames(FifoDataFile *file, std::vector &frameInfo) -{ - // Load BP memory - u32 *bpMem = file->GetBPMem(); - memcpy(&m_BpMem, bpMem, sizeof(BPMemory)); - - u32 *cpMem = file->GetCPMem(); - FifoAnalyzer::LoadCPReg(0x50, cpMem[0x50], m_CpMem); - FifoAnalyzer::LoadCPReg(0x60, cpMem[0x60], m_CpMem); - - for (int i = 0; i < 8; ++i) - { - FifoAnalyzer::LoadCPReg(0x70 + i, cpMem[0x70 + i], m_CpMem); - FifoAnalyzer::LoadCPReg(0x80 + i, cpMem[0x80 + i], m_CpMem); - FifoAnalyzer::LoadCPReg(0x90 + i, cpMem[0x90 + i], m_CpMem); - } - - frameInfo.clear(); - frameInfo.resize(file->GetFrameCount()); - - for (int frameIdx = 0; frameIdx < file->GetFrameCount(); ++frameIdx) - { - const FifoFrameInfo& frame = file->GetFrame(frameIdx); - AnalyzedFrameInfo& analyzed = frameInfo[frameIdx]; - - m_DrawingObject = false; - - u32 cmdStart = 0; - u32 nextMemUpdate = 0; - - // Debugging - vector prevCmds; - - while (cmdStart < frame.fifoDataSize) - { - // Add memory updates that have occured before this point in the frame - while (nextMemUpdate < frame.memoryUpdates.size() && frame.memoryUpdates[nextMemUpdate].fifoPosition <= cmdStart) - { - AddMemoryUpdate(frame.memoryUpdates[nextMemUpdate], analyzed); - ++nextMemUpdate; - } - - bool wasDrawing = m_DrawingObject; - - u32 cmdSize = DecodeCommand(&frame.fifoData[cmdStart]); - -#if (LOG_FIFO_CMDS) - CmdData cmdData; - cmdData.offset = cmdStart; - cmdData.ptr = &frame.fifoData[cmdStart]; - cmdData.size = cmdSize; - prevCmds.push_back(cmdData); -#endif - - // Check for error - if (cmdSize == 0) - { - // Clean up frame analysis - analyzed.objectStarts.clear(); - analyzed.objectEnds.clear(); - - return; - } - - if (wasDrawing != m_DrawingObject) - { - if (m_DrawingObject) - analyzed.objectStarts.push_back(cmdStart); - else - analyzed.objectEnds.push_back(cmdStart); - } - - cmdStart += cmdSize; - } - - if (analyzed.objectEnds.size() < analyzed.objectStarts.size()) - analyzed.objectEnds.push_back(cmdStart); - } -} - -void FifoPlaybackAnalyzer::AddMemoryUpdate(MemoryUpdate memUpdate, AnalyzedFrameInfo &frameInfo) -{ - u32 begin = memUpdate.address; - u32 end = memUpdate.address + memUpdate.size; - - // Remove portions of memUpdate that overlap with memory ranges that have been written by the GP - for (unsigned int i = 0; i < m_WrittenMemory.size(); ++i) - { - const MemoryRange &range = m_WrittenMemory[i]; - - if (range.begin < end && - range.end > begin) - { - s32 preSize = range.begin - begin; - s32 postSize = end - range.end; - - if (postSize > 0) - { - if (preSize > 0) - { - memUpdate.size = preSize; - AddMemoryUpdate(memUpdate, frameInfo); - } - - u32 bytesToRangeEnd = range.end - memUpdate.address; - memUpdate.data += bytesToRangeEnd; - memUpdate.size = postSize; - memUpdate.address = range.end; - } - else if (preSize > 0) - { - memUpdate.size = preSize; - } - else - { - // Ignore all of memUpdate - return; - } - } - } - - frameInfo.memoryUpdates.push_back(memUpdate); -} - -u32 FifoPlaybackAnalyzer::DecodeCommand(u8 *data) -{ - u8 *dataStart = data; - - int cmd = ReadFifo8(data); - - switch(cmd) - { - case GX_NOP: - case 0x44: - case GX_CMD_INVL_VC: - break; - - case GX_LOAD_CP_REG: - { - m_DrawingObject = false; - - u32 cmd2 = ReadFifo8(data); - u32 value = ReadFifo32(data); - FifoAnalyzer::LoadCPReg(cmd2, value, m_CpMem); - } - break; - - case GX_LOAD_XF_REG: - { - m_DrawingObject = false; - - u32 cmd2 = ReadFifo32(data); - u8 streamSize = ((cmd2 >> 16) & 15) + 1; - - data += streamSize * 4; - } - break; - - case GX_LOAD_INDX_A: - case GX_LOAD_INDX_B: - case GX_LOAD_INDX_C: - case GX_LOAD_INDX_D: - m_DrawingObject = false; - data += 4; - break; - - case GX_CMD_CALL_DL: - // The recorder should have expanded display lists into the fifo stream and skipped the call to start them - // That is done to make it easier to track where memory is updated - _assert_(false); - data += 8; - break; - - case GX_LOAD_BP_REG: - { - m_DrawingObject = false; - - u32 cmd2 = ReadFifo32(data); - BPCmd bp = FifoAnalyzer::DecodeBPCmd(cmd2, m_BpMem); - - FifoAnalyzer::LoadBPReg(bp, m_BpMem); - - if (bp.address == BPMEM_TRIGGER_EFB_COPY) - StoreEfbCopyRegion(); - } - break; - - default: - if (cmd & 0x80) - { - m_DrawingObject = true; - - u32 vtxAttrGroup = cmd & GX_VAT_MASK; - int vertexSize = FifoAnalyzer::CalculateVertexSize(vtxAttrGroup, m_CpMem); - - u16 streamSize = ReadFifo16(data); - - data += streamSize * vertexSize; - } - else - { - PanicAlert("FifoPlayer: Unknown Opcode (0x%x).\nAborting frame analysis.\n", cmd); - return 0; - } - break; - } - - return data - dataStart; -} - -void FifoPlaybackAnalyzer::StoreEfbCopyRegion() -{ - UPE_Copy peCopy = m_BpMem.triggerEFBCopy; - - u32 copyfmt = peCopy.tp_realFormat(); - bool bFromZBuffer = m_BpMem.zcontrol.pixel_format == PIXELFMT_Z24; - u32 address = bpmem.copyTexDest << 5; - - u32 format = copyfmt; - - if (peCopy.copy_to_xfb) - { - // Fake format to calculate size correctly - format = GX_TF_IA8; - } - else if (bFromZBuffer) - { - format |= _GX_TF_ZTF; - if (copyfmt == 11) - format = GX_TF_Z16; - else if (format < GX_TF_Z8 || format > GX_TF_Z24X8) - format |= _GX_TF_CTF; - } - else - { - if (copyfmt > GX_TF_RGBA8 || (copyfmt < GX_TF_RGB565 && !peCopy.intensity_fmt)) - format |= _GX_TF_CTF; - } - - int width = (m_BpMem.copyTexSrcWH.x + 1) >> peCopy.half_scale; - int height = (m_BpMem.copyTexSrcWH.y + 1) >> peCopy.half_scale; - - u16 blkW = TexDecoder_GetBlockWidthInTexels(format) - 1; - u16 blkH = TexDecoder_GetBlockHeightInTexels(format) - 1; - - s32 expandedWidth = (width + blkW) & (~blkW); - s32 expandedHeight = (height + blkH) & (~blkH); - - int sizeInBytes = TexDecoder_GetTextureSizeInBytes(expandedWidth, expandedHeight, format); - - StoreWrittenRegion(address, sizeInBytes); -} - -void FifoPlaybackAnalyzer::StoreWrittenRegion(u32 address, u32 size) -{ - u32 end = address + size; - vector::iterator newRangeIter = m_WrittenMemory.end(); - - // Search for overlapping memory regions and expand them to include the new region - for (vector::iterator iter = m_WrittenMemory.begin(); iter != m_WrittenMemory.end();) - { - MemoryRange &range = *iter; - - if (range.begin < end && range.end > address) - { - // range at iterator and new range overlap - - if (newRangeIter == m_WrittenMemory.end()) - { - // Expand range to include the written region - range.begin = std::min(address, range.begin); - range.end = std::max(end, range.end); - newRangeIter = iter; - - ++iter; - } - else - { - // Expand region at rangeIter to include this range - MemoryRange &used = *newRangeIter; - used.begin = std::min(used.begin, range.begin); - used.end = std::max(used.end, range.end); - - // Remove this entry - iter = m_WrittenMemory.erase(iter); - } - } - else - { - ++iter; - } - } - - if (newRangeIter == m_WrittenMemory.end()) - { - MemoryRange range; - range.begin = address; - range.end = end; - - m_WrittenMemory.push_back(range); - } +// Copyright (C) 2003 Dolphin Project. + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, version 2.0. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License 2.0 for more details. + +// A copy of the GPL 2.0 should have been included with the program. +// If not, see http://www.gnu.org/licenses/ + +// Official SVN repository and contact information can be found at +// http://code.google.com/p/dolphin-emu/ + +#include "FifoAnalyzer.h" +#include "FifoDataFile.h" +#include "FifoPlaybackAnalyzer.h" + +#include "Common.h" + +#include "OpcodeDecoding.h" +#include "TextureDecoder.h" +#include "VertexLoader.h" + +using namespace std; +using namespace FifoAnalyzer; + +// For debugging +#define LOG_FIFO_CMDS 0 +struct CmdData +{ + u32 size; + u32 offset; + u8 *ptr; +}; + +FifoPlaybackAnalyzer::FifoPlaybackAnalyzer() +{ + FifoAnalyzer::Init(); +} + +void FifoPlaybackAnalyzer::AnalyzeFrames(FifoDataFile *file, std::vector &frameInfo) +{ + // Load BP memory + u32 *bpMem = file->GetBPMem(); + memcpy(&m_BpMem, bpMem, sizeof(BPMemory)); + + u32 *cpMem = file->GetCPMem(); + FifoAnalyzer::LoadCPReg(0x50, cpMem[0x50], m_CpMem); + FifoAnalyzer::LoadCPReg(0x60, cpMem[0x60], m_CpMem); + + for (int i = 0; i < 8; ++i) + { + FifoAnalyzer::LoadCPReg(0x70 + i, cpMem[0x70 + i], m_CpMem); + FifoAnalyzer::LoadCPReg(0x80 + i, cpMem[0x80 + i], m_CpMem); + FifoAnalyzer::LoadCPReg(0x90 + i, cpMem[0x90 + i], m_CpMem); + } + + frameInfo.clear(); + frameInfo.resize(file->GetFrameCount()); + + for (int frameIdx = 0; frameIdx < file->GetFrameCount(); ++frameIdx) + { + const FifoFrameInfo& frame = file->GetFrame(frameIdx); + AnalyzedFrameInfo& analyzed = frameInfo[frameIdx]; + + m_DrawingObject = false; + + u32 cmdStart = 0; + u32 nextMemUpdate = 0; + + // Debugging + vector prevCmds; + + while (cmdStart < frame.fifoDataSize) + { + // Add memory updates that have occured before this point in the frame + while (nextMemUpdate < frame.memoryUpdates.size() && frame.memoryUpdates[nextMemUpdate].fifoPosition <= cmdStart) + { + AddMemoryUpdate(frame.memoryUpdates[nextMemUpdate], analyzed); + ++nextMemUpdate; + } + + bool wasDrawing = m_DrawingObject; + + u32 cmdSize = DecodeCommand(&frame.fifoData[cmdStart]); + +#if (LOG_FIFO_CMDS) + CmdData cmdData; + cmdData.offset = cmdStart; + cmdData.ptr = &frame.fifoData[cmdStart]; + cmdData.size = cmdSize; + prevCmds.push_back(cmdData); +#endif + + // Check for error + if (cmdSize == 0) + { + // Clean up frame analysis + analyzed.objectStarts.clear(); + analyzed.objectEnds.clear(); + + return; + } + + if (wasDrawing != m_DrawingObject) + { + if (m_DrawingObject) + analyzed.objectStarts.push_back(cmdStart); + else + analyzed.objectEnds.push_back(cmdStart); + } + + cmdStart += cmdSize; + } + + if (analyzed.objectEnds.size() < analyzed.objectStarts.size()) + analyzed.objectEnds.push_back(cmdStart); + } +} + +void FifoPlaybackAnalyzer::AddMemoryUpdate(MemoryUpdate memUpdate, AnalyzedFrameInfo &frameInfo) +{ + u32 begin = memUpdate.address; + u32 end = memUpdate.address + memUpdate.size; + + // Remove portions of memUpdate that overlap with memory ranges that have been written by the GP + for (unsigned int i = 0; i < m_WrittenMemory.size(); ++i) + { + const MemoryRange &range = m_WrittenMemory[i]; + + if (range.begin < end && + range.end > begin) + { + s32 preSize = range.begin - begin; + s32 postSize = end - range.end; + + if (postSize > 0) + { + if (preSize > 0) + { + memUpdate.size = preSize; + AddMemoryUpdate(memUpdate, frameInfo); + } + + u32 bytesToRangeEnd = range.end - memUpdate.address; + memUpdate.data += bytesToRangeEnd; + memUpdate.size = postSize; + memUpdate.address = range.end; + } + else if (preSize > 0) + { + memUpdate.size = preSize; + } + else + { + // Ignore all of memUpdate + return; + } + } + } + + frameInfo.memoryUpdates.push_back(memUpdate); +} + +u32 FifoPlaybackAnalyzer::DecodeCommand(u8 *data) +{ + u8 *dataStart = data; + + int cmd = ReadFifo8(data); + + switch(cmd) + { + case GX_NOP: + case 0x44: + case GX_CMD_INVL_VC: + break; + + case GX_LOAD_CP_REG: + { + m_DrawingObject = false; + + u32 cmd2 = ReadFifo8(data); + u32 value = ReadFifo32(data); + FifoAnalyzer::LoadCPReg(cmd2, value, m_CpMem); + } + break; + + case GX_LOAD_XF_REG: + { + m_DrawingObject = false; + + u32 cmd2 = ReadFifo32(data); + u8 streamSize = ((cmd2 >> 16) & 15) + 1; + + data += streamSize * 4; + } + break; + + case GX_LOAD_INDX_A: + case GX_LOAD_INDX_B: + case GX_LOAD_INDX_C: + case GX_LOAD_INDX_D: + m_DrawingObject = false; + data += 4; + break; + + case GX_CMD_CALL_DL: + // The recorder should have expanded display lists into the fifo stream and skipped the call to start them + // That is done to make it easier to track where memory is updated + _assert_(false); + data += 8; + break; + + case GX_LOAD_BP_REG: + { + m_DrawingObject = false; + + u32 cmd2 = ReadFifo32(data); + BPCmd bp = FifoAnalyzer::DecodeBPCmd(cmd2, m_BpMem); + + FifoAnalyzer::LoadBPReg(bp, m_BpMem); + + if (bp.address == BPMEM_TRIGGER_EFB_COPY) + StoreEfbCopyRegion(); + } + break; + + default: + if (cmd & 0x80) + { + m_DrawingObject = true; + + u32 vtxAttrGroup = cmd & GX_VAT_MASK; + int vertexSize = FifoAnalyzer::CalculateVertexSize(vtxAttrGroup, m_CpMem); + + u16 streamSize = ReadFifo16(data); + + data += streamSize * vertexSize; + } + else + { + PanicAlert("FifoPlayer: Unknown Opcode (0x%x).\nAborting frame analysis.\n", cmd); + return 0; + } + break; + } + + return data - dataStart; +} + +void FifoPlaybackAnalyzer::StoreEfbCopyRegion() +{ + UPE_Copy peCopy = m_BpMem.triggerEFBCopy; + + u32 copyfmt = peCopy.tp_realFormat(); + bool bFromZBuffer = m_BpMem.zcontrol.pixel_format == PIXELFMT_Z24; + u32 address = bpmem.copyTexDest << 5; + + u32 format = copyfmt; + + if (peCopy.copy_to_xfb) + { + // Fake format to calculate size correctly + format = GX_TF_IA8; + } + else if (bFromZBuffer) + { + format |= _GX_TF_ZTF; + if (copyfmt == 11) + format = GX_TF_Z16; + else if (format < GX_TF_Z8 || format > GX_TF_Z24X8) + format |= _GX_TF_CTF; + } + else + { + if (copyfmt > GX_TF_RGBA8 || (copyfmt < GX_TF_RGB565 && !peCopy.intensity_fmt)) + format |= _GX_TF_CTF; + } + + int width = (m_BpMem.copyTexSrcWH.x + 1) >> peCopy.half_scale; + int height = (m_BpMem.copyTexSrcWH.y + 1) >> peCopy.half_scale; + + u16 blkW = TexDecoder_GetBlockWidthInTexels(format) - 1; + u16 blkH = TexDecoder_GetBlockHeightInTexels(format) - 1; + + s32 expandedWidth = (width + blkW) & (~blkW); + s32 expandedHeight = (height + blkH) & (~blkH); + + int sizeInBytes = TexDecoder_GetTextureSizeInBytes(expandedWidth, expandedHeight, format); + + StoreWrittenRegion(address, sizeInBytes); +} + +void FifoPlaybackAnalyzer::StoreWrittenRegion(u32 address, u32 size) +{ + u32 end = address + size; + vector::iterator newRangeIter = m_WrittenMemory.end(); + + // Search for overlapping memory regions and expand them to include the new region + for (vector::iterator iter = m_WrittenMemory.begin(); iter != m_WrittenMemory.end();) + { + MemoryRange &range = *iter; + + if (range.begin < end && range.end > address) + { + // range at iterator and new range overlap + + if (newRangeIter == m_WrittenMemory.end()) + { + // Expand range to include the written region + range.begin = std::min(address, range.begin); + range.end = std::max(end, range.end); + newRangeIter = iter; + + ++iter; + } + else + { + // Expand region at rangeIter to include this range + MemoryRange &used = *newRangeIter; + used.begin = std::min(used.begin, range.begin); + used.end = std::max(used.end, range.end); + + // Remove this entry + iter = m_WrittenMemory.erase(iter); + } + } + else + { + ++iter; + } + } + + if (newRangeIter == m_WrittenMemory.end()) + { + MemoryRange range; + range.begin = address; + range.end = end; + + m_WrittenMemory.push_back(range); + } } \ No newline at end of file diff --git a/Source/Core/Core/Src/FifoPlayer/FifoPlaybackAnalyzer.h b/Source/Core/Core/Src/FifoPlayer/FifoPlaybackAnalyzer.h index 8c779d818d..e8e582cf4c 100644 --- a/Source/Core/Core/Src/FifoPlayer/FifoPlaybackAnalyzer.h +++ b/Source/Core/Core/Src/FifoPlayer/FifoPlaybackAnalyzer.h @@ -1,64 +1,64 @@ -// Copyright (C) 2003 Dolphin Project. - -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, version 2.0. - -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License 2.0 for more details. - -// A copy of the GPL 2.0 should have been included with the program. -// If not, see http://www.gnu.org/licenses/ - -// Official SVN repository and contact information can be found at -// http://code.google.com/p/dolphin-emu/ - -#ifndef _FIFOPLAYBACKANALYZER_H_ -#define _FIFOPLAYBACKANALYZER_H_ - -#include "FifoAnalyzer.h" -#include "FifoDataFile.h" - -#include -#include - -struct AnalyzedFrameInfo -{ - std::vector objectStarts; - std::vector objectEnds; - std::vector memoryUpdates; -}; - -class FifoPlaybackAnalyzer -{ -public: - FifoPlaybackAnalyzer(); - - void AnalyzeFrames(FifoDataFile *file, std::vector &frameInfo); - -private: - struct MemoryRange - { - u32 begin; - u32 end; - }; - - void AddMemoryUpdate(MemoryUpdate memUpdate, AnalyzedFrameInfo &frameInfo); - - u32 DecodeCommand(u8 *data); - void LoadBP(u32 value0); - - void StoreEfbCopyRegion(); - void StoreWrittenRegion(u32 address, u32 size); - - bool m_DrawingObject; - - std::vector m_WrittenMemory; - - BPMemory m_BpMem; - FifoAnalyzer::CPMemory m_CpMem; -}; - +// Copyright (C) 2003 Dolphin Project. + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, version 2.0. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License 2.0 for more details. + +// A copy of the GPL 2.0 should have been included with the program. +// If not, see http://www.gnu.org/licenses/ + +// Official SVN repository and contact information can be found at +// http://code.google.com/p/dolphin-emu/ + +#ifndef _FIFOPLAYBACKANALYZER_H_ +#define _FIFOPLAYBACKANALYZER_H_ + +#include "FifoAnalyzer.h" +#include "FifoDataFile.h" + +#include +#include + +struct AnalyzedFrameInfo +{ + std::vector objectStarts; + std::vector objectEnds; + std::vector memoryUpdates; +}; + +class FifoPlaybackAnalyzer +{ +public: + FifoPlaybackAnalyzer(); + + void AnalyzeFrames(FifoDataFile *file, std::vector &frameInfo); + +private: + struct MemoryRange + { + u32 begin; + u32 end; + }; + + void AddMemoryUpdate(MemoryUpdate memUpdate, AnalyzedFrameInfo &frameInfo); + + u32 DecodeCommand(u8 *data); + void LoadBP(u32 value0); + + void StoreEfbCopyRegion(); + void StoreWrittenRegion(u32 address, u32 size); + + bool m_DrawingObject; + + std::vector m_WrittenMemory; + + BPMemory m_BpMem; + FifoAnalyzer::CPMemory m_CpMem; +}; + #endif \ No newline at end of file diff --git a/Source/Core/Core/Src/FifoPlayer/FifoRecordAnalyzer.cpp b/Source/Core/Core/Src/FifoPlayer/FifoRecordAnalyzer.cpp index a8214a82c0..bb7b8e3d04 100644 --- a/Source/Core/Core/Src/FifoPlayer/FifoRecordAnalyzer.cpp +++ b/Source/Core/Core/Src/FifoPlayer/FifoRecordAnalyzer.cpp @@ -1,305 +1,305 @@ -// Copyright (C) 2003 Dolphin Project. - -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, version 2.0. - -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License 2.0 for more details. - -// A copy of the GPL 2.0 should have been included with the program. -// If not, see http://www.gnu.org/licenses/ - -// Official SVN repository and contact information can be found at -// http://code.google.com/p/dolphin-emu/ - -#include "FifoAnalyzer.h" -#include "FifoRecordAnalyzer.h" -#include "FifoRecorder.h" - -#include "Core.h" -#include "HW/Memmap.h" - -#include "OpcodeDecoding.h" -#include "TextureDecoder.h" - -using namespace FifoAnalyzer; - - -FifoRecordAnalyzer::FifoRecordAnalyzer() : - m_DrawingObject(false), - m_BpMem(NULL) -{ -} - -void FifoRecordAnalyzer::Initialize(u32 *bpMem, u32 *cpMem) -{ - m_DrawingObject = false; - - m_BpMem = (BPMemory*)bpMem; - - FifoAnalyzer::LoadCPReg(0x50, *(cpMem + 0x50), m_CpMem); - FifoAnalyzer::LoadCPReg(0x60, *(cpMem + 0x60), m_CpMem); - for (int i = 0; i < 8; ++i) - FifoAnalyzer::LoadCPReg(0x70 + i, *(cpMem + 0x70 + i), m_CpMem); - - memcpy(m_CpMem.arrayBases, cpMem + 0xA0, 16 * 4); - memcpy(m_CpMem.arrayStrides, cpMem + 0xB0, 16 * 4); -} - -void FifoRecordAnalyzer::AnalyzeGPCommand(u8 *data) -{ - DecodeOpcode(data); -} - -void FifoRecordAnalyzer::DecodeOpcode(u8 *data) -{ - int cmd = ReadFifo8(data); - - switch (cmd) - { - case GX_NOP: - case 0x44: - case GX_CMD_INVL_VC: - break; - - case GX_LOAD_CP_REG: - { - m_DrawingObject = false; - - u32 cmd2 = ReadFifo8(data); - u32 value = ReadFifo32(data); - FifoAnalyzer::LoadCPReg(cmd2, value, m_CpMem); - } - - break; - - case GX_LOAD_XF_REG: - m_DrawingObject = false; - break; - - case GX_LOAD_INDX_A: - m_DrawingObject = false; - ProcessLoadIndexedXf(ReadFifo32(data), 0xc); - break; - case GX_LOAD_INDX_B: - m_DrawingObject = false; - ProcessLoadIndexedXf(ReadFifo32(data), 0xd); - break; - case GX_LOAD_INDX_C: - m_DrawingObject = false; - ProcessLoadIndexedXf(ReadFifo32(data), 0xe); - break; - case GX_LOAD_INDX_D: - m_DrawingObject = false; - ProcessLoadIndexedXf(ReadFifo32(data), 0xf); - break; - - case GX_CMD_CALL_DL: - { - // The recorder should have expanded display lists into the fifo stream and skipped the call to start them - // That is done to make it easier to track where memory is updated - _assert_(false); - } - break; - - case GX_LOAD_BP_REG: - { - m_DrawingObject = false; - - u32 cmd2 = ReadFifo32(data); - BPCmd bp = FifoAnalyzer::DecodeBPCmd(cmd2, *m_BpMem); - - if (bp.address == BPMEM_LOADTLUT1) - ProcessLoadTlut1(); - } - break; - - default: - if (cmd & 0x80) - { - if (!m_DrawingObject) - { - m_DrawingObject = true; - ProcessTexMaps(); - } - - ProcessVertexArrays(data, cmd & GX_VAT_MASK); - } - else - { - PanicAlert("FifoRecordAnalyzer: Unknown Opcode (0x%x).\n", cmd); - } - } -} - -void FifoRecordAnalyzer::ProcessLoadTlut1() -{ - u32 tlutXferCount; - u32 tlutMemAddr; - u32 memAddr; - - GetTlutLoadData(tlutMemAddr, memAddr, tlutXferCount, *m_BpMem); - - FifoRecorder::GetInstance().WriteMemory(memAddr, tlutXferCount, MemoryUpdate::TLUT); -} - -void FifoRecordAnalyzer::ProcessLoadIndexedXf(u32 val, int array) -{ - int index = val >> 16; - int size = ((val >> 12) & 0xF) + 1; - - u32 address = m_CpMem.arrayBases[array] + m_CpMem.arrayStrides[array] * index; - - FifoRecorder::GetInstance().WriteMemory(address, size * 4, MemoryUpdate::XF_DATA); -} - -void FifoRecordAnalyzer::ProcessVertexArrays(u8 *data, u8 vtxAttrGroup) -{ - int sizes[21]; - FifoAnalyzer::CalculateVertexElementSizes(sizes, vtxAttrGroup, m_CpMem); - - // Determine offset of each element from start of vertex data - int offsets[12]; - int offset = 0; - for (int i = 0; i < 12; ++i) - { - offsets[i] = offset; - offset += sizes[i + 9]; - } - - int vertexSize = offset; - int numVertices = ReadFifo16(data); - - if (numVertices > 0) - { - for (int i = 0; i < 12; ++i) - { - WriteVertexArray(i, data + offsets[i], vertexSize, numVertices); - } - } -} - -void FifoRecordAnalyzer::WriteVertexArray(int arrayIndex, u8 *vertexData, int vertexSize, int numVertices) -{ - // Skip if not indexed array - int arrayType = (m_CpMem.vtxDesc.Hex >> (9 + (arrayIndex * 2))) & 3; - if (arrayType < 2) - return; - - int maxIndex = 0; - - // Determine min and max indices - if (arrayType == INDEX8) - { - for (int i = 0; i < numVertices; ++i) - { - int index = *vertexData; - vertexData += vertexSize; - - // 0xff skips the vertex - if (index != 0xff) - { - if (index > maxIndex) - maxIndex = index; - } - } - } - else - { - for (int i = 0; i < numVertices; ++i) - { - int index = Common::swap16(vertexData); - vertexData += vertexSize; - - // 0xffff skips the vertex - if (index != 0xffff) - { - if (index > maxIndex) - maxIndex = index; - } - } - } - - u32 arrayStart = m_CpMem.arrayBases[arrayIndex]; - u32 arraySize = m_CpMem.arrayStrides[arrayIndex] * (maxIndex + 1); - - FifoRecorder::GetInstance().WriteMemory(arrayStart, arraySize, MemoryUpdate::VERTEX_STREAM); -} - -void FifoRecordAnalyzer::ProcessTexMaps() -{ - u32 writtenTexMaps = 0; - - // Texture maps used in TEV indirect stages - for (u32 i = 0; i < m_BpMem->genMode.numindstages; ++i) - { - u32 texMap = m_BpMem->tevindref.getTexMap(i); - - WriteTexMapMemory(texMap, writtenTexMaps); - } - - // Texture maps used in TEV direct stages - for (u32 i = 0; i <= m_BpMem->genMode.numtevstages; ++i) - { - int stageNum2 = i >> 1; - int stageOdd = i & 1; - TwoTevStageOrders &order = m_BpMem->tevorders[stageNum2]; - int texMap = order.getTexMap(stageOdd); - - if (order.getEnable(stageOdd)) - WriteTexMapMemory(texMap, writtenTexMaps); - } -} - -void FifoRecordAnalyzer::WriteTexMapMemory(int texMap, u32 &writtenTexMaps) -{ - // Avoid rechecking the same texture map - u32 texMapMask = 1 << texMap; - if (writtenTexMaps & texMapMask) - return; - - writtenTexMaps |= texMapMask; - - FourTexUnits& texUnit = m_BpMem->tex[(texMap >> 2) & 1]; - u8 subTexmap = texMap & 3; - - TexImage0& ti0 = texUnit.texImage0[subTexmap]; - - u32 width = ti0.width + 1; - u32 height = ti0.height + 1; - u32 imageBase = texUnit.texImage3[subTexmap].image_base << 5; - - u32 fmtWidth = TexDecoder_GetBlockWidthInTexels(ti0.format) - 1; - u32 fmtHeight = TexDecoder_GetBlockHeightInTexels(ti0.format) - 1; - int fmtDepth = TexDecoder_GetTexelSizeInNibbles(ti0.format); - - // Round width and height up to the next block - width = (width + fmtWidth) & (~fmtWidth); - height = (height + fmtHeight) & (~fmtHeight); - - u32 textureSize = (width * height * fmtDepth) / 2; - - // TODO: mip maps - int mip = texUnit.texMode1[subTexmap].max_lod; - if ((texUnit.texMode0[subTexmap].min_filter & 3) == 0) - mip = 0; - - while (mip) - { - width >>= 1; - height >>= 1; - - width = max(width, fmtWidth); - height = max(height, fmtHeight); - u32 size = (width * height * fmtDepth) >> 1; - - textureSize += size; - - mip--; - } - - FifoRecorder::GetInstance().WriteMemory(imageBase, textureSize, MemoryUpdate::TEXTURE_MAP); +// Copyright (C) 2003 Dolphin Project. + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, version 2.0. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License 2.0 for more details. + +// A copy of the GPL 2.0 should have been included with the program. +// If not, see http://www.gnu.org/licenses/ + +// Official SVN repository and contact information can be found at +// http://code.google.com/p/dolphin-emu/ + +#include "FifoAnalyzer.h" +#include "FifoRecordAnalyzer.h" +#include "FifoRecorder.h" + +#include "Core.h" +#include "HW/Memmap.h" + +#include "OpcodeDecoding.h" +#include "TextureDecoder.h" + +using namespace FifoAnalyzer; + + +FifoRecordAnalyzer::FifoRecordAnalyzer() : + m_DrawingObject(false), + m_BpMem(NULL) +{ +} + +void FifoRecordAnalyzer::Initialize(u32 *bpMem, u32 *cpMem) +{ + m_DrawingObject = false; + + m_BpMem = (BPMemory*)bpMem; + + FifoAnalyzer::LoadCPReg(0x50, *(cpMem + 0x50), m_CpMem); + FifoAnalyzer::LoadCPReg(0x60, *(cpMem + 0x60), m_CpMem); + for (int i = 0; i < 8; ++i) + FifoAnalyzer::LoadCPReg(0x70 + i, *(cpMem + 0x70 + i), m_CpMem); + + memcpy(m_CpMem.arrayBases, cpMem + 0xA0, 16 * 4); + memcpy(m_CpMem.arrayStrides, cpMem + 0xB0, 16 * 4); +} + +void FifoRecordAnalyzer::AnalyzeGPCommand(u8 *data) +{ + DecodeOpcode(data); +} + +void FifoRecordAnalyzer::DecodeOpcode(u8 *data) +{ + int cmd = ReadFifo8(data); + + switch (cmd) + { + case GX_NOP: + case 0x44: + case GX_CMD_INVL_VC: + break; + + case GX_LOAD_CP_REG: + { + m_DrawingObject = false; + + u32 cmd2 = ReadFifo8(data); + u32 value = ReadFifo32(data); + FifoAnalyzer::LoadCPReg(cmd2, value, m_CpMem); + } + + break; + + case GX_LOAD_XF_REG: + m_DrawingObject = false; + break; + + case GX_LOAD_INDX_A: + m_DrawingObject = false; + ProcessLoadIndexedXf(ReadFifo32(data), 0xc); + break; + case GX_LOAD_INDX_B: + m_DrawingObject = false; + ProcessLoadIndexedXf(ReadFifo32(data), 0xd); + break; + case GX_LOAD_INDX_C: + m_DrawingObject = false; + ProcessLoadIndexedXf(ReadFifo32(data), 0xe); + break; + case GX_LOAD_INDX_D: + m_DrawingObject = false; + ProcessLoadIndexedXf(ReadFifo32(data), 0xf); + break; + + case GX_CMD_CALL_DL: + { + // The recorder should have expanded display lists into the fifo stream and skipped the call to start them + // That is done to make it easier to track where memory is updated + _assert_(false); + } + break; + + case GX_LOAD_BP_REG: + { + m_DrawingObject = false; + + u32 cmd2 = ReadFifo32(data); + BPCmd bp = FifoAnalyzer::DecodeBPCmd(cmd2, *m_BpMem); + + if (bp.address == BPMEM_LOADTLUT1) + ProcessLoadTlut1(); + } + break; + + default: + if (cmd & 0x80) + { + if (!m_DrawingObject) + { + m_DrawingObject = true; + ProcessTexMaps(); + } + + ProcessVertexArrays(data, cmd & GX_VAT_MASK); + } + else + { + PanicAlert("FifoRecordAnalyzer: Unknown Opcode (0x%x).\n", cmd); + } + } +} + +void FifoRecordAnalyzer::ProcessLoadTlut1() +{ + u32 tlutXferCount; + u32 tlutMemAddr; + u32 memAddr; + + GetTlutLoadData(tlutMemAddr, memAddr, tlutXferCount, *m_BpMem); + + FifoRecorder::GetInstance().WriteMemory(memAddr, tlutXferCount, MemoryUpdate::TLUT); +} + +void FifoRecordAnalyzer::ProcessLoadIndexedXf(u32 val, int array) +{ + int index = val >> 16; + int size = ((val >> 12) & 0xF) + 1; + + u32 address = m_CpMem.arrayBases[array] + m_CpMem.arrayStrides[array] * index; + + FifoRecorder::GetInstance().WriteMemory(address, size * 4, MemoryUpdate::XF_DATA); +} + +void FifoRecordAnalyzer::ProcessVertexArrays(u8 *data, u8 vtxAttrGroup) +{ + int sizes[21]; + FifoAnalyzer::CalculateVertexElementSizes(sizes, vtxAttrGroup, m_CpMem); + + // Determine offset of each element from start of vertex data + int offsets[12]; + int offset = 0; + for (int i = 0; i < 12; ++i) + { + offsets[i] = offset; + offset += sizes[i + 9]; + } + + int vertexSize = offset; + int numVertices = ReadFifo16(data); + + if (numVertices > 0) + { + for (int i = 0; i < 12; ++i) + { + WriteVertexArray(i, data + offsets[i], vertexSize, numVertices); + } + } +} + +void FifoRecordAnalyzer::WriteVertexArray(int arrayIndex, u8 *vertexData, int vertexSize, int numVertices) +{ + // Skip if not indexed array + int arrayType = (m_CpMem.vtxDesc.Hex >> (9 + (arrayIndex * 2))) & 3; + if (arrayType < 2) + return; + + int maxIndex = 0; + + // Determine min and max indices + if (arrayType == INDEX8) + { + for (int i = 0; i < numVertices; ++i) + { + int index = *vertexData; + vertexData += vertexSize; + + // 0xff skips the vertex + if (index != 0xff) + { + if (index > maxIndex) + maxIndex = index; + } + } + } + else + { + for (int i = 0; i < numVertices; ++i) + { + int index = Common::swap16(vertexData); + vertexData += vertexSize; + + // 0xffff skips the vertex + if (index != 0xffff) + { + if (index > maxIndex) + maxIndex = index; + } + } + } + + u32 arrayStart = m_CpMem.arrayBases[arrayIndex]; + u32 arraySize = m_CpMem.arrayStrides[arrayIndex] * (maxIndex + 1); + + FifoRecorder::GetInstance().WriteMemory(arrayStart, arraySize, MemoryUpdate::VERTEX_STREAM); +} + +void FifoRecordAnalyzer::ProcessTexMaps() +{ + u32 writtenTexMaps = 0; + + // Texture maps used in TEV indirect stages + for (u32 i = 0; i < m_BpMem->genMode.numindstages; ++i) + { + u32 texMap = m_BpMem->tevindref.getTexMap(i); + + WriteTexMapMemory(texMap, writtenTexMaps); + } + + // Texture maps used in TEV direct stages + for (u32 i = 0; i <= m_BpMem->genMode.numtevstages; ++i) + { + int stageNum2 = i >> 1; + int stageOdd = i & 1; + TwoTevStageOrders &order = m_BpMem->tevorders[stageNum2]; + int texMap = order.getTexMap(stageOdd); + + if (order.getEnable(stageOdd)) + WriteTexMapMemory(texMap, writtenTexMaps); + } +} + +void FifoRecordAnalyzer::WriteTexMapMemory(int texMap, u32 &writtenTexMaps) +{ + // Avoid rechecking the same texture map + u32 texMapMask = 1 << texMap; + if (writtenTexMaps & texMapMask) + return; + + writtenTexMaps |= texMapMask; + + FourTexUnits& texUnit = m_BpMem->tex[(texMap >> 2) & 1]; + u8 subTexmap = texMap & 3; + + TexImage0& ti0 = texUnit.texImage0[subTexmap]; + + u32 width = ti0.width + 1; + u32 height = ti0.height + 1; + u32 imageBase = texUnit.texImage3[subTexmap].image_base << 5; + + u32 fmtWidth = TexDecoder_GetBlockWidthInTexels(ti0.format) - 1; + u32 fmtHeight = TexDecoder_GetBlockHeightInTexels(ti0.format) - 1; + int fmtDepth = TexDecoder_GetTexelSizeInNibbles(ti0.format); + + // Round width and height up to the next block + width = (width + fmtWidth) & (~fmtWidth); + height = (height + fmtHeight) & (~fmtHeight); + + u32 textureSize = (width * height * fmtDepth) / 2; + + // TODO: mip maps + int mip = texUnit.texMode1[subTexmap].max_lod; + if ((texUnit.texMode0[subTexmap].min_filter & 3) == 0) + mip = 0; + + while (mip) + { + width >>= 1; + height >>= 1; + + width = max(width, fmtWidth); + height = max(height, fmtHeight); + u32 size = (width * height * fmtDepth) >> 1; + + textureSize += size; + + mip--; + } + + FifoRecorder::GetInstance().WriteMemory(imageBase, textureSize, MemoryUpdate::TEXTURE_MAP); } \ No newline at end of file diff --git a/Source/Core/Core/Src/FifoPlayer/FifoRecordAnalyzer.h b/Source/Core/Core/Src/FifoPlayer/FifoRecordAnalyzer.h index acfbbc38b5..ccec314272 100644 --- a/Source/Core/Core/Src/FifoPlayer/FifoRecordAnalyzer.h +++ b/Source/Core/Core/Src/FifoPlayer/FifoRecordAnalyzer.h @@ -1,56 +1,56 @@ -// Copyright (C) 2003 Dolphin Project. - -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, version 2.0. - -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License 2.0 for more details. - -// A copy of the GPL 2.0 should have been included with the program. -// If not, see http://www.gnu.org/licenses/ - -// Official SVN repository and contact information can be found at -// http://code.google.com/p/dolphin-emu/ - -#ifndef _FIFORECORDANALYZER_H_ -#define _FIFORECORDANALYZER_H_ - -#include "FifoAnalyzer.h" - -#include "Common.h" - -#include "BPMemory.h" - -class FifoRecordAnalyzer -{ -public: - FifoRecordAnalyzer(); - - // Must call this before analyzing GP commands - void Initialize(u32 *bpMem, u32 *cpMem); - - // Assumes data contains all information for the command - // Calls FifoRecorder::WriteMemory - void AnalyzeGPCommand(u8 *data); - -private: - void DecodeOpcode(u8 *data); - - void ProcessLoadTlut1(); - void ProcessLoadIndexedXf(u32 val, int array); - void ProcessVertexArrays(u8 *data, u8 vtxAttrGroup); - void ProcessTexMaps(); - - void WriteVertexArray(int arrayIndex, u8 *vertexData, int vertexSize, int numVertices); - void WriteTexMapMemory(int texMap, u32 &writtenTexMaps); - - bool m_DrawingObject; - - BPMemory *m_BpMem; - FifoAnalyzer::CPMemory m_CpMem; -}; - +// Copyright (C) 2003 Dolphin Project. + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, version 2.0. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License 2.0 for more details. + +// A copy of the GPL 2.0 should have been included with the program. +// If not, see http://www.gnu.org/licenses/ + +// Official SVN repository and contact information can be found at +// http://code.google.com/p/dolphin-emu/ + +#ifndef _FIFORECORDANALYZER_H_ +#define _FIFORECORDANALYZER_H_ + +#include "FifoAnalyzer.h" + +#include "Common.h" + +#include "BPMemory.h" + +class FifoRecordAnalyzer +{ +public: + FifoRecordAnalyzer(); + + // Must call this before analyzing GP commands + void Initialize(u32 *bpMem, u32 *cpMem); + + // Assumes data contains all information for the command + // Calls FifoRecorder::WriteMemory + void AnalyzeGPCommand(u8 *data); + +private: + void DecodeOpcode(u8 *data); + + void ProcessLoadTlut1(); + void ProcessLoadIndexedXf(u32 val, int array); + void ProcessVertexArrays(u8 *data, u8 vtxAttrGroup); + void ProcessTexMaps(); + + void WriteVertexArray(int arrayIndex, u8 *vertexData, int vertexSize, int numVertices); + void WriteTexMapMemory(int texMap, u32 &writtenTexMaps); + + bool m_DrawingObject; + + BPMemory *m_BpMem; + FifoAnalyzer::CPMemory m_CpMem; +}; + #endif \ No newline at end of file diff --git a/Source/Core/DolphinWX/SConscript b/Source/Core/DolphinWX/SConscript index 46502c3c60..a5a62bb558 100644 --- a/Source/Core/DolphinWX/SConscript +++ b/Source/Core/DolphinWX/SConscript @@ -28,6 +28,7 @@ else: 'Src/Debugger/MemoryWindow.cpp', 'Src/Debugger/RegisterView.cpp', 'Src/Debugger/RegisterWindow.cpp', + 'Src/FifoPlayerDlg.cpp', 'Src/Frame.cpp', 'Src/FrameAui.cpp', 'Src/FrameTools.cpp',