gsdump: switch to Add instead of += overloading, unlink about and gsdump

This commit is contained in:
Gauvain 'GovanifY' Roussel-Tarbouriech 2021-03-08 13:25:24 +01:00 committed by Kojin
parent d8b52111cf
commit f407c5aabd
3 changed files with 30 additions and 855 deletions

View File

@ -1,825 +0,0 @@
/* PCSX2 - PS2 Emulator for PCs
* Copyright (C) 2002-2020 PCSX2 Dev Team
*
* PCSX2 is free software: you can redistribute it and/or modify it under the terms
* of the GNU Lesser General Public License as published by the Free Software Found-
* ation, either version 3 of the License, or (at your option) any later version.
*
* PCSX2 is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
* PURPOSE. See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with PCSX2.
* If not, see <http://www.gnu.org/licenses/>.
*/
#include "PrecompiledHeader.h"
#include "App.h"
#include "AppCommon.h"
#include "MSWstuff.h"
#include "Dialogs/ModalPopups.h"
#include "Utilities/EmbeddedImage.h"
#include "Resources/NoIcon.h"
#include "GS.h"
#include "PathDefs.h"
#include "AppConfig.h"
#include "Plugins.h"
#include "GSFrame.h"
#include "Counters.h"
#include <wx/mstream.h>
#include <wx/listctrl.h>
#include <wx/filepicker.h>
#include <wx/radiobut.h>
#include <wx/button.h>
#include <wx/treectrl.h>
#include <wx/checkbox.h>
#include <wx/dir.h>
#include <wx/image.h>
#include <wx/wfstream.h>
#include <functional>
namespace GSDump
{
bool isRunning = false;
}
using namespace pxSizerFlags;
// --------------------------------------------------------------------------------------
// GSDumpDialog Implementation
// --------------------------------------------------------------------------------------
Dialogs::GSDumpDialog::GSDumpDialog(wxWindow* parent)
: wxDialogWithHelpers(parent, _("GSDumpGov"), pxDialogFlags())
, m_dump_list(new wxListView(this, ID_DUMP_LIST, wxDefaultPosition, wxSize(400, 300), wxLC_NO_HEADER | wxLC_REPORT | wxLC_SINGLE_SEL))
, m_preview_image(new wxStaticBitmap(this, wxID_ANY, wxBitmap(EmbeddedImage<res_NoIcon>().Get()), wxDefaultPosition, wxSize(400,250)))
, m_debug_mode(new wxCheckBox(this, ID_DEBUG_MODE, _("Debug Mode")))
, m_renderer_overrides(new wxRadioBox())
, m_gif_list(new wxTreeCtrl(this, ID_SEL_PACKET, wxDefaultPosition, wxSize(400, 300), wxTR_HIDE_ROOT | wxTR_HAS_BUTTONS | wxTR_LINES_AT_ROOT))
, m_gif_packet(new wxTreeCtrl(this, wxID_ANY, wxDefaultPosition, wxSize(400, 300), wxTR_HIDE_ROOT | wxTR_HAS_BUTTONS | wxTR_LINES_AT_ROOT))
, m_start(new wxButton(this, ID_RUN_START, _("Go to Start"), wxDefaultPosition, wxSize(150,50)))
, m_step(new wxButton(this, ID_RUN_START, _("Step"), wxDefaultPosition, wxSize(150, 50)))
, m_selection(new wxButton(this, ID_RUN_START, _("Run to Selection"), wxDefaultPosition, wxSize(150, 50)))
, m_vsync(new wxButton(this, ID_RUN_START, _("Go to next VSync"), wxDefaultPosition, wxSize(150, 50)))
, m_thread(std::make_unique<GSThread>(this))
, m_run(new wxButton(this, ID_RUN_DUMP, _("Run"), wxDefaultPosition, wxSize(150, 100)))
{
wxBoxSizer& dump_info(*new wxBoxSizer(wxVERTICAL));
wxBoxSizer& dump_preview(*new wxBoxSizer(wxVERTICAL));
wxFlexGridSizer& debugger(*new wxFlexGridSizer(3, StdPadding, StdPadding));
wxBoxSizer& dumps(*new wxBoxSizer(wxHORIZONTAL));
wxBoxSizer& dbg_tree(*new wxBoxSizer(wxVERTICAL));
wxBoxSizer& dbg_actions(*new wxBoxSizer(wxVERTICAL));
wxBoxSizer& gif(*new wxBoxSizer(wxVERTICAL));
wxBoxSizer& dumps_list(*new wxBoxSizer(wxVERTICAL));
wxArrayString rdoverrides;
rdoverrides.Add("None");
rdoverrides.Add("OGL SW");
rdoverrides.Add("D3D11 HW");
rdoverrides.Add("OGL HW");
m_renderer_overrides->Create(this, wxID_ANY, "Renderer overrides", wxDefaultPosition, wxDefaultSize, rdoverrides, 1);
dbg_tree += new wxStaticText(this, wxID_ANY, _("GIF Packets"));
dbg_tree += m_gif_list | StdExpand();
dbg_actions += m_debug_mode;
dbg_actions += m_start | StdExpand();
dbg_actions += m_step | StdExpand();
dbg_actions += m_selection | StdExpand();
dbg_actions += m_vsync | StdExpand();
gif += new wxStaticText(this, wxID_ANY, _("Packet Content"));
gif += m_gif_packet | StdExpand();
dumps_list += new wxStaticText(this, wxID_ANY, _("GS Dumps List")) | StdExpand();
dumps_list += m_dump_list | StdExpand();
dump_info += m_renderer_overrides | StdExpand();
dump_info += m_run | StdExpand();
dump_preview += new wxStaticText(this, wxID_ANY, _("Preview")) | StdExpand();
dump_preview += m_preview_image | StdCenter();
dumps += dumps_list;
dumps += dump_info;
dumps += dump_preview;
debugger += dbg_tree;
debugger += dbg_actions;
debugger += gif;
*this += dumps;
*this += debugger;
// populate UI and setup state
m_debug_mode->Disable();
m_start->Disable();
m_step->Disable();
m_selection->Disable();
m_vsync->Disable();
GetDumpsList();
m_fs_watcher.SetOwner(this);
m_fs_watcher.Add(wxFileName(g_Conf->Folders.Snapshots.ToAscii()));
wxEvtHandler::Connect(wxEVT_FSWATCHER, wxFileSystemWatcherEventHandler(Dialogs::GSDumpDialog::PathChanged));
Bind(wxEVT_LIST_ITEM_SELECTED, &Dialogs::GSDumpDialog::SelectedDump, this, ID_DUMP_LIST);
Bind(wxEVT_BUTTON, &Dialogs::GSDumpDialog::RunDump, this, ID_RUN_DUMP);
Bind(wxEVT_BUTTON, &Dialogs::GSDumpDialog::ToStart, this, ID_RUN_START);
Bind(wxEVT_BUTTON, &Dialogs::GSDumpDialog::StepPacket, this, ID_RUN_STEP);
Bind(wxEVT_BUTTON, &Dialogs::GSDumpDialog::ToCursor, this, ID_RUN_CURSOR);
Bind(wxEVT_BUTTON, &Dialogs::GSDumpDialog::ToVSync, this, ID_RUN_VSYNC);
Bind(wxEVT_TREE_SEL_CHANGED, &Dialogs::GSDumpDialog::ParsePacket, this, ID_SEL_PACKET);
Bind(wxEVT_CHECKBOX, &Dialogs::GSDumpDialog::CheckDebug, this, ID_DEBUG_MODE);
}
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;
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);
while (cont)
{
m_dump_list->InsertItem(i, filename.substr(0, filename.find_last_of(".")));
i++;
cont = snaps.GetNext(&filename);
}
}
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_preview))
{
auto img = wxImage(filename_preview);
img.Rescale(400,250, wxIMAGE_QUALITY_HIGH);
m_preview_image->SetBitmap(wxBitmap(img));
}
else
m_preview_image->SetBitmap(EmbeddedImage<res_NoIcon>().Get());
m_selected_dump = wxString(filename);
}
void Dialogs::GSDumpDialog::RunDump(wxCommandEvent& event)
{
m_debug_mode->Enable();
m_start->Enable();
m_step->Enable();
m_selection->Enable();
m_vsync->Enable();
m_run->Disable();
GetCorePlugins().Shutdown();
m_thread->m_dump_file = std::make_unique<pxInputStream>(m_selected_dump, new wxFFileInputStream(m_selected_dump));
if (!(m_thread->m_dump_file)->IsOk())
{
wxString s;
s.Printf(_("Failed to load the dump %s !"), m_selected_dump);
wxMessageBox(s, _("GSDumpGov"), wxICON_ERROR);
return;
}
m_thread->Start();
return;
}
void Dialogs::GSDumpDialog::ProcessDumpEvent(const GSData& event, char* regs)
{
switch (event.id)
{
case Transfer:
{
switch (event.path)
{
case Path1Old:
{
std::unique_ptr<char[]> data(new char[16384]);
int addr = 16384 - event.length;
memcpy(data.get(), event.data.get() + addr, event.length);
GSgifTransfer1((u32*)data.get(), addr);
break;
}
case Path1New:
GSgifTransfer((u32*)event.data.get(), event.length / 16);
break;
case Path2:
GSgifTransfer2((u32*)event.data.get(), event.length / 16);
break;
case Path3:
GSgifTransfer3((u32*)event.data.get(), event.length / 16);
break;
default:
break;
}
break;
}
case VSync:
{
GSvsync((*((int*)(regs + 4096)) & 0x2000) > 0 ? (u8)1 : (u8)0);
g_FrameCount++;
Pcsx2App* app = (Pcsx2App*)wxApp::GetInstance();
if (app)
app->FpsManager.DoFrame();
break;
}
case ReadFIFO2:
{
std::unique_ptr<char[]> arr(new char[*((int*)event.data.get())]);
GSreadFIFO2((u64*)arr.get(), *((int*)event.data.get()));
break;
}
case Registers:
memcpy(regs, event.data.get(), 8192);
break;
}
}
void Dialogs::GSDumpDialog::StepPacket(wxCommandEvent& event)
{
m_button_events.push_back(GSEvent{Step, 0});
}
void Dialogs::GSDumpDialog::ToCursor(wxCommandEvent& event)
{
m_button_events.push_back(GSEvent{RunCursor, wxAtoi(m_gif_list->GetItemText(m_gif_list->GetFocusedItem()).BeforeFirst('-'))});
}
void Dialogs::GSDumpDialog::ToVSync(wxCommandEvent& event)
{
m_button_events.push_back(GSEvent{RunVSync, 0});
}
void Dialogs::GSDumpDialog::ToStart(wxCommandEvent& event)
{
m_button_events.push_back(GSEvent{RunCursor, 0});
}
void Dialogs::GSDumpDialog::GenPacketList()
{
int i = 0;
m_gif_list->DeleteAllItems();
wxTreeItemId mainrootId = m_gif_list->AddRoot("root");
wxTreeItemId rootId = m_gif_list->AppendItem(mainrootId, "0 - VSync");
for (auto& element : m_dump_packets)
{
wxString s, t;
element.id == Transfer ? t.Printf(" - %s", GSTransferPathNames[element.path]) : t.Printf("");
s.Printf("%d - %s%s - %d byte", i, GSTypeNames[element.id], t, element.length);
if (element.id == VSync)
{
m_gif_list->SetItemText(rootId, s);
rootId = m_gif_list->AppendItem(mainrootId, "VSync");
}
else
m_gif_list->AppendItem(rootId, s);
i++;
}
m_gif_list->Delete(rootId);
}
void Dialogs::GSDumpDialog::GenPacketInfo(GSData& dump)
{
m_gif_packet->DeleteAllItems();
wxTreeItemId rootId = m_gif_packet->AddRoot("root");
switch (dump.id)
{
case Transfer:
{
wxTreeItemId trootId;
wxString s;
s.Printf("Transfer Path %s", GSTransferPathNames[dump.path]);
trootId = m_gif_packet->AppendItem(rootId, s);
u64 tag = *(u64*)(dump.data.get());
u64 regs = *(u64*)(dump.data.get() + 8);
u32 nloop = tag & ((1 << 15) - 1);
u8 eop = (tag >> 15) & 1;
u8 pre = (tag >> 46) & 1;
u32 prim = (tag >> 47) & ((1 << 11) - 1);
u8 flg = ((tag >> 58) & 3);
u32 nreg = (u32)((tag >> 60) & ((1 << 4) - 1));
if (nreg == 0)
nreg = 16;
std::vector<wxString> infos(7);
m_stored_q = 1.0;
infos[0].Printf("nloop = %u", nloop);
infos[1].Printf("eop = %u", eop);
infos[2].Printf("flg = %s", GifFlagNames[flg]);
infos[3].Printf("pre = %u", pre);
infos[4].Printf("Prim");
infos[5].Printf("nreg = %u", nreg);
infos[6].Printf("reg");
wxTreeItemId primId;
wxTreeItemId regId;
for (int i = 0; i < 7; i++)
{
wxTreeItemId res = m_gif_packet->AppendItem(trootId, infos[i]);
switch (i)
{
case 4:
ParseTreePrim(res, prim);
break;
case 6:
regId = res;
break;
}
}
int p = 16;
switch ((GifFlag)flg)
{
case GIF_FLG_PACKED:
{
for (u32 j = 0; j < nloop; j++)
{
for (u32 i = 0; i < nreg; i++)
{
u128 reg_data;
reg_data.lo = *(u64*)(dump.data.get() + p);
reg_data.hi = *(u64*)(dump.data.get() + p + 8);
ParseTreeReg(regId, (GIFReg)((regs >> (i * 4)) & ((u64)(1 << 4) - 1)), reg_data, true);
p += 16;
}
}
break;
}
case GIF_FLG_REGLIST:
{
for (u32 j = 0; j < nloop; j++)
{
for (u32 i = 0; i < nreg; i++)
{
u128 reg_data;
reg_data.lo = *(u64*)(dump.data.get() + p);
ParseTreeReg(regId, (GIFReg)((regs >> (i * 4)) & ((u64)(1 << 4) - 1)), reg_data, false);
p += 8;
}
}
break;
}
case GIF_FLG_IMAGE:
case GIF_FLG_IMAGE2:
{
wxString z;
s.Printf("IMAGE %d bytes", nloop * 16);
m_gif_packet->AppendItem(regId, z);
break;
}
}
break;
}
case VSync:
{
wxString s;
s.Printf("Field = %u", *(u8*)(dump.data.get()));
m_gif_packet->AppendItem(rootId, s);
break;
}
case ReadFIFO2:
{
wxString s;
s.Printf("ReadFIFO2: Size = %d byte", dump.length);
m_gif_packet->AppendItem(rootId, s);
break;
}
case Registers:
m_gif_packet->AppendItem(rootId, "Registers");
break;
}
m_gif_packet->ExpandAll();
}
void Dialogs::GSDumpDialog::ParsePacket(wxTreeEvent& event)
{
int id = wxAtoi(m_gif_list->GetItemText(event.GetItem()).BeforeFirst('-'));
GenPacketInfo(m_dump_packets[id]);
}
void Dialogs::GSDumpDialog::ParseTreeReg(wxTreeItemId& id, GIFReg reg, u128 data, bool packed)
{
wxTreeItemId rootId = m_gif_packet->AppendItem(id, wxString(GIFRegName(reg)));
switch (reg)
{
case PRIM:
ParseTreePrim(rootId, data.lo);
break;
case RGBAQ:
{
std::vector<wxString> rgb_infos(5);
if (packed)
{
rgb_infos[0].Printf("R = %u", (u32)(data.lo & ((u64)(1 << 8) - 1)));
rgb_infos[1].Printf("G = %u", (u32)((data.lo >> 32) & ((u64)(1 << 8) - 1)));
rgb_infos[2].Printf("B = %u", (u32)(data.hi & ((u64)(1 << 8) - 1)));
rgb_infos[3].Printf("A = %u", (u32)((data.hi >> 32) & ((u64)(1 << 8) - 1)));
rgb_infos[4].Printf("Q = %u", m_stored_q);
}
else
{
rgb_infos[0].Printf("R = %u", (u32)(data.lo & ((u64)(1 << 8) - 1)));
rgb_infos[1].Printf("G = %u", (u32)((data.lo >> 8) & ((u64)(1 << 8) - 1)));
rgb_infos[2].Printf("B = %u", (u32)((data.lo >> 16) & ((u64)(1 << 8) - 1)));
rgb_infos[3].Printf("A = %u", (u32)((data.lo >> 24) & ((u64)(1 << 8) - 1)));
rgb_infos[4].Printf("Q = %u", *(u32*)(&data.lo + 4));
}
for (auto& el : rgb_infos)
m_gif_packet->AppendItem(rootId, el);
break;
}
case ST:
{
std::vector<wxString> st_infos(2);
st_infos[0].Printf("S = %f", *(float*)(&data.lo));
st_infos[1].Printf("T = %f", *(float*)(&data.lo + 4));
if (packed)
{
wxString q;
m_stored_q = *(float*)(&data.hi + 4);
q.Printf("Q = %f", m_stored_q);
st_infos.push_back(q);
}
for (auto& el : st_infos)
m_gif_packet->AppendItem(rootId, el);
break;
}
case UV:
{
wxString s, t;
double v;
s.Printf("U = %f", (double)(data.lo & ((u64)(1 << 14) - 1)) / 16.0);
if (packed)
v = (double)((data.lo >> 32) & ((u64)(1 << 14) - 1)) / 16.0;
else
v = (double)((data.lo >> 16) & ((u64)(1 << 14) - 1)) / 16.0;
t.Printf("V = %u", v);
m_gif_packet->AppendItem(rootId, s);
m_gif_packet->AppendItem(rootId, t);
break;
}
case XYZF2:
case XYZF3:
{
if (packed && (reg == XYZF2) && ((data.lo >> 47) & ((u64)(1 << 1) - 1)) == 1)
m_gif_packet->SetItemText(rootId, GIFRegName(XYZF3));
std::vector<wxString> xyzf_infos(4);
if (packed)
{
xyzf_infos[0].Printf("X = %f", (float)(data.lo & ((u64)(1 << 16) - 1)) / 16.0);
xyzf_infos[1].Printf("Y = %f", (float)((data.lo >> 32) & ((u64)(1 << 16) - 1)) / 16.0);
xyzf_infos[2].Printf("Z = %u", (u32)((data.hi >> 4) & ((u64)(1 << 24) - 1)));
xyzf_infos[3].Printf("F = %u", (u32)((data.hi >> 36) & ((u64)(1 << 8) - 1)));
}
else
{
xyzf_infos[0].Printf("X = %f", (float)(data.lo & ((u64)(1 << 16) - 1)) / 16.0);
xyzf_infos[1].Printf("Y = %f", (float)((data.lo >> 16) & ((u64)(1 << 16) - 1)) / 16.0);
xyzf_infos[2].Printf("Z = %u", (u32)((data.lo >> 32) & ((u64)(1 << 24) - 1)));
xyzf_infos[3].Printf("F = %u", (u32)((data.lo >> 56) & ((u64)(1 << 8) - 1)));
}
for (auto& el : xyzf_infos)
m_gif_packet->AppendItem(rootId, el);
break;
}
case XYZ2:
case XYZ3:
{
if (packed && (reg == XYZ2) && ((data.lo >> 47) & ((u64)(1 << 1) - 1)) == 1)
m_gif_packet->SetItemText(rootId, GIFRegName(XYZ3));
std::vector<wxString> xyz_infos(3);
if (packed)
{
xyz_infos[0].Printf("X = %f", (float)(data.lo & ((u64)(1 << 16) - 1)) / 16.0);
xyz_infos[1].Printf("Y = %f", (float)((data.lo >> 32) & ((u64)(1 << 16) - 1)) / 16.0);
xyz_infos[2].Printf("Z = %u", *(u32*)(&data.hi));
}
else
{
xyz_infos[0].Printf("X = %f", (float)(data.lo & ((u64)(1 << 16) - 1)) / 16.0);
xyz_infos[1].Printf("Y = %f", (float)((data.lo >> 16) & ((u64)(1 << 16) - 1)) / 16.0);
xyz_infos[2].Printf("Z = %u", *(u32*)(&data.lo)+4);
}
for (auto& el : xyz_infos)
m_gif_packet->AppendItem(rootId, el);
break;
}
case TEX0_1:
case TEX0_2:
{
std::vector<wxString> tex_infos(12);
tex_infos[0].Printf("TBP0 = %u", (u32)(data.lo & ((u64)(1 << 14) - 1)));
tex_infos[1].Printf("TBW = %u", (u32)((data.lo >> 14) & ((u64)(1 << 6) - 1)));
tex_infos[2].Printf("PSM = %s", TEXPSMNames[(u32)((data.lo >> 20) & ((u64)(1 << 6) - 1))]);
tex_infos[3].Printf("TW = %u", (u32)((data.lo >> 26) & ((u64)(1 << 4) - 1)));
tex_infos[4].Printf("TH = %u", (u32)((data.lo >> 30) & ((u64)(1 << 4) - 1)));
tex_infos[5].Printf("TCC = %s", TEXTCCNames[(u32)((data.lo >> 34) & ((u64)(1 << 1) - 1))]);
tex_infos[6].Printf("TFX = %s", TEXTFXNames[(u32)((data.lo >> 35) & ((u64)(1 << 2) - 1))]);
tex_infos[7].Printf("CBP = %u", (u32)((data.lo >> 37) & ((u64)(1 << 14) - 1)));
tex_infos[8].Printf("CPSM = %s", TEXCPSMNames[(u32)((data.lo >> 51) & ((u64)(1 << 4) - 1))]);
tex_infos[9].Printf("CSM = %s", TEXCSMNames[(u32)((data.lo >> 55) & ((u64)(1 << 1) - 1))]);
tex_infos[10].Printf("CSA = %u", (u32)((data.lo >> 56) & ((u64)(1 << 5) - 1)));
tex_infos[11].Printf("CLD = %u", (u32)((data.lo >> 61) & ((u64)(1 << 3) - 1)));
for (auto& el : tex_infos)
m_gif_packet->AppendItem(rootId, el);
break;
}
case FOG:
{
wxString s;
if (packed)
s.Printf("F = %u", (u32)((data.hi >> 36) & ((u64)(1 << 8) - 1)));
else
s.Printf("F = %u", (u32)((data.lo >> 56) & ((u64)(1 << 8) - 1)));
m_gif_packet->AppendItem(rootId, s);
break;
}
case AD:
{
GIFReg nreg = (GIFReg)(data.hi & ((u64)(1 << 8) - 1));
if ((GIFReg)nreg == AD)
{
wxString s;
s.Printf("NOP");
m_gif_packet->AppendItem(id, s);
}
else
ParseTreeReg(id, nreg, data, packed);
m_gif_packet->Delete(rootId);
break;
}
default:
break;
}
}
void Dialogs::GSDumpDialog::ParseTreePrim(wxTreeItemId& id, u32 prim)
{
std::vector<wxString> prim_infos(9);
prim_infos[0].Printf("Primitive Type = %s", GsPrimNames[(prim & ((u64)(1 << 3) - 1))]);
prim_infos[1].Printf("IIP = %s", GsIIPNames[((prim >> 3) & 1)]);
prim_infos[2].Printf("TME = %s", (bool)((prim >> 4) & 1) ? "True" : "False");
prim_infos[3].Printf("FGE = %s", (bool)((prim >> 5) & 1) ? "True" : "False");
prim_infos[4].Printf("FGE = %s", (bool)((prim >> 6) & 1) ? "True" : "False");
prim_infos[5].Printf("AA1 = %s", (bool)((prim >> 7) & 1) ? "True" : "False");
prim_infos[6].Printf("FST = %s", GsFSTNames[((prim >> 3) & 1)]);
prim_infos[7].Printf("CTXT = %s", GsCTXTNames[((prim >> 9) & 1)]);
prim_infos[8].Printf("FIX = %s", GsFIXNames[((prim >> 10) & 1)]);
for (auto& el : prim_infos)
m_gif_packet->AppendItem(id, el);
}
void Dialogs::GSDumpDialog::CheckDebug(wxCommandEvent& event)
{
if (m_debug_mode->GetValue())
GenPacketList();
else
{
m_gif_list->DeleteAllItems();
m_gif_packet->DeleteAllItems();
m_gif_list->Refresh();
}
}
Dialogs::GSDumpDialog::GSThread::GSThread(GSDumpDialog* dlg)
: pxThread("GSDump")
, m_root_window(dlg)
{
}
Dialogs::GSDumpDialog::GSThread::~GSThread()
{
try
{
pxThread::Cancel();
}
DESTRUCTOR_CATCHALL
}
void Dialogs::GSDumpDialog::GSThread::OnStop()
{
m_root_window->m_debug_mode->Disable();
m_root_window->m_start->Disable();
m_root_window->m_step->Disable();
m_root_window->m_selection->Disable();
m_root_window->m_vsync->Disable();
m_root_window->m_gif_list->DeleteAllItems();
m_root_window->m_gif_packet->DeleteAllItems();
m_root_window->m_gif_list->Refresh();
m_root_window->m_button_events.clear();
m_root_window->m_debug_mode->SetValue(false);
m_root_window->m_run->Enable();
m_dump_file->Close();
}
void Dialogs::GSDumpDialog::GSThread::ExecuteTaskInThread()
{
GSDump::isRunning = true;
u32 crc = 0, ss = 0;
s8 renderer_override = 0;
switch (m_root_window->m_renderer_overrides->GetSelection())
{
// OGL SW
case 1:
renderer_override = 13;
break;
// D3D11 HW
case 2:
renderer_override = 3;
break;
// OGL HW
case 3:
renderer_override = 12;
break;
default:
break;
}
char regs[8192];
m_dump_file->Read(&crc, 4);
m_dump_file->Read(&ss, 4);
std::unique_ptr<char[]> state_data(new char[ss]);
m_dump_file->Read(state_data.get(), ss);
m_dump_file->Read(&regs, 8192);
freezeData fd = {(int)ss, (s8*)state_data.get()};
m_root_window->m_dump_packets.clear();
while ( m_dump_file->Tell() < m_dump_file->Length())
{
GSType id = Transfer;
m_dump_file->Read(&id, 1);
switch (id)
{
case Transfer:
{
GSTransferPath id_transfer;
m_dump_file->Read(&id_transfer, 1);
s32 size = 0;
m_dump_file->Read(&size, 4);
std::unique_ptr<char[]> transfer_data(new char[size]);
m_dump_file->Read(transfer_data.get(), size);
m_root_window->m_dump_packets.push_back({id, std::move(transfer_data), size, id_transfer});
break;
}
case VSync:
{
std::unique_ptr<char[]> vsync(new char[1]);
m_dump_file->Read(vsync.get(), 1);
m_root_window->m_dump_packets.push_back({id, std::move(vsync), 1, Dummy});
break;
}
case ReadFIFO2:
{
std::unique_ptr<char[]> fifo(new char[4]);
m_dump_file->Read(fifo.get(), 4);
m_root_window->m_dump_packets.push_back({id, std::move(fifo), 4, Dummy});
break;
}
case Registers:
{
std::unique_ptr<char[]> regs_tmp(new char[8192]);
m_dump_file->Read(regs_tmp.get(), 8192);
m_root_window->m_dump_packets.push_back({id, std::move(regs_tmp), 8192, Dummy});
break;
}
}
}
if (m_root_window->m_debug_mode->GetValue())
m_root_window->GenPacketList();
//return here to debug pre gs
//return;
GetCorePlugins().Init();
sApp.OpenGsPanel();
// to gather the gs frame object we have to be a bit hacky since sApp is not syntax complete
Pcsx2App* app = (Pcsx2App*)wxApp::GetInstance();
GSFrame* window = nullptr;
if (app)
{
app->FpsManager.Reset();
window = app->GetGsFramePtr();
g_FrameCount = 0;
}
GSsetBaseMem((void*)regs);
if (GSopen2((void*)pDsp, (renderer_override<<24)) != 0)
{
OnStop();
return;
}
GSsetGameCRC((int)crc, 0);
if (!GetCorePlugins().DoFreeze(PluginId_GS, 0, &fd, true))
GSDump::isRunning = false;
GSvsync(1);
GSreset();
GSsetBaseMem((void*)regs);
GetCorePlugins().DoFreeze(PluginId_GS, 0, &fd, true);
size_t i = 0;
size_t RunTo = 0;
size_t debug_idx = 0;
while (GSDump::isRunning)
{
if (m_root_window->m_debug_mode->GetValue())
{
if (m_root_window->m_button_events.size() > 0)
{
switch (m_root_window->m_button_events[0].index)
{
case Step:
if (debug_idx >= m_root_window->m_dump_packets.size())
debug_idx = 0;
RunTo = debug_idx;
break;
case RunCursor:
RunTo = m_root_window->m_button_events[0].index;
if (debug_idx > RunTo)
debug_idx = 0;
break;
case RunVSync:
if (debug_idx >= m_root_window->m_dump_packets.size())
debug_idx = 1;
auto it = std::find_if(m_root_window->m_dump_packets.begin() + debug_idx, m_root_window->m_dump_packets.end(), [](const GSData& gs) { return gs.id == Registers; });
if (it != std::end(m_root_window->m_dump_packets))
RunTo = std::distance(m_root_window->m_dump_packets.begin(), it);
break;
}
m_root_window->m_button_events.erase(m_root_window->m_button_events.begin());
if (debug_idx <= RunTo)
{
while (debug_idx <= RunTo)
{
m_root_window->ProcessDumpEvent(m_root_window->m_dump_packets[debug_idx++], regs);
}
auto it = std::find_if(m_root_window->m_dump_packets.begin() + debug_idx, m_root_window->m_dump_packets.end(), [](const GSData& gs) { return gs.id == Registers; });
if (it != std::end(m_root_window->m_dump_packets))
m_root_window->ProcessDumpEvent(*it, regs);
debug_idx--;
}
// do vsync
m_root_window->ProcessDumpEvent({VSync, 0, 0, Dummy}, regs);
}
}
else
{
while (i < (m_root_window->m_dump_packets.size()))
{
m_root_window->ProcessDumpEvent(m_root_window->m_dump_packets[i++], regs);
if (i >= m_root_window->m_dump_packets.size() || m_root_window->m_dump_packets[i].id == VSync)
break;
}
if (i >= m_root_window->m_dump_packets.size())
i = 0;
}
if (window)
{
if (!window->IsShown())
{
sApp.CloseGsPanel();
GSDump::isRunning = false;
}
}
}
GetCorePlugins().Close();
OnStop();
return;
}
void Dialogs::GSDumpDialog::PathChanged(wxFileSystemWatcherEvent& event)
{
GetDumpsList();
}

