GSDumpGUI: .gs.xz support

This commit is contained in:
TellowKrinkle 2021-10-20 19:23:32 -05:00 committed by lightningterror
parent 234d643dd3
commit 5ec5fb17ca
4 changed files with 51 additions and 39 deletions

View File

@ -34,6 +34,11 @@ GSDumpFile::GSDumpFile(char* filename, const char* repack_filename)
} }
} }
GSDumpFile::GSDumpFile(FILE* file, FILE* repack_file)
: m_repack_fp(repack_file), m_fp(file)
{
}
void GSDumpFile::Repack(void* ptr, size_t size) void GSDumpFile::Repack(void* ptr, size_t size)
{ {
if (m_repack_fp == nullptr) if (m_repack_fp == nullptr)
@ -56,7 +61,17 @@ GSDumpFile::~GSDumpFile()
GSDumpLzma::GSDumpLzma(char* filename, const char* repack_filename) GSDumpLzma::GSDumpLzma(char* filename, const char* repack_filename)
: GSDumpFile(filename, repack_filename) : GSDumpFile(filename, repack_filename)
{ {
Initialize();
}
GSDumpLzma::GSDumpLzma(FILE* file, FILE* repack_file)
: GSDumpFile(file, repack_file)
{
Initialize();
}
void GSDumpLzma::Initialize()
{
memset(&m_strm, 0, sizeof(lzma_stream)); memset(&m_strm, 0, sizeof(lzma_stream));
lzma_ret ret = lzma_stream_decoder(&m_strm, UINT32_MAX, 0); lzma_ret ret = lzma_stream_decoder(&m_strm, UINT32_MAX, 0);
@ -166,11 +181,11 @@ GSDumpLzma::~GSDumpLzma()
GSDumpRaw::GSDumpRaw(char* filename, const char* repack_filename) GSDumpRaw::GSDumpRaw(char* filename, const char* repack_filename)
: GSDumpFile(filename, repack_filename) : GSDumpFile(filename, repack_filename)
{ {
m_buff_size = 0; }
m_area = nullptr;
m_inbuf = nullptr; GSDumpRaw::GSDumpRaw(FILE* file, FILE* repack_file)
m_avail = 0; : GSDumpFile(file, repack_file)
m_start = 0; {
} }
bool GSDumpRaw::IsEof() bool GSDumpRaw::IsEof()

View File

@ -29,6 +29,7 @@ public:
virtual bool Read(void* ptr, size_t size) = 0; virtual bool Read(void* ptr, size_t size) = 0;
GSDumpFile(char* filename, const char* repack_filename); GSDumpFile(char* filename, const char* repack_filename);
GSDumpFile(FILE* file, FILE* repack_file);
virtual ~GSDumpFile(); virtual ~GSDumpFile();
}; };
@ -44,9 +45,11 @@ class GSDumpLzma : public GSDumpFile
size_t m_start; size_t m_start;
void Decompress(); void Decompress();
void Initialize();
public: public:
GSDumpLzma(char* filename, const char* repack_filename); GSDumpLzma(char* filename, const char* repack_filename);
GSDumpLzma(FILE* file, FILE* repack_file);
virtual ~GSDumpLzma(); virtual ~GSDumpLzma();
bool IsEof() final; bool IsEof() final;
@ -55,15 +58,9 @@ public:
class GSDumpRaw : public GSDumpFile class GSDumpRaw : public GSDumpFile
{ {
size_t m_buff_size;
uint8_t* m_area;
uint8_t* m_inbuf;
size_t m_avail;
size_t m_start;
public: public:
GSDumpRaw(char* filename, const char* repack_filename); GSDumpRaw(char* filename, const char* repack_filename);
GSDumpRaw(FILE* file, FILE* repack_file);
virtual ~GSDumpRaw() = default; virtual ~GSDumpRaw() = default;
bool IsEof() final; bool IsEof() final;

View File

@ -277,25 +277,34 @@ void Dialogs::GSDumpDialog::GetDumpsList()
m_dump_list->ClearAll(); m_dump_list->ClearAll();
wxDir snaps(g_Conf->Folders.Snapshots.ToAscii()); wxDir snaps(g_Conf->Folders.Snapshots.ToAscii());
wxString filename; wxString filename;
bool cont = snaps.GetFirst(&filename, "*.gs", wxDIR_DEFAULT); bool cont = snaps.GetFirst(&filename);
int i = 0, h = 0, j = 0; int h = 0, j = 0;
m_dump_list->AppendColumn("Dumps"); m_dump_list->AppendColumn("Dumps");
// set the column size to be exactly of the size of our list // set the column size to be exactly of the size of our list
m_dump_list->GetSize(&h, &j); m_dump_list->GetSize(&h, &j);
m_dump_list->SetColumnWidth(0, h); m_dump_list->SetColumnWidth(0, h);
std::vector<wxString> dumps;
while (cont) while (cont)
{ {
m_dump_list->InsertItem(i, filename.substr(0, filename.find_last_of("."))); if (filename.EndsWith(".gs"))
i++; dumps.push_back(filename.substr(0, filename.length() - 3));
else if (filename.EndsWith(".gs.xz"))
dumps.push_back(filename.substr(0, filename.length() - 6));
cont = snaps.GetNext(&filename); cont = snaps.GetNext(&filename);
} }
std::sort(dumps.begin(), dumps.end(), [](const wxString& a, const wxString& b) { return a.CmpNoCase(b) < 0; });
dumps.erase(std::unique(dumps.begin(), dumps.end()), dumps.end()); // In case there was both .gs and .gs.xz
for (size_t i = 0; i < dumps.size(); i++)
m_dump_list->InsertItem(i, dumps[i]);
} }
void Dialogs::GSDumpDialog::SelectedDump(wxListEvent& evt) void Dialogs::GSDumpDialog::SelectedDump(wxListEvent& evt)
{ {
wxString filename_preview = g_Conf->Folders.Snapshots.ToAscii() + ("/" + evt.GetText()) + ".png"; wxString filename_preview = g_Conf->Folders.Snapshots.ToAscii() + ("/" + evt.GetText()) + ".png";
wxString filename = g_Conf->Folders.Snapshots.ToAscii() + ("/" + evt.GetText()) + ".gs"; wxString filename = g_Conf->Folders.Snapshots.ToAscii() + ("/" + evt.GetText()) + ".gs";
if (!wxFileExists(filename))
filename.append(".xz");
if (wxFileExists(filename_preview)) if (wxFileExists(filename_preview))
{ {
auto img = wxImage(filename_preview); auto img = wxImage(filename_preview);
@ -337,15 +346,18 @@ void Dialogs::GSDumpDialog::RunDump(wxCommandEvent& event)
{ {
if (!m_run->IsEnabled()) if (!m_run->IsEnabled())
return; return;
m_thread->m_dump_file = std::make_unique<pxInputStream>(m_selected_dump, new wxFFileInputStream(m_selected_dump)); FILE* dumpfile = wxFopen(m_selected_dump, L"rb");
if (!dumpfile)
if (!(m_thread->m_dump_file)->IsOk())
{ {
wxString s; wxString s;
s.Printf(_("Failed to load the dump %s !"), m_selected_dump); s.Printf(_("Failed to load the dump %s !"), m_selected_dump);
wxMessageBox(s, _("GS Debugger"), wxICON_ERROR); wxMessageBox(s, _("GS Debugger"), wxICON_ERROR);
return; return;
} }
if (m_selected_dump.EndsWith(".xz"))
m_thread->m_dump_file = std::make_unique<GSDumpLzma>(dumpfile, nullptr);
else
m_thread->m_dump_file = std::make_unique<GSDumpRaw >(dumpfile, nullptr);
m_run->Disable(); m_run->Disable();
m_settings->Disable(); m_settings->Disable();
m_debug_mode->Enable(); m_debug_mode->Enable();
@ -851,7 +863,7 @@ Dialogs::GSDumpDialog::GSThread::~GSThread()
void Dialogs::GSDumpDialog::GSThread::OnStop() void Dialogs::GSDumpDialog::GSThread::OnStop()
{ {
m_root_window->m_button_events.clear(); m_root_window->m_button_events.clear();
m_dump_file->Close(); m_dump_file = nullptr;
wxCommandEvent event(EVT_CLOSE_DUMP); wxCommandEvent event(EVT_CLOSE_DUMP);
wxPostEvent(m_root_window, event); wxPostEvent(m_root_window, event);
@ -900,29 +912,17 @@ void Dialogs::GSDumpDialog::GSThread::ExecuteTaskInThread()
freezeData fd = {(int)ss, (u8*)state_data.get()}; freezeData fd = {(int)ss, (u8*)state_data.get()};
m_root_window->m_dump_packets.clear(); m_root_window->m_dump_packets.clear();
// Calling Length() internally does fseek() -> ftell() -> fseek(). Slow. while (!m_dump_file->IsEof())
// Calling ftell() for Tell() doesn't seem to be very cheap either.
// So we track the position ourselves.
const wxFileOffset length = m_dump_file->Length();
wxFileOffset pos = m_dump_file->Tell();
#define READ_FROM_DUMP_FILE(var, size) \
do \
{ \
m_dump_file->Read(var, size); \
pos += size; \
} while (0)
while (pos < length)
{ {
GSType id; GSType id;
GSTransferPath id_transfer = GSTransferPath::Dummy; GSTransferPath id_transfer = GSTransferPath::Dummy;
READ_FROM_DUMP_FILE(&id, 1); m_dump_file->Read(&id, 1);
s32 size = 0; s32 size = 0;
switch (id) switch (id)
{ {
case GSType::Transfer: case GSType::Transfer:
READ_FROM_DUMP_FILE(&id_transfer, 1); m_dump_file->Read(&id_transfer, 1);
READ_FROM_DUMP_FILE(&size, 4); m_dump_file->Read(&size, 4);
break; break;
case GSType::VSync: case GSType::VSync:
size = 1; size = 1;
@ -935,10 +935,9 @@ void Dialogs::GSDumpDialog::GSThread::ExecuteTaskInThread()
break; break;
} }
std::unique_ptr<char[]> data(new char[size]); std::unique_ptr<char[]> data(new char[size]);
READ_FROM_DUMP_FILE(data.get(), size); m_dump_file->Read(data.get(), size);
m_root_window->m_dump_packets.push_back({id, std::move(data), size, id_transfer}); m_root_window->m_dump_packets.push_back({id, std::move(data), size, id_transfer});
} }
#undef READ_FROM_DUMP_FILE
GSinit(); GSinit();
sApp.OpenGsPanel(); sApp.OpenGsPanel();

View File

@ -19,6 +19,7 @@
#include "ConfigurationDialog.h" #include "ConfigurationDialog.h"
#include "gui/Panels/ConfigurationPanels.h" #include "gui/Panels/ConfigurationPanels.h"
#include "common/pxStreams.h" #include "common/pxStreams.h"
#include "GS/GSLzma.h"
#include <wx/wizard.h> #include <wx/wizard.h>
#include <wx/treectrl.h> #include <wx/treectrl.h>
@ -276,7 +277,7 @@ namespace Dialogs
int m_renderer = 0; int m_renderer = 0;
bool m_debug = false; bool m_debug = false;
size_t m_debug_index; size_t m_debug_index;
std::unique_ptr<pxInputStream> m_dump_file; std::unique_ptr<GSDumpFile> m_dump_file;
GSThread(GSDumpDialog* dlg); GSThread(GSDumpDialog* dlg);
virtual ~GSThread(); virtual ~GSThread();
}; };