mirror of
https://github.com/RPCS3/rpcs3.git
synced 2024-11-17 17:11:23 +00:00
Introducing RSX debugger entry (main debugger)
This commit is contained in:
parent
62cb532460
commit
dbecf0fa50
@ -5,6 +5,7 @@
|
||||
#include "Emu/Cell/RawSPUThread.h"
|
||||
#include "Emu/Cell/lv2/sys_mmapper.h"
|
||||
#include "Emu/Cell/lv2/sys_event.h"
|
||||
#include "Emu/RSX/RSXThread.h"
|
||||
#include "Thread.h"
|
||||
#include "Utilities/JIT.h"
|
||||
#include <typeinfo>
|
||||
@ -104,6 +105,32 @@ void fmt_class_string<std::thread::id>::format(std::string& out, u64 arg)
|
||||
out += ss.str();
|
||||
}
|
||||
|
||||
std::string dump_useful_thread_info()
|
||||
{
|
||||
thread_local volatile bool guard = false;
|
||||
|
||||
std::string result;
|
||||
|
||||
// In case the dumping function was the cause for the exception/access violation
|
||||
// Avoid recursion
|
||||
if (std::exchange(guard, true))
|
||||
{
|
||||
return result;
|
||||
}
|
||||
|
||||
if (auto cpu = get_current_cpu_thread())
|
||||
{
|
||||
result = cpu->dump_all();
|
||||
}
|
||||
else if (auto render = rsx::get_current_renderer(); render && render->is_current_thread())
|
||||
{
|
||||
result = render->dump_regs();
|
||||
}
|
||||
|
||||
guard = false;
|
||||
return result;
|
||||
}
|
||||
|
||||
#ifndef _WIN32
|
||||
bool IsDebuggerPresent()
|
||||
{
|
||||
@ -1531,7 +1558,7 @@ bool handle_access_violation(u32 addr, bool is_writing, x64_context* context) no
|
||||
{
|
||||
if (!g_tls_access_violation_recovered)
|
||||
{
|
||||
vm_log.notice("\n%s", cpu->dump_all());
|
||||
vm_log.notice("\n%s", dump_useful_thread_info());
|
||||
vm_log.error("Access violation %s location 0x%x (%s) [type=u%u]", is_writing ? "writing" : "reading", addr, (is_writing && vm::check_addr(addr)) ? "read-only memory" : "unmapped memory", d_size * 8);
|
||||
}
|
||||
|
||||
@ -1560,9 +1587,9 @@ bool handle_access_violation(u32 addr, bool is_writing, x64_context* context) no
|
||||
|
||||
Emu.Pause();
|
||||
|
||||
if (cpu && !g_tls_access_violation_recovered)
|
||||
if (!g_tls_access_violation_recovered)
|
||||
{
|
||||
vm_log.notice("\n%s", cpu->dump_all());
|
||||
vm_log.notice("\n%s", dump_useful_thread_info());
|
||||
}
|
||||
|
||||
// Note: a thread may access violate more than once after hack_alloc recovery
|
||||
@ -1647,10 +1674,7 @@ static LONG exception_filter(PEXCEPTION_POINTERS pExp) noexcept
|
||||
{
|
||||
fmt::append(msg, "Emu Thread Name: '%s'.\n", thread_ctrl::get_name());
|
||||
|
||||
if (const auto cpu = get_current_cpu_thread())
|
||||
{
|
||||
sys_log.notice("\n%s", cpu->dump_all());
|
||||
}
|
||||
sys_log.notice("\n%s", dump_useful_thread_info());
|
||||
}
|
||||
|
||||
// TODO: Report full thread name if not an emu thread
|
||||
@ -1775,16 +1799,12 @@ static void signal_handler(int sig, siginfo_t* info, void* uct) noexcept
|
||||
}
|
||||
}
|
||||
|
||||
if (const auto cpu = get_current_cpu_thread())
|
||||
{
|
||||
sys_log.notice("\n%s", cpu->dump_all());
|
||||
}
|
||||
|
||||
std::string msg = fmt::format("Segfault %s location %p at %p.\n", cause, info->si_addr, RIP(context));
|
||||
|
||||
if (thread_ctrl::get_current())
|
||||
{
|
||||
fmt::append(msg, "Emu Thread Name: '%s'.\n", thread_ctrl::get_name());
|
||||
sys_log.notice("\n%s", dump_useful_thread_info());
|
||||
}
|
||||
|
||||
// TODO: Report full thread name if not an emu thread
|
||||
@ -2391,6 +2411,11 @@ u64 thread_base::get_cycles()
|
||||
|
||||
[[noreturn]] void thread_ctrl::emergency_exit(std::string_view reason)
|
||||
{
|
||||
if (std::string info = dump_useful_thread_info(); !info.empty())
|
||||
{
|
||||
sys_log.notice("\%s", info);
|
||||
}
|
||||
|
||||
sig_log.fatal("Thread terminated due to fatal error: %s", reason);
|
||||
|
||||
std::fprintf(stderr, "Thread '%s' terminated due to fatal error: %s\n", g_tls_log_prefix().c_str(), std::string(reason).c_str());
|
||||
|
@ -531,7 +531,7 @@ void cpu_thread::operator()()
|
||||
{
|
||||
if (_this)
|
||||
{
|
||||
sys_log.warning("CPU Thread '%s' terminated abnormally:\n%s", name, _this->dump_all());
|
||||
sys_log.warning("CPU Thread '%s' terminated abnormally!", name);
|
||||
cleanup();
|
||||
}
|
||||
}
|
||||
|
@ -10,6 +10,7 @@
|
||||
#include "Capture/rsx_capture.h"
|
||||
#include "rsx_methods.h"
|
||||
#include "rsx_utils.h"
|
||||
#include "gcm_printing.h"
|
||||
#include "Emu/Cell/lv2/sys_event.h"
|
||||
#include "Emu/Cell/Modules/cellGcmSys.h"
|
||||
#include "Overlays/overlay_perf_metrics.h"
|
||||
@ -469,7 +470,7 @@ namespace rsx
|
||||
if (capture_current_frame)
|
||||
{
|
||||
u32 element_count = rsx::method_registers.current_draw_clause.get_elements_count();
|
||||
capture_frame("Draw " + rsx::to_string(rsx::method_registers.current_draw_clause.primitive) + std::to_string(element_count));
|
||||
capture_frame(fmt::format("Draw %s %d", rsx::method_registers.current_draw_clause.primitive, element_count));
|
||||
}
|
||||
}
|
||||
|
||||
@ -524,8 +525,6 @@ namespace rsx
|
||||
g_fxo->get<rsx::dma_manager>()->init();
|
||||
on_init_thread();
|
||||
|
||||
method_registers.init();
|
||||
|
||||
if (!zcull_ctrl)
|
||||
{
|
||||
//Backend did not provide an implementation, provide NULL object
|
||||
@ -2018,11 +2017,13 @@ namespace rsx
|
||||
|
||||
void thread::init(u32 ctrlAddress)
|
||||
{
|
||||
method_registers.init();
|
||||
|
||||
dma_address = ctrlAddress;
|
||||
ctrl = vm::_ptr<RsxDmaControl>(ctrlAddress);
|
||||
flip_status = CELL_GCM_DISPLAY_FLIP_STATUS_DONE;
|
||||
|
||||
memset(display_buffers, 0, sizeof(display_buffers));
|
||||
std::memset(display_buffers, 0, sizeof(display_buffers));
|
||||
|
||||
on_init_rsx();
|
||||
m_rsx_thread_exiting = false;
|
||||
@ -2565,6 +2566,18 @@ namespace rsx
|
||||
recovered_fifo_cmds_history.push({fifo_ctrl->last_cmd(), current_time});
|
||||
}
|
||||
|
||||
std::vector<std::pair<u32, u32>> thread::dump_callstack() const
|
||||
{
|
||||
std::vector<std::pair<u32, u32>> result;
|
||||
|
||||
if (u32 addr = fifo_ret_addr; addr != RSX_CALL_STACK_EMPTY)
|
||||
{
|
||||
result.emplace_back(addr, 0);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
void thread::fifo_wake_delay(u64 div)
|
||||
{
|
||||
// TODO: Nanoseconds accuracy
|
||||
@ -2626,6 +2639,48 @@ namespace rsx
|
||||
return fifo_ctrl->last_cmd();
|
||||
}
|
||||
|
||||
void invalid_method(thread*, u32, u32);
|
||||
|
||||
std::string thread::dump_regs() const
|
||||
{
|
||||
std::string result;
|
||||
|
||||
for (u32 i = 0; i < 1 << 14; i++)
|
||||
{
|
||||
if (rsx::methods[i] == &invalid_method)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
switch (i)
|
||||
{
|
||||
case NV4097_NO_OPERATION:
|
||||
case NV4097_INVALIDATE_L2:
|
||||
case NV4097_INVALIDATE_VERTEX_FILE:
|
||||
case NV4097_INVALIDATE_VERTEX_CACHE_FILE:
|
||||
case NV4097_INVALIDATE_ZCULL:
|
||||
case NV4097_WAIT_FOR_IDLE:
|
||||
case NV4097_PM_TRIGGER:
|
||||
case NV4097_ZCULL_SYNC:
|
||||
continue;
|
||||
|
||||
default:
|
||||
{
|
||||
if (i >= NV308A_COLOR && i < NV3089_SET_OBJECT)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
fmt::append(result, "[%04x] %s\n", i, ensure(rsx::get_pretty_printing_function(i))(i, method_registers.registers[i]));
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
flags32_t thread::read_barrier(u32 memory_address, u32 memory_range, bool unconditional)
|
||||
{
|
||||
flags32_t zcull_flags = (unconditional)? reports::sync_none : reports::sync_defer_copy;
|
||||
|
@ -615,6 +615,8 @@ namespace rsx
|
||||
// FIFO
|
||||
public:
|
||||
std::unique_ptr<FIFO::FIFO_control> fifo_ctrl;
|
||||
std::vector<std::pair<u32, u32>> dump_callstack() const;
|
||||
|
||||
protected:
|
||||
FIFO::flattening_helper m_flattener;
|
||||
u32 fifo_ret_addr = RSX_CALL_STACK_EMPTY;
|
||||
@ -652,6 +654,8 @@ namespace rsx
|
||||
void recover_fifo();
|
||||
static void fifo_wake_delay(u64 div = 1);
|
||||
u32 get_fifo_cmd() const;
|
||||
|
||||
std::string dump_regs() const;
|
||||
|
||||
// Performance approximation counters
|
||||
struct
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -466,12 +466,6 @@ enum
|
||||
CELL_GCM_DISPLAY_FLIP_STATUS_WAITING = 1,
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
CELL_GCM_LOCATION_LOCAL = 0,
|
||||
CELL_GCM_LOCATION_MAIN = 1,
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
CELL_GCM_FREQUENCY_MODULO = 1,
|
||||
@ -511,7 +505,7 @@ enum
|
||||
};
|
||||
|
||||
// GCM Texture
|
||||
enum
|
||||
enum CellGcmTexture : u32
|
||||
{
|
||||
// Color Flag
|
||||
CELL_GCM_TEXTURE_B8 = 0x81,
|
||||
@ -815,8 +809,11 @@ enum
|
||||
};
|
||||
|
||||
// GPU Class Handles
|
||||
enum
|
||||
enum CellGcmLocation : u32
|
||||
{
|
||||
CELL_GCM_LOCATION_LOCAL = 0,
|
||||
CELL_GCM_LOCATION_MAIN = 1,
|
||||
|
||||
CELL_GCM_CONTEXT_DMA_MEMORY_FRAME_BUFFER = 0xFEED0000, // Local memory
|
||||
CELL_GCM_CONTEXT_DMA_MEMORY_HOST_BUFFER = 0xFEED0001, // Main memory
|
||||
CELL_GCM_CONTEXT_DMA_REPORT_LOCATION_LOCAL = 0x66626660,
|
||||
@ -830,7 +827,7 @@ enum
|
||||
CELL_GCM_CONTEXT_DMA_DEVICE_R = 0x56616661
|
||||
};
|
||||
|
||||
enum
|
||||
enum CellGcmMethod : u16
|
||||
{
|
||||
// NV40_CHANNEL_DMA (NV406E)
|
||||
NV406E_SET_REFERENCE = 0x00000050 >> 2,
|
||||
|
@ -6,62 +6,69 @@
|
||||
namespace
|
||||
{
|
||||
constexpr u32 opcode_list[] = {NV4097_SET_VIEWPORT_HORIZONTAL, NV4097_SET_VIEWPORT_VERTICAL,
|
||||
NV4097_SET_SCISSOR_HORIZONTAL, NV4097_SET_SCISSOR_VERTICAL, NV4097_SET_SURFACE_CLIP_HORIZONTAL,
|
||||
NV4097_SET_SURFACE_CLIP_VERTICAL, NV4097_SET_CLEAR_RECT_HORIZONTAL,
|
||||
NV4097_SET_CLEAR_RECT_VERTICAL, NV3089_CLIP_POINT, NV3089_CLIP_SIZE, NV3089_IMAGE_OUT_POINT,
|
||||
NV3089_IMAGE_OUT_SIZE, NV3089_IMAGE_IN_SIZE, NV3062_SET_PITCH, NV308A_POINT,
|
||||
NV4097_SET_DEPTH_TEST_ENABLE, NV4097_SET_DEPTH_MASK, NV4097_SET_ALPHA_TEST_ENABLE,
|
||||
NV4097_SET_STENCIL_TEST_ENABLE, NV4097_SET_RESTART_INDEX_ENABLE,
|
||||
NV4097_SET_DEPTH_BOUNDS_TEST_ENABLE, NV4097_SET_LOGIC_OP_ENABLE, NV4097_SET_DITHER_ENABLE,
|
||||
NV4097_SET_BLEND_ENABLE, NV4097_SET_LINE_SMOOTH_ENABLE, NV4097_SET_POLY_OFFSET_POINT_ENABLE,
|
||||
NV4097_SET_POLY_OFFSET_LINE_ENABLE, NV4097_SET_POLY_OFFSET_FILL_ENABLE,
|
||||
NV4097_SET_CULL_FACE_ENABLE, NV4097_SET_POLY_SMOOTH_ENABLE,
|
||||
NV4097_SET_TWO_SIDED_STENCIL_TEST_ENABLE, NV4097_SET_TWO_SIDE_LIGHT_EN,
|
||||
NV4097_SET_RESTART_INDEX, NV4097_SET_SURFACE_COLOR_AOFFSET, NV4097_SET_SURFACE_COLOR_BOFFSET,
|
||||
NV4097_SET_SURFACE_COLOR_COFFSET, NV4097_SET_SURFACE_COLOR_DOFFSET, NV4097_SET_SURFACE_PITCH_A,
|
||||
NV4097_SET_SURFACE_PITCH_B, NV4097_SET_SURFACE_PITCH_C, NV4097_SET_SURFACE_PITCH_D,
|
||||
NV4097_SET_SURFACE_ZETA_OFFSET, NV4097_SET_SURFACE_PITCH_Z,
|
||||
NV4097_SET_VERTEX_ATTRIB_OUTPUT_MASK, NV4097_SET_SHADER_CONTROL,
|
||||
NV4097_SET_VERTEX_DATA_BASE_OFFSET, NV4097_SET_INDEX_ARRAY_ADDRESS,
|
||||
NV4097_SET_VERTEX_DATA_BASE_INDEX, NV4097_SET_SHADER_PROGRAM,
|
||||
NV4097_SET_TRANSFORM_PROGRAM_START, NV406E_SET_CONTEXT_DMA_SEMAPHORE, NV406E_SEMAPHORE_OFFSET, NV4097_SET_SEMAPHORE_OFFSET,
|
||||
NV3089_IMAGE_IN_OFFSET, NV3062_SET_OFFSET_DESTIN, NV309E_SET_OFFSET, NV3089_DS_DX, NV3089_DT_DY,
|
||||
NV0039_PITCH_IN, NV0039_PITCH_OUT, NV0039_LINE_LENGTH_IN, NV0039_LINE_COUNT, NV0039_OFFSET_OUT,
|
||||
NV0039_OFFSET_IN, NV4097_SET_VERTEX_ATTRIB_INPUT_MASK, NV4097_SET_FREQUENCY_DIVIDER_OPERATION,
|
||||
NV4097_SET_DEPTH_BOUNDS_MIN, NV4097_SET_DEPTH_BOUNDS_MAX, NV4097_SET_FOG_PARAMS,
|
||||
NV4097_SET_FOG_PARAMS + 1, NV4097_SET_CLIP_MIN, NV4097_SET_CLIP_MAX,
|
||||
NV4097_SET_POLYGON_OFFSET_SCALE_FACTOR, NV4097_SET_POLYGON_OFFSET_BIAS,
|
||||
NV4097_SET_VIEWPORT_SCALE, NV4097_SET_VIEWPORT_SCALE + 1, NV4097_SET_VIEWPORT_SCALE + 2,
|
||||
NV4097_SET_VIEWPORT_SCALE + 3, NV4097_SET_VIEWPORT_OFFSET, NV4097_SET_VIEWPORT_OFFSET + 1,
|
||||
NV4097_SET_VIEWPORT_OFFSET + 2, NV4097_SET_VIEWPORT_OFFSET + 3, NV4097_SET_DEPTH_FUNC,
|
||||
NV4097_SET_STENCIL_FUNC, NV4097_SET_BACK_STENCIL_FUNC, NV4097_SET_STENCIL_OP_FAIL,
|
||||
NV4097_SET_STENCIL_OP_ZFAIL, NV4097_SET_STENCIL_OP_ZPASS, NV4097_SET_BACK_STENCIL_OP_FAIL,
|
||||
NV4097_SET_BACK_STENCIL_OP_ZFAIL, NV4097_SET_BACK_STENCIL_OP_ZPASS, NV4097_SET_LOGIC_OP,
|
||||
NV4097_SET_FRONT_FACE, NV4097_SET_CULL_FACE, NV4097_SET_SURFACE_COLOR_TARGET,
|
||||
NV4097_SET_FOG_MODE, NV4097_SET_ALPHA_FUNC, NV4097_SET_BEGIN_END, NV3089_SET_OPERATION,
|
||||
NV3089_SET_COLOR_FORMAT, NV3089_SET_CONTEXT_SURFACE, NV3062_SET_COLOR_FORMAT,
|
||||
NV4097_SET_STENCIL_FUNC_REF, NV4097_SET_BACK_STENCIL_FUNC_REF, NV4097_SET_STENCIL_FUNC_MASK,
|
||||
NV4097_SET_BACK_STENCIL_FUNC_MASK, NV4097_SET_ALPHA_REF, NV4097_SET_COLOR_CLEAR_VALUE,
|
||||
NV4097_SET_STENCIL_MASK, NV4097_SET_BACK_STENCIL_MASK, NV4097_SET_BLEND_EQUATION,
|
||||
NV4097_SET_BLEND_FUNC_SFACTOR, NV4097_SET_BLEND_FUNC_DFACTOR, NV4097_SET_COLOR_MASK,
|
||||
NV4097_SET_SHADER_WINDOW, NV4097_SET_BLEND_ENABLE_MRT, NV4097_SET_USER_CLIP_PLANE_CONTROL,
|
||||
NV4097_SET_LINE_WIDTH, NV4097_SET_SURFACE_FORMAT, NV4097_SET_WINDOW_OFFSET,
|
||||
NV4097_SET_ZSTENCIL_CLEAR_VALUE, NV4097_SET_INDEX_ARRAY_DMA, NV4097_SET_CONTEXT_DMA_COLOR_A,
|
||||
NV4097_SET_CONTEXT_DMA_COLOR_B, NV4097_SET_CONTEXT_DMA_COLOR_C, NV4097_SET_CONTEXT_DMA_COLOR_D,
|
||||
NV4097_SET_CONTEXT_DMA_ZETA, NV3089_SET_CONTEXT_DMA_IMAGE, NV3062_SET_CONTEXT_DMA_IMAGE_DESTIN,
|
||||
NV309E_SET_CONTEXT_DMA_IMAGE, NV0039_SET_CONTEXT_DMA_BUFFER_OUT,
|
||||
NV0039_SET_CONTEXT_DMA_BUFFER_IN, NV4097_SET_CONTEXT_DMA_REPORT, NV3089_IMAGE_IN_FORMAT,
|
||||
NV309E_SET_FORMAT, NV0039_FORMAT, NV4097_SET_BLEND_COLOR2, NV4097_SET_BLEND_COLOR,
|
||||
NV3089_IMAGE_IN, NV4097_NO_OPERATION, NV4097_INVALIDATE_VERTEX_CACHE_FILE,
|
||||
NV4097_INVALIDATE_VERTEX_FILE, NV4097_SET_ANTI_ALIASING_CONTROL, NV4097_SET_FRONT_POLYGON_MODE,
|
||||
NV4097_SET_BACK_POLYGON_MODE,
|
||||
EXPAND_RANGE_16(0, DECLARE_VERTEX_DATA_ARRAY_FORMAT)
|
||||
EXPAND_RANGE_16(0, DECLARE_VERTEX_DATA_ARRAY_OFFSET)
|
||||
EXPAND_RANGE_32(0, DECLARE_TRANSFORM_CONSTANT) NV4097_SET_TRANSFORM_CONSTANT_LOAD,
|
||||
NV4097_DRAW_ARRAYS, NV4097_DRAW_INDEX_ARRAY,
|
||||
EXPAND_RANGE_512(0, DECLARE_TRANSFORM_PROGRAM) NV4097_SET_TRANSFORM_PROGRAM_LOAD};
|
||||
NV4097_SET_SCISSOR_HORIZONTAL, NV4097_SET_SCISSOR_VERTICAL, NV4097_SET_SURFACE_CLIP_HORIZONTAL,
|
||||
NV4097_SET_SURFACE_CLIP_VERTICAL, NV4097_SET_CLEAR_RECT_HORIZONTAL,
|
||||
NV4097_SET_CLEAR_RECT_VERTICAL, NV3089_CLIP_POINT, NV3089_CLIP_SIZE, NV3089_IMAGE_OUT_POINT,
|
||||
NV3089_IMAGE_OUT_SIZE, NV3089_IMAGE_IN_SIZE, NV3062_SET_PITCH, NV308A_POINT,
|
||||
NV4097_SET_DEPTH_TEST_ENABLE, NV4097_SET_DEPTH_MASK, NV4097_SET_ALPHA_TEST_ENABLE,
|
||||
NV4097_SET_STENCIL_TEST_ENABLE, NV4097_SET_RESTART_INDEX_ENABLE,
|
||||
NV4097_SET_DEPTH_BOUNDS_TEST_ENABLE, NV4097_SET_LOGIC_OP_ENABLE, NV4097_SET_DITHER_ENABLE,
|
||||
NV4097_SET_BLEND_ENABLE, NV4097_SET_LINE_SMOOTH_ENABLE, NV4097_SET_POLY_OFFSET_POINT_ENABLE,
|
||||
NV4097_SET_POLY_OFFSET_LINE_ENABLE, NV4097_SET_POLY_OFFSET_FILL_ENABLE,
|
||||
NV4097_SET_CULL_FACE_ENABLE, NV4097_SET_POLY_SMOOTH_ENABLE,
|
||||
NV4097_SET_TWO_SIDED_STENCIL_TEST_ENABLE, NV4097_SET_TWO_SIDE_LIGHT_EN,
|
||||
NV4097_SET_RESTART_INDEX, NV4097_SET_SURFACE_COLOR_AOFFSET, NV4097_SET_SURFACE_COLOR_BOFFSET,
|
||||
NV4097_SET_SURFACE_COLOR_COFFSET, NV4097_SET_SURFACE_COLOR_DOFFSET, NV4097_SET_SURFACE_PITCH_A,
|
||||
NV4097_SET_SURFACE_PITCH_B, NV4097_SET_SURFACE_PITCH_C, NV4097_SET_SURFACE_PITCH_D,
|
||||
NV4097_SET_SURFACE_ZETA_OFFSET, NV4097_SET_SURFACE_PITCH_Z,
|
||||
NV4097_SET_VERTEX_ATTRIB_OUTPUT_MASK, NV4097_SET_SHADER_CONTROL,
|
||||
NV4097_SET_VERTEX_DATA_BASE_OFFSET, NV4097_SET_INDEX_ARRAY_ADDRESS,
|
||||
NV4097_SET_VERTEX_DATA_BASE_INDEX, NV4097_SET_SHADER_PROGRAM,
|
||||
NV4097_SET_TRANSFORM_PROGRAM_START, NV406E_SET_CONTEXT_DMA_SEMAPHORE, NV406E_SEMAPHORE_OFFSET, NV4097_SET_SEMAPHORE_OFFSET,
|
||||
NV3089_IMAGE_IN_OFFSET, NV3062_SET_OFFSET_DESTIN, NV309E_SET_OFFSET, NV3089_DS_DX, NV3089_DT_DY,
|
||||
NV0039_PITCH_IN, NV0039_PITCH_OUT, NV0039_LINE_LENGTH_IN, NV0039_LINE_COUNT, NV0039_OFFSET_OUT,
|
||||
NV0039_OFFSET_IN, NV4097_SET_VERTEX_ATTRIB_INPUT_MASK, NV4097_SET_FREQUENCY_DIVIDER_OPERATION,
|
||||
NV4097_SET_DEPTH_BOUNDS_MIN, NV4097_SET_DEPTH_BOUNDS_MAX, NV4097_SET_FOG_PARAMS,
|
||||
NV4097_SET_FOG_PARAMS + 1, NV4097_SET_CLIP_MIN, NV4097_SET_CLIP_MAX,
|
||||
NV4097_SET_POLYGON_OFFSET_SCALE_FACTOR, NV4097_SET_POLYGON_OFFSET_BIAS,
|
||||
NV4097_SET_VIEWPORT_SCALE, NV4097_SET_VIEWPORT_SCALE + 1, NV4097_SET_VIEWPORT_SCALE + 2,
|
||||
NV4097_SET_VIEWPORT_SCALE + 3, NV4097_SET_VIEWPORT_OFFSET, NV4097_SET_VIEWPORT_OFFSET + 1,
|
||||
NV4097_SET_VIEWPORT_OFFSET + 2, NV4097_SET_VIEWPORT_OFFSET + 3, NV4097_SET_DEPTH_FUNC,
|
||||
NV4097_SET_STENCIL_FUNC, NV4097_SET_BACK_STENCIL_FUNC, NV4097_SET_STENCIL_OP_FAIL,
|
||||
NV4097_SET_STENCIL_OP_ZFAIL, NV4097_SET_STENCIL_OP_ZPASS, NV4097_SET_BACK_STENCIL_OP_FAIL,
|
||||
NV4097_SET_BACK_STENCIL_OP_ZFAIL, NV4097_SET_BACK_STENCIL_OP_ZPASS, NV4097_SET_LOGIC_OP,
|
||||
NV4097_SET_FRONT_FACE, NV4097_SET_CULL_FACE, NV4097_SET_SURFACE_COLOR_TARGET,
|
||||
NV4097_SET_FOG_MODE, NV4097_SET_ALPHA_FUNC, NV4097_SET_BEGIN_END, NV3089_SET_OPERATION,
|
||||
NV3089_SET_COLOR_FORMAT, NV3089_SET_CONTEXT_SURFACE, NV3062_SET_COLOR_FORMAT,
|
||||
NV4097_SET_STENCIL_FUNC_REF, NV4097_SET_BACK_STENCIL_FUNC_REF, NV4097_SET_STENCIL_FUNC_MASK,
|
||||
NV4097_SET_BACK_STENCIL_FUNC_MASK, NV4097_SET_ALPHA_REF, NV4097_SET_COLOR_CLEAR_VALUE,
|
||||
NV4097_SET_STENCIL_MASK, NV4097_SET_BACK_STENCIL_MASK, NV4097_SET_BLEND_EQUATION,
|
||||
NV4097_SET_BLEND_FUNC_SFACTOR, NV4097_SET_BLEND_FUNC_DFACTOR, NV4097_SET_COLOR_MASK,
|
||||
NV4097_SET_SHADER_WINDOW, NV4097_SET_BLEND_ENABLE_MRT, NV4097_SET_USER_CLIP_PLANE_CONTROL,
|
||||
NV4097_SET_LINE_WIDTH, NV4097_SET_SURFACE_FORMAT, NV4097_SET_WINDOW_OFFSET,
|
||||
NV4097_SET_ZSTENCIL_CLEAR_VALUE, NV4097_SET_INDEX_ARRAY_DMA, NV4097_SET_CONTEXT_DMA_COLOR_A,
|
||||
NV4097_SET_CONTEXT_DMA_COLOR_B, NV4097_SET_CONTEXT_DMA_COLOR_C, NV4097_SET_CONTEXT_DMA_COLOR_D,
|
||||
NV4097_SET_CONTEXT_DMA_ZETA, NV3089_SET_CONTEXT_DMA_IMAGE, NV3062_SET_CONTEXT_DMA_IMAGE_DESTIN,
|
||||
NV309E_SET_CONTEXT_DMA_IMAGE, NV0039_SET_CONTEXT_DMA_BUFFER_OUT,
|
||||
NV0039_SET_CONTEXT_DMA_BUFFER_IN, NV4097_SET_CONTEXT_DMA_REPORT, NV3089_IMAGE_IN_FORMAT,
|
||||
NV309E_SET_FORMAT, NV0039_FORMAT, NV4097_SET_BLEND_COLOR2, NV4097_SET_BLEND_COLOR,
|
||||
NV3089_IMAGE_IN, NV4097_NO_OPERATION, NV4097_INVALIDATE_VERTEX_CACHE_FILE,
|
||||
NV4097_INVALIDATE_VERTEX_FILE, NV4097_SET_ANTI_ALIASING_CONTROL, NV4097_SET_FRONT_POLYGON_MODE,
|
||||
NV4097_SET_BACK_POLYGON_MODE, NV406E_SET_REFERENCE, NV406E_SEMAPHORE_RELEASE, NV406E_SEMAPHORE_ACQUIRE,
|
||||
NV4097_SET_ZCULL_EN, NV4097_SET_ZCULL_STATS_ENABLE, NV4097_SET_ZPASS_PIXEL_COUNT_ENABLE,
|
||||
EXPAND_RANGE_16(0, DECLARE_VERTEX_DATA_ARRAY_FORMAT)
|
||||
EXPAND_RANGE_16(0, DECLARE_VERTEX_DATA_ARRAY_OFFSET)
|
||||
EXPAND_RANGE_32(0, DECLARE_TRANSFORM_CONSTANT) NV4097_SET_TRANSFORM_CONSTANT_LOAD,
|
||||
NV4097_DRAW_ARRAYS, NV4097_DRAW_INDEX_ARRAY,
|
||||
EXPAND_RANGE_32(0, DECLARE_TRANSFORM_PROGRAM) NV4097_SET_TRANSFORM_PROGRAM_LOAD,
|
||||
EXPAND_RANGE_16(0, DECLARE_TEXTURE_OFFSET) EXPAND_RANGE_16(0, DECLARE_TEXTURE_FORMAT)
|
||||
EXPAND_RANGE_16(0, DECLARE_TEXTURE_IMAGE_RECT) EXPAND_RANGE_16(0, DECLARE_TEXTURE_CONTROL0)
|
||||
EXPAND_RANGE_16(0, DECLARE_TEXTURE_CONTROL3) EXPAND_RANGE_4(0, DECLARE_VERTEX_TEXTURE_CONTROL0)};
|
||||
|
||||
const std::unordered_map<u32, const char*> methods_name = {
|
||||
#define KEY_STR(key) { key, #key }
|
||||
|
||||
const std::unordered_map<u32, std::string_view> methods_name =
|
||||
{
|
||||
{NV406E_SET_REFERENCE, "NV406E_SET_REFERENCE"},
|
||||
{NV406E_SET_CONTEXT_DMA_SEMAPHORE, "NV406E_SET_CONTEXT_DMA_SEMAPHORE"},
|
||||
{NV406E_SEMAPHORE_OFFSET, "NV406E_SEMAPHORE_OFFSET"},
|
||||
@ -321,7 +328,37 @@ namespace
|
||||
{NV4097_SET_EDGE_FLAG, "NV4097_SET_EDGE_FLAG"},
|
||||
{NV4097_SET_USER_CLIP_PLANE_CONTROL, "NV4097_SET_USER_CLIP_PLANE_CONTROL"},
|
||||
{NV4097_SET_POLYGON_STIPPLE, "NV4097_SET_POLYGON_STIPPLE"},
|
||||
{NV4097_SET_POLYGON_STIPPLE_PATTERN, "NV4097_SET_POLYGON_STIPPLE_PATTERN"},
|
||||
KEY_STR(NV4097_SET_POLYGON_STIPPLE_PATTERN),
|
||||
KEY_STR(NV4097_SET_POLYGON_STIPPLE_PATTERN + 1),
|
||||
KEY_STR(NV4097_SET_POLYGON_STIPPLE_PATTERN + 2),
|
||||
KEY_STR(NV4097_SET_POLYGON_STIPPLE_PATTERN + 3),
|
||||
KEY_STR(NV4097_SET_POLYGON_STIPPLE_PATTERN + 4),
|
||||
KEY_STR(NV4097_SET_POLYGON_STIPPLE_PATTERN + 5),
|
||||
KEY_STR(NV4097_SET_POLYGON_STIPPLE_PATTERN + 6),
|
||||
KEY_STR(NV4097_SET_POLYGON_STIPPLE_PATTERN + 7),
|
||||
KEY_STR(NV4097_SET_POLYGON_STIPPLE_PATTERN + 8),
|
||||
KEY_STR(NV4097_SET_POLYGON_STIPPLE_PATTERN + 9),
|
||||
KEY_STR(NV4097_SET_POLYGON_STIPPLE_PATTERN + 10),
|
||||
KEY_STR(NV4097_SET_POLYGON_STIPPLE_PATTERN + 11),
|
||||
KEY_STR(NV4097_SET_POLYGON_STIPPLE_PATTERN + 12),
|
||||
KEY_STR(NV4097_SET_POLYGON_STIPPLE_PATTERN + 13),
|
||||
KEY_STR(NV4097_SET_POLYGON_STIPPLE_PATTERN + 14),
|
||||
KEY_STR(NV4097_SET_POLYGON_STIPPLE_PATTERN + 15),
|
||||
KEY_STR(NV4097_SET_POLYGON_STIPPLE_PATTERN + 16),
|
||||
KEY_STR(NV4097_SET_POLYGON_STIPPLE_PATTERN + 17),
|
||||
KEY_STR(NV4097_SET_POLYGON_STIPPLE_PATTERN + 18),
|
||||
KEY_STR(NV4097_SET_POLYGON_STIPPLE_PATTERN + 19),
|
||||
KEY_STR(NV4097_SET_POLYGON_STIPPLE_PATTERN + 20),
|
||||
KEY_STR(NV4097_SET_POLYGON_STIPPLE_PATTERN + 21),
|
||||
KEY_STR(NV4097_SET_POLYGON_STIPPLE_PATTERN + 22),
|
||||
KEY_STR(NV4097_SET_POLYGON_STIPPLE_PATTERN + 23),
|
||||
KEY_STR(NV4097_SET_POLYGON_STIPPLE_PATTERN + 24),
|
||||
KEY_STR(NV4097_SET_POLYGON_STIPPLE_PATTERN + 25),
|
||||
KEY_STR(NV4097_SET_POLYGON_STIPPLE_PATTERN + 26),
|
||||
KEY_STR(NV4097_SET_POLYGON_STIPPLE_PATTERN + 28),
|
||||
KEY_STR(NV4097_SET_POLYGON_STIPPLE_PATTERN + 29),
|
||||
KEY_STR(NV4097_SET_POLYGON_STIPPLE_PATTERN + 30),
|
||||
KEY_STR(NV4097_SET_POLYGON_STIPPLE_PATTERN + 31),
|
||||
{NV4097_SET_VERTEX_DATA3F_M, "NV4097_SET_VERTEX_DATA3F_M"},
|
||||
{NV4097_SET_VERTEX_DATA3F_M + 4 / 4, "NV4097_SET_VERTEX_DATA3F_M + 4"},
|
||||
{NV4097_SET_VERTEX_DATA3F_M + 8 / 4, "NV4097_SET_VERTEX_DATA3F_M + 8"},
|
||||
@ -853,149 +890,36 @@ namespace
|
||||
{NV3089_IMAGE_IN_FORMAT, "NV3089_IMAGE_IN_FORMAT"},
|
||||
{NV3089_IMAGE_IN_OFFSET, "NV3089_IMAGE_IN_OFFSET"},
|
||||
{NV3089_IMAGE_IN, "NV3089_IMAGE_IN"},
|
||||
{GCM_SET_DRIVER_OBJECT, "GCM_SET_DRIVER_OBJECT"},
|
||||
{GCM_DRIVER_QUEUE, "GCM_DRIVER_QUEUE + 0x0"},
|
||||
{GCM_DRIVER_QUEUE+1, "GCM_DRIVER_QUEUE + 0x4"},
|
||||
{GCM_FLIP_HEAD, "GCM_FLIP_HEAD"},
|
||||
{GCM_FLIP_HEAD+1, "GCM_FLIP_HEAD + 0x4"},
|
||||
{GCM_SET_USER_COMMAND, "GCM_SET_USER_COMMAND"},
|
||||
{GCM_FLIP_COMMAND, "GCM_FLIP_COMMAND"},
|
||||
{GCM_SET_DRIVER_OBJECT, "SET_DRIVER_OBJECT"},
|
||||
{GCM_DRIVER_QUEUE, "DRIVER_QUEUE + 0x0"},
|
||||
{GCM_DRIVER_QUEUE+1, "DRIVER_QUEUE + 0x4"},
|
||||
{GCM_FLIP_HEAD, "FLIP_HEAD"},
|
||||
{GCM_FLIP_HEAD+1, "FLIP_HEAD + 0x4"},
|
||||
{GCM_SET_USER_COMMAND, "SET_USER_COMMAND"},
|
||||
{GCM_FLIP_COMMAND, "FLIP_COMMAND"},
|
||||
};
|
||||
|
||||
#undef KEY_STR
|
||||
}
|
||||
|
||||
std::string rsx::get_method_name(const u32 id)
|
||||
{
|
||||
auto found = methods_name.find(id);
|
||||
if (found != methods_name.end()) {
|
||||
return std::string("CELL_GCM_") + found->second;
|
||||
const auto found = methods_name.find(id);
|
||||
|
||||
if (found != methods_name.end())
|
||||
{
|
||||
std::string prefix("CELL_GCM_"sv);
|
||||
prefix.append(found->second.data(), found->second.size());
|
||||
return prefix;
|
||||
}
|
||||
|
||||
return fmt::format("Unknown/illegal method [0x%04x]", id << 2);
|
||||
return fmt::format("Unnamed method 0x%04x", id);
|
||||
}
|
||||
|
||||
// Various parameter pretty printing function
|
||||
namespace
|
||||
{
|
||||
std::string ptr_to_string(u32 ptr)
|
||||
{
|
||||
return fmt::format("0x%08x", ptr);
|
||||
}
|
||||
|
||||
std::string dma_mode(u32 arg)
|
||||
{
|
||||
switch (arg)
|
||||
{
|
||||
case CELL_GCM_LOCATION_LOCAL:
|
||||
case CELL_GCM_CONTEXT_DMA_MEMORY_FRAME_BUFFER: return "Local memory";
|
||||
case CELL_GCM_LOCATION_MAIN:
|
||||
case CELL_GCM_CONTEXT_DMA_MEMORY_HOST_BUFFER: return "Main memory";
|
||||
}
|
||||
return "Error";
|
||||
}
|
||||
|
||||
std::string texture_dimension(u8 dim)
|
||||
{
|
||||
switch (rsx::to_texture_dimension(dim))
|
||||
{
|
||||
case rsx::texture_dimension::dimension1d: return "1D";
|
||||
case rsx::texture_dimension::dimension2d: return "2D";
|
||||
case rsx::texture_dimension::dimension3d: return "3D";
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
std::string get_vertex_attribute_format(u8 type)
|
||||
{
|
||||
switch (rsx::to_vertex_base_type(type))
|
||||
{
|
||||
case rsx::vertex_base_type::s1: return "Signed short normalized";
|
||||
case rsx::vertex_base_type::f: return "Float";
|
||||
case rsx::vertex_base_type::sf: return "Half float";
|
||||
case rsx::vertex_base_type::ub: return "Unsigned byte normalized";
|
||||
case rsx::vertex_base_type::s32k: return "Signed short unormalized";
|
||||
case rsx::vertex_base_type::cmp: return "CMP";
|
||||
case rsx::vertex_base_type::ub256: return "Unsigned byte unormalized";
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
std::string unpack_vertex_format(u32 arg)
|
||||
{
|
||||
u32 frequency = arg >> 16;
|
||||
u32 stride = (arg >> 8) & 0xff;
|
||||
u32 size = (arg >> 4) & 0xf;
|
||||
u32 type = arg & 0xf;
|
||||
if (size == 0) return "(disabled)";
|
||||
|
||||
return "Type = " + get_vertex_attribute_format(type) + " size = " + std::to_string(size) +
|
||||
" stride = " + std::to_string(stride) + " frequency = " + std::to_string(frequency);
|
||||
}
|
||||
|
||||
std::string transform_constant(usz index, u32 arg)
|
||||
{
|
||||
return "Transform constant " + std::to_string(index) + ": " + std::to_string(arg) + "/" +
|
||||
std::to_string(std::bit_cast<f32>(arg));
|
||||
}
|
||||
|
||||
std::string texture_offset(usz index, u32 arg)
|
||||
{
|
||||
return "Texture " + std::to_string(index) + ": Offset @" + ptr_to_string(arg);
|
||||
}
|
||||
|
||||
std::string texture_size(usz index, u32 arg)
|
||||
{
|
||||
return "Texture " + std::to_string(index) + ": width = " + std::to_string(arg & 0xffff) +
|
||||
" height = " + std::to_string(arg >> 16);
|
||||
}
|
||||
|
||||
static std::string get_texture_format_name(u32 format)
|
||||
{
|
||||
switch (format)
|
||||
{
|
||||
case CELL_GCM_TEXTURE_COMPRESSED_HILO8: return "CELL_GCM_TEXTURE_COMPRESSED_HILO8";
|
||||
case CELL_GCM_TEXTURE_COMPRESSED_HILO_S8: return "CELL_GCM_TEXTURE_COMPRESSED_HILO_S8";
|
||||
case CELL_GCM_TEXTURE_B8: return "CELL_GCM_TEXTURE_B8";
|
||||
case CELL_GCM_TEXTURE_A1R5G5B5: return "CELL_GCM_TEXTURE_A1R5G5B5";
|
||||
case CELL_GCM_TEXTURE_A4R4G4B4: return "CELL_GCM_TEXTURE_A4R4G4B4";
|
||||
case CELL_GCM_TEXTURE_R5G6B5: return "CELL_GCM_TEXTURE_R5G6B5";
|
||||
case CELL_GCM_TEXTURE_A8R8G8B8: return "CELL_GCM_TEXTURE_A8R8G8B8";
|
||||
case CELL_GCM_TEXTURE_COMPRESSED_DXT1: return "CELL_GCM_TEXTURE_COMPRESSED_DXT1";
|
||||
case CELL_GCM_TEXTURE_COMPRESSED_DXT23: return "CELL_GCM_TEXTURE_COMPRESSED_DXT23";
|
||||
case CELL_GCM_TEXTURE_COMPRESSED_DXT45: return "CELL_GCM_TEXTURE_COMPRESSED_DXT45";
|
||||
case CELL_GCM_TEXTURE_G8B8: return "CELL_GCM_TEXTURE_G8B8";
|
||||
case CELL_GCM_TEXTURE_R6G5B5: return "CELL_GCM_TEXTURE_R6G5B5";
|
||||
case CELL_GCM_TEXTURE_DEPTH24_D8: return "CELL_GCM_TEXTURE_DEPTH24_D8";
|
||||
case CELL_GCM_TEXTURE_DEPTH24_D8_FLOAT: return "CELL_GCM_TEXTURE_DEPTH24_D8_FLOAT";
|
||||
case CELL_GCM_TEXTURE_DEPTH16: return "CELL_GCM_TEXTURE_DEPTH16";
|
||||
case CELL_GCM_TEXTURE_DEPTH16_FLOAT: return "CELL_GCM_TEXTURE_DEPTH16_FLOAT";
|
||||
case CELL_GCM_TEXTURE_X16: return "CELL_GCM_TEXTURE_X16";
|
||||
case CELL_GCM_TEXTURE_Y16_X16: return "CELL_GCM_TEXTURE_Y16_X16";
|
||||
case CELL_GCM_TEXTURE_R5G5B5A1: return "CELL_GCM_TEXTURE_R5G5B5A1";
|
||||
case CELL_GCM_TEXTURE_W16_Z16_Y16_X16_FLOAT: return "CELL_GCM_TEXTURE_W16_Z16_Y16_X16_FLOAT";
|
||||
case CELL_GCM_TEXTURE_W32_Z32_Y32_X32_FLOAT: return "CELL_GCM_TEXTURE_W32_Z32_Y32_X32_FLOAT";
|
||||
case CELL_GCM_TEXTURE_X32_FLOAT: return "CELL_GCM_TEXTURE_X32_FLOAT";
|
||||
case CELL_GCM_TEXTURE_D1R5G5B5: return "CELL_GCM_TEXTURE_D1R5G5B5";
|
||||
case CELL_GCM_TEXTURE_D8R8G8B8: return "CELL_GCM_TEXTURE_D8R8G8B8";
|
||||
case CELL_GCM_TEXTURE_Y16_X16_FLOAT: return "CELL_GCM_TEXTURE_Y16_X16_FLOAT";
|
||||
case CELL_GCM_TEXTURE_COMPRESSED_B8R8_G8R8: return "CELL_GCM_TEXTURE_COMPRESSED_B8R8_G8R8";
|
||||
case CELL_GCM_TEXTURE_COMPRESSED_R8B8_R8G8: return "CELL_GCM_TEXTURE_COMPRESSED_R8B8_R8G8";
|
||||
}
|
||||
return "Error";
|
||||
}
|
||||
|
||||
std::string texture_format(usz index, u32 arg)
|
||||
{
|
||||
int format = ((arg >> 8) & 0xFF);
|
||||
return "Texture " + std::to_string(index) + ": location = " + ptr_to_string((arg & 0x3) - 1) +
|
||||
(((arg >> 2) & 0x1) ? " cubemap " : "") + " border type = " +
|
||||
std::to_string((arg >> 3) & 0x1) + " dimension = " + std::to_string((arg >> 4) & 0xF) +
|
||||
" format = " +
|
||||
get_texture_format_name(format & ~(CELL_GCM_TEXTURE_LN | CELL_GCM_TEXTURE_UN)) +
|
||||
((format & CELL_GCM_TEXTURE_LN) ? "" : " swizzled") +
|
||||
((format & CELL_GCM_TEXTURE_UN) ? " unormalized coordinates" : "") + " mipmap levels = " +
|
||||
std::to_string((arg >> 16) & 0xFFFF);
|
||||
}
|
||||
|
||||
/*
|
||||
std::string get_texture_wrap_mode(u8 wrap)
|
||||
{
|
||||
switch (rsx::to_texture_wrap_mode(wrap))
|
||||
@ -1012,22 +936,6 @@ namespace
|
||||
return "Error";
|
||||
}
|
||||
|
||||
std::string get_zfunc_name(u8 op)
|
||||
{
|
||||
switch (op)
|
||||
{
|
||||
case 0: return "Never";
|
||||
case 1: return "Less";
|
||||
case 2: return "Equal";
|
||||
case 3: return "LEqual";
|
||||
case 4: return "Greater";
|
||||
case 5: return "NotEqual";
|
||||
case 6: return "GreaterOrEqual";
|
||||
case 7: return "Always";
|
||||
}
|
||||
return "Error";
|
||||
}
|
||||
|
||||
std::string texture_address(usz index, u32 arg)
|
||||
{
|
||||
return "Texture " + std::to_string(index) + ": wrap_s = " + get_texture_wrap_mode(arg & 0xF) +
|
||||
@ -1038,36 +946,6 @@ namespace
|
||||
std::to_string((arg >> 4) & 0xF) + " signed remap = " + std::to_string((arg >> 24) & 0xF);
|
||||
}
|
||||
|
||||
std::string get_texture_max_aniso_name(u8 aniso)
|
||||
{
|
||||
switch (rsx::to_texture_max_anisotropy(aniso))
|
||||
{
|
||||
case rsx::texture_max_anisotropy::x1: return "1";
|
||||
case rsx::texture_max_anisotropy::x2: return "2";
|
||||
case rsx::texture_max_anisotropy::x4: return "4";
|
||||
case rsx::texture_max_anisotropy::x6: return "6";
|
||||
case rsx::texture_max_anisotropy::x8: return "8";
|
||||
case rsx::texture_max_anisotropy::x10: return "10";
|
||||
case rsx::texture_max_anisotropy::x12: return "12";
|
||||
case rsx::texture_max_anisotropy::x16: return "16";
|
||||
}
|
||||
return "Error";
|
||||
}
|
||||
|
||||
std::string texture_control0(usz index, u32 arg)
|
||||
{
|
||||
std::string result = "Texture " + std::to_string(index);
|
||||
if ((arg >> 31) & 0x1) {
|
||||
result += " min lod = " + std::to_string((arg >> 19) & 0xFFF) + " max lod = " +
|
||||
std::to_string((arg >> 7) & 0xFFF) + " max aniso = " +
|
||||
get_texture_max_aniso_name((arg >> 4) & 0x7) + " alpha kill = " +
|
||||
(((arg >> 2) & 0x1) ? "true" : "false");
|
||||
}
|
||||
else
|
||||
result += " (disabled)";
|
||||
return result;
|
||||
}
|
||||
|
||||
std::string get_remap_channel(u8 op) noexcept
|
||||
{
|
||||
switch (op)
|
||||
@ -1088,12 +966,6 @@ namespace
|
||||
get_remap_channel((arg >> 6) & 0x3);
|
||||
}
|
||||
|
||||
std::string texture_control3(usz index, u32 arg)
|
||||
{
|
||||
return "Texture " + std::to_string(index) + " depth = " + std::to_string(arg >> 20) +
|
||||
" pitch = " + std::to_string(arg & 0xFFFFF);
|
||||
}
|
||||
|
||||
std::string texture_border_color(usz index, u32 arg)
|
||||
{
|
||||
return "Texture " + std::to_string(index) + " border color = " + std::to_string(arg);
|
||||
@ -1107,32 +979,33 @@ namespace
|
||||
std::to_string((arg >> 13) & 0xF) + " a_signed = " + std::to_string((arg >> 28) & 0x1) +
|
||||
" r_signed = " + std::to_string((arg >> 29) & 0x1) + " g_signed = " +
|
||||
std::to_string((arg >> 30) & 0x1) + " b_signed = " + std::to_string((arg >> 31) & 0x1);
|
||||
}
|
||||
}*/
|
||||
|
||||
namespace
|
||||
{
|
||||
template <u32 opcode>
|
||||
auto register_pretty_printing(u32 arg)
|
||||
template <u32 Opcode>
|
||||
std::string register_pretty_function(u32 /*id*/, u32 arg)
|
||||
{
|
||||
typename rsx::registers_decoder<opcode>::decoded_type decoded_value(arg);
|
||||
return rsx::registers_decoder<opcode>::dump(std::move(arg));
|
||||
return rsx::registers_decoder<Opcode>::dump(arg);
|
||||
}
|
||||
|
||||
template <typename T, T... Index>
|
||||
auto create_printing_table(std::integer_sequence<T, Index...> seq)
|
||||
std::array<std::string(*)(u32, u32), 1 << 14> create_printing_table(std::integer_sequence<T, Index...> seq)
|
||||
{
|
||||
std::unordered_map<u32, std::string (*)(u32)> result;
|
||||
(result.insert({
|
||||
{opcode_list[Index * 5 + 0], ®ister_pretty_printing<opcode_list[Index * 5 + 0]>},
|
||||
{opcode_list[Index * 5 + 1], ®ister_pretty_printing<opcode_list[Index * 5 + 1]>},
|
||||
{opcode_list[Index * 5 + 2], ®ister_pretty_printing<opcode_list[Index * 5 + 2]>},
|
||||
{opcode_list[Index * 5 + 3], ®ister_pretty_printing<opcode_list[Index * 5 + 3]>},
|
||||
{opcode_list[Index * 5 + 4], ®ister_pretty_printing<opcode_list[Index * 5 + 4]>}}), ...);
|
||||
std::array<std::string(*)(u32, u32), 1 << 14> result{};
|
||||
|
||||
((result[opcode_list[Index * 5 + 0]] = ®ister_pretty_function<opcode_list[Index * 5 + 0]>,
|
||||
result[opcode_list[Index * 5 + 1]] = ®ister_pretty_function<opcode_list[Index * 5 + 1]>,
|
||||
result[opcode_list[Index * 5 + 2]] = ®ister_pretty_function<opcode_list[Index * 5 + 2]>,
|
||||
result[opcode_list[Index * 5 + 3]] = ®ister_pretty_function<opcode_list[Index * 5 + 3]>,
|
||||
result[opcode_list[Index * 5 + 4]] = ®ister_pretty_function<opcode_list[Index * 5 + 4]>
|
||||
), ...);
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
const std::unordered_map<u32, std::string (*)(u32)> printing_functions =
|
||||
const auto printing_functions =
|
||||
create_printing_table(std::make_index_sequence<std::size(opcode_list) / 5>());
|
||||
|
||||
static_assert(std::size(opcode_list) % 5 == 0);
|
||||
@ -1141,8 +1014,6 @@ namespace
|
||||
1) + " vertex starting from " + std::to_string(arg & 0xFFFFFF); } },
|
||||
{ NV4097_DRAW_INDEX_ARRAY, [](u32 arg) -> std::string { return "Draw " + std::to_string((arg >>
|
||||
24) + 1) + " index starting from " + std::to_string(arg & 0xFFFFFF); } },
|
||||
{ NV4097_SET_SEMAPHORE_OFFSET, [](u32 arg) -> std::string { return "Semaphore: @ " +
|
||||
ptr_to_string(arg); } },
|
||||
{ NV4097_TEXTURE_READ_SEMAPHORE_RELEASE, [](u32 arg) -> std::string { return "Write semaphore
|
||||
value " + std::to_string(arg); } },
|
||||
{ NV4097_CLEAR_SURFACE, [](u32 arg) -> std::string { return "Clear surface " + std::string(arg &
|
||||
@ -1151,12 +1022,20 @@ namespace
|
||||
};*/
|
||||
}
|
||||
|
||||
std::function<std::string(u32)> rsx::get_pretty_printing_function(u32 id)
|
||||
std::add_pointer_t<std::string(u32, u32)> rsx::get_pretty_printing_function(u32 id)
|
||||
{
|
||||
auto found = printing_functions.find(id);
|
||||
if (found != printing_functions.end()) {
|
||||
return found->second;
|
||||
const auto found = id < printing_functions.size() ? printing_functions[id] : nullptr;
|
||||
|
||||
if (found)
|
||||
{
|
||||
return found;
|
||||
}
|
||||
|
||||
return [=](u32 v) { return fmt::format("%s : 0x%08x", rsx::get_method_name(id), v); };
|
||||
return [](u32 id, u32 v)
|
||||
{
|
||||
const std::string name = rsx::get_method_name(id);
|
||||
const std::string_view view = name, prefix = "CELL_GCM_"sv;
|
||||
|
||||
return fmt::format("%s: 0x%08x", name.starts_with("CELL_GCM_"sv) ? view.substr(prefix.size()) : view, v);
|
||||
};
|
||||
}
|
||||
|
@ -8,5 +8,5 @@ namespace rsx
|
||||
{
|
||||
std::string get_method_name(u32 id);
|
||||
|
||||
std::function<std::string(u32)> get_pretty_printing_function(u32 id);
|
||||
std::add_pointer_t<std::string(u32, u32)> get_pretty_printing_function(u32 id);
|
||||
}
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -25,7 +25,7 @@ namespace rsx
|
||||
rsx->recover_fifo();
|
||||
}
|
||||
|
||||
void trace_method(thread* rsx, u32 _reg, u32 arg)
|
||||
static void trace_method(thread* rsx, u32 _reg, u32 arg)
|
||||
{
|
||||
// For unknown yet valid methods
|
||||
rsx_log.trace("RSX method 0x%x (arg=0x%x)", _reg << 2, arg);
|
||||
|
@ -11,6 +11,7 @@
|
||||
|
||||
#include "Emu/System.h"
|
||||
#include "Emu/IdManager.h"
|
||||
#include "Emu/RSX/RSXThread.h"
|
||||
#include "Emu/Cell/PPUDisAsm.h"
|
||||
#include "Emu/Cell/PPUThread.h"
|
||||
#include "Emu/Cell/SPUDisAsm.h"
|
||||
@ -337,13 +338,32 @@ void debugger_frame::keyPressEvent(QKeyEvent* event)
|
||||
}
|
||||
}
|
||||
|
||||
rsx::thread* debugger_frame::get_rsx()
|
||||
{
|
||||
// m_rsx is raw pointer, when emulation is stopped it won't be cleared
|
||||
// Therefore need to do invalidation checks manually
|
||||
|
||||
if (g_fxo->get<rsx::thread>() != m_rsx)
|
||||
{
|
||||
m_rsx = nullptr;
|
||||
}
|
||||
|
||||
if (m_rsx && !m_rsx->ctrl)
|
||||
{
|
||||
m_rsx = nullptr;
|
||||
}
|
||||
|
||||
return m_rsx;
|
||||
}
|
||||
|
||||
void debugger_frame::UpdateUI()
|
||||
{
|
||||
UpdateUnitList();
|
||||
|
||||
const auto cpu = this->cpu.lock();
|
||||
const auto rsx = this->get_rsx();
|
||||
|
||||
if (!cpu)
|
||||
if (!cpu && !rsx)
|
||||
{
|
||||
if (m_last_pc != umax || !m_last_query_state.empty())
|
||||
{
|
||||
@ -351,10 +371,15 @@ void debugger_frame::UpdateUI()
|
||||
m_last_pc = -1;
|
||||
DoUpdate();
|
||||
}
|
||||
|
||||
m_btn_run->setEnabled(false);
|
||||
m_btn_step->setEnabled(false);
|
||||
m_btn_step_over->setEnabled(false);
|
||||
}
|
||||
else if (rsx)
|
||||
{
|
||||
if (m_last_pc != rsx->ctrl->get || !m_last_query_state.empty())
|
||||
{
|
||||
m_last_query_state.clear();
|
||||
m_last_pc = rsx->ctrl->get;
|
||||
DoUpdate();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -387,6 +412,7 @@ void debugger_frame::UpdateUI()
|
||||
}
|
||||
|
||||
Q_DECLARE_METATYPE(std::weak_ptr<cpu_thread>);
|
||||
Q_DECLARE_METATYPE(::rsx::thread*);
|
||||
|
||||
void debugger_frame::UpdateUnitList()
|
||||
{
|
||||
@ -424,6 +450,13 @@ void debugger_frame::UpdateUnitList()
|
||||
|
||||
idm::select<named_thread<ppu_thread>>(on_select);
|
||||
idm::select<named_thread<spu_thread>>(on_select);
|
||||
|
||||
if (auto render = g_fxo->get<rsx::thread>(); render && render->ctrl)
|
||||
{
|
||||
QVariant var_cpu = QVariant::fromValue<rsx::thread*>(render);
|
||||
m_choice_units->addItem("RSX[0x55555555]", var_cpu);
|
||||
if (old_cpu == var_cpu) m_choice_units->setCurrentIndex(m_choice_units->count() - 1);
|
||||
}
|
||||
}
|
||||
|
||||
OnSelectUnit();
|
||||
@ -436,15 +469,22 @@ void debugger_frame::OnSelectUnit()
|
||||
if (m_choice_units->count() < 1) return;
|
||||
|
||||
const auto weak = m_choice_units->currentData().value<std::weak_ptr<cpu_thread>>();
|
||||
const auto render = m_choice_units->currentData().value<rsx::thread*>();
|
||||
|
||||
if (!weak.owner_before(cpu) && !cpu.owner_before(weak))
|
||||
if (!render && !weak.owner_before(cpu) && !cpu.owner_before(weak))
|
||||
{
|
||||
// They match, nothing to do.
|
||||
return;
|
||||
}
|
||||
|
||||
if (render && render == this->get_rsx())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
m_disasm.reset();
|
||||
cpu.reset();
|
||||
m_rsx = nullptr;
|
||||
|
||||
if (!weak.expired())
|
||||
{
|
||||
@ -468,6 +508,10 @@ void debugger_frame::OnSelectUnit()
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
m_rsx = render;
|
||||
}
|
||||
|
||||
EnableButtons(true);
|
||||
|
||||
@ -494,8 +538,9 @@ void debugger_frame::DoUpdate()
|
||||
void debugger_frame::WritePanels()
|
||||
{
|
||||
const auto cpu = this->cpu.lock();
|
||||
const auto rsx = this->get_rsx();
|
||||
|
||||
if (!cpu)
|
||||
if (!cpu && !rsx)
|
||||
{
|
||||
m_misc_state->clear();
|
||||
m_regs->clear();
|
||||
@ -506,15 +551,15 @@ void debugger_frame::WritePanels()
|
||||
|
||||
loc = m_misc_state->verticalScrollBar()->value();
|
||||
m_misc_state->clear();
|
||||
m_misc_state->setText(qstr(cpu->dump_misc()));
|
||||
m_misc_state->setText(qstr(rsx ? "" : cpu->dump_misc()));
|
||||
m_misc_state->verticalScrollBar()->setValue(loc);
|
||||
|
||||
loc = m_regs->verticalScrollBar()->value();
|
||||
m_regs->clear();
|
||||
m_regs->setText(qstr(cpu->dump_regs()));
|
||||
m_regs->setText(qstr(rsx ? rsx->dump_regs() : cpu->dump_regs()));
|
||||
m_regs->verticalScrollBar()->setValue(loc);
|
||||
|
||||
Q_EMIT CallStackUpdateRequested(cpu->dump_callstack_list());
|
||||
Q_EMIT CallStackUpdateRequested(rsx ? rsx->dump_callstack() : cpu->dump_callstack_list());
|
||||
}
|
||||
|
||||
void debugger_frame::ShowGotoAddressDialog()
|
||||
@ -581,16 +626,16 @@ void debugger_frame::ShowGotoAddressDialog()
|
||||
|
||||
u64 debugger_frame::EvaluateExpression(const QString& expression)
|
||||
{
|
||||
auto thread = cpu.lock();
|
||||
|
||||
if (!thread) return 0;
|
||||
|
||||
bool ok = false;
|
||||
|
||||
// Parse expression(or at least used to, was nuked to remove the need for QtJsEngine)
|
||||
const QString fixed_expression = QRegExp("^[A-Fa-f0-9]+$").exactMatch(expression) ? "0x" + expression : expression;
|
||||
const u64 res = static_cast<u64>(fixed_expression.toULong(&ok, 16));
|
||||
return ok ? res : thread->get_pc();
|
||||
|
||||
if (ok) return res;
|
||||
if (auto thread = get_rsx()) return thread->ctrl->get;
|
||||
if (auto thread = cpu.lock()) return thread->get_pc();
|
||||
return 0;
|
||||
}
|
||||
|
||||
void debugger_frame::ClearBreakpoints()
|
||||
@ -606,7 +651,11 @@ void debugger_frame::ClearCallStack()
|
||||
void debugger_frame::ShowPC()
|
||||
{
|
||||
const auto cpu0 = cpu.lock();
|
||||
m_debugger_list->ShowAddress(cpu0 ? cpu0->get_pc() : 0);
|
||||
|
||||
const u32 pc = get_rsx() ? +m_rsx->ctrl->get
|
||||
: (cpu0 ? cpu0->get_pc() : 0);
|
||||
|
||||
m_debugger_list->ShowAddress(pc);
|
||||
}
|
||||
|
||||
void debugger_frame::DoStep(bool stepOver)
|
||||
|
@ -20,6 +20,11 @@ class breakpoint_list;
|
||||
class breakpoint_handler;
|
||||
class call_stack_list;
|
||||
|
||||
namespace rsx
|
||||
{
|
||||
class thread;
|
||||
}
|
||||
|
||||
class debugger_frame : public custom_dock_widget
|
||||
{
|
||||
Q_OBJECT
|
||||
@ -50,6 +55,7 @@ class debugger_frame : public custom_dock_widget
|
||||
|
||||
std::shared_ptr<CPUDisAsm> m_disasm;
|
||||
std::weak_ptr<cpu_thread> cpu;
|
||||
rsx::thread* m_rsx = nullptr;
|
||||
|
||||
breakpoint_list* m_breakpoint_list;
|
||||
breakpoint_handler* m_breakpoint_handler;
|
||||
@ -58,6 +64,7 @@ class debugger_frame : public custom_dock_widget
|
||||
|
||||
std::shared_ptr<gui_settings> xgui_settings;
|
||||
|
||||
rsx::thread* get_rsx(); // Do not read m_rsx directy, use this instead.
|
||||
public:
|
||||
explicit debugger_frame(std::shared_ptr<gui_settings> settings, QWidget *parent = 0);
|
||||
|
||||
|
@ -645,11 +645,12 @@ void rsx_debugger::GetMemory()
|
||||
}
|
||||
|
||||
std::string dump;
|
||||
u32 cmd_i = 0;
|
||||
|
||||
for (u32 i = 0; i < frame_debug.command_queue.size(); i++)
|
||||
for (const auto& command : frame_debug.command_queue)
|
||||
{
|
||||
const std::string& str = rsx::get_pretty_printing_function(frame_debug.command_queue[i].first)(frame_debug.command_queue[i].second);
|
||||
m_list_captured_frame->setItem(i, 0, new QTableWidgetItem(qstr(str)));
|
||||
const std::string str = rsx::get_pretty_printing_function(command.first)(command.first, command.second);
|
||||
m_list_captured_frame->setItem(cmd_i++, 0, new QTableWidgetItem(qstr(str)));
|
||||
|
||||
dump += str;
|
||||
dump += '\n';
|
||||
@ -739,93 +740,6 @@ void rsx_debugger::GetBuffers()
|
||||
//m_buffer_tex->showImage(QImage(buffer, m_text_width, m_text_height, QImage::Format_RGB32));
|
||||
}
|
||||
|
||||
const char* rsx_debugger::ParseGCMEnum(u32 value, u32 type)
|
||||
{
|
||||
switch(type)
|
||||
{
|
||||
case CELL_GCM_ENUM:
|
||||
{
|
||||
switch(value)
|
||||
{
|
||||
case 0x0200: return "Never";
|
||||
case 0x0201: return "Less";
|
||||
case 0x0202: return "Equal";
|
||||
case 0x0203: return "Less or Equal";
|
||||
case 0x0204: return "Greater";
|
||||
case 0x0205: return "Not Equal";
|
||||
case 0x0206: return "Greater or Equal";
|
||||
case 0x0207: return "Always";
|
||||
|
||||
case 0x0: return "Zero";
|
||||
case 0x1: return "One";
|
||||
case 0x0300: return "SRC_COLOR";
|
||||
case 0x0301: return "1 - SRC_COLOR";
|
||||
case 0x0302: return "SRC_ALPHA";
|
||||
case 0x0303: return "1 - SRC_ALPHA";
|
||||
case 0x0304: return "DST_ALPHA";
|
||||
case 0x0305: return "1 - DST_ALPHA";
|
||||
case 0x0306: return "DST_COLOR";
|
||||
case 0x0307: return "1 - DST_COLOR";
|
||||
case 0x0308: return "SRC_ALPHA_SATURATE";
|
||||
case 0x8001: return "CONSTANT_COLOR";
|
||||
case 0x8002: return "1 - CONSTANT_COLOR";
|
||||
case 0x8003: return "CONSTANT_ALPHA";
|
||||
case 0x8004: return "1 - CONSTANT_ALPHA";
|
||||
|
||||
case 0x8006: return "Add";
|
||||
case 0x8007: return "Min";
|
||||
case 0x8008: return "Max";
|
||||
case 0x800A: return "Substract";
|
||||
case 0x800B: return "Reverse Substract";
|
||||
case 0xF005: return "Reverse Substract Signed";
|
||||
case 0xF006: return "Add Signed";
|
||||
case 0xF007: return "Reverse Add Signed";
|
||||
|
||||
default: return "Wrong Value!";
|
||||
}
|
||||
}
|
||||
case CELL_GCM_PRIMITIVE_ENUM:
|
||||
{
|
||||
switch(value)
|
||||
{
|
||||
case 1: return "POINTS";
|
||||
case 2: return "LINES";
|
||||
case 3: return "LINE_LOOP";
|
||||
case 4: return "LINE_STRIP";
|
||||
case 5: return "TRIANGLES";
|
||||
case 6: return "TRIANGLE_STRIP";
|
||||
case 7: return "TRIANGLE_FAN";
|
||||
case 8: return "QUADS";
|
||||
case 9: return "QUAD_STRIP";
|
||||
case 10: return "POLYGON";
|
||||
|
||||
default: return "Wrong Value!";
|
||||
}
|
||||
}
|
||||
default: return "Unknown!";
|
||||
}
|
||||
}
|
||||
|
||||
#define case_16(a, m) \
|
||||
case a + m: \
|
||||
case a + m * 2: \
|
||||
case a + m * 3: \
|
||||
case a + m * 4: \
|
||||
case a + m * 5: \
|
||||
case a + m * 6: \
|
||||
case a + m * 7: \
|
||||
case a + m * 8: \
|
||||
case a + m * 9: \
|
||||
case a + m * 10: \
|
||||
case a + m * 11: \
|
||||
case a + m * 12: \
|
||||
case a + m * 13: \
|
||||
case a + m * 14: \
|
||||
case a + m * 15: \
|
||||
index = (cmd - a) / m; \
|
||||
[[fallthrough]]; \
|
||||
case a \
|
||||
|
||||
QString rsx_debugger::DisAsmCommand(u32 cmd, u32 count, u32 ioAddr)
|
||||
{
|
||||
std::string disasm;
|
||||
@ -874,30 +788,10 @@ QString rsx_debugger::DisAsmCommand(u32 cmd, u32 count, u32 ioAddr)
|
||||
DISASM("Flip and change current buffer: %d", args[0]);
|
||||
break;
|
||||
}
|
||||
case_16(NV4097_SET_TEXTURE_OFFSET, 0x20):
|
||||
{
|
||||
DISASM("Texture Offset[%d]: %07x", index, args[0]);
|
||||
switch ((args[1] & 0x3) - 1)
|
||||
{
|
||||
case CELL_GCM_LOCATION_LOCAL: DISASM("(Local memory);"); break;
|
||||
case CELL_GCM_LOCATION_MAIN: DISASM("(Main memory);"); break;
|
||||
default: DISASM("(Bad location!);"); break;
|
||||
}
|
||||
DISASM(" Cubemap:%s; Dimension:0x%x; Format:0x%x; Mipmap:0x%x",
|
||||
(((args[1] >> 2) & 0x1) ? "True" : "False"),
|
||||
((args[1] >> 4) & 0xf),
|
||||
((args[1] >> 8) & 0xff),
|
||||
((args[1] >> 16) & 0xffff));
|
||||
break;
|
||||
}
|
||||
case NV4097_SET_DEPTH_BOUNDS_TEST_ENABLE:
|
||||
{
|
||||
DISASM("Depth bounds test: %s", args[0] ? "Enable" : "Disable");
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
std::string str = rsx::get_pretty_printing_function((cmd & 0x3ffff) >> 2)(args[0]);
|
||||
const u32 id = (cmd & 0x3ffff) >> 2;
|
||||
std::string str = rsx::get_pretty_printing_function(id)(id, args[0]);
|
||||
DISASM("%s", str.c_str());
|
||||
break;
|
||||
}
|
||||
|
@ -72,7 +72,6 @@ public:
|
||||
virtual void GetMemory();
|
||||
virtual void GetBuffers();
|
||||
|
||||
const char* ParseGCMEnum(u32 value, u32 type);
|
||||
QString DisAsmCommand(u32 cmd, u32 count, u32 ioAddr);
|
||||
|
||||
void SetPC(const uint pc);
|
||||
|
Loading…
Reference in New Issue
Block a user