Merge pull request #19722 from hrydgard/more-cleanup

More GE debugger code cleanup
This commit is contained in:
Henrik Rydgård authored and GitHub committed 2024-12-12 22:29:42 +01:00
commit d32ac2c29d
18 files changed
+623 -594

No files matched your search

+12 -18
View File
@@ -36,10 +36,7 @@
#include "Core/Debugger/SymbolMap.h"
#include "Core/Debugger/DisassemblyManager.h"
std::map<u32, DisassemblyEntry*> DisassemblyManager::entries;
std::recursive_mutex DisassemblyManager::entriesLock_;
DebugInterface* DisassemblyManager::cpu_;
int DisassemblyManager::maxParamChars = 29;
DisassemblyManager g_disassemblyManager;
bool isInInterval(u32 start, u32 size, u32 value) {
return start <= value && value <= (start+size-1);
@@ -185,6 +182,11 @@ std::map<u32,DisassemblyEntry*>::iterator findDisassemblyEntry(std::map<u32,Disa
return entries.end();
}
void DisassemblyManager::setCpu(DebugInterface *cpu) {
_dbg_assert_(cpu);
cpu_ = cpu;
};
void DisassemblyManager::analyze(u32 address, u32 size = 1024)
{
u32 end = address+size;
@@ -519,7 +521,7 @@ void DisassemblyFunction::generateBranchLines()
u32 end = address+size;
std::lock_guard<std::recursive_mutex> guard(lock_);
DebugInterface *cpu = DisassemblyManager::getCpu();
DebugInterface *cpu = g_disassemblyManager.getCpu();
for (u32 funcPos = address; funcPos < end; funcPos += 4)
{
MIPSAnalyst::MipsOpcodeInfo opInfo = MIPSAnalyst::GetOpcodeInfo(cpu, funcPos);
@@ -612,7 +614,7 @@ void DisassemblyFunction::load()
}
}
DebugInterface *cpu = DisassemblyManager::getCpu();
DebugInterface *cpu = g_disassemblyManager.getCpu();
u32 funcPos = address;
u32 funcEnd = address+size;
@@ -747,11 +749,7 @@ void DisassemblyFunction::clear()
hash = 0;
}
bool DisassemblyOpcode::disassemble(u32 address, DisassemblyLineInfo &dest, bool insertSymbols, DebugInterface *cpuDebug)
{
if (!cpuDebug)
cpuDebug = DisassemblyManager::getCpu();
bool DisassemblyOpcode::disassemble(u32 address, DisassemblyLineInfo &dest, bool insertSymbols, DebugInterface *cpuDebug) {
char opcode[64],arguments[256];
char dizz[512];
DisAsm(address, dizz, sizeof(dizz));
@@ -778,7 +776,7 @@ void DisassemblyOpcode::getBranchLines(u32 start, u32 size, std::vector<BranchLi
int lane = 0;
for (u32 pos = start; pos < start+size; pos += 4)
{
MIPSAnalyst::MipsOpcodeInfo info = MIPSAnalyst::GetOpcodeInfo(DisassemblyManager::getCpu(),pos);
MIPSAnalyst::MipsOpcodeInfo info = MIPSAnalyst::GetOpcodeInfo(g_disassemblyManager.getCpu(),pos);
if (info.isBranch && !info.isBranchToRegister && !info.isLinkedBranch) {
if (!Memory::IsValidAddress(info.branchTarget))
continue;
@@ -823,9 +821,6 @@ void DisassemblyMacro::setMacroMemory(std::string_view _name, u32 _immediate, u8
bool DisassemblyMacro::disassemble(u32 address, DisassemblyLineInfo &dest, bool insertSymbols, DebugInterface *cpuDebug)
{
if (!cpuDebug)
cpuDebug = DisassemblyManager::getCpu();
char buffer[64];
dest.type = DISTYPE_MACRO;
dest.info = MIPSAnalyst::GetOpcodeInfo(cpuDebug, address);
@@ -875,7 +870,6 @@ bool DisassemblyMacro::disassemble(u32 address, DisassemblyLineInfo &dest, bool
return true;
}
DisassemblyData::DisassemblyData(u32 _address, u32 _size, DataType _type): address(_address), size(_size), type(_type)
{
_dbg_assert_(PSP_IsInited());
@@ -950,8 +944,8 @@ void DisassemblyData::createLines()
lineAddresses.clear();
u32 pos = address;
u32 end = address+size;
u32 maxChars = DisassemblyManager::getMaxParamChars();
const u32 end = address+size;
const u32 maxChars = g_disassemblyManager.getMaxParamChars();
std::string currentLine;
u32 currentLineStart = pos;
+11 -8
View File
@@ -202,9 +202,9 @@ public:
void clear();
static void setCpu(DebugInterface *cpu) { cpu_ = cpu; };
void setCpu(DebugInterface *cpu);
void setMaxParamChars(int num) { maxParamChars = num; clear(); };
void getLine(u32 address, bool insertSymbols, DisassemblyLineInfo &dest, DebugInterface *cpuDebug = nullptr);
void getLine(u32 address, bool insertSymbols, DisassemblyLineInfo &dest, DebugInterface *cpuDebug);
void analyze(u32 address, u32 size);
std::vector<BranchLine> getBranchLines(u32 start, u32 size);
@@ -212,14 +212,17 @@ public:
u32 getNthPreviousAddress(u32 address, int n = 1);
u32 getNthNextAddress(u32 address, int n = 1);
static DebugInterface *getCpu() { return cpu_; };
static int getMaxParamChars() { return maxParamChars; };
DebugInterface *getCpu() { return cpu_; };
int getMaxParamChars() { return maxParamChars; };
private:
static std::map<u32,DisassemblyEntry*> entries;
static std::recursive_mutex entriesLock_;
static DebugInterface *cpu_;
static int maxParamChars;
std::map<u32,DisassemblyEntry*> entries;
std::recursive_mutex entriesLock_;
DebugInterface *cpu_;
int maxParamChars = 29;
};
extern DisassemblyManager g_disassemblyManager;
bool isInInterval(u32 start, u32 size, u32 value);
bool IsLikelyStringAt(uint32_t addr);
@@ -227,9 +227,8 @@ void WebSocketCPUBreakpointList(DebuggerRequest &req) {
else
json.writeString("symbol", symbol);
DisassemblyManager manager;
DisassemblyLineInfo line;
manager.getLine(manager.getStartAddress(bp.addr), true, line);
g_disassemblyManager.getLine(g_disassemblyManager.getStartAddress(bp.addr), true, line, currentDebugMIPS);
json.writeString("code", line.name + " " + line.params);
json.pop();
+12 -14
View File
@@ -34,10 +34,10 @@
class WebSocketDisasmState : public DebuggerSubscriber {
public:
WebSocketDisasmState() {
disasm_.setCpu(currentDebugMIPS);
g_disassemblyManager.setCpu(currentDebugMIPS);
}
~WebSocketDisasmState() {
disasm_.clear();
g_disassemblyManager.clear();
}
void Base(DebuggerRequest &req);
@@ -48,8 +48,6 @@ public:
protected:
void WriteDisasmLine(JsonWriter &json, const DisassemblyLineInfo &l);
void WriteBranchGuide(JsonWriter &json, const BranchLine &l);
DisassemblyManager disasm_;
};
DebuggerSubscriber *WebSocketDisasmInit(DebuggerEventHandlerMap &map) {
@@ -316,18 +314,18 @@ void WebSocketDisasmState::Disasm(DebuggerRequest &req) {
if (count != 0) {
count = std::min(count, MAX_RANGE);
// Let's assume everything is two instructions.
disasm_.analyze(start - 4, count * 8 + 8);
start = disasm_.getStartAddress(start);
g_disassemblyManager.analyze(start - 4, count * 8 + 8);
start = g_disassemblyManager.getStartAddress(start);
if (start == -1)
req.ParamU32("address", &start);
end = disasm_.getNthNextAddress(start, count);
end = g_disassemblyManager.getNthNextAddress(start, count);
} else if (req.ParamU32("end", &end)) {
end = std::max(start, end);
if (end - start > MAX_RANGE * 4)
end = start + MAX_RANGE * 4;
// Let's assume everything is two instructions at most.
disasm_.analyze(start - 4, end - start + 8);
start = disasm_.getStartAddress(start);
g_disassemblyManager.analyze(start - 4, end - start + 8);
start = g_disassemblyManager.getStartAddress(start);
if (start == -1)
req.ParamU32("address", &start);
// Correct end and calculate count based on it.
@@ -336,11 +334,11 @@ void WebSocketDisasmState::Disasm(DebuggerRequest &req) {
u32 next = start;
count = 0;
if (stop < start) {
for (next = start; next > stop; next = disasm_.getNthNextAddress(next, 1)) {
for (next = start; next > stop; next = g_disassemblyManager.getNthNextAddress(next, 1)) {
count++;
}
}
for (end = next; end < stop && end >= next; end = disasm_.getNthNextAddress(end, 1)) {
for (end = next; end < stop && end >= next; end = g_disassemblyManager.getNthNextAddress(end, 1)) {
count++;
}
} else {
@@ -362,7 +360,7 @@ void WebSocketDisasmState::Disasm(DebuggerRequest &req) {
DisassemblyLineInfo line;
uint32_t addr = start;
for (uint32_t i = 0; i < count; ++i) {
disasm_.getLine(addr, displaySymbols, line, cpuDebug);
g_disassemblyManager.getLine(addr, displaySymbols, line, cpuDebug);
WriteDisasmLine(json, line);
addr += line.totalSize;
@@ -373,7 +371,7 @@ void WebSocketDisasmState::Disasm(DebuggerRequest &req) {
json.pop();
json.pushArray("branchGuides");
auto branchGuides = disasm_.getBranchLines(start, end - start);
auto branchGuides = g_disassemblyManager.getBranchLines(start, end - start);
for (auto bl : branchGuides)
WriteBranchGuide(json, bl);
json.pop();
@@ -428,7 +426,7 @@ void WebSocketDisasmState::SearchDisasm(DebuggerRequest &req) {
bool found = false;
uint32_t addr = start;
do {
disasm_.getLine(addr, displaySymbols, line, cpuDebug);
g_disassemblyManager.getLine(addr, displaySymbols, line, cpuDebug);
const std::string addressSymbol = g_symbolMap->GetLabelString(addr);
std::string mergeForSearch;
+4 -8
View File
@@ -297,8 +297,7 @@ void WebSocketHLEFuncAdd(DebuggerRequest &req) {
}
// Clear cache for branch lines and such.
DisassemblyManager manager;
manager.clear();
g_disassemblyManager.clear();
JsonWriter &json = req.Respond();
json.writeUint("address", addr);
@@ -354,8 +353,7 @@ void WebSocketHLEFuncRemove(DebuggerRequest &req) {
}
// Clear cache for branch lines and such.
DisassemblyManager manager;
manager.clear();
g_disassemblyManager.clear();
JsonWriter &json = req.Respond();
json.writeUint("address", funcBegin);
@@ -392,8 +390,7 @@ static u32 RemoveFuncSymbolsInRange(u32 addr, u32 size) {
}
// Clear cache for branch lines and such.
DisassemblyManager manager;
manager.clear();
g_disassemblyManager.clear();
}
return counter;
}
@@ -592,9 +589,8 @@ void WebSocketHLEBacktrace(DebuggerRequest &req) {
json.writeUint("sp", f.sp);
json.writeUint("stackSize", f.stackSize);
DisassemblyManager manager;
DisassemblyLineInfo line;
manager.getLine(manager.getStartAddress(f.pc), true, line, cpuDebug);
g_disassemblyManager.getLine(g_disassemblyManager.getStartAddress(f.pc), true, line, cpuDebug);
json.writeString("code", line.name + " " + line.params);
json.pop();
@@ -30,10 +30,10 @@ using namespace MIPSAnalyst;
struct WebSocketSteppingState : public DebuggerSubscriber {
WebSocketSteppingState() {
disasm_.setCpu(currentDebugMIPS);
g_disassemblyManager.setCpu(currentDebugMIPS);
}
~WebSocketSteppingState() {
disasm_.clear();
g_disassemblyManager.clear();
}
void Into(DebuggerRequest &req);
@@ -47,8 +47,6 @@ protected:
int GetNextInstructionCount(DebugInterface *cpuDebug);
void PrepareResume();
void AddThreadCondition(uint32_t breakpointAddress, uint32_t threadID);
DisassemblyManager disasm_;
};
DebuggerSubscriber *WebSocketSteppingInit(DebuggerEventHandlerMap &map) {
@@ -266,8 +264,8 @@ void WebSocketSteppingState::HLE(DebuggerRequest &req) {
}
uint32_t WebSocketSteppingState::GetNextAddress(DebugInterface *cpuDebug) {
uint32_t current = disasm_.getStartAddress(cpuDebug->GetPC());
return disasm_.getNthNextAddress(current, 1);
uint32_t current = g_disassemblyManager.getStartAddress(cpuDebug->GetPC());
return g_disassemblyManager.getNthNextAddress(current, 1);
}
int WebSocketSteppingState::GetNextInstructionCount(DebugInterface *cpuDebug) {
+440
View File
@@ -1,11 +1,14 @@
#include <cstdio>
#include "Common/Common.h"
#include "Common/StringUtils.h"
#include "Common/Data/Convert/ColorConv.h"
#include "GPU/Debugger/State.h"
#include "GPU/GPU.h"
#include "GPU/Common/GPUStateUtils.h"
#include "GPU/Common/GPUDebugInterface.h"
#include "GPU/GeDisasm.h"
#include "GPU/Common/VertexDecoderCommon.h"
#include "GPU/Common/SplineCommon.h"
#include "Core/System.h"
void FormatStateRow(GPUDebugInterface *gpudebug, char *dest, size_t destSize, CmdFormatType fmt, u32 value, bool enabled, u32 otherValue, u32 otherValue2) {
@@ -646,3 +649,440 @@ static void FormatVertColRawColor(char *dest, size_t destSize, const void *data,
break;
}
}
static void SwapUVs(GPUDebugVertex &a, GPUDebugVertex &b) {
float tempu = a.u;
float tempv = a.v;
a.u = b.u;
a.v = b.v;
b.u = tempu;
b.v = tempv;
}
static void RotateUVThrough(GPUDebugVertex v[4]) {
float x1 = v[2].x;
float x2 = v[0].x;
float y1 = v[2].y;
float y2 = v[0].y;
if ((x1 < x2 && y1 > y2) || (x1 > x2 && y1 < y2))
SwapUVs(v[1], v[3]);
}
static void ExpandRectangles(std::vector<GPUDebugVertex> &vertices, std::vector<u16> &indices, int &count, bool throughMode) {
static std::vector<GPUDebugVertex> newVerts;
static std::vector<u16> newInds;
bool useInds = true;
size_t numInds = indices.size();
if (indices.empty()) {
useInds = false;
numInds = count;
}
//rectangles always need 2 vertices, disregard the last one if there's an odd number
numInds = numInds & ~1;
// Will need 4 coords and 6 points per rectangle (currently 2 each.)
newVerts.resize(numInds * 2);
newInds.resize(numInds * 3);
u16 v = 0;
GPUDebugVertex *vert = &newVerts[0];
u16 *ind = &newInds[0];
for (size_t i = 0; i < numInds; i += 2) {
const auto &orig_tl = useInds ? vertices[indices[i + 0]] : vertices[i + 0];
const auto &orig_br = useInds ? vertices[indices[i + 1]] : vertices[i + 1];
vert[0] = orig_br;
// Top right.
vert[1] = orig_br;
vert[1].y = orig_tl.y;
vert[1].v = orig_tl.v;
vert[2] = orig_tl;
// Bottom left.
vert[3] = orig_br;
vert[3].x = orig_tl.x;
vert[3].u = orig_tl.u;
// That's the four corners. Now process UV rotation.
// This is the same for through and non-through, since it's already transformed.
RotateUVThrough(vert);
// Build the two 3 point triangles from our 4 coordinates.
*ind++ = v + 0;
*ind++ = v + 1;
*ind++ = v + 2;
*ind++ = v + 3;
*ind++ = v + 0;
*ind++ = v + 2;
vert += 4;
v += 4;
}
std::swap(vertices, newVerts);
std::swap(indices, newInds);
count *= 3;
}
static void ExpandBezier(int &count, int op, const std::vector<SimpleVertex> &simpleVerts, const std::vector<u16> &indices, std::vector<SimpleVertex> &generatedVerts, std::vector<u16> &generatedInds) {
using namespace Spline;
int count_u = (op >> 0) & 0xFF;
int count_v = (op >> 8) & 0xFF;
// Real hardware seems to draw nothing when given < 4 either U or V.
if (count_u < 4 || count_v < 4)
return;
BezierSurface surface;
surface.num_points_u = count_u;
surface.num_points_v = count_v;
surface.tess_u = gstate.getPatchDivisionU();
surface.tess_v = gstate.getPatchDivisionV();
surface.num_patches_u = (count_u - 1) / 3;
surface.num_patches_v = (count_v - 1) / 3;
surface.primType = gstate.getPatchPrimitiveType();
surface.patchFacing = false;
int num_points = count_u * count_v;
// Make an array of pointers to the control points, to get rid of indices.
std::vector<const SimpleVertex *> points(num_points);
for (int idx = 0; idx < num_points; idx++)
points[idx] = simpleVerts.data() + (!indices.empty() ? indices[idx] : idx);
int total_patches = surface.num_patches_u * surface.num_patches_v;
generatedVerts.resize((surface.tess_u + 1) * (surface.tess_v + 1) * total_patches);
generatedInds.resize(surface.tess_u * surface.tess_v * 6 * total_patches);
OutputBuffers output;
output.vertices = generatedVerts.data();
output.indices = generatedInds.data();
output.count = 0;
ControlPoints cpoints;
cpoints.pos = new Vec3f[num_points];
cpoints.tex = new Vec2f[num_points];
cpoints.col = new Vec4f[num_points];
cpoints.Convert(points.data(), num_points);
surface.Init((int)generatedVerts.size());
SoftwareTessellation(output, surface, gstate.vertType, cpoints);
count = output.count;
delete[] cpoints.pos;
delete[] cpoints.tex;
delete[] cpoints.col;
}
static void ExpandSpline(int &count, int op, const std::vector<SimpleVertex> &simpleVerts, const std::vector<u16> &indices, std::vector<SimpleVertex> &generatedVerts, std::vector<u16> &generatedInds) {
using namespace Spline;
int count_u = (op >> 0) & 0xFF;
int count_v = (op >> 8) & 0xFF;
// Real hardware seems to draw nothing when given < 4 either U or V.
if (count_u < 4 || count_v < 4)
return;
SplineSurface surface;
surface.num_points_u = count_u;
surface.num_points_v = count_v;
surface.tess_u = gstate.getPatchDivisionU();
surface.tess_v = gstate.getPatchDivisionV();
surface.type_u = (op >> 16) & 0x3;
surface.type_v = (op >> 18) & 0x3;
surface.num_patches_u = count_u - 3;
surface.num_patches_v = count_v - 3;
surface.primType = gstate.getPatchPrimitiveType();
surface.patchFacing = false;
int num_points = count_u * count_v;
// Make an array of pointers to the control points, to get rid of indices.
std::vector<const SimpleVertex *> points(num_points);
for (int idx = 0; idx < num_points; idx++)
points[idx] = simpleVerts.data() + (!indices.empty() ? indices[idx] : idx);
int patch_div_s = surface.num_patches_u * surface.tess_u;
int patch_div_t = surface.num_patches_v * surface.tess_v;
generatedVerts.resize((patch_div_s + 1) * (patch_div_t + 1));
generatedInds.resize(patch_div_s * patch_div_t * 6);
OutputBuffers output;
output.vertices = generatedVerts.data();
output.indices = generatedInds.data();
output.count = 0;
ControlPoints cpoints;
cpoints.pos = (Vec3f *)AllocateAlignedMemory(sizeof(Vec3f) * num_points, 16);
cpoints.tex = (Vec2f *)AllocateAlignedMemory(sizeof(Vec2f) * num_points, 16);
cpoints.col = (Vec4f *)AllocateAlignedMemory(sizeof(Vec4f) * num_points, 16);
cpoints.Convert(points.data(), num_points);
surface.Init((int)generatedVerts.size());
SoftwareTessellation(output, surface, gstate.vertType, cpoints);
count = output.count;
FreeAlignedMemory(cpoints.pos);
FreeAlignedMemory(cpoints.tex);
FreeAlignedMemory(cpoints.col);
}
bool GetPrimPreview(u32 op, int which, GEPrimitiveType &prim, std::vector<GPUDebugVertex> &vertices, std::vector<u16> &indices, int &count) {
u32 prim_type = GE_PRIM_INVALID;
int count_u = 0;
int count_v = 0;
const u32 cmd = op >> 24;
if (cmd == GE_CMD_PRIM) {
prim_type = (op >> 16) & 0x7;
count = op & 0xFFFF;
} else {
const GEPrimitiveType primLookup[] = { GE_PRIM_TRIANGLES, GE_PRIM_LINES, GE_PRIM_POINTS, GE_PRIM_POINTS };
if (gstate.getPatchPrimitiveType() < ARRAY_SIZE(primLookup))
prim_type = primLookup[gstate.getPatchPrimitiveType()];
count_u = (op & 0x00FF) >> 0;
count_v = (op & 0xFF00) >> 8;
count = count_u * count_v;
}
if (prim_type >= 7) {
ERROR_LOG(Log::G3D, "Unsupported prim type: %x", op);
return false;
}
if (!gpuDebug) {
ERROR_LOG(Log::G3D, "Invalid debugging environment, shutting down?");
return false;
}
if (count == 0 || which == 0) {
return false;
}
prim = static_cast<GEPrimitiveType>(prim_type);
if (!gpuDebug->GetCurrentSimpleVertices(count, vertices, indices)) {
ERROR_LOG(Log::G3D, "Vertex preview not yet supported");
return false;
}
if (cmd != GE_CMD_PRIM) {
static std::vector<SimpleVertex> generatedVerts;
static std::vector<u16> generatedInds;
static std::vector<SimpleVertex> simpleVerts;
simpleVerts.resize(vertices.size());
for (size_t i = 0; i < vertices.size(); ++i) {
// For now, let's just copy back so we can use TessellateBezierPatch/TessellateSplinePatch...
simpleVerts[i].uv[0] = vertices[i].u;
simpleVerts[i].uv[1] = vertices[i].v;
simpleVerts[i].pos = Vec3Packedf(vertices[i].x, vertices[i].y, vertices[i].z);
}
if (cmd == GE_CMD_BEZIER) {
ExpandBezier(count, op, simpleVerts, indices, generatedVerts, generatedInds);
} else if (cmd == GE_CMD_SPLINE) {
ExpandSpline(count, op, simpleVerts, indices, generatedVerts, generatedInds);
}
vertices.resize(generatedVerts.size());
for (size_t i = 0; i < vertices.size(); ++i) {
vertices[i].u = generatedVerts[i].uv[0];
vertices[i].v = generatedVerts[i].uv[1];
vertices[i].x = generatedVerts[i].pos.x;
vertices[i].y = generatedVerts[i].pos.y;
vertices[i].z = generatedVerts[i].pos.z;
}
indices = generatedInds;
}
if (prim == GE_PRIM_RECTANGLES) {
ExpandRectangles(vertices, indices, count, gpuDebug->GetGState().isModeThrough());
}
// TODO: Probably there's a better way and place to do this.
u16 minIndex = 0;
u16 maxIndex = count - 1;
if (!indices.empty()) {
_dbg_assert_(count <= indices.size());
minIndex = 0xFFFF;
maxIndex = 0;
for (int i = 0; i < count; ++i) {
if (minIndex > indices[i]) {
minIndex = indices[i];
}
if (maxIndex < indices[i]) {
maxIndex = indices[i];
}
}
}
auto wrapCoord = [](float &coord) {
if (coord < 0.0f) {
coord += ceilf(-coord);
}
if (coord > 1.0f) {
coord -= floorf(coord);
}
};
const float invTexWidth = 1.0f / gpuDebug->GetGState().getTextureWidth(0);
const float invTexHeight = 1.0f / gpuDebug->GetGState().getTextureHeight(0);
bool clampS = gpuDebug->GetGState().isTexCoordClampedS();
bool clampT = gpuDebug->GetGState().isTexCoordClampedT();
for (u16 i = minIndex; i <= maxIndex; ++i) {
vertices[i].u *= invTexWidth;
vertices[i].v *= invTexHeight;
if (!clampS)
wrapCoord(vertices[i].u);
if (!clampT)
wrapCoord(vertices[i].v);
}
return true;
}
void DescribePixel(u32 pix, GPUDebugBufferFormat fmt, int x, int y, char desc[256]) {
switch (fmt) {
case GPU_DBG_FORMAT_565:
case GPU_DBG_FORMAT_565_REV:
case GPU_DBG_FORMAT_5551:
case GPU_DBG_FORMAT_5551_REV:
case GPU_DBG_FORMAT_5551_BGRA:
case GPU_DBG_FORMAT_4444:
case GPU_DBG_FORMAT_4444_REV:
case GPU_DBG_FORMAT_4444_BGRA:
case GPU_DBG_FORMAT_8888:
case GPU_DBG_FORMAT_8888_BGRA:
DescribePixelRGBA(pix, fmt, x, y, desc);
break;
case GPU_DBG_FORMAT_16BIT:
snprintf(desc, 256, "%d,%d: %d / %f", x, y, pix, pix * (1.0f / 65535.0f));
break;
case GPU_DBG_FORMAT_8BIT:
snprintf(desc, 256, "%d,%d: %d / %f", x, y, pix, pix * (1.0f / 255.0f));
break;
case GPU_DBG_FORMAT_24BIT_8X:
{
DepthScaleFactors depthScale = GetDepthScaleFactors(gstate_c.UseFlags());
// These are only ever going to be depth values, so let's also show scaled to 16 bit.
snprintf(desc, 256, "%d,%d: %d / %f / %f", x, y, pix & 0x00FFFFFF, (pix & 0x00FFFFFF) * (1.0f / 16777215.0f), depthScale.DecodeToU16((pix & 0x00FFFFFF) * (1.0f / 16777215.0f)));
break;
}
case GPU_DBG_FORMAT_24BIT_8X_DIV_256:
{
// These are only ever going to be depth values, so let's also show scaled to 16 bit.
int z24 = pix & 0x00FFFFFF;
int z16 = z24 - 0x800000 + 0x8000;
snprintf(desc, 256, "%d,%d: %d / %f", x, y, z16, z16 * (1.0f / 65535.0f));
}
break;
case GPU_DBG_FORMAT_24X_8BIT:
snprintf(desc, 256, "%d,%d: %d / %f", x, y, (pix >> 24) & 0xFF, ((pix >> 24) & 0xFF) * (1.0f / 255.0f));
break;
case GPU_DBG_FORMAT_FLOAT:
{
float pixf = *(float *)&pix;
DepthScaleFactors depthScale = GetDepthScaleFactors(gstate_c.UseFlags());
snprintf(desc, 256, "%d,%d: %f / %f", x, y, pixf, depthScale.DecodeToU16(pixf));
break;
}
case GPU_DBG_FORMAT_FLOAT_DIV_256:
{
double z = *(float *)&pix;
int z24 = (int)(z * 16777215.0);
DepthScaleFactors factors = GetDepthScaleFactors(gstate_c.UseFlags());
// TODO: Use GetDepthScaleFactors here too, verify it's the same.
int z16 = z24 - 0x800000 + 0x8000;
int z16_2 = factors.DecodeToU16(z);
snprintf(desc, 256, "%d,%d: %d / %f", x, y, z16, (z - 0.5 + (1.0 / 512.0)) * 256.0);
}
break;
default:
snprintf(desc, 256, "Unexpected format");
}
}
void DescribePixelRGBA(u32 pix, GPUDebugBufferFormat fmt, int x, int y, char desc[256]) {
u32 r = -1, g = -1, b = -1, a = -1;
switch (fmt) {
case GPU_DBG_FORMAT_565:
r = Convert5To8((pix >> 0) & 0x1F);
g = Convert6To8((pix >> 5) & 0x3F);
b = Convert5To8((pix >> 11) & 0x1F);
break;
case GPU_DBG_FORMAT_565_REV:
b = Convert5To8((pix >> 0) & 0x1F);
g = Convert6To8((pix >> 5) & 0x3F);
r = Convert5To8((pix >> 11) & 0x1F);
break;
case GPU_DBG_FORMAT_5551:
r = Convert5To8((pix >> 0) & 0x1F);
g = Convert5To8((pix >> 5) & 0x1F);
b = Convert5To8((pix >> 10) & 0x1F);
a = (pix >> 15) & 1 ? 255 : 0;
break;
case GPU_DBG_FORMAT_5551_REV:
a = pix & 1 ? 255 : 0;
b = Convert5To8((pix >> 1) & 0x1F);
g = Convert5To8((pix >> 6) & 0x1F);
r = Convert5To8((pix >> 11) & 0x1F);
break;
case GPU_DBG_FORMAT_5551_BGRA:
b = Convert5To8((pix >> 0) & 0x1F);
g = Convert5To8((pix >> 5) & 0x1F);
r = Convert5To8((pix >> 10) & 0x1F);
a = (pix >> 15) & 1 ? 255 : 0;
break;
case GPU_DBG_FORMAT_4444:
r = Convert4To8((pix >> 0) & 0x0F);
g = Convert4To8((pix >> 4) & 0x0F);
b = Convert4To8((pix >> 8) & 0x0F);
a = Convert4To8((pix >> 12) & 0x0F);
break;
case GPU_DBG_FORMAT_4444_REV:
a = Convert4To8((pix >> 0) & 0x0F);
b = Convert4To8((pix >> 4) & 0x0F);
g = Convert4To8((pix >> 8) & 0x0F);
r = Convert4To8((pix >> 12) & 0x0F);
break;
case GPU_DBG_FORMAT_4444_BGRA:
b = Convert4To8((pix >> 0) & 0x0F);
g = Convert4To8((pix >> 4) & 0x0F);
r = Convert4To8((pix >> 8) & 0x0F);
a = Convert4To8((pix >> 12) & 0x0F);
break;
case GPU_DBG_FORMAT_8888:
r = (pix >> 0) & 0xFF;
g = (pix >> 8) & 0xFF;
b = (pix >> 16) & 0xFF;
a = (pix >> 24) & 0xFF;
break;
case GPU_DBG_FORMAT_8888_BGRA:
b = (pix >> 0) & 0xFF;
g = (pix >> 8) & 0xFF;
r = (pix >> 16) & 0xFF;
a = (pix >> 24) & 0xFF;
break;
default:
snprintf(desc, 256, "Unexpected format");
return;
}
snprintf(desc, 256, "%d,%d: r=%d, g=%d, b=%d, a=%d", x, y, r, g, b, a);
}
+10 -1
View File
@@ -7,7 +7,8 @@
#include "Common/CommonTypes.h"
#include "GPU/Debugger/GECommandTable.h"
// Extracted from Windows/GE Debugger/TabState.cpp
#include "GPU/Common/SplineCommon.h"
#include "GPU/Common/GPUDebugInterface.h"
enum VertexListCols {
VERTEXLIST_COL_X,
@@ -39,3 +40,11 @@ class VertexDecoder;
void FormatStateRow(GPUDebugInterface *debug, char *dest, size_t destSize, CmdFormatType fmt, u32 value, bool enabled, u32 otherValue, u32 otherValue2);
void FormatVertCol(char *dest, size_t destSize, const GPUDebugVertex &vert, int col);
void FormatVertColRaw(VertexDecoder *decoder, char *dest, size_t destSize, int row, int col);
// These are utilities used by the debugger vertex preview.
// Later I hope to re-use more of the real logic.
bool GetPrimPreview(u32 op, int which, GEPrimitiveType &prim, std::vector<GPUDebugVertex> &vertices, std::vector<u16> &indices, int &count);
void DescribePixel(u32 pix, GPUDebugBufferFormat fmt, int x, int y, char desc[256]);
void DescribePixelRGBA(u32 pix, GPUDebugBufferFormat fmt, int x, int y, char desc[256]);
+1 -1
View File
@@ -892,7 +892,7 @@ void ImDebugger::Frame(MIPSDebugInterface *mipsDebug, GPUDebugInterface *gpuDebu
}
// TODO: Pass mipsDebug in where needed instead.
DisassemblyManager::setCpu(mipsDebug);
g_disassemblyManager.setCpu(mipsDebug);
disasm_.View().setDebugger(mipsDebug);
for (int i = 0; i < 4; i++) {
mem_[i].View().setDebugger(mipsDebug);
+41 -41
View File
@@ -33,11 +33,11 @@ ImDisasmView::ImDisasmView() {
}
ImDisasmView::~ImDisasmView() {
manager.clear();
g_disassemblyManager.clear();
}
void ImDisasmView::ScanVisibleFunctions() {
manager.analyze(windowStart_, manager.getNthNextAddress(windowStart_, visibleRows_) - windowStart_);
g_disassemblyManager.analyze(windowStart_, g_disassemblyManager.getNthNextAddress(windowStart_, visibleRows_) - windowStart_);
}
static ImColor scaleColor(ImColor color, float factor) {
@@ -130,7 +130,7 @@ void ImDisasmView::assembleOpcode(u32 address, const std::string &defaultText) {
ScanVisibleFunctions();
if (address == curAddress)
gotoAddr(manager.getNthNextAddress(curAddress, 1));
gotoAddr(g_disassemblyManager.getNthNextAddress(curAddress, 1));
redraw();
} else {
@@ -141,7 +141,7 @@ void ImDisasmView::assembleOpcode(u32 address, const std::string &defaultText) {
}
void ImDisasmView::drawBranchLine(ImDrawList *drawList, Bounds rect, std::map<u32, float> &addressPositions, const BranchLine &line) {
u32 windowEnd = manager.getNthNextAddress(windowStart_, visibleRows_);
u32 windowEnd = g_disassemblyManager.getNthNextAddress(windowStart_, visibleRows_);
float topY;
float bottomY;
@@ -235,7 +235,7 @@ std::set<std::string> ImDisasmView::getSelectedLineArguments() {
std::set<std::string> args;
DisassemblyLineInfo line;
for (u32 addr = selectRangeStart_; addr < selectRangeEnd_; addr += 4) {
manager.getLine(addr, displaySymbols_, line);
g_disassemblyManager.getLine(addr, displaySymbols_, line, debugger_);
size_t p = 0, nextp = line.params.find(',');
while (nextp != line.params.npos) {
args.emplace(line.params.substr(p, nextp - p));
@@ -350,7 +350,7 @@ void ImDisasmView::Draw(ImDrawList *drawList, ImControl &control) {
const u32 pc = debugger_->GetPC();
for (int i = 0; i < visibleRows_; i++) {
manager.getLine(address, displaySymbols_, line);
g_disassemblyManager.getLine(address, displaySymbols_, line, debugger_);
float rowY1 = rowHeight_ * i;
float rowY2 = rowHeight_ * (i + 1);
@@ -413,7 +413,7 @@ void ImDisasmView::Draw(ImDrawList *drawList, ImControl &control) {
address += line.totalSize;
}
std::vector<BranchLine> branchLines = manager.getBranchLines(windowStart_, address - windowStart_);
std::vector<BranchLine> branchLines = g_disassemblyManager.getBranchLines(windowStart_, address - windowStart_);
for (size_t i = 0; i < branchLines.size(); i++) {
drawBranchLine(drawList, bounds, addressPositions, branchLines[i]);
}
@@ -443,9 +443,9 @@ void ImDisasmView::Draw(ImDrawList *drawList, ImControl &control) {
if (is_hovered) {
if (io.MouseWheel > 0.0f) { // TODO: Scale steps by the value.
windowStart_ = manager.getNthPreviousAddress(windowStart_, 4);
windowStart_ = g_disassemblyManager.getNthPreviousAddress(windowStart_, 4);
} else if (io.MouseWheel < 0.0f) {
windowStart_ = manager.getNthNextAddress(windowStart_, 4);
windowStart_ = g_disassemblyManager.getNthNextAddress(windowStart_, 4);
}
}
@@ -479,9 +479,9 @@ void ImDisasmView::NotifyStep() {
void ImDisasmView::ScrollRelative(int amount) {
if (amount > 0) {
windowStart_ = manager.getNthNextAddress(windowStart_, amount);
windowStart_ = g_disassemblyManager.getNthNextAddress(windowStart_, amount);
} else if (amount < 0) {
windowStart_ = manager.getNthPreviousAddress(windowStart_, amount);
windowStart_ = g_disassemblyManager.getNthPreviousAddress(windowStart_, amount);
}
ScanVisibleFunctions();
}
@@ -489,7 +489,7 @@ void ImDisasmView::ScrollRelative(int amount) {
// Follows branches and jumps.
void ImDisasmView::FollowBranch() {
DisassemblyLineInfo line;
manager.getLine(curAddress_, true, line);
g_disassemblyManager.getLine(curAddress_, true, line, debugger_);
if (line.type == DISTYPE_OPCODE || line.type == DISTYPE_MACRO) {
if (line.info.isBranch) {
@@ -551,7 +551,7 @@ void ImDisasmView::ProcessKeyboardShortcuts(bool focused) {
return;
}
u32 windowEnd = manager.getNthNextAddress(windowStart_, visibleRows_);
u32 windowEnd = g_disassemblyManager.getNthNextAddress(windowStart_, visibleRows_);
keyTaken = true;
ImGuiIO& io = ImGui::GetIO();
@@ -591,27 +591,27 @@ void ImDisasmView::ProcessKeyboardShortcuts(bool focused) {
ScanVisibleFunctions();
}
if (ImGui::IsKeyPressed(ImGuiKey_PageDown)) {
setCurAddress(manager.getNthPreviousAddress(windowEnd, 1), (io.KeyMods & ImGuiMod_Shift) != 0);
setCurAddress(g_disassemblyManager.getNthPreviousAddress(windowEnd, 1), (io.KeyMods & ImGuiMod_Shift) != 0);
}
if (ImGui::IsKeyPressed(ImGuiKey_PageUp)) {
setCurAddress(windowStart_, ImGui::IsKeyDown(ImGuiKey_LeftShift));
}
} else {
if (ImGui::IsKeyPressed(ImGuiKey_PageDown)) {
windowStart_ = manager.getNthNextAddress(windowStart_, visibleRows_);
windowStart_ = g_disassemblyManager.getNthNextAddress(windowStart_, visibleRows_);
}
if (ImGui::IsKeyPressed(ImGuiKey_PageUp)) {
windowStart_ = manager.getNthPreviousAddress(windowStart_, visibleRows_);
windowStart_ = g_disassemblyManager.getNthPreviousAddress(windowStart_, visibleRows_);
}
if (ImGui::IsKeyPressed(ImGuiKey_F3)) {
SearchNext(!ImGui::IsKeyPressed(ImGuiKey_LeftShift));
}
if (ImGui::IsKeyPressed(ImGuiKey_DownArrow)) {
setCurAddress(manager.getNthNextAddress(curAddress_, 1), (io.KeyMods & ImGuiMod_Shift) != 0);
setCurAddress(g_disassemblyManager.getNthNextAddress(curAddress_, 1), (io.KeyMods & ImGuiMod_Shift) != 0);
scrollAddressIntoView();
}
if (ImGui::IsKeyPressed(ImGuiKey_UpArrow)) {
setCurAddress(manager.getNthPreviousAddress(curAddress_, 1), (io.KeyMods & ImGuiMod_Shift) != 0);
setCurAddress(g_disassemblyManager.getNthPreviousAddress(curAddress_, 1), (io.KeyMods & ImGuiMod_Shift) != 0);
scrollAddressIntoView();
}
if (ImGui::IsKeyPressed(ImGuiKey_RightArrow)) {
@@ -637,11 +637,11 @@ void ImDisasmView::ProcessKeyboardShortcuts(bool focused) {
} else {
switch (wParam & 0xFFFF) {
case VK_NEXT:
if (manager.getNthNextAddress(curAddress, 1) != windowEnd && curAddressIsVisible()) {
setCurAddress(manager.getNthPreviousAddress(windowEnd, 1), KeyDownAsync(VK_SHIFT));
if (g_disassemblyManager.getNthNextAddress(curAddress, 1) != windowEnd && curAddressIsVisible()) {
setCurAddress(g_disassemblyManager.getNthPreviousAddress(windowEnd, 1), KeyDownAsync(VK_SHIFT));
scrollAddressIntoView();
} else {
setCurAddress(manager.getNthNextAddress(windowEnd, visibleRows_ - 1), KeyDownAsync(VK_SHIFT));
setCurAddress(g_disassemblyManager.getNthNextAddress(windowEnd, visibleRows_ - 1), KeyDownAsync(VK_SHIFT));
scrollAddressIntoView();
}
break;
@@ -650,7 +650,7 @@ void ImDisasmView::ProcessKeyboardShortcuts(bool focused) {
setCurAddress(windowStart_, KeyDownAsync(VK_SHIFT));
scrollAddressIntoView();
} else {
setCurAddress(manager.getNthPreviousAddress(windowStart_, visibleRows_), KeyDownAsync(VK_SHIFT));
setCurAddress(g_disassemblyManager.getNthPreviousAddress(windowStart_, visibleRows_), KeyDownAsync(VK_SHIFT));
scrollAddressIntoView();
}
break;
@@ -666,18 +666,18 @@ void ImDisasmView::ProcessKeyboardShortcuts(bool focused) {
}
void ImDisasmView::scrollAddressIntoView() {
u32 windowEnd = manager.getNthNextAddress(windowStart_, visibleRows_);
u32 windowEnd = g_disassemblyManager.getNthNextAddress(windowStart_, visibleRows_);
if (curAddress_ < windowStart_)
windowStart_ = curAddress_;
else if (curAddress_ >= windowEnd)
windowStart_ = manager.getNthPreviousAddress(curAddress_, visibleRows_ - 1);
windowStart_ = g_disassemblyManager.getNthPreviousAddress(curAddress_, visibleRows_ - 1);
ScanVisibleFunctions();
}
bool ImDisasmView::curAddressIsVisible() {
u32 windowEnd = manager.getNthNextAddress(windowStart_, visibleRows_);
u32 windowEnd = g_disassemblyManager.getNthNextAddress(windowStart_, visibleRows_);
return curAddress_ >= windowStart_ && curAddress_ < windowEnd;
}
@@ -828,7 +828,7 @@ void ImDisasmView::PopupMenu(ImControl &control) {
g_symbolMap->RemoveFunction(funcBegin, true);
g_symbolMap->SortSymbols();
manager.clear();
g_disassemblyManager.clear();
mapReloaded_ = true;
} else {
@@ -852,7 +852,7 @@ void ImDisasmView::PopupMenu(ImControl &control) {
snprintf(symname, 128, "u_un_%08X", curAddress_);
g_symbolMap->AddFunction(symname, curAddress_, newSize);
g_symbolMap->SortSymbols();
manager.clear();
g_disassemblyManager.clear();
mapReloaded_ = true;
}
@@ -902,7 +902,7 @@ void ImDisasmView::updateStatusBarText() {
char text[512];
DisassemblyLineInfo line;
manager.getLine(curAddress_, true, line);
g_disassemblyManager.getLine(curAddress_, true, line, debugger_);
text[0] = 0;
if (line.type == DISTYPE_OPCODE || line.type == DISTYPE_MACRO) {
@@ -997,7 +997,7 @@ void ImDisasmView::updateStatusBarText() {
u32 ImDisasmView::yToAddress(float y) {
int line = (int)(y / rowHeight_);
return manager.getNthNextAddress(windowStart_, line);
return g_disassemblyManager.getNthNextAddress(windowStart_, line);
}
void ImDisasmView::calculatePixelPositions() {
@@ -1022,7 +1022,7 @@ void ImDisasmView::SearchNext(bool forward) {
}
// Note: Search will replace matchAddress_ with the current address.
u32 searchAddress = manager.getNthNextAddress(matchAddress_, 1);
u32 searchAddress = g_disassemblyManager.getNthNextAddress(matchAddress_, 1);
// limit address to sensible ranges
if (searchAddress < 0x04000000)
@@ -1038,7 +1038,7 @@ void ImDisasmView::SearchNext(bool forward) {
DisassemblyLineInfo lineInfo;
while (searchAddress < 0x0A000000) {
manager.getLine(searchAddress, displaySymbols_, lineInfo);
g_disassemblyManager.getLine(searchAddress, displaySymbols_, lineInfo, debugger_);
char addressText[64];
getDisasmAddressText(searchAddress, addressText, true, lineInfo.type == DISTYPE_OPCODE);
@@ -1071,7 +1071,7 @@ void ImDisasmView::SearchNext(bool forward) {
return;
}
searchAddress = manager.getNthNextAddress(searchAddress, 1);
searchAddress = g_disassemblyManager.getNthNextAddress(searchAddress, 1);
if (searchAddress >= 0x04200000 && searchAddress < 0x08000000) searchAddress = 0x08000000;
}
@@ -1102,7 +1102,7 @@ std::string ImDisasmView::disassembleRange(u32 start, u32 size) {
while (disAddress < start + size) {
char addressText[64], buffer[512];
manager.getLine(disAddress, displaySymbols_, line);
g_disassemblyManager.getLine(disAddress, displaySymbols_, line, debugger_);
bool isLabel = getDisasmAddressText(disAddress, addressText, false, line.type == DISTYPE_OPCODE);
if (isLabel) {
@@ -1162,23 +1162,23 @@ void ImDisasmView::disassembleToFile() { // get size
void ImDisasmView::getOpcodeText(u32 address, char* dest, int bufsize) {
DisassemblyLineInfo line;
address = manager.getStartAddress(address);
manager.getLine(address, displaySymbols_, line);
address = g_disassemblyManager.getStartAddress(address);
g_disassemblyManager.getLine(address, displaySymbols_, line, debugger_);
snprintf(dest, bufsize, "%s %s", line.name.c_str(), line.params.c_str());
}
void ImDisasmView::scrollStepping(u32 newPc) {
u32 windowEnd = manager.getNthNextAddress(windowStart_, visibleRows_);
u32 windowEnd = g_disassemblyManager.getNthNextAddress(windowStart_, visibleRows_);
newPc = manager.getStartAddress(newPc);
if (newPc >= windowEnd || newPc >= manager.getNthPreviousAddress(windowEnd, 1))
newPc = g_disassemblyManager.getStartAddress(newPc);
if (newPc >= windowEnd || newPc >= g_disassemblyManager.getNthPreviousAddress(windowEnd, 1))
{
windowStart_ = manager.getNthPreviousAddress(newPc, visibleRows_ - 2);
windowStart_ = g_disassemblyManager.getNthPreviousAddress(newPc, visibleRows_ - 2);
}
}
u32 ImDisasmView::getInstructionSizeAt(u32 address) {
u32 start = manager.getStartAddress(address);
u32 next = manager.getNthNextAddress(start, 1);
u32 start = g_disassemblyManager.getStartAddress(address);
u32 next = g_disassemblyManager.getNthNextAddress(start, 1);
return next - address;
}
+7 -8
View File
@@ -40,7 +40,7 @@ public:
void scrollAddressIntoView();
bool curAddressIsVisible();
void ScanVisibleFunctions();
void clearFunctions() { manager.clear(); };
void clearFunctions() { g_disassemblyManager.clear(); };
void getOpcodeText(u32 address, char *dest, int bufsize);
u32 yToAddress(float y);
@@ -49,7 +49,7 @@ public:
if (debugger_ != deb) {
debugger_ = deb;
curAddress_ = debugger_->GetPC();
manager.setCpu(deb);
g_disassemblyManager.setCpu(deb);
}
}
@@ -63,11 +63,11 @@ public:
void gotoAddr(unsigned int addr) {
if (positionLocked_ != 0)
return;
u32 windowEnd = manager.getNthNextAddress(windowStart_, visibleRows_);
u32 newAddress = manager.getStartAddress(addr);
u32 windowEnd = g_disassemblyManager.getNthNextAddress(windowStart_, visibleRows_);
u32 newAddress = g_disassemblyManager.getStartAddress(addr);
if (newAddress < windowStart_ || newAddress >= windowEnd) {
windowStart_ = manager.getNthPreviousAddress(newAddress, visibleRows_ / 2);
windowStart_ = g_disassemblyManager.getNthPreviousAddress(newAddress, visibleRows_ / 2);
}
setCurAddress(newAddress);
@@ -89,8 +89,8 @@ public:
void editBreakpoint(ImConfig &cfg);
void setCurAddress(u32 newAddress, bool extend = false) {
newAddress = manager.getStartAddress(newAddress);
const u32 after = manager.getNthNextAddress(newAddress, 1);
newAddress = g_disassemblyManager.getStartAddress(newAddress);
const u32 after = g_disassemblyManager.getNthNextAddress(newAddress, 1);
curAddress_ = newAddress;
selectRangeStart_ = extend ? std::min(selectRangeStart_, newAddress) : newAddress;
selectRangeEnd_ = extend ? std::max(selectRangeEnd_, after) : after;
@@ -137,7 +137,6 @@ private:
std::set<std::string> getSelectedLineArguments();
void drawArguments(ImDrawList *list, Bounds rc, const DisassemblyLineInfo &line, float x, float y, ImColor textColor, const std::set<std::string> &currentArguments);
DisassemblyManager manager;
u32 curAddress_ = 0;
u32 selectRangeStart_ = 0;
u32 selectRangeEnd_ = 0;
+16 -2
View File
@@ -243,6 +243,17 @@ void ImGeDisasmView::Draw(GPUDebugInterface *gpuDebug) {
}
}
static const char *DLStateToString(DisplayListState state) {
switch (state) {
case PSP_GE_DL_STATE_NONE: return "None";
case PSP_GE_DL_STATE_QUEUED: return "Queued";
case PSP_GE_DL_STATE_RUNNING: return "Running";
case PSP_GE_DL_STATE_COMPLETED: return "Completed";
case PSP_GE_DL_STATE_PAUSED: return "Paused";
default: return "N/A (bad)";
}
}
void ImGeDebuggerWindow::Draw(ImConfig &cfg, ImControl &control, GPUDebugInterface *gpuDebug) {
ImGui::SetNextWindowSize(ImVec2(520, 600), ImGuiCond_FirstUseEver);
if (!ImGui::Begin(Title(), &cfg.geDebuggerOpen)) {
@@ -333,14 +344,17 @@ void ImGeDebuggerWindow::Draw(ImConfig &cfg, ImControl &control, GPUDebugInterfa
const auto &list = gpuDebug->GetDisplayList(index);
char title[64];
snprintf(title, sizeof(title), "List %d", list.id);
if (ImGui::CollapsingHeader(title, ImGuiTreeNodeFlags_DefaultOpen)) {
if (ImGui::CollapsingHeader(title)) {
ImGui::Text("State: %s", DLStateToString(list.state));
ImGui::TextUnformatted("PC:");
ImGui::SameLine();
ImClickableAddress(list.pc, control, ImCmd::SHOW_IN_GE_DISASM);
ImGui::Text("StartPC:");
ImGui::SameLine();
ImClickableAddress(list.startpc, control, ImCmd::SHOW_IN_GE_DISASM);
ImGui::Text("Pending interrupt: %d", (int)list.pendingInterrupt);
if (list.pendingInterrupt) {
ImGui::TextUnformatted("(Pending interrupt)");
}
ImGui::Text("Stack depth: %d", (int)list.stackptr);
ImGui::Text("BBOX result: %d", (int)list.bboxResult);
}
+40 -40
View File
@@ -63,7 +63,7 @@ void CtrlDisAsmView::deinit()
void CtrlDisAsmView::scanVisibleFunctions()
{
manager.analyze(windowStart,manager.getNthNextAddress(windowStart,visibleRows)-windowStart);
g_disassemblyManager.analyze(windowStart, g_disassemblyManager.getNthNextAddress(windowStart,visibleRows)-windowStart);
}
LRESULT CALLBACK CtrlDisAsmView::wndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
@@ -206,7 +206,7 @@ CtrlDisAsmView::~CtrlDisAsmView()
{
DeleteObject(font);
DeleteObject(boldfont);
manager.clear();
g_disassemblyManager.clear();
}
static COLORREF scaleColor(COLORREF color, float factor)
@@ -326,7 +326,7 @@ void CtrlDisAsmView::assembleOpcode(u32 address, const std::string &defaultText)
scanVisibleFunctions();
if (address == curAddress)
gotoAddr(manager.getNthNextAddress(curAddress,1));
gotoAddr(g_disassemblyManager.getNthNextAddress(curAddress,1));
redraw();
} else {
@@ -337,7 +337,7 @@ void CtrlDisAsmView::assembleOpcode(u32 address, const std::string &defaultText)
void CtrlDisAsmView::drawBranchLine(HDC hdc, std::map<u32,int> &addressPositions, const BranchLine &line) {
HPEN pen;
u32 windowEnd = manager.getNthNextAddress(windowStart,visibleRows);
u32 windowEnd = g_disassemblyManager.getNthNextAddress(windowStart,visibleRows);
int topY;
int bottomY;
@@ -433,7 +433,7 @@ std::set<std::string> CtrlDisAsmView::getSelectedLineArguments() {
DisassemblyLineInfo line;
for (u32 addr = selectRangeStart; addr < selectRangeEnd; addr += 4) {
manager.getLine(addr, displaySymbols, line);
g_disassemblyManager.getLine(addr, displaySymbols, line, debugger);
size_t p = 0, nextp = line.params.find(',');
while (nextp != line.params.npos) {
args.emplace(line.params.substr(p, nextp - p));
@@ -520,7 +520,7 @@ void CtrlDisAsmView::onPaint(WPARAM wParam, LPARAM lParam)
DisassemblyLineInfo line;
for (int i = 0; i < visibleRows; i++)
{
manager.getLine(address,displaySymbols,line);
g_disassemblyManager.getLine(address,displaySymbols,line, debugger);
int rowY1 = rowHeight*i;
int rowY2 = rowHeight*(i+1);
@@ -594,7 +594,7 @@ void CtrlDisAsmView::onPaint(WPARAM wParam, LPARAM lParam)
address += line.totalSize;
}
std::vector<BranchLine> branchLines = manager.getBranchLines(windowStart,address-windowStart);
std::vector<BranchLine> branchLines = g_disassemblyManager.getBranchLines(windowStart,address-windowStart);
for (size_t i = 0; i < branchLines.size(); i++)
{
drawBranchLine(hdc,addressPositions,branchLines[i]);
@@ -627,16 +627,16 @@ void CtrlDisAsmView::onVScroll(WPARAM wParam, LPARAM lParam)
switch (wParam & 0xFFFF)
{
case SB_LINEDOWN:
windowStart = manager.getNthNextAddress(windowStart,1);
windowStart = g_disassemblyManager.getNthNextAddress(windowStart,1);
break;
case SB_LINEUP:
windowStart = manager.getNthPreviousAddress(windowStart,1);
windowStart = g_disassemblyManager.getNthPreviousAddress(windowStart,1);
break;
case SB_PAGEDOWN:
windowStart = manager.getNthNextAddress(windowStart,visibleRows);
windowStart = g_disassemblyManager.getNthNextAddress(windowStart,visibleRows);
break;
case SB_PAGEUP:
windowStart = manager.getNthPreviousAddress(windowStart,visibleRows);
windowStart = g_disassemblyManager.getNthPreviousAddress(windowStart,visibleRows);
break;
default:
return;
@@ -649,7 +649,7 @@ void CtrlDisAsmView::onVScroll(WPARAM wParam, LPARAM lParam)
void CtrlDisAsmView::followBranch()
{
DisassemblyLineInfo line;
manager.getLine(curAddress,true,line);
g_disassemblyManager.getLine(curAddress, true, line, debugger);
if (line.type == DISTYPE_OPCODE || line.type == DISTYPE_MACRO)
{
@@ -721,7 +721,7 @@ void CtrlDisAsmView::onKeyDown(WPARAM wParam, LPARAM lParam)
return;
dontRedraw = false;
u32 windowEnd = manager.getNthNextAddress(windowStart,visibleRows);
u32 windowEnd = g_disassemblyManager.getNthNextAddress(windowStart,visibleRows);
keyTaken = true;
if (KeyDownAsync(VK_CONTROL))
@@ -764,7 +764,7 @@ void CtrlDisAsmView::onKeyDown(WPARAM wParam, LPARAM lParam)
scanVisibleFunctions();
break;
case VK_NEXT:
setCurAddress(manager.getNthPreviousAddress(windowEnd,1),KeyDownAsync(VK_SHIFT));
setCurAddress(g_disassemblyManager.getNthPreviousAddress(windowEnd,1),KeyDownAsync(VK_SHIFT));
break;
case VK_PRIOR:
setCurAddress(windowStart,KeyDownAsync(VK_SHIFT));
@@ -774,19 +774,19 @@ void CtrlDisAsmView::onKeyDown(WPARAM wParam, LPARAM lParam)
switch (wParam & 0xFFFF)
{
case VK_DOWN:
setCurAddress(manager.getNthNextAddress(curAddress,1), KeyDownAsync(VK_SHIFT));
setCurAddress(g_disassemblyManager.getNthNextAddress(curAddress,1), KeyDownAsync(VK_SHIFT));
scrollAddressIntoView();
break;
case VK_UP:
setCurAddress(manager.getNthPreviousAddress(curAddress,1), KeyDownAsync(VK_SHIFT));
setCurAddress(g_disassemblyManager.getNthPreviousAddress(curAddress,1), KeyDownAsync(VK_SHIFT));
scrollAddressIntoView();
break;
case VK_NEXT:
if (manager.getNthNextAddress(curAddress,1) != windowEnd && curAddressIsVisible()) {
setCurAddress(manager.getNthPreviousAddress(windowEnd,1), KeyDownAsync(VK_SHIFT));
if (g_disassemblyManager.getNthNextAddress(curAddress,1) != windowEnd && curAddressIsVisible()) {
setCurAddress(g_disassemblyManager.getNthPreviousAddress(windowEnd,1), KeyDownAsync(VK_SHIFT));
scrollAddressIntoView();
} else {
setCurAddress(manager.getNthNextAddress(windowEnd,visibleRows-1), KeyDownAsync(VK_SHIFT));
setCurAddress(g_disassemblyManager.getNthNextAddress(windowEnd,visibleRows-1), KeyDownAsync(VK_SHIFT));
scrollAddressIntoView();
}
break;
@@ -795,7 +795,7 @@ void CtrlDisAsmView::onKeyDown(WPARAM wParam, LPARAM lParam)
setCurAddress(windowStart, KeyDownAsync(VK_SHIFT));
scrollAddressIntoView();
} else {
setCurAddress(manager.getNthPreviousAddress(windowStart,visibleRows), KeyDownAsync(VK_SHIFT));
setCurAddress(g_disassemblyManager.getNthPreviousAddress(windowStart,visibleRows), KeyDownAsync(VK_SHIFT));
scrollAddressIntoView();
}
break;
@@ -836,19 +836,19 @@ void CtrlDisAsmView::onKeyUp(WPARAM wParam, LPARAM lParam)
void CtrlDisAsmView::scrollAddressIntoView()
{
u32 windowEnd = manager.getNthNextAddress(windowStart,visibleRows);
u32 windowEnd = g_disassemblyManager.getNthNextAddress(windowStart,visibleRows);
if (curAddress < windowStart)
windowStart = curAddress;
else if (curAddress >= windowEnd)
windowStart = manager.getNthPreviousAddress(curAddress,visibleRows-1);
windowStart = g_disassemblyManager.getNthPreviousAddress(curAddress,visibleRows-1);
scanVisibleFunctions();
}
bool CtrlDisAsmView::curAddressIsVisible()
{
u32 windowEnd = manager.getNthNextAddress(windowStart,visibleRows);
u32 windowEnd = g_disassemblyManager.getNthNextAddress(windowStart,visibleRows);
return curAddress >= windowStart && curAddress < windowEnd;
}
@@ -1060,7 +1060,7 @@ void CtrlDisAsmView::onMouseUp(WPARAM wParam, LPARAM lParam, int button)
g_symbolMap->RemoveFunction(funcBegin,true);
g_symbolMap->SortSymbols();
manager.clear();
g_disassemblyManager.clear();
SendMessage(GetParent(wnd), WM_DEB_MAPLOADED, 0, 0);
}
@@ -1094,7 +1094,7 @@ void CtrlDisAsmView::onMouseUp(WPARAM wParam, LPARAM lParam, int button)
snprintf(symname,128,"u_un_%08X",curAddress);
g_symbolMap->AddFunction(symname,curAddress,newSize);
g_symbolMap->SortSymbols();
manager.clear();
g_disassemblyManager.clear();
SendMessage(GetParent(wnd), WM_DEB_MAPLOADED, 0, 0);
}
@@ -1143,7 +1143,7 @@ void CtrlDisAsmView::updateStatusBarText()
char text[512];
DisassemblyLineInfo line;
manager.getLine(curAddress,true,line);
g_disassemblyManager.getLine(curAddress,true,line, debugger);
text[0] = 0;
if (line.type == DISTYPE_OPCODE || line.type == DISTYPE_MACRO)
@@ -1242,7 +1242,7 @@ void CtrlDisAsmView::updateStatusBarText()
u32 CtrlDisAsmView::yToAddress(int y)
{
int line = y/rowHeight;
return manager.getNthNextAddress(windowStart,line);
return g_disassemblyManager.getNthNextAddress(windowStart,line);
}
void CtrlDisAsmView::calculatePixelPositions()
@@ -1272,9 +1272,9 @@ void CtrlDisAsmView::search(bool continueSearch)
searchQuery[i] = tolower(searchQuery[i]);
}
SetFocus(wnd);
searchAddress = manager.getNthNextAddress(curAddress,1);
searchAddress = g_disassemblyManager.getNthNextAddress(curAddress,1);
} else {
searchAddress = manager.getNthNextAddress(matchAddress,1);
searchAddress = g_disassemblyManager.getNthNextAddress(matchAddress,1);
}
// limit address to sensible ranges
@@ -1291,7 +1291,7 @@ void CtrlDisAsmView::search(bool continueSearch)
DisassemblyLineInfo lineInfo;
while (searchAddress < 0x0A000000)
{
manager.getLine(searchAddress,displaySymbols,lineInfo);
g_disassemblyManager.getLine(searchAddress,displaySymbols,lineInfo, debugger);
char addressText[64];
getDisasmAddressText(searchAddress,addressText,true,lineInfo.type == DISTYPE_OPCODE);
@@ -1326,7 +1326,7 @@ void CtrlDisAsmView::search(bool continueSearch)
return;
}
searchAddress = manager.getNthNextAddress(searchAddress,1);
searchAddress = g_disassemblyManager.getNthNextAddress(searchAddress,1);
if (searchAddress >= 0x04200000 && searchAddress < 0x08000000) searchAddress = 0x08000000;
}
@@ -1361,7 +1361,7 @@ std::string CtrlDisAsmView::disassembleRange(u32 start, u32 size)
{
char addressText[64],buffer[512];
manager.getLine(disAddress,displaySymbols,line);
g_disassemblyManager.getLine(disAddress,displaySymbols,line, debugger);
bool isLabel = getDisasmAddressText(disAddress,addressText,false,line.type == DISTYPE_OPCODE);
if (isLabel)
@@ -1423,25 +1423,25 @@ void CtrlDisAsmView::disassembleToFile() {
void CtrlDisAsmView::getOpcodeText(u32 address, char* dest, int bufsize)
{
DisassemblyLineInfo line;
address = manager.getStartAddress(address);
manager.getLine(address,displaySymbols,line);
address = g_disassemblyManager.getStartAddress(address);
g_disassemblyManager.getLine(address,displaySymbols,line, debugger);
snprintf(dest, bufsize, "%s %s",line.name.c_str(),line.params.c_str());
}
void CtrlDisAsmView::scrollStepping(u32 newPc)
{
u32 windowEnd = manager.getNthNextAddress(windowStart,visibleRows);
u32 windowEnd = g_disassemblyManager.getNthNextAddress(windowStart,visibleRows);
newPc = manager.getStartAddress(newPc);
if (newPc >= windowEnd || newPc >= manager.getNthPreviousAddress(windowEnd,1))
newPc = g_disassemblyManager.getStartAddress(newPc);
if (newPc >= windowEnd || newPc >= g_disassemblyManager.getNthPreviousAddress(windowEnd,1))
{
windowStart = manager.getNthPreviousAddress(newPc,visibleRows-2);
windowStart = g_disassemblyManager.getNthPreviousAddress(newPc,visibleRows-2);
}
}
u32 CtrlDisAsmView::getInstructionSizeAt(u32 address)
{
u32 start = manager.getStartAddress(address);
u32 next = manager.getNthNextAddress(start,1);
u32 start = g_disassemblyManager.getStartAddress(address);
u32 next = g_disassemblyManager.getNthNextAddress(start,1);
return next - address;
}
+9 -10
View File
@@ -29,7 +29,6 @@ class CtrlDisAsmView
HFONT boldfont;
RECT rect;
DisassemblyManager manager;
u32 curAddress;
u32 selectRangeStart;
u32 selectRangeEnd;
@@ -101,7 +100,7 @@ public:
bool curAddressIsVisible();
void redraw();
void scanVisibleFunctions();
void clearFunctions() { manager.clear(); };
void clearFunctions() { g_disassemblyManager.clear(); };
void getOpcodeText(u32 address, char* dest, int bufsize);
int getRowHeight() { return rowHeight; };
@@ -112,7 +111,7 @@ public:
{
debugger=deb;
curAddress=debugger->GetPC();
manager.setCpu(deb);
g_disassemblyManager.setCpu(deb);
}
DebugInterface *getDebugger()
{
@@ -126,12 +125,12 @@ public:
{
if (positionLocked_ != 0)
return;
u32 windowEnd = manager.getNthNextAddress(windowStart,visibleRows);
u32 newAddress = manager.getStartAddress(addr);
u32 windowEnd = g_disassemblyManager.getNthNextAddress(windowStart,visibleRows);
u32 newAddress = g_disassemblyManager.getStartAddress(addr);
if (newAddress < windowStart || newAddress >= windowEnd)
{
windowStart = manager.getNthPreviousAddress(newAddress,visibleRows/2);
windowStart = g_disassemblyManager.getNthPreviousAddress(newAddress,visibleRows/2);
}
setCurAddress(newAddress);
@@ -158,9 +157,9 @@ public:
void scrollWindow(int lines)
{
if (lines < 0)
windowStart = manager.getNthPreviousAddress(windowStart,abs(lines));
windowStart = g_disassemblyManager.getNthPreviousAddress(windowStart,abs(lines));
else
windowStart = manager.getNthNextAddress(windowStart,lines);
windowStart = g_disassemblyManager.getNthNextAddress(windowStart,lines);
scanVisibleFunctions();
redraw();
@@ -168,8 +167,8 @@ public:
void setCurAddress(u32 newAddress, bool extend = false)
{
newAddress = manager.getStartAddress(newAddress);
const u32 after = manager.getNthNextAddress(newAddress,1);
newAddress = g_disassemblyManager.getStartAddress(newAddress);
const u32 after = g_disassemblyManager.getNthNextAddress(newAddress,1);
curAddress = newAddress;
selectRangeStart = extend ? std::min(selectRangeStart, newAddress) : newAddress;
selectRangeEnd = extend ? std::max(selectRangeEnd, after) : after;
+1 -2
View File
@@ -178,8 +178,7 @@ void EditSymbolsWindow::Remove() {
}
// Clear cache for branch lines and such.
DisassemblyManager manager;
manager.clear();
g_disassemblyManager.clear();
}
}
+5 -143
View File
@@ -53,6 +53,7 @@
#include "GPU/Debugger/Breakpoints.h"
#include "GPU/Debugger/Debugger.h"
#include "GPU/Debugger/Record.h"
#include "GPU/Debugger/State.h"
#include "GPU/Debugger/Stepping.h"
using namespace GPUBreakpoints;
@@ -568,7 +569,10 @@ void CGEDebugger::UpdatePreviews() {
UpdatePrimaryPreview(state);
UpdateSecondPreview(state);
u32 primOp = PrimPreviewOp();
u32 primOp = 0;
if (!showClut_) {
primOp = PrimPreviewOp();
}
if (primOp != 0) {
UpdatePrimPreview(primOp, 3);
}
@@ -826,148 +830,6 @@ void CGEDebugger::SecondPreviewHover(int x, int y) {
SetDlgItemText(m_hDlg, IDC_GEDBG_TEXADDR, w_desc);
}
void CGEDebugger::DescribePixel(u32 pix, GPUDebugBufferFormat fmt, int x, int y, char desc[256]) {
switch (fmt) {
case GPU_DBG_FORMAT_565:
case GPU_DBG_FORMAT_565_REV:
case GPU_DBG_FORMAT_5551:
case GPU_DBG_FORMAT_5551_REV:
case GPU_DBG_FORMAT_5551_BGRA:
case GPU_DBG_FORMAT_4444:
case GPU_DBG_FORMAT_4444_REV:
case GPU_DBG_FORMAT_4444_BGRA:
case GPU_DBG_FORMAT_8888:
case GPU_DBG_FORMAT_8888_BGRA:
DescribePixelRGBA(pix, fmt, x, y, desc);
break;
case GPU_DBG_FORMAT_16BIT:
snprintf(desc, 256, "%d,%d: %d / %f", x, y, pix, pix * (1.0f / 65535.0f));
break;
case GPU_DBG_FORMAT_8BIT:
snprintf(desc, 256, "%d,%d: %d / %f", x, y, pix, pix * (1.0f / 255.0f));
break;
case GPU_DBG_FORMAT_24BIT_8X:
{
DepthScaleFactors depthScale = GetDepthScaleFactors(gstate_c.UseFlags());
// These are only ever going to be depth values, so let's also show scaled to 16 bit.
snprintf(desc, 256, "%d,%d: %d / %f / %f", x, y, pix & 0x00FFFFFF, (pix & 0x00FFFFFF) * (1.0f / 16777215.0f), depthScale.DecodeToU16((pix & 0x00FFFFFF) * (1.0f / 16777215.0f)));
break;
}
case GPU_DBG_FORMAT_24BIT_8X_DIV_256:
{
// These are only ever going to be depth values, so let's also show scaled to 16 bit.
int z24 = pix & 0x00FFFFFF;
int z16 = z24 - 0x800000 + 0x8000;
snprintf(desc, 256, "%d,%d: %d / %f", x, y, z16, z16 * (1.0f / 65535.0f));
}
break;
case GPU_DBG_FORMAT_24X_8BIT:
snprintf(desc, 256, "%d,%d: %d / %f", x, y, (pix >> 24) & 0xFF, ((pix >> 24) & 0xFF) * (1.0f / 255.0f));
break;
case GPU_DBG_FORMAT_FLOAT: {
float pixf = *(float *)&pix;
DepthScaleFactors depthScale = GetDepthScaleFactors(gstate_c.UseFlags());
snprintf(desc, 256, "%d,%d: %f / %f", x, y, pixf, depthScale.DecodeToU16(pixf));
break;
}
case GPU_DBG_FORMAT_FLOAT_DIV_256:
{
double z = *(float *)&pix;
int z24 = (int)(z * 16777215.0);
DepthScaleFactors factors = GetDepthScaleFactors(gstate_c.UseFlags());
// TODO: Use GetDepthScaleFactors here too, verify it's the same.
int z16 = z24 - 0x800000 + 0x8000;
int z16_2 = factors.DecodeToU16(z);
snprintf(desc, 256, "%d,%d: %d / %f", x, y, z16, (z - 0.5 + (1.0 / 512.0)) * 256.0);
}
break;
default:
snprintf(desc, 256, "Unexpected format");
}
}
void CGEDebugger::DescribePixelRGBA(u32 pix, GPUDebugBufferFormat fmt, int x, int y, char desc[256]) {
u32 r = -1, g = -1, b = -1, a = -1;
switch (fmt) {
case GPU_DBG_FORMAT_565:
r = Convert5To8((pix >> 0) & 0x1F);
g = Convert6To8((pix >> 5) & 0x3F);
b = Convert5To8((pix >> 11) & 0x1F);
break;
case GPU_DBG_FORMAT_565_REV:
b = Convert5To8((pix >> 0) & 0x1F);
g = Convert6To8((pix >> 5) & 0x3F);
r = Convert5To8((pix >> 11) & 0x1F);
break;
case GPU_DBG_FORMAT_5551:
r = Convert5To8((pix >> 0) & 0x1F);
g = Convert5To8((pix >> 5) & 0x1F);
b = Convert5To8((pix >> 10) & 0x1F);
a = (pix >> 15) & 1 ? 255 : 0;
break;
case GPU_DBG_FORMAT_5551_REV:
a = pix & 1 ? 255 : 0;
b = Convert5To8((pix >> 1) & 0x1F);
g = Convert5To8((pix >> 6) & 0x1F);
r = Convert5To8((pix >> 11) & 0x1F);
break;
case GPU_DBG_FORMAT_5551_BGRA:
b = Convert5To8((pix >> 0) & 0x1F);
g = Convert5To8((pix >> 5) & 0x1F);
r = Convert5To8((pix >> 10) & 0x1F);
a = (pix >> 15) & 1 ? 255 : 0;
break;
case GPU_DBG_FORMAT_4444:
r = Convert4To8((pix >> 0) & 0x0F);
g = Convert4To8((pix >> 4) & 0x0F);
b = Convert4To8((pix >> 8) & 0x0F);
a = Convert4To8((pix >> 12) & 0x0F);
break;
case GPU_DBG_FORMAT_4444_REV:
a = Convert4To8((pix >> 0) & 0x0F);
b = Convert4To8((pix >> 4) & 0x0F);
g = Convert4To8((pix >> 8) & 0x0F);
r = Convert4To8((pix >> 12) & 0x0F);
break;
case GPU_DBG_FORMAT_4444_BGRA:
b = Convert4To8((pix >> 0) & 0x0F);
g = Convert4To8((pix >> 4) & 0x0F);
r = Convert4To8((pix >> 8) & 0x0F);
a = Convert4To8((pix >> 12) & 0x0F);
break;
case GPU_DBG_FORMAT_8888:
r = (pix >> 0) & 0xFF;
g = (pix >> 8) & 0xFF;
b = (pix >> 16) & 0xFF;
a = (pix >> 24) & 0xFF;
break;
case GPU_DBG_FORMAT_8888_BGRA:
b = (pix >> 0) & 0xFF;
g = (pix >> 8) & 0xFF;
r = (pix >> 16) & 0xFF;
a = (pix >> 24) & 0xFF;
break;
default:
snprintf(desc, 256, "Unexpected format");
return;
}
snprintf(desc, 256, "%d,%d: r=%d, g=%d, b=%d, a=%d", x, y, r, g, b, a);
}
void CGEDebugger::UpdateTextureLevel(int level) {
GPUgstate state{};
if (gpuDebug != nullptr) {
+1 -3
View File
@@ -102,7 +102,7 @@ private:
void UpdatePreviews();
void UpdatePrimaryPreview(const GPUgstate &state);
void UpdateSecondPreview(const GPUgstate &state);
u32 PrimPreviewOp();
static u32 PrimPreviewOp();
void UpdatePrimPreview(u32 op, int which);
void CleanupPrimPreview();
void HandleRedraw(int which);
@@ -115,8 +115,6 @@ private:
void SecondPreviewHover(int x, int y);
void PreviewExport(const GPUDebugBuffer *buffer);
void PreviewToClipboard(const GPUDebugBuffer *buffer, bool saveAlpha);
static void DescribePixel(u32 pix, GPUDebugBufferFormat fmt, int x, int y, char desc[256]);
static void DescribePixelRGBA(u32 pix, GPUDebugBufferFormat fmt, int x, int y, char desc[256]);
void UpdateMenus();
void UpdateTab(GEDebuggerTab *tab);
void AddTab(GEDebuggerTab *tab, GETabPosition mask);
+8 -287
View File
@@ -25,6 +25,7 @@
#include "GPU/GPUCommon.h"
#include "GPU/Common/GPUDebugInterface.h"
#include "GPU/Common/SplineCommon.h"
#include "GPU/Debugger/State.h"
#include "GPU/GPUState.h"
#include "Common/Log.h"
#include "Common/MemoryUtil.h"
@@ -73,318 +74,37 @@ static void BindPreviewProgram(GLSLProgram *&prog) {
glsl_bind(prog);
}
static void SwapUVs(GPUDebugVertex &a, GPUDebugVertex &b) {
float tempu = a.u;
float tempv = a.v;
a.u = b.u;
a.v = b.v;
b.u = tempu;
b.v = tempv;
}
static void RotateUVThrough(GPUDebugVertex v[4]) {
float x1 = v[2].x;
float x2 = v[0].x;
float y1 = v[2].y;
float y2 = v[0].y;
if ((x1 < x2 && y1 > y2) || (x1 > x2 && y1 < y2))
SwapUVs(v[1], v[3]);
}
static void ExpandRectangles(std::vector<GPUDebugVertex> &vertices, std::vector<u16> &indices, int &count, bool throughMode) {
static std::vector<GPUDebugVertex> newVerts;
static std::vector<u16> newInds;
bool useInds = true;
size_t numInds = indices.size();
if (indices.empty()) {
useInds = false;
numInds = count;
}
//rectangles always need 2 vertices, disregard the last one if there's an odd number
numInds = numInds & ~1;
// Will need 4 coords and 6 points per rectangle (currently 2 each.)
newVerts.resize(numInds * 2);
newInds.resize(numInds * 3);
u16 v = 0;
GPUDebugVertex *vert = &newVerts[0];
u16 *ind = &newInds[0];
for (size_t i = 0; i < numInds; i += 2) {
const auto &orig_tl = useInds ? vertices[indices[i + 0]] : vertices[i + 0];
const auto &orig_br = useInds ? vertices[indices[i + 1]] : vertices[i + 1];
vert[0] = orig_br;
// Top right.
vert[1] = orig_br;
vert[1].y = orig_tl.y;
vert[1].v = orig_tl.v;
vert[2] = orig_tl;
// Bottom left.
vert[3] = orig_br;
vert[3].x = orig_tl.x;
vert[3].u = orig_tl.u;
// That's the four corners. Now process UV rotation.
// This is the same for through and non-through, since it's already transformed.
RotateUVThrough(vert);
// Build the two 3 point triangles from our 4 coordinates.
*ind++ = v + 0;
*ind++ = v + 1;
*ind++ = v + 2;
*ind++ = v + 3;
*ind++ = v + 0;
*ind++ = v + 2;
vert += 4;
v += 4;
}
std::swap(vertices, newVerts);
std::swap(indices, newInds);
count *= 3;
}
u32 CGEDebugger::PrimPreviewOp() {
DisplayList list;
if (gpuDebug != nullptr && gpuDebug->GetCurrentDisplayList(list) && !showClut_) {
if (gpuDebug != nullptr && gpuDebug->GetCurrentDisplayList(list)) {
const u32 op = Memory::Read_U32(list.pc);
const u32 cmd = op >> 24;
if (cmd == GE_CMD_PRIM || cmd == GE_CMD_BEZIER || cmd == GE_CMD_SPLINE) {
return op;
}
}
return 0;
}
static void ExpandBezier(int &count, int op, const std::vector<SimpleVertex> &simpleVerts, const std::vector<u16> &indices, std::vector<SimpleVertex> &generatedVerts, std::vector<u16> &generatedInds) {
using namespace Spline;
int count_u = (op >> 0) & 0xFF;
int count_v = (op >> 8) & 0xFF;
// Real hardware seems to draw nothing when given < 4 either U or V.
if (count_u < 4 || count_v < 4)
return;
BezierSurface surface;
surface.num_points_u = count_u;
surface.num_points_v = count_v;
surface.tess_u = gstate.getPatchDivisionU();
surface.tess_v = gstate.getPatchDivisionV();
surface.num_patches_u = (count_u - 1) / 3;
surface.num_patches_v = (count_v - 1) / 3;
surface.primType = gstate.getPatchPrimitiveType();
surface.patchFacing = false;
int num_points = count_u * count_v;
// Make an array of pointers to the control points, to get rid of indices.
std::vector<const SimpleVertex *> points(num_points);
for (int idx = 0; idx < num_points; idx++)
points[idx] = simpleVerts.data() + (!indices.empty() ? indices[idx] : idx);
int total_patches = surface.num_patches_u * surface.num_patches_v;
generatedVerts.resize((surface.tess_u + 1) * (surface.tess_v + 1) * total_patches);
generatedInds.resize(surface.tess_u * surface.tess_v * 6 * total_patches);
OutputBuffers output;
output.vertices = generatedVerts.data();
output.indices = generatedInds.data();
output.count = 0;
ControlPoints cpoints;
cpoints.pos = new Vec3f[num_points];
cpoints.tex = new Vec2f[num_points];
cpoints.col = new Vec4f[num_points];
cpoints.Convert(points.data(), num_points);
surface.Init((int)generatedVerts.size());
SoftwareTessellation(output, surface, gstate.vertType, cpoints);
count = output.count;
delete [] cpoints.pos;
delete [] cpoints.tex;
delete [] cpoints.col;
}
static void ExpandSpline(int &count, int op, const std::vector<SimpleVertex> &simpleVerts, const std::vector<u16> &indices, std::vector<SimpleVertex> &generatedVerts, std::vector<u16> &generatedInds) {
using namespace Spline;
int count_u = (op >> 0) & 0xFF;
int count_v = (op >> 8) & 0xFF;
// Real hardware seems to draw nothing when given < 4 either U or V.
if (count_u < 4 || count_v < 4)
return;
SplineSurface surface;
surface.num_points_u = count_u;
surface.num_points_v = count_v;
surface.tess_u = gstate.getPatchDivisionU();
surface.tess_v = gstate.getPatchDivisionV();
surface.type_u = (op >> 16) & 0x3;
surface.type_v = (op >> 18) & 0x3;
surface.num_patches_u = count_u - 3;
surface.num_patches_v = count_v - 3;
surface.primType = gstate.getPatchPrimitiveType();
surface.patchFacing = false;
int num_points = count_u * count_v;
// Make an array of pointers to the control points, to get rid of indices.
std::vector<const SimpleVertex *> points(num_points);
for (int idx = 0; idx < num_points; idx++)
points[idx] = simpleVerts.data() + (!indices.empty() ? indices[idx] : idx);
int patch_div_s = surface.num_patches_u * surface.tess_u;
int patch_div_t = surface.num_patches_v * surface.tess_v;
generatedVerts.resize((patch_div_s + 1) * (patch_div_t + 1));
generatedInds.resize(patch_div_s * patch_div_t * 6);
OutputBuffers output;
output.vertices = generatedVerts.data();
output.indices = generatedInds.data();
output.count = 0;
ControlPoints cpoints;
cpoints.pos = (Vec3f *)AllocateAlignedMemory(sizeof(Vec3f) * num_points, 16);
cpoints.tex = (Vec2f *)AllocateAlignedMemory(sizeof(Vec2f) * num_points, 16);
cpoints.col = (Vec4f *)AllocateAlignedMemory(sizeof(Vec4f) * num_points, 16);
cpoints.Convert(points.data(), num_points);
surface.Init((int)generatedVerts.size());
SoftwareTessellation(output, surface, gstate.vertType, cpoints);
count = output.count;
FreeAlignedMemory(cpoints.pos);
FreeAlignedMemory(cpoints.tex);
FreeAlignedMemory(cpoints.col);
}
void CGEDebugger::UpdatePrimPreview(u32 op, int which) {
u32 prim_type = GE_PRIM_INVALID;
int count = 0;
int count_u = 0;
int count_v = 0;
const u32 cmd = op >> 24;
if (cmd == GE_CMD_PRIM) {
prim_type = (op >> 16) & 0x7;
count = op & 0xFFFF;
} else {
const GEPrimitiveType primLookup[] = { GE_PRIM_TRIANGLES, GE_PRIM_LINES, GE_PRIM_POINTS, GE_PRIM_POINTS };
if (gstate.getPatchPrimitiveType() < ARRAY_SIZE(primLookup))
prim_type = primLookup[gstate.getPatchPrimitiveType()];
count_u = (op & 0x00FF) >> 0;
count_v = (op & 0xFF00) >> 8;
count = count_u * count_v;
}
if (prim_type >= 7) {
ERROR_LOG(Log::G3D, "Unsupported prim type: %x", op);
return;
}
if (!gpuDebug) {
ERROR_LOG(Log::G3D, "Invalid debugging environment, shutting down?");
return;
}
which &= previewsEnabled_;
if (count == 0 || which == 0) {
return;
}
const GEPrimitiveType prim = static_cast<GEPrimitiveType>(prim_type);
static std::vector<GPUDebugVertex> vertices;
static std::vector<u16> indices;
if (!gpuDebug->GetCurrentSimpleVertices(count, vertices, indices)) {
ERROR_LOG(Log::G3D, "Vertex preview not yet supported");
int count = 0;
GEPrimitiveType prim;
if (!GetPrimPreview(op, which, prim, vertices, indices, count)) {
return;
}
if (cmd != GE_CMD_PRIM) {
static std::vector<SimpleVertex> generatedVerts;
static std::vector<u16> generatedInds;
static std::vector<SimpleVertex> simpleVerts;
simpleVerts.resize(vertices.size());
for (size_t i = 0; i < vertices.size(); ++i) {
// For now, let's just copy back so we can use TessellateBezierPatch/TessellateSplinePatch...
simpleVerts[i].uv[0] = vertices[i].u;
simpleVerts[i].uv[1] = vertices[i].v;
simpleVerts[i].pos = Vec3Packedf(vertices[i].x, vertices[i].y, vertices[i].z);
}
if (cmd == GE_CMD_BEZIER) {
ExpandBezier(count, op, simpleVerts, indices, generatedVerts, generatedInds);
} else if (cmd == GE_CMD_SPLINE) {
ExpandSpline(count, op, simpleVerts, indices, generatedVerts, generatedInds);
}
vertices.resize(generatedVerts.size());
for (size_t i = 0; i < vertices.size(); ++i) {
vertices[i].u = generatedVerts[i].uv[0];
vertices[i].v = generatedVerts[i].uv[1];
vertices[i].x = generatedVerts[i].pos.x;
vertices[i].y = generatedVerts[i].pos.y;
vertices[i].z = generatedVerts[i].pos.z;
}
indices = generatedInds;
}
if (prim == GE_PRIM_RECTANGLES) {
ExpandRectangles(vertices, indices, count, gpuDebug->GetGState().isModeThrough());
}
float fw, fh;
float x, y;
// TODO: Probably there's a better way and place to do this.
u16 minIndex = 0;
u16 maxIndex = count - 1;
if (!indices.empty()) {
_dbg_assert_(count <= indices.size());
minIndex = 0xFFFF;
maxIndex = 0;
for (int i = 0; i < count; ++i) {
if (minIndex > indices[i]) {
minIndex = indices[i];
}
if (maxIndex < indices[i]) {
maxIndex = indices[i];
}
}
}
auto wrapCoord = [](float &coord) {
if (coord < 0.0f) {
coord += ceilf(-coord);
}
if (coord > 1.0f) {
coord -= floorf(coord);
}
};
const float invTexWidth = 1.0f / gpuDebug->GetGState().getTextureWidth(0);
const float invTexHeight = 1.0f / gpuDebug->GetGState().getTextureHeight(0);
const float invRealTexWidth = 1.0f / gstate_c.curTextureWidth;
const float invRealTexHeight = 1.0f / gstate_c.curTextureHeight;
bool clampS = gpuDebug->GetGState().isTexCoordClampedS();
bool clampT = gpuDebug->GetGState().isTexCoordClampedT();
for (u16 i = minIndex; i <= maxIndex; ++i) {
vertices[i].u *= invTexWidth;
vertices[i].v *= invTexHeight;
if (!clampS)
wrapCoord(vertices[i].u);
if (!clampT)
wrapCoord(vertices[i].v);
}
// Preview positions on the framebuffer
if (which & 1) {
primaryWindow->Begin();
primaryWindow->GetContentSize(x, y, fw, fh);
@@ -451,6 +171,7 @@ void CGEDebugger::UpdatePrimPreview(u32 op, int which) {
primaryWindow->End();
}
// Preview UVs on the texture
if (which & 2) {
secondWindow->Begin();
secondWindow->GetContentSize(x, y, fw, fh);
@@ -533,7 +254,7 @@ void CGEDebugger::HandleRedraw(int which) {
}
u32 op = PrimPreviewOp();
if (op) {
if (op && !showClut_) {
UpdatePrimPreview(op, which);
}
}