GS: Use single array for dump packets

This commit is contained in:
Connor McLaughlin 2022-03-14 19:27:36 +10:00 committed by refractionpcsx2
parent 6a15d46461
commit 16cfde0538
5 changed files with 89 additions and 54 deletions

View File

@ -114,11 +114,11 @@ bool GSDumpFile::GetPreviewImageFromDump(const char* filename, u32* width, u32*
bool GSDumpFile::ReadFile()
{
u32 ss;
if (!Read(&m_crc, 4) || !Read(&ss, 4))
if (Read(&m_crc, sizeof(m_crc)) != sizeof(m_crc) || Read(&ss, sizeof(ss)) != sizeof(ss))
return false;
m_state_data.resize(ss);
if (!Read(m_state_data.data(), ss))
if (Read(m_state_data.data(), ss) != ss)
return false;
// Pull serial out of new header, if present.
@ -149,34 +149,68 @@ bool GSDumpFile::ReadFile()
// Read the real state data
m_state_data.resize(header.state_size);
if (!Read(m_state_data.data(), header.state_size))
if (Read(m_state_data.data(), header.state_size) != header.state_size)
return false;
}
m_regs_data.resize(8192);
if (!Read(m_regs_data.data(), m_regs_data.size()))
if (Read(m_regs_data.data(), m_regs_data.size()) != m_regs_data.size())
return false;
// read all the packet data in
// TODO: make this suck less by getting the full/extracted size and preallocating
for (;;)
{
GSData packet;
packet.path = GSTransferPath::Dummy;
if (!Read(&packet.id, 1))
{
if (IsEof())
break;
const size_t packet_data_size = m_packet_data.size();
m_packet_data.resize(std::max<size_t>(packet_data_size * 2, 8 * _1mb));
return false;
const size_t read_size = m_packet_data.size() - packet_data_size;
const size_t read = Read(m_packet_data.data() + packet_data_size, read_size);
if (read != read_size)
{
if (!IsEof())
return false;
m_packet_data.resize(packet_data_size + read);
m_packet_data.shrink_to_fit();
break;
}
}
u8* data = m_packet_data.data();
size_t remaining = m_packet_data.size();
#define GET_BYTE(dst) \
do \
{ \
if (remaining < sizeof(u8)) \
return false; \
std::memcpy(dst, data, sizeof(u8)); \
data++; \
remaining--; \
} while (0)
#define GET_WORD(dst) \
do \
{ \
if (remaining < sizeof(u32)) \
return false; \
std::memcpy(dst, data, sizeof(u32)); \
data += sizeof(u32); \
remaining -= sizeof(u32); \
} while (0)
while (remaining > 0)
{
GSData packet = {};
packet.path = GSTransferPath::Dummy;
GET_BYTE(&packet.id);
switch (packet.id)
{
case GSType::Transfer:
{
if (!Read(&packet.path, 1) || !Read(&packet.length, 4))
return false;
}
break;
GET_BYTE(&packet.path);
GET_WORD(&packet.length);
break;
case GSType::VSync:
packet.length = 1;
break;
@ -186,18 +220,26 @@ bool GSDumpFile::ReadFile()
case GSType::Registers:
packet.length = 8192;
break;
default:
return false;
}
if (packet.length > 0)
{
packet.data = std::unique_ptr<u8[]>(new u8[packet.length]);
if (!Read(packet.data.get(), packet.length))
if (remaining < packet.length)
return false;
packet.data = data;
data += packet.length;
remaining -= packet.length;
}
m_dump_packets.push_back(std::move(packet));
}
#undef GET_WORD
#undef GET_BYTE
return true;
}
@ -275,7 +317,7 @@ bool GSDumpLzma::IsEof()
return feof(m_fp) && m_avail == 0 && m_strm.avail_in == 0;
}
bool GSDumpLzma::Read(void* ptr, size_t size)
size_t GSDumpLzma::Read(void* ptr, size_t size)
{
size_t off = 0;
uint8_t* dst = (uint8_t*)ptr;
@ -295,13 +337,10 @@ bool GSDumpLzma::Read(void* ptr, size_t size)
off += l;
}
if (size == 0)
{
Repack(ptr, full_size);
return true;
}
if (off > 0)
Repack(ptr, off);
return false;
return off;
}
GSDumpLzma::~GSDumpLzma()
@ -326,20 +365,17 @@ bool GSDumpRaw::IsEof()
return !!feof(m_fp);
}
bool GSDumpRaw::Read(void* ptr, size_t size)
size_t GSDumpRaw::Read(void* ptr, size_t size)
{
size_t ret = fread(ptr, 1, size, m_fp);
if (ret != size && ferror(m_fp))
{
fprintf(stderr, "GSDumpRaw:: Read error (%zu/%zu)\n", ret, size);
return false;
return ret;
}
if (ret == size)
{
Repack(ptr, size);
return true;
}
if (ret > 0)
Repack(ptr, ret);
return false;
return ret;
}

View File

