diff --git a/Source/Core/Core/FifoPlayer/FifoAnalyzer.cpp b/Source/Core/Core/FifoPlayer/FifoAnalyzer.cpp index f7f70d5b1d9c..05eb13cce5ce 100644 --- a/Source/Core/Core/FifoPlayer/FifoAnalyzer.cpp +++ b/Source/Core/Core/FifoPlayer/FifoAnalyzer.cpp @@ -19,34 +19,34 @@ void Init() VertexLoader_Normal::Init(); } -u8 ReadFifo8(u8 *&data) +u8 ReadFifo8(u8*& data) { u8 value = data[0]; data += 1; return value; } -u16 ReadFifo16(u8 *&data) +u16 ReadFifo16(u8*& data) { u16 value = Common::swap16(data); data += 2; return value; } -u32 ReadFifo32(u8 *&data) +u32 ReadFifo32(u8*& data) { u32 value = Common::swap32(data); data += 4; return value; } -void InitBPMemory(BPMemory *bpMem) +void InitBPMemory(BPMemory* bpMem) { memset(bpMem, 0, sizeof(BPMemory)); bpMem->bpMask = 0x00FFFFFF; } -BPCmd DecodeBPCmd(u32 value, const BPMemory &bpMem) +BPCmd DecodeBPCmd(u32 value, const BPMemory& bpMem) { //handle the mask register int opcode = value >> 24; @@ -59,7 +59,7 @@ BPCmd DecodeBPCmd(u32 value, const BPMemory &bpMem) return bp; } -void LoadBPReg(const BPCmd &bp, BPMemory &bpMem) +void LoadBPReg(const BPCmd& bp, BPMemory& bpMem) { ((u32*)&bpMem)[bp.address] = bp.newvalue; @@ -68,19 +68,7 @@ void LoadBPReg(const BPCmd &bp, BPMemory &bpMem) bpMem.bpMask = 0xFFFFFF; } -void GetTlutLoadData(u32 &tlutAddr, u32 &memAddr, u32 &tlutXferCount, BPMemory &bpMem) -{ - tlutAddr = (bpMem.tmem_config.tlut_dest & 0x3FF) << 9; - tlutXferCount = (bpMem.tmem_config.tlut_dest & 0x1FFC00) >> 5; - - // TODO - figure out a cleaner way. - if (SConfig::GetInstance().bWii) - memAddr = bpMem.tmem_config.tlut_src << 5; - else - memAddr = (bpMem.tmem_config.tlut_src & 0xFFFFF) << 5; -} - -void LoadCPReg(u32 subCmd, u32 value, CPMemory &cpMem) +void LoadCPReg(u32 subCmd, u32 value, CPMemory& cpMem) { switch (subCmd & 0xF0) { @@ -119,7 +107,7 @@ void LoadCPReg(u32 subCmd, u32 value, CPMemory &cpMem) } } -u32 CalculateVertexSize(int vatIndex, const CPMemory &cpMem) +u32 CalculateVertexSize(int vatIndex, const CPMemory& cpMem) { u32 vertexSize = 0; @@ -132,7 +120,7 @@ u32 CalculateVertexSize(int vatIndex, const CPMemory &cpMem) return vertexSize; } -void CalculateVertexElementSizes(int sizes[], int vatIndex, const CPMemory &cpMem) +void CalculateVertexElementSizes(int sizes[], int vatIndex, const CPMemory& cpMem) { const TVtxDesc &vtxDesc = cpMem.vtxDesc; const VAT &vtxAttr = cpMem.vtxAttr[vatIndex]; diff --git a/Source/Core/Core/FifoPlayer/FifoAnalyzer.h b/Source/Core/Core/FifoPlayer/FifoAnalyzer.h index 98234d00d31d..fed230ba5c52 100644 --- a/Source/Core/Core/FifoPlayer/FifoAnalyzer.h +++ b/Source/Core/Core/FifoPlayer/FifoAnalyzer.h @@ -13,15 +13,15 @@ namespace FifoAnalyzer { void Init(); - u8 ReadFifo8(u8 *&data); - u16 ReadFifo16(u8 *&data); - u32 ReadFifo32(u8 *&data); + u8 ReadFifo8(u8*& data); + u16 ReadFifo16(u8*& data); + u32 ReadFifo32(u8*& data); // TODO- move to video common - void InitBPMemory(BPMemory *bpMem); + 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); + void LoadBPReg(const BPCmd& bp, BPMemory &bpMem); + void GetTlutLoadData(u32& tlutAddr, u32 &memAddr, u32 &tlutXferCount, BPMemory &bpMem); struct CPMemory { @@ -31,8 +31,8 @@ namespace FifoAnalyzer u32 arrayStrides[16]; }; - void LoadCPReg(u32 subCmd, u32 value, CPMemory &cpMem); + void LoadCPReg(u32 subCmd, u32 value, CPMemory& cpMem); - u32 CalculateVertexSize(int vatIndex, const CPMemory &cpMem); - void CalculateVertexElementSizes(int sizes[], int vatIndex, const CPMemory &cpMem); + u32 CalculateVertexSize(int vatIndex, const CPMemory& cpMem); + void CalculateVertexElementSizes(int sizes[], int vatIndex, const CPMemory& cpMem); } diff --git a/Source/Core/Core/FifoPlayer/FifoDataFile.cpp b/Source/Core/Core/FifoPlayer/FifoDataFile.cpp index 7281018d3eaf..1c9b029daf51 100644 --- a/Source/Core/Core/FifoPlayer/FifoDataFile.cpp +++ b/Source/Core/Core/FifoPlayer/FifoDataFile.cpp @@ -28,6 +28,11 @@ FifoDataFile::~FifoDataFile() } } +bool FifoDataFile::HasBrokenEFBCopies() const +{ + return version < 2; +} + void FifoDataFile::SetIsWii(bool isWii) { SetFlag(FLAG_IS_WII, isWii); @@ -38,7 +43,7 @@ bool FifoDataFile::GetIsWii() const return GetFlag(FLAG_IS_WII); } -void FifoDataFile::AddFrame(const FifoFrameInfo &frameInfo) +void FifoDataFile::AddFrame(const FifoFrameInfo& frameInfo) { m_Frames.push_back(frameInfo); } @@ -126,7 +131,7 @@ bool FifoDataFile::Save(const std::string& filename) return true; } -FifoDataFile *FifoDataFile::Load(const std::string &filename, bool flagsOnly) +FifoDataFile* FifoDataFile::Load(const std::string &filename, bool flagsOnly) { File::IOFile file; file.Open(filename, "rb"); @@ -214,7 +219,7 @@ bool FifoDataFile::GetFlag(u32 flag) const return !!(m_Flags & flag); } -u64 FifoDataFile::WriteMemoryUpdates(const std::vector &memUpdates, File::IOFile &file) +u64 FifoDataFile::WriteMemoryUpdates(const std::vector& memUpdates, File::IOFile& file) { // Add space for memory update list u64 updateListOffset = file.Tell(); @@ -244,7 +249,7 @@ u64 FifoDataFile::WriteMemoryUpdates(const std::vector &memUpdates return updateListOffset; } -void FifoDataFile::ReadMemoryUpdates(u64 fileOffset, u32 numUpdates, std::vector &memUpdates, File::IOFile &file) +void FifoDataFile::ReadMemoryUpdates(u64 fileOffset, u32 numUpdates, std::vector& memUpdates, File::IOFile& file) { memUpdates.resize(numUpdates); @@ -255,7 +260,7 @@ void FifoDataFile::ReadMemoryUpdates(u64 fileOffset, u32 numUpdates, std::vector FileMemoryUpdate srcUpdate; file.ReadBytes(&srcUpdate, sizeof(FileMemoryUpdate)); - MemoryUpdate &dstUpdate = memUpdates[i]; + MemoryUpdate& dstUpdate = memUpdates[i]; dstUpdate.address = srcUpdate.address; dstUpdate.fifoPosition = srcUpdate.fifoPosition; dstUpdate.size = srcUpdate.dataSize; diff --git a/Source/Core/Core/FifoPlayer/FifoDataFile.h b/Source/Core/Core/FifoPlayer/FifoDataFile.h index 607168f2dc94..d45e58f02451 100644 --- a/Source/Core/Core/FifoPlayer/FifoDataFile.h +++ b/Source/Core/Core/FifoPlayer/FifoDataFile.h @@ -27,13 +27,13 @@ struct MemoryUpdate u32 fifoPosition; u32 address; u32 size; - u8 *data; + u8* data; Type type; }; struct FifoFrameInfo { - u8 *fifoData; + u8* fifoData; u32 fifoDataSize; u32 fifoStart; @@ -59,6 +59,7 @@ class FifoDataFile void SetIsWii(bool isWii); bool GetIsWii() const; + bool HasBrokenEFBCopies() const; u32 *GetBPMem() { return m_BPMem; } u32 *GetCPMem() { return m_CPMem; } @@ -71,7 +72,7 @@ class FifoDataFile bool Save(const std::string& filename); - static FifoDataFile *Load(const std::string &filename, bool flagsOnly); + static FifoDataFile* Load(const std::string &filename, bool flagsOnly); private: enum @@ -84,8 +85,8 @@ class FifoDataFile void SetFlag(u32 flag, bool set); bool GetFlag(u32 flag) const; - u64 WriteMemoryUpdates(const std::vector &memUpdates, File::IOFile &file); - static void ReadMemoryUpdates(u64 fileOffset, u32 numUpdates, std::vector &memUpdates, File::IOFile &file); + u64 WriteMemoryUpdates(const std::vector& memUpdates, File::IOFile &file); + static void ReadMemoryUpdates(u64 fileOffset, u32 numUpdates, std::vector& memUpdates, File::IOFile& file); u32 m_BPMem[BP_MEM_SIZE]; u32 m_CPMem[CP_MEM_SIZE]; @@ -93,6 +94,7 @@ class FifoDataFile u32 m_XFRegs[XF_REGS_SIZE]; u32 m_Flags; + u32 version; std::vector m_Frames; }; diff --git a/Source/Core/Core/FifoPlayer/FifoFileStruct.h b/Source/Core/Core/FifoPlayer/FifoFileStruct.h index 9ca2ade3328a..4cf81aca72ba 100644 --- a/Source/Core/Core/FifoPlayer/FifoFileStruct.h +++ b/Source/Core/Core/FifoPlayer/FifoFileStruct.h @@ -12,7 +12,7 @@ namespace FifoFileStruct enum { FILE_ID = 0x0d01f1f0, - VERSION_NUMBER = 1, + VERSION_NUMBER = 2, MIN_LOADER_VERSION = 1, }; diff --git a/Source/Core/Core/FifoPlayer/FifoPlaybackAnalyzer.cpp b/Source/Core/Core/FifoPlayer/FifoPlaybackAnalyzer.cpp index 910e9bdae05c..4ca0335fe001 100644 --- a/Source/Core/Core/FifoPlayer/FifoPlaybackAnalyzer.cpp +++ b/Source/Core/Core/FifoPlayer/FifoPlaybackAnalyzer.cpp @@ -20,7 +20,7 @@ struct CmdData { u32 size; u32 offset; - u8 *ptr; + u8* ptr; }; FifoPlaybackAnalyzer::FifoPlaybackAnalyzer() @@ -28,13 +28,13 @@ FifoPlaybackAnalyzer::FifoPlaybackAnalyzer() FifoAnalyzer::Init(); } -void FifoPlaybackAnalyzer::AnalyzeFrames(FifoDataFile *file, std::vector &frameInfo) +void FifoPlaybackAnalyzer::AnalyzeFrames(FifoDataFile* file, std::vector& frameInfo) { // Load BP memory - u32 *bpMem = file->GetBPMem(); + u32* bpMem = file->GetBPMem(); memcpy(&m_BpMem, bpMem, sizeof(BPMemory)); - u32 *cpMem = file->GetCPMem(); + u32* cpMem = file->GetCPMem(); FifoAnalyzer::LoadCPReg(0x50, cpMem[0x50], m_CpMem); FifoAnalyzer::LoadCPReg(0x60, cpMem[0x60], m_CpMem); @@ -110,7 +110,7 @@ void FifoPlaybackAnalyzer::AnalyzeFrames(FifoDataFile *file, std::vector &frameInfo); + void AnalyzeFrames(FifoDataFile* file, std::vector& frameInfo); private: struct MemoryRange @@ -31,9 +31,9 @@ class FifoPlaybackAnalyzer u32 end; }; - void AddMemoryUpdate(MemoryUpdate memUpdate, AnalyzedFrameInfo &frameInfo); + void AddMemoryUpdate(MemoryUpdate memUpdate, AnalyzedFrameInfo& frameInfo); - u32 DecodeCommand(u8 *data); + u32 DecodeCommand(u8* data); void StoreEfbCopyRegion(); void StoreWrittenRegion(u32 address, u32 size); diff --git a/Source/Core/Core/FifoPlayer/FifoPlayer.cpp b/Source/Core/Core/FifoPlayer/FifoPlayer.cpp index 0d4696c1613d..f4bef742a795 100644 --- a/Source/Core/Core/FifoPlayer/FifoPlayer.cpp +++ b/Source/Core/Core/FifoPlayer/FifoPlayer.cpp @@ -63,8 +63,7 @@ bool FifoPlayer::Play() if (m_File->GetFrameCount() == 0) return false; - // Currently these is no such thing as a Fifolog without broken EFB copies. - IsPlayingBackFifologWithBrokenEFBCopies = true; + IsPlayingBackFifologWithBrokenEFBCopies = m_File->HasBrokenEFBCopies(); m_CurrentFrame = m_FrameRangeStart; @@ -154,7 +153,7 @@ void FifoPlayer::SetFrameRangeEnd(u32 end) } } -FifoPlayer &FifoPlayer::GetInstance() +FifoPlayer& FifoPlayer::GetInstance() { static FifoPlayer instance; return instance; @@ -174,7 +173,7 @@ FifoPlayer::FifoPlayer() : m_Loop = SConfig::GetInstance().bLoopFifoReplay; } -void FifoPlayer::WriteFrame(const FifoFrameInfo &frame, const AnalyzedFrameInfo &info) +void FifoPlayer::WriteFrame(const FifoFrameInfo& frame, const AnalyzedFrameInfo& info) { // Core timing information m_CyclesPerFrame = SystemTimers::GetTicksPerSecond() / VideoInterface::TargetRefreshRate; @@ -233,9 +232,9 @@ void FifoPlayer::WriteFrame(const FifoFrameInfo &frame, const AnalyzedFrameInfo FlushWGP(); } -void FifoPlayer::WriteFramePart(u32 dataStart, u32 dataEnd, u32 &nextMemUpdate, const FifoFrameInfo &frame, const AnalyzedFrameInfo &info) +void FifoPlayer::WriteFramePart(u32 dataStart, u32 dataEnd, u32& nextMemUpdate, const FifoFrameInfo& frame, const AnalyzedFrameInfo& info) { - u8 *data = frame.fifoData; + u8* data = frame.fifoData; while (nextMemUpdate < frame.memoryUpdates.size() && dataStart < dataEnd) { @@ -290,7 +289,7 @@ void FifoPlayer::WriteMemory(const MemoryUpdate& memUpdate) memcpy(mem, memUpdate.data, memUpdate.size); } -void FifoPlayer::WriteFifo(u8 *data, u32 start, u32 end) +void FifoPlayer::WriteFifo(u8* data, u32 start, u32 end) { u32 written = start; u32 lastBurstEnd = end - 1; @@ -453,7 +452,7 @@ void FifoPlayer::LoadXFReg(u16 reg, u32 value) GPFifo::Write32(value); } -void FifoPlayer::LoadXFMem16(u16 address, u32 *data) +void FifoPlayer::LoadXFMem16(u16 address, u32* data) { // Loads 16 * 4 bytes in xf memory starting at address GPFifo::Write8(0x10); // load XF reg diff --git a/Source/Core/Core/FifoPlayer/FifoPlayer.h b/Source/Core/Core/FifoPlayer/FifoPlayer.h index 24a3cb8c886c..ff484dc6bba4 100644 --- a/Source/Core/Core/FifoPlayer/FifoPlayer.h +++ b/Source/Core/Core/FifoPlayer/FifoPlayer.h @@ -87,15 +87,15 @@ class FifoPlayer private: FifoPlayer(); - void WriteFrame(const FifoFrameInfo &frame, const AnalyzedFrameInfo &info); - void WriteFramePart(u32 dataStart, u32 dataEnd, u32 &nextMemUpdate, const FifoFrameInfo &frame, const AnalyzedFrameInfo &info); + void WriteFrame(const FifoFrameInfo& frame, const AnalyzedFrameInfo &info); + void WriteFramePart(u32 dataStart, u32 dataEnd, u32 &nextMemUpdate, const FifoFrameInfo& frame, const AnalyzedFrameInfo& info); void WriteAllMemoryUpdates(); void WriteMemory(const MemoryUpdate &memUpdate); // writes a range of data to the fifo // start and end must be relative to frame's fifo data so elapsed cycles are figured correctly - void WriteFifo(u8 *data, u32 start, u32 end); + void WriteFifo(u8* data, u32 start, u32 end); void SetupFifo(); @@ -131,7 +131,7 @@ class FifoPlayer CallbackFunc m_FileLoadedCb; CallbackFunc m_FrameWrittenCb; - FifoDataFile *m_File; + FifoDataFile* m_File; std::vector m_FrameInfo; }; diff --git a/Source/Core/Core/FifoPlayer/FifoRecordAnalyzer.cpp b/Source/Core/Core/FifoPlayer/FifoRecordAnalyzer.cpp index cb8f82350e12..754e2d87d296 100644 --- a/Source/Core/Core/FifoPlayer/FifoRecordAnalyzer.cpp +++ b/Source/Core/Core/FifoPlayer/FifoRecordAnalyzer.cpp @@ -22,7 +22,7 @@ FifoRecordAnalyzer::FifoRecordAnalyzer() : { } -void FifoRecordAnalyzer::Initialize(u32 *bpMem, u32 *cpMem) +void FifoRecordAnalyzer::Initialize(u32* bpMem, u32* cpMem) { m_DrawingObject = false; @@ -37,12 +37,12 @@ void FifoRecordAnalyzer::Initialize(u32 *bpMem, u32 *cpMem) memcpy(m_CpMem.arrayStrides, cpMem + 0xB0, 16 * 4); } -void FifoRecordAnalyzer::AnalyzeGPCommand(u8 *data) +void FifoRecordAnalyzer::AnalyzeGPCommand(u8* data) { DecodeOpcode(data); } -void FifoRecordAnalyzer::DecodeOpcode(u8 *data) +void FifoRecordAnalyzer::DecodeOpcode(u8* data) { int cmd = ReadFifo8(data); @@ -99,11 +99,6 @@ void FifoRecordAnalyzer::DecodeOpcode(u8 *data) u32 cmd2 = ReadFifo32(data); BPCmd bp = FifoAnalyzer::DecodeBPCmd(cmd2, *m_BpMem); - - if (bp.address == BPMEM_LOADTLUT1) - ProcessLoadTlut1(); - if (bp.address == BPMEM_PRELOAD_MODE) - ProcessPreloadTexture(); } break; @@ -113,7 +108,6 @@ void FifoRecordAnalyzer::DecodeOpcode(u8 *data) if (!m_DrawingObject) { m_DrawingObject = true; - ProcessTexMaps(); } ProcessVertexArrays(data, cmd & GX_VAT_MASK); @@ -125,26 +119,6 @@ void FifoRecordAnalyzer::DecodeOpcode(u8 *data) } } -void FifoRecordAnalyzer::ProcessLoadTlut1() -{ - u32 tlutXferCount; - u32 tlutMemAddr; - u32 memAddr; - - GetTlutLoadData(tlutMemAddr, memAddr, tlutXferCount, *m_BpMem); - - FifoRecorder::GetInstance().WriteMemory(memAddr, tlutXferCount, MemoryUpdate::TMEM); -} - -void FifoRecordAnalyzer::ProcessPreloadTexture() -{ - BPS_TmemConfig& tmem_cfg = m_BpMem->tmem_config; - //u32 tmem_addr = tmem_cfg.preload_tmem_even * TMEM_LINE_SIZE; - u32 size = tmem_cfg.preload_tile_info.count * TMEM_LINE_SIZE; // TODO: Should this be half size for RGBA8 preloads? - - FifoRecorder::GetInstance().WriteMemory(tmem_cfg.preload_addr << 5, size, MemoryUpdate::TMEM); -} - void FifoRecordAnalyzer::ProcessLoadIndexedXf(u32 val, int array) { int index = val >> 16; @@ -152,10 +126,10 @@ void FifoRecordAnalyzer::ProcessLoadIndexedXf(u32 val, int array) u32 address = m_CpMem.arrayBases[array] + m_CpMem.arrayStrides[array] * index; - FifoRecorder::GetInstance().WriteMemory(address, size * 4, MemoryUpdate::XF_DATA); + FifoRecorder::GetInstance().UseMemory(address, size * 4, MemoryUpdate::XF_DATA); } -void FifoRecordAnalyzer::ProcessVertexArrays(u8 *data, u8 vtxAttrGroup) +void FifoRecordAnalyzer::ProcessVertexArrays(u8* data, u8 vtxAttrGroup) { int sizes[21]; FifoAnalyzer::CalculateVertexElementSizes(sizes, vtxAttrGroup, m_CpMem); @@ -181,7 +155,7 @@ void FifoRecordAnalyzer::ProcessVertexArrays(u8 *data, u8 vtxAttrGroup) } } -void FifoRecordAnalyzer::WriteVertexArray(int arrayIndex, u8 *vertexData, int vertexSize, int 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; @@ -225,80 +199,5 @@ void FifoRecordAnalyzer::WriteVertexArray(int arrayIndex, u8 *vertexData, int ve 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 = std::max(width, fmtWidth); - height = std::max(height, fmtHeight); - u32 size = (width * height * fmtDepth) >> 1; - - textureSize += size; - - mip--; - } - - FifoRecorder::GetInstance().WriteMemory(imageBase, textureSize, MemoryUpdate::TEXTURE_MAP); + FifoRecorder::GetInstance().UseMemory(arrayStart, arraySize, MemoryUpdate::VERTEX_STREAM); } diff --git a/Source/Core/Core/FifoPlayer/FifoRecordAnalyzer.h b/Source/Core/Core/FifoPlayer/FifoRecordAnalyzer.h index cc0268acdc3f..28d815b31d80 100644 --- a/Source/Core/Core/FifoPlayer/FifoRecordAnalyzer.h +++ b/Source/Core/Core/FifoPlayer/FifoRecordAnalyzer.h @@ -16,26 +16,22 @@ class FifoRecordAnalyzer FifoRecordAnalyzer(); // Must call this before analyzing GP commands - void Initialize(u32 *bpMem, u32 *cpMem); + void Initialize(u32* bpMem, u32* cpMem); // Assumes data contains all information for the command - // Calls FifoRecorder::WriteMemory - void AnalyzeGPCommand(u8 *data); + // Calls FifoRecorder::UseMemory + void AnalyzeGPCommand(u8* data); private: - void DecodeOpcode(u8 *data); + void DecodeOpcode(u8* data); - void ProcessLoadTlut1(); - void ProcessPreloadTexture(); void ProcessLoadIndexedXf(u32 val, int array); - void ProcessVertexArrays(u8 *data, u8 vtxAttrGroup); - void ProcessTexMaps(); + void ProcessVertexArrays(u8* data, u8 vtxAttrGroup); - void WriteVertexArray(int arrayIndex, u8 *vertexData, int vertexSize, int numVertices); - void WriteTexMapMemory(int texMap, u32 &writtenTexMaps); + void WriteVertexArray(int arrayIndex, u8* vertexData, int vertexSize, int numVertices); bool m_DrawingObject; - BPMemory *m_BpMem; + BPMemory* m_BpMem; FifoAnalyzer::CPMemory m_CpMem; }; diff --git a/Source/Core/Core/FifoPlayer/FifoRecorder.cpp b/Source/Core/Core/FifoPlayer/FifoRecorder.cpp index eaf118012c16..8906b04a8276 100644 --- a/Source/Core/Core/FifoPlayer/FifoRecorder.cpp +++ b/Source/Core/Core/FifoPlayer/FifoRecorder.cpp @@ -64,7 +64,7 @@ void FifoRecorder::StopRecording() m_RequestedRecordingEnd = true; } -void FifoRecorder::WriteGPCommand(u8 *data, u32 size) +void FifoRecorder::WriteGPCommand(u8* data, u32 size) { if (!m_SkipNextData) { @@ -102,10 +102,10 @@ void FifoRecorder::WriteGPCommand(u8 *data, u32 size) m_SkipNextData = m_SkipFutureData; } -void FifoRecorder::WriteMemory(u32 address, u32 size, MemoryUpdate::Type type) +void FifoRecorder::UseMemory(u32 address, u32 size, MemoryUpdate::Type type, bool dynamicUpdate) { - u8 *curData; - u8 *newData; + u8* curData; + u8* newData; if (address & 0x10000000) { curData = &m_ExRam[address & Memory::EXRAM_MASK]; @@ -117,7 +117,7 @@ void FifoRecorder::WriteMemory(u32 address, u32 size, MemoryUpdate::Type type) newData = &Memory::m_pRAM[address & Memory::RAM_MASK]; } - if (memcmp(curData, newData, size) != 0) + if (!dynamicUpdate && memcmp(curData, newData, size) != 0) { // Update current memory memcpy(curData, newData, size); @@ -133,6 +133,11 @@ void FifoRecorder::WriteMemory(u32 address, u32 size, MemoryUpdate::Type type) m_CurrentFrame.memoryUpdates.push_back(memUpdate); } + else if (dynamicUpdate) + { + // Shadow the data so it won't be recorded as changed by a future UseMemory + memcpy(curData, newData, size); + } } void FifoRecorder::EndFrame(u32 fifoStart, u32 fifoEnd) @@ -200,7 +205,7 @@ void FifoRecorder::SetVideoMemory(u32 *bpMem, u32 *cpMem, u32 *xfMem, u32 *xfReg sMutex.unlock(); } -FifoRecorder &FifoRecorder::GetInstance() +FifoRecorder& FifoRecorder::GetInstance() { return instance; } diff --git a/Source/Core/Core/FifoPlayer/FifoRecorder.h b/Source/Core/Core/FifoPlayer/FifoRecorder.h index f39c92bf0352..767a4f9610cf 100644 --- a/Source/Core/Core/FifoPlayer/FifoRecorder.h +++ b/Source/Core/Core/FifoPlayer/FifoRecorder.h @@ -20,25 +20,28 @@ class FifoRecorder void StartRecording(s32 numFrames, CallbackFunc finishedCb); void StopRecording(); - FifoDataFile *GetRecordedFile() { return m_File; } + FifoDataFile* GetRecordedFile() { return m_File; } // Called from video thread // Must write one full GP command at a time - void WriteGPCommand(u8 *data, u32 size); + void WriteGPCommand(u8* data, u32 size); - void WriteMemory(u32 address, u32 size, MemoryUpdate::Type type); + // Track memory that has been used and write it to the fifolog if it has changed. + // If memory is updated by the video backend (dynamicUpdate == true) take special care to make sure the data + // isn't baked into the fifolog. + void UseMemory(u32 address, u32 size, MemoryUpdate::Type type, bool dynamicUpdate = false); void EndFrame(u32 fifoStart, u32 fifoEnd); // This function must be called before writing GP commands // bpMem must point to the actual bp mem array used by the plugin because it will be read as fifo data is recorded - void SetVideoMemory(u32 *bpMem, u32 *cpMem, u32 *xfMem, u32 *xfRegs, u32 xfRegsSize); + void SetVideoMemory(u32* bpMem, u32* cpMem, u32* xfMem, u32* xfRegs, u32 xfRegsSize); // Checked once per frame prior to callng EndFrame() bool IsRecording() const { return m_IsRecording; } - static FifoRecorder &GetInstance(); + static FifoRecorder& GetInstance(); private: // Accessed from both GUI and video threads @@ -51,7 +54,7 @@ class FifoRecorder volatile s32 m_RecordFramesRemaining; volatile CallbackFunc m_FinishedCb; - FifoDataFile *volatile m_File; + FifoDataFile* volatile m_File; // Accessed only from video thread diff --git a/Source/Core/VideoCommon/BPStructs.cpp b/Source/Core/VideoCommon/BPStructs.cpp index e30aa2fcaa6f..4dc4643afbf8 100644 --- a/Source/Core/VideoCommon/BPStructs.cpp +++ b/Source/Core/VideoCommon/BPStructs.cpp @@ -8,6 +8,7 @@ #include "Common/Thread.h" #include "Core/ConfigManager.h" #include "Core/Core.h" +#include "Core/FifoPlayer/FifoRecorder.h" #include "Core/HW/Memmap.h" #include "VideoCommon/BoundingBox.h" @@ -281,6 +282,9 @@ static void BPWritten(const BPCmd& bp) Memory::CopyFromEmu(texMem + tlutTMemAddr, addr, tlutXferCount); + if (g_bRecordFifoData) + FifoRecorder::GetInstance().UseMemory(addr, tlutXferCount, MemoryUpdate::TMEM); + return; } case BPMEM_FOGRANGE: // Fog Settings Control @@ -455,15 +459,16 @@ static void BPWritten(const BPCmd& bp) BPS_TmemConfig& tmem_cfg = bpmem.tmem_config; u32 src_addr = tmem_cfg.preload_addr << 5; // TODO: Should we add mask here on GC? - u32 size = tmem_cfg.preload_tile_info.count * TMEM_LINE_SIZE; + u32 bytes_read = 0; u32 tmem_addr_even = tmem_cfg.preload_tmem_even * TMEM_LINE_SIZE; if (tmem_cfg.preload_tile_info.type != 3) { - if (tmem_addr_even + size > TMEM_SIZE) - size = TMEM_SIZE - tmem_addr_even; + bytes_read = tmem_cfg.preload_tile_info.count * TMEM_LINE_SIZE; + if (tmem_addr_even + bytes_read > TMEM_SIZE) + bytes_read = TMEM_SIZE - tmem_addr_even; - Memory::CopyFromEmu(texMem + tmem_addr_even, src_addr, size); + Memory::CopyFromEmu(texMem + tmem_addr_even, src_addr, bytes_read); } else // RGBA8 tiles (and CI14, but that might just be stupid libogc!) { @@ -471,21 +476,23 @@ static void BPWritten(const BPCmd& bp) // AR and GB tiles are stored in separate TMEM banks => can't use a single memcpy for everything u32 tmem_addr_odd = tmem_cfg.preload_tmem_odd * TMEM_LINE_SIZE; + u32 bytes_read = 0; for (u32 i = 0; i < tmem_cfg.preload_tile_info.count; ++i) { - if (tmem_addr_even + TMEM_LINE_SIZE > TMEM_SIZE || - tmem_addr_odd + TMEM_LINE_SIZE > TMEM_SIZE) - return; + if (tmem_addr_even + TMEM_LINE_SIZE > TMEM_SIZE || tmem_addr_odd + TMEM_LINE_SIZE > TMEM_SIZE) + break; - // TODO: This isn't very optimised, does a whole lot of small memcpys - memcpy(texMem + tmem_addr_even, src_ptr, TMEM_LINE_SIZE); - memcpy(texMem + tmem_addr_odd, src_ptr + TMEM_LINE_SIZE, TMEM_LINE_SIZE); + memcpy(texMem + tmem_addr_even, src_ptr + bytes_read, TMEM_LINE_SIZE); + memcpy(texMem + tmem_addr_odd, src_ptr + bytes_read + TMEM_LINE_SIZE, TMEM_LINE_SIZE); tmem_addr_even += TMEM_LINE_SIZE; tmem_addr_odd += TMEM_LINE_SIZE; - src_ptr += TMEM_LINE_SIZE * 2; + bytes_read += TMEM_LINE_SIZE * 2; } } + + if (g_bRecordFifoData) + FifoRecorder::GetInstance().UseMemory(src_addr, bytes_read, MemoryUpdate::TMEM); } return; diff --git a/Source/Core/VideoCommon/OpcodeDecoding.h b/Source/Core/VideoCommon/OpcodeDecoding.h index ec1b2652e427..a79bf54be25c 100644 --- a/Source/Core/VideoCommon/OpcodeDecoding.h +++ b/Source/Core/VideoCommon/OpcodeDecoding.h @@ -38,8 +38,6 @@ #define GX_DRAW_LINE_STRIP 0x6 // 0xB0 #define GX_DRAW_POINTS 0x7 // 0xB8 -extern bool g_bRecordFifoData; - void OpcodeDecoder_Init(); void OpcodeDecoder_Shutdown(); diff --git a/Source/Core/VideoCommon/TextureCacheBase.cpp b/Source/Core/VideoCommon/TextureCacheBase.cpp index 694aa80c0a2d..e93e6955f4f4 100644 --- a/Source/Core/VideoCommon/TextureCacheBase.cpp +++ b/Source/Core/VideoCommon/TextureCacheBase.cpp @@ -11,6 +11,7 @@ #include "Core/ConfigManager.h" #include "Core/FifoPlayer/FifoPlayer.h" +#include "Core/FifoPlayer/FifoRecorder.h" #include "Core/HW/Memmap.h" #include "VideoCommon/Debugger.h" @@ -19,6 +20,7 @@ #include "VideoCommon/RenderBase.h" #include "VideoCommon/Statistics.h" #include "VideoCommon/TextureCacheBase.h" +#include "VideoCommon/VideoCommon.h" #include "VideoCommon/VideoConfig.h" static const u64 TEXHASH_INVALID = 0; @@ -395,6 +397,25 @@ TextureCache::TCacheEntryBase* TextureCache::Load(const u32 stage) full_format = texformat | (tlutfmt << 16); const u32 texture_size = TexDecoder_GetTextureSizeInBytes(expandedWidth, expandedHeight, texformat); + u32 additional_mips_size = 0; // not including level 0, which is texture_size + + // GPUs don't like when the specified mipmap count would require more than one 1x1-sized LOD in the mipmap chain + // e.g. 64x64 with 7 LODs would have the mipmap chain 64x64,32x32,16x16,8x8,4x4,2x2,1x1,0x0, so we limit the mipmap count to 6 there + tex_levels = std::min(IntLog2(std::max(width, height)) + 1, tex_levels); + + for (u32 level = 1; level != tex_levels; ++level) + { + // We still need to calculate the original size of the mips + const u32 expanded_mip_width = ROUND_UP(CalculateLevelSize(width, level), bsw); + const u32 expanded_mip_height = ROUND_UP(CalculateLevelSize(height, level), bsh); + + additional_mips_size += TexDecoder_GetTextureSizeInBytes(expanded_mip_width, expanded_mip_height, texformat); + } + + // If we are recording a FifoLog, keep track of what memory we read. + // FifiRecorder does it's own memory modification tracking independant of the texture hashing below. + if (g_bRecordFifoData && !from_tmem) + FifoRecorder::GetInstance().UseMemory(address, texture_size + additional_mips_size, MemoryUpdate::TEXTURE_MAP); const u8* src_data; if (from_tmem) @@ -415,10 +436,6 @@ TextureCache::TCacheEntryBase* TextureCache::Load(const u32 stage) full_hash = base_hash; } - // GPUs don't like when the specified mipmap count would require more than one 1x1-sized LOD in the mipmap chain - // e.g. 64x64 with 7 LODs would have the mipmap chain 64x64,32x32,16x16,8x8,4x4,2x2,1x1,0x0, so we limit the mipmap count to 6 there - tex_levels = std::min(IntLog2(std::max(width, height)) + 1, tex_levels); - // Search the texture cache for textures by address // // Find all texture cache entries for the current texture address, and decide whether to use one of @@ -740,7 +757,7 @@ void TextureCache::CopyRenderTargetToTexture(u32 dstAddr, unsigned int dstFormat // // For historical reasons, Dolphin doesn't actually implement "pure" EFB to RAM emulation, but only EFB to texture and hybrid EFB copies. - float colmat[28] = {0}; + float colmat[28] = { 0 }; float *const fConstAdd = colmat + 16; float *const ColorMask = colmat + 20; ColorMask[0] = ColorMask[1] = ColorMask[2] = ColorMask[3] = 255.0f; @@ -1058,6 +1075,17 @@ void TextureCache::CopyRenderTargetToTexture(u32 dstAddr, unsigned int dstFormat count++), 0); } + if (g_bRecordFifoData) + { + // Mark the memory behind this efb copy as dynamicly generated for the Fifo log + u32 address = dstAddr; + for (u32 i = 0; i < entry->NumBlocksY(); i++) + { + FifoRecorder::GetInstance().UseMemory(address, entry->CacheLinesPerRow() * 32, MemoryUpdate::TEXTURE_MAP, true); + address += entry->memory_stride; + } + } + textures_by_address.emplace((u64)dstAddr, entry); } diff --git a/Source/Core/VideoCommon/VideoCommon.h b/Source/Core/VideoCommon/VideoCommon.h index 4234bbb8bedc..ba339e5c4fc3 100644 --- a/Source/Core/VideoCommon/VideoCommon.h +++ b/Source/Core/VideoCommon/VideoCommon.h @@ -12,6 +12,9 @@ #include "Common/MathUtil.h" #include "VideoCommon/VideoBackendBase.h" +// Global flag to signal if FifoRecorder is active. +extern bool g_bRecordFifoData; + // These are accurate (disregarding AA modes). enum {