diff --git a/pcsx2/GS/GSLzma.cpp b/pcsx2/GS/GSLzma.cpp index d2fd8d128d..39842170de 100644 --- a/pcsx2/GS/GSLzma.cpp +++ b/pcsx2/GS/GSLzma.cpp @@ -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) { if (m_repack_fp == nullptr) @@ -56,7 +61,17 @@ GSDumpFile::~GSDumpFile() GSDumpLzma::GSDumpLzma(char* filename, const char* 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)); 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) : GSDumpFile(filename, repack_filename) { - m_buff_size = 0; - m_area = nullptr; - m_inbuf = nullptr; - m_avail = 0; - m_start = 0; +} + +GSDumpRaw::GSDumpRaw(FILE* file, FILE* repack_file) + : GSDumpFile(file, repack_file) +{ } bool GSDumpRaw::IsEof() diff --git a/pcsx2/GS/GSLzma.h b/pcsx2/GS/GSLzma.h index 9efe7b6ef9..363999cfbd 100644 --- a/pcsx2/GS/GSLzma.h +++ b/pcsx2/GS/GSLzma.h @@ -29,6 +29,7 @@ public: virtual bool Read(void* ptr, size_t size) = 0; GSDumpFile(char* filename, const char* repack_filename); + GSDumpFile(FILE* file, FILE* repack_file); virtual ~GSDumpFile(); }; @@ -44,9 +45,11 @@ class GSDumpLzma : public GSDumpFile size_t m_start; void Decompress(); + void Initialize(); public: GSDumpLzma(char* filename, const char* repack_filename); + GSDumpLzma(FILE* file, FILE* repack_file); virtual ~GSDumpLzma(); bool IsEof() final; @@ -55,15 +58,9 @@ public: 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: GSDumpRaw(char* filename, const char* repack_filename); + GSDumpRaw(FILE* file, FILE* repack_file); virtual ~GSDumpRaw() = default; bool IsEof() final; diff --git a/pcsx2/gui/Dialogs/GSDumpDialog.cpp b/pcsx2/gui/Dialogs/GSDumpDialog.cpp index 8c0ea6d1da..9f467931b8 100644 --- a/pcsx2/gui/Dialogs/GSDumpDialog.cpp +++ b/pcsx2/gui/Dialogs/GSDumpDialog.cpp @@ -277,25 +277,34 @@ void Dialogs::GSDumpDialog::GetDumpsList() m_dump_list->ClearAll(); wxDir snaps(g_Conf->Folders.Snapshots.ToAscii()); wxString filename; - bool cont = snaps.GetFirst(&filename, "*.gs", wxDIR_DEFAULT); - int i = 0, h = 0, j = 0; + bool cont = snaps.GetFirst(&filename); + int h = 0, j = 0; m_dump_list->AppendColumn("Dumps"); // set the column size to be exactly of the size of our list m_dump_list->GetSize(&h, &j); m_dump_list->SetColumnWidth(0, h); + std::vector dumps; while (cont) { - m_dump_list->InsertItem(i, filename.substr(0, filename.find_last_of("."))); - i++; + if (filename.EndsWith(".gs")) + 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); } + 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) { wxString filename_preview = g_Conf->Folders.Snapshots.ToAscii() + ("/" + evt.GetText()) + ".png"; wxString filename = g_Conf->Folders.Snapshots.ToAscii() + ("/" + evt.GetText()) + ".gs"; + if (!wxFileExists(filename)) + filename.append(".xz"); if (wxFileExists(filename_preview)) { auto img = wxImage(filename_preview); @@ -337,15 +346,18 @@ void Dialogs::GSDumpDialog::RunDump(wxCommandEvent& event) { if (!m_run->IsEnabled()) return; - m_thread->m_dump_file = std::make_unique(m_selected_dump, new wxFFileInputStream(m_selected_dump)); - - if (!(m_thread->m_dump_file)->IsOk()) + FILE* dumpfile = wxFopen(m_selected_dump, L"rb"); + if (!dumpfile) { wxString s; s.Printf(_("Failed to load the dump %s !"), m_selected_dump); wxMessageBox(s, _("GS Debugger"), wxICON_ERROR); return; } + if (m_selected_dump.EndsWith(".xz")) + m_thread->m_dump_file = std::make_unique(dumpfile, nullptr); + else + m_thread->m_dump_file = std::make_unique(dumpfile, nullptr); m_run->Disable(); m_settings->Disable(); m_debug_mode->Enable(); @@ -851,7 +863,7 @@ Dialogs::GSDumpDialog::GSThread::~GSThread() void Dialogs::GSDumpDialog::GSThread::OnStop() { m_root_window->m_button_events.clear(); - m_dump_file->Close(); + m_dump_file = nullptr; wxCommandEvent event(EVT_CLOSE_DUMP); wxPostEvent(m_root_window, event); @@ -900,29 +912,17 @@ void Dialogs::GSDumpDialog::GSThread::ExecuteTaskInThread() freezeData fd = {(int)ss, (u8*)state_data.get()}; m_root_window->m_dump_packets.clear(); - // Calling Length() internally does fseek() -> ftell() -> fseek(). Slow. - // 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) + while (!m_dump_file->IsEof()) { GSType id; GSTransferPath id_transfer = GSTransferPath::Dummy; - READ_FROM_DUMP_FILE(&id, 1); + m_dump_file->Read(&id, 1); s32 size = 0; switch (id) { case GSType::Transfer: - READ_FROM_DUMP_FILE(&id_transfer, 1); - READ_FROM_DUMP_FILE(&size, 4); + m_dump_file->Read(&id_transfer, 1); + m_dump_file->Read(&size, 4); break; case GSType::VSync: size = 1; @@ -935,10 +935,9 @@ void Dialogs::GSDumpDialog::GSThread::ExecuteTaskInThread() break; } std::unique_ptr 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}); } -#undef READ_FROM_DUMP_FILE GSinit(); sApp.OpenGsPanel(); diff --git a/pcsx2/gui/Dialogs/ModalPopups.h b/pcsx2/gui/Dialogs/ModalPopups.h index e9c8552214..b601d64c88 100644 --- a/pcsx2/gui/Dialogs/ModalPopups.h +++ b/pcsx2/gui/Dialogs/ModalPopups.h @@ -19,6 +19,7 @@ #include "ConfigurationDialog.h" #include "gui/Panels/ConfigurationPanels.h" #include "common/pxStreams.h" +#include "GS/GSLzma.h" #include #include @@ -276,7 +277,7 @@ namespace Dialogs int m_renderer = 0; bool m_debug = false; size_t m_debug_index; - std::unique_ptr m_dump_file; + std::unique_ptr m_dump_file; GSThread(GSDumpDialog* dlg); virtual ~GSThread(); };