@ -291,7 +291,7 @@ public:
struct GSData
{
GSDumpTypes::GSType id;
std::unique_ptr<u8[]> data;
const u8* data;
s32 length;
GSDumpTypes::GSTransferPath path;
};
@ -317,7 +317,7 @@ protected:
GSDumpFile(FILE* file, FILE* repack_file);
virtual bool IsEof() = 0;
virtual bool Read(void* ptr, size_t size) = 0;
virtual size_t Read(void* ptr, size_t size) = 0;
void Repack(void* ptr, size_t size);
@ -331,9 +331,8 @@ private:
std::vector<u8> m_regs_data;
std::vector<u8> m_state_data;
std::vector<u8> m_packet_data;
// TODO: Allocate a single, large buffer, and store pointers to
// each packet instead of a buffer per packet.
GSDataArray m_dump_packets;
};
@ -356,7 +355,7 @@ public:
virtual ~GSDumpLzma();
bool IsEof() final;
bool Read(void* ptr, size_t size) final;
size_t Read(void* ptr, size_t size) final;
};
class GSDumpRaw : public GSDumpFile
@ -366,5 +365,5 @@ public:
virtual ~GSDumpRaw() = default;
bool IsEof() final;
bool Read(void* ptr, size_t size) final;
size_t Read(void* ptr, size_t size) final;
};

View File

@ -225,7 +225,7 @@ void GSDumpReplayerCpuStep()
{
std::unique_ptr<u8[]> data(new u8[16384]);
const s32 addr = 16384 - packet.length;
std::memcpy(data.get(), packet.data.get() + addr, packet.length);
std::memcpy(data.get(), packet.data + addr, packet.length);
GSDumpReplayerSendPacketToMTGS(GIF_PATH_1, data.get(), packet.length);
}
break;
@ -235,7 +235,7 @@ void GSDumpReplayerCpuStep()
case GSDumpTypes::GSTransferPath::Path3:
{
GSDumpReplayerSendPacketToMTGS(static_cast<GIF_PATH>(static_cast<u8>(packet.path) - 1),
reinterpret_cast<const u8*>(packet.data.get()), packet.length);
packet.data, packet.length);
}
break;
@ -258,14 +258,14 @@ void GSDumpReplayerCpuStep()
case GSDumpTypes::GSType::ReadFIFO2:
{
std::unique_ptr<char[]> arr(new char[*((int*)packet.data.get())]);
GSreadFIFO2((u8*)arr.get(), *((int*)packet.data.get()));
std::unique_ptr<char[]> arr(new char[*((int*)packet.data)]);
GSreadFIFO2((u8*)arr.get(), *((int*)packet.data));
}
break;
case GSDumpTypes::GSType::Registers:
{
std::memcpy(PS2MEM_GS, packet.data.get(), std::min<s32>(packet.length, Ps2MemSize::GSregs));
std::memcpy(PS2MEM_GS, packet.data, std::min<s32>(packet.length, Ps2MemSize::GSregs));
}
break;
}

View File

@ -433,7 +433,7 @@ void Dialogs::GSDumpDialog::GenPacketInfo(const GSDumpFile::GSData& dump)
{
case GSType::Transfer:
{
u8* data = dump.data.get();
const u8* data = dump.data;
u32 remaining = dump.length;
int idx = 0;
while (remaining >= 16)
@ -468,7 +468,7 @@ void Dialogs::GSDumpDialog::GenPacketInfo(const GSDumpFile::GSData& dump)
}
}
void Dialogs::GSDumpDialog::ParseTransfer(wxTreeItemId& trootId, u8* data)
void Dialogs::GSDumpDialog::ParseTransfer(wxTreeItemId& trootId, const u8* data)
{
u64 tag = *(u64*)data;
u64 regs = *(u64*)(data + 8);
@ -746,18 +746,18 @@ void Dialogs::GSDumpDialog::ProcessDumpEvent(const GSDumpFile::GSData& event, u8
{
std::unique_ptr<char[]> data(new char[16384]);
int addr = 16384 - event.length;
memcpy(data.get(), event.data.get() + addr, event.length);
memcpy(data.get(), event.data + addr, event.length);
GSgifTransfer1((u8*)data.get(), addr);
break;
}
case GSTransferPath::Path1New:
GSgifTransfer((u8*)event.data.get(), event.length / 16);
GSgifTransfer((u8*)event.data, event.length / 16);
break;
case GSTransferPath::Path2:
GSgifTransfer2((u8*)event.data.get(), event.length / 16);
GSgifTransfer2((u8*)event.data, event.length / 16);
break;
case GSTransferPath::Path3:
GSgifTransfer3((u8*)event.data.get(), event.length / 16);
GSgifTransfer3((u8*)event.data, event.length / 16);
break;
default:
break;
@ -772,12 +772,12 @@ void Dialogs::GSDumpDialog::ProcessDumpEvent(const GSDumpFile::GSData& event, u8
}
case GSType::ReadFIFO2:
{
std::unique_ptr<char[]> arr(new char[*((int*)event.data.get())]);
GSreadFIFO2((u8*)arr.get(), *((int*)event.data.get()));
std::unique_ptr<char[]> arr(new char[*((int*)event.data)]);
GSreadFIFO2((u8*)arr.get(), *((int*)event.data));
break;
}
case GSType::Registers:
memcpy(regs, event.data.get(), 8192);
memcpy(regs, event.data, 8192);
break;
}
}

View File

@ -145,7 +145,7 @@ namespace Dialogs
u32 ReadPacketSize(const void* packet);
void GenPacketList();
void GenPacketInfo(const GSDumpFile::GSData& dump);
void ParseTransfer(wxTreeItemId& id, u8* data);
void ParseTransfer(wxTreeItemId& id, const u8* data);
void ParseTreeReg(wxTreeItemId& id, GSDumpTypes::GIFReg reg, u128 data, bool packed);
void ParseTreePrim(wxTreeItemId& id, u32 prim);
void CloseDump(wxCommandEvent& event);