mirror of
https://github.com/dolphin-emu/dolphin.git
synced 2025-07-23 14:19:46 -06:00
FifoRecorder: Use Video Common to record efb2ram correctly.
Texture updates have been moved into TextureCache, while TMEM updates where moved into bpmem. Code for handling efb2ram updates was added to TextureCache. There was a bug for preloaded RGBA8 textures, it only copied half the texture. The TODO was wrong too.
This commit is contained in:
@ -68,18 +68,6 @@ 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)
|
||||
{
|
||||
switch (subCmd & 0xF0)
|
||||
|
@ -28,6 +28,11 @@ FifoDataFile::~FifoDataFile()
|
||||
}
|
||||
}
|
||||
|
||||
bool FifoDataFile::HasBrokenEFBCopies() const
|
||||
{
|
||||
return version < 2;
|
||||
}
|
||||
|
||||
void FifoDataFile::SetIsWii(bool isWii)
|
||||
{
|
||||
SetFlag(FLAG_IS_WII, isWii);
|
||||
|
@ -59,6 +59,7 @@ public:
|
||||
|
||||
void SetIsWii(bool isWii);
|
||||
bool GetIsWii() const;
|
||||
bool HasBrokenEFBCopies() const;
|
||||
|
||||
u32 *GetBPMem() { return m_BPMem; }
|
||||
u32 *GetCPMem() { return m_CPMem; }
|
||||
@ -93,6 +94,7 @@ private:
|
||||
u32 m_XFRegs[XF_REGS_SIZE];
|
||||
|
||||
u32 m_Flags;
|
||||
u32 version;
|
||||
|
||||
std::vector<FifoFrameInfo> m_Frames;
|
||||
};
|
||||
|
@ -12,7 +12,7 @@ namespace FifoFileStruct
|
||||
enum
|
||||
{
|
||||
FILE_ID = 0x0d01f1f0,
|
||||
VERSION_NUMBER = 1,
|
||||
VERSION_NUMBER = 2,
|
||||
MIN_LOADER_VERSION = 1,
|
||||
};
|
||||
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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,7 +126,7 @@ 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)
|
||||
@ -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);
|
||||
}
|
||||
|
@ -19,20 +19,16 @@ public:
|
||||
void Initialize(u32 *bpMem, u32 *cpMem);
|
||||
|
||||
// Assumes data contains all information for the command
|
||||
// Calls FifoRecorder::WriteMemory
|
||||
// Calls FifoRecorder::UseMemory
|
||||
void AnalyzeGPCommand(u8 *data);
|
||||
|
||||
private:
|
||||
void DecodeOpcode(u8 *data);
|
||||
|
||||
void ProcessLoadTlut1();
|
||||
void ProcessPreloadTexture();
|
||||
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;
|
||||
|
||||
|
@ -102,7 +102,7 @@ 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;
|
||||
@ -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)
|
||||
|
@ -27,7 +27,10 @@ public:
|
||||
// Must write one full GP command at a time
|
||||
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);
|
||||
|
||||
|
Reference in New Issue
Block a user