View File

@ -69,14 +69,14 @@ Dialogs::GSDumpDialog::GSDumpDialog(wxWindow* parent)
, m_thread(std::make_unique<GSThread>(this))
, m_run(new wxButton(this, ID_RUN_DUMP, _("Run"), wxDefaultPosition, wxSize(150, 100)))
{
wxBoxSizer& dump_info(*new wxBoxSizer(wxVERTICAL));
wxBoxSizer& dump_preview(*new wxBoxSizer(wxVERTICAL));
wxFlexGridSizer& debugger(*new wxFlexGridSizer(3, StdPadding, StdPadding));
wxBoxSizer& dumps(*new wxBoxSizer(wxHORIZONTAL));
wxBoxSizer& dbg_tree(*new wxBoxSizer(wxVERTICAL));
wxBoxSizer& dbg_actions(*new wxBoxSizer(wxVERTICAL));
wxBoxSizer& gif(*new wxBoxSizer(wxVERTICAL));
wxBoxSizer& dumps_list(*new wxBoxSizer(wxVERTICAL));
wxBoxSizer* dump_info = new wxBoxSizer(wxVERTICAL);
wxBoxSizer* dump_preview = new wxBoxSizer(wxVERTICAL);
wxFlexGridSizer* debugger = new wxFlexGridSizer(3, StdPadding, StdPadding);
wxBoxSizer* dumps = new wxBoxSizer(wxHORIZONTAL);
wxBoxSizer* dbg_tree = new wxBoxSizer(wxVERTICAL);
wxBoxSizer* dbg_actions = new wxBoxSizer(wxVERTICAL);
wxBoxSizer* gif = new wxBoxSizer(wxVERTICAL);
wxBoxSizer* dumps_list = new wxBoxSizer(wxVERTICAL);
wxArrayString rdoverrides;
rdoverrides.Add("None");
@ -85,30 +85,30 @@ Dialogs::GSDumpDialog::GSDumpDialog(wxWindow* parent)
rdoverrides.Add("OGL HW");
m_renderer_overrides->Create(this, wxID_ANY, "Renderer overrides", wxDefaultPosition, wxDefaultSize, rdoverrides, 1);
dbg_tree += new wxStaticText(this, wxID_ANY, _("GIF Packets"));
dbg_tree += m_gif_list | StdExpand();
dbg_actions += m_debug_mode;
dbg_actions += m_start | StdExpand();
dbg_actions += m_step | StdExpand();
dbg_actions += m_selection | StdExpand();
dbg_actions += m_vsync | StdExpand();
gif += new wxStaticText(this, wxID_ANY, _("Packet Content"));
gif += m_gif_packet | StdExpand();
dbg_tree->Add(new wxStaticText(this, wxID_ANY, _("GIF Packets")));
dbg_tree->Add(m_gif_list, StdExpand());
dbg_actions->Add(m_debug_mode);
dbg_actions->Add(m_start, StdExpand());
dbg_actions->Add(m_step, StdExpand());
dbg_actions->Add(m_selection, StdExpand());
dbg_actions->Add(m_vsync, StdExpand());
gif->Add(new wxStaticText(this, wxID_ANY, _("Packet Content")));
gif->Add(m_gif_packet, StdExpand());
dumps_list += new wxStaticText(this, wxID_ANY, _("GS Dumps List")) | StdExpand();
dumps_list += m_dump_list | StdExpand();
dump_info += m_renderer_overrides | StdExpand();
dump_info += m_run | StdExpand();
dump_preview += new wxStaticText(this, wxID_ANY, _("Preview")) | StdExpand();
dump_preview += m_preview_image | StdCenter();
dumps_list->Add(new wxStaticText(this, wxID_ANY, _("GS Dumps List")), StdExpand());
dumps_list->Add(m_dump_list, StdExpand());
dump_info->Add(m_renderer_overrides, StdExpand());
dump_info->Add(m_run, StdExpand());
dump_preview->Add(new wxStaticText(this, wxID_ANY, _("Preview")), StdExpand());
dump_preview->Add(m_preview_image, StdCenter());
dumps += dumps_list;
dumps += dump_info;
dumps += dump_preview;
dumps->Add(dumps_list);
dumps->Add(dump_info);
dumps->Add(dump_preview);
debugger += dbg_tree;
debugger += dbg_actions;
debugger += gif;
debugger->Add(dbg_tree);
debugger->Add(dbg_actions);
debugger->Add(gif);
*this += dumps;
*this += debugger;

View File

@ -142,7 +142,7 @@ namespace Dialogs
static wxString GetNameStatic()
{
return L"AboutBox";
return L"GSDumpGov";
}
wxString GetDialogName() const
{