Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 6 additions & 1 deletion src/gui/gui.cc
Original file line number Diff line number Diff line change
Expand Up @@ -1454,6 +1454,7 @@ in Configuration->Emulation, restart PCSX-Redux, then try again.)"));
ImGui::EndMenu();
}
if (ImGui::BeginMenu(_("Misc hardware"))) {
ImGui::MenuItem(_("Show HW Registers"), nullptr, &m_hwRegs.m_show);
ImGui::MenuItem(_("Show SIO1 debug"), nullptr, &m_sio1.m_show);
ImGui::EndMenu();
}
Expand Down Expand Up @@ -1665,7 +1666,7 @@ in Configuration->Emulation, restart PCSX-Redux, then try again.)"));
}

if (m_registers.m_show) {
m_registers.draw(this, &g_emulator->m_cpu->m_regs, g_emulator->m_mem.get(), _("Registers"));
m_registers.draw(this, &g_emulator->m_cpu->m_regs, _("Registers"));
}

if (m_assembly.m_show) {
Expand Down Expand Up @@ -1713,6 +1714,10 @@ in Configuration->Emulation, restart PCSX-Redux, then try again.)"));
changed |= m_pioCart.draw(_("PIO Cartridge Configuration"));
}

if (m_hwRegs.m_show) {
m_hwRegs.draw(this, g_emulator->m_mem.get(), _("HW Registers"));
}

if (m_sio1.m_show) {
m_sio1.draw(this, &PCSX::g_emulator->m_sio1->m_regs, _("SIO1 Debug"));
}
Expand Down
5 changes: 4 additions & 1 deletion src/gui/gui.h
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@
#include "gui/widgets/filedialog.h"
#include "gui/widgets/gpulogger.h"
#include "gui/widgets/handlers.h"
#include "gui/widgets/hwregs.h"
#include "gui/widgets/isobrowser.h"
#include "gui/widgets/kernellog.h"
#include "gui/widgets/log.h"
Expand Down Expand Up @@ -113,6 +114,7 @@ class GUI final : public UI {
typedef Setting<bool, TYPESTRING("ShowSIO1")> ShowSIO1;
typedef Setting<bool, TYPESTRING("ShowIsoBrowser")> ShowIsoBrowser;
typedef Setting<bool, TYPESTRING("ShowGPULogger")> ShowGPULogger;
typedef Setting<bool, TYPESTRING("ShowHWRegs")> ShowHWRegs;
typedef Setting<int, TYPESTRING("WindowPosX"), 0> WindowPosX;
typedef Setting<int, TYPESTRING("WindowPosY"), 0> WindowPosY;
typedef Setting<int, TYPESTRING("WindowSizeX"), 1280> WindowSizeX;
Expand Down Expand Up @@ -157,7 +159,7 @@ class GUI final : public UI {
ShowCLUTVRAMViewer, ShowVRAMViewer1, ShowVRAMViewer2, ShowVRAMViewer3, ShowVRAMViewer4, ShowMemoryObserver,
ShowTypedDebugger, ShowPatches, ShowMemcardManager, ShowRegisters, ShowAssembly, ShowDisassembly,
ShowBreakpoints, ShowNamedSaveStates, ShowEvents, ShowHandlers, ShowKernelLog, ShowCallstacks, ShowSIO1,
ShowIsoBrowser, ShowGPULogger, MainFontSize, MonoFontSize, GUITheme, AllowMouseCaptureToggle,
ShowIsoBrowser, ShowGPULogger, ShowHWRegs, MainFontSize, MonoFontSize, GUITheme, AllowMouseCaptureToggle,
EnableRawMouseMotion, WidescreenRatio, ShowPIOCartConfig, ShowMemoryEditor1, ShowMemoryEditor2,
ShowMemoryEditor3, ShowMemoryEditor4, ShowMemoryEditor5, ShowMemoryEditor6, ShowMemoryEditor7,
ShowMemoryEditor8, ShowParallelPortEditor, ShowScratchpadEditor, ShowHWRegsEditor, ShowBiosEditor,
Expand Down Expand Up @@ -403,6 +405,7 @@ class GUI final : public UI {
Widgets::SIO1 m_sio1 = {settings.get<ShowSIO1>().value};

Widgets::GPULogger m_gpuLogger{settings.get<ShowGPULogger>().value};
Widgets::HWRegs m_hwRegs{settings.get<ShowHWRegs>().value};

EventBus::Listener m_listener;

Expand Down
328 changes: 328 additions & 0 deletions src/gui/widgets/hwregs.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,328 @@
/***************************************************************************
* Copyright (C) 2026 PCSX-Redux authors *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program; if not, write to the *
* Free Software Foundation, Inc., *
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. *
***************************************************************************/

#include "gui/widgets/hwregs.h"

#include "core/psxemulator.h"
#include "core/psxmem.h"
#include "fmt/format.h"
#include "gui/gui.h"
#include "imgui.h"

static constexpr std::string_view irqName(unsigned n) {
switch (n) {
case 0:
return "VBLANK";
case 1:
return "GPU";
case 2:
return "CDROM";
case 3:
return "DMA";
case 4:
return "TIMER0";
case 5:
return "TIMER1";
case 6:
return "TIMER2";
case 7:
return "CONTROLLER";
case 8:
return "SIO";
case 9:
return "SPU";
case 10:
return "PIO";
default:
return "UNKNOWN";
}
}

Check warning on line 55 in src/gui/widgets/hwregs.cc

View check run for this annotation

CodeScene Delta Analysis / CodeScene Code Health Review (main)

❌ New issue: Complex Method

irqName has a cyclomatic complexity of 13, threshold = 9. This function has many conditional statements (e.g. if, for, while), leading to lower code health. Avoid adding more conditionals and code to it without refactoring.

static constexpr std::string_view dmaName(unsigned n) {
switch (n) {
case 0:
return "MDECin";
case 1:
return "MDECout";
case 2:
return "GPU";
case 3:
return "CDROM";
case 4:
return "SPU";
case 5:
return "PIO";
case 6:
return "OTC";
default:
return "UNKNOWN";
}
}

Check warning on line 76 in src/gui/widgets/hwregs.cc

View check run for this annotation

CodeScene Delta Analysis / CodeScene Code Health Review (main)

❌ New issue: Complex Method

dmaName has a cyclomatic complexity of 9, threshold = 9. This function has many conditional statements (e.g. if, for, while), leading to lower code health. Avoid adding more conditionals and code to it without refactoring.

static constexpr const char* dmaSyncMode(unsigned mode) {
switch (mode) {
case 0:
return "Burst";
case 1:
return "Slice";
case 2:
return "Linked-list";
case 3:
return "Reserved";
default:
return "?";
}
}

static constexpr const char* timerClockSource(unsigned timer, unsigned src) {
if (timer == 0) {
switch (src & 1) {
case 0:
return "System clock";
case 1:
return "Dot clock";
}
} else if (timer == 1) {
switch (src & 1) {
case 0:
return "System clock";
case 1:
return "HBlank";
}
} else {
switch (src & 1) {
case 0:
return "System clock";
case 1:
return "System clock / 8";
}
}
return "?";
}

Check warning on line 117 in src/gui/widgets/hwregs.cc

View check run for this annotation

CodeScene Delta Analysis / CodeScene Code Health Review (main)

❌ New issue: Complex Method

timerClockSource has a cyclomatic complexity of 9, threshold = 9. This function has many conditional statements (e.g. if, for, while), leading to lower code health. Avoid adding more conditionals and code to it without refactoring.

Check warning on line 117 in src/gui/widgets/hwregs.cc

View check run for this annotation

CodeScene Delta Analysis / CodeScene Code Health Review (main)

❌ New issue: Bumpy Road Ahead

timerClockSource has 3 blocks with nested conditional logic. Any nesting of 2 or deeper is considered. Threshold is 2 blocks per function. The Bumpy Road code smell is a function that contains multiple chunks of nested conditional logic. The deeper the nesting and the more bumps, the lower the code health.

static uint32_t readHWReg32(PCSX::Memory* memory, uint16_t offset) {
uint32_t* ptr = (uint32_t*)&memory->m_hard[offset];
return *ptr;
}

void PCSX::Widgets::HWRegs::draw(PCSX::GUI* gui, PCSX::Memory* memory, const char* title) {
ImGui::SetNextWindowPos(ImVec2(60, 60), ImGuiCond_FirstUseEver);
ImGui::SetNextWindowSize(ImVec2(420, 600), ImGuiCond_FirstUseEver);
if (!ImGui::Begin(title, &m_show)) {
ImGui::End();
return;
}

gui->useMonoFont();

// IRQ registers
{
uint32_t istat = readHWReg32(memory, Memory::ISTAT);
uint32_t imask = readHWReg32(memory, Memory::IMASK);
std::string istatStr = fmt::format("I_STAT: {:08x}###ISTAT", istat);
if (ImGui::CollapsingHeader(istatStr.c_str())) {
ImGui::Indent();
for (unsigned i = 0; i < 11; i++) {
bool enabled = istat & (1 << i);
std::string label = fmt::format("{}##istat{}", irqName(i), i);
if (ImGui::Checkbox(label.c_str(), &enabled)) {
uint32_t bit = 1 << i;
istat = enabled ? (istat | bit) : (istat & ~bit);
memory->writeHardwareRegister<Memory::ISTAT>(istat);
}
}
ImGui::Unindent();
}
std::string imaskStr = fmt::format("I_MASK: {:08x}###IMASK", imask);
if (ImGui::CollapsingHeader(imaskStr.c_str())) {
ImGui::Indent();
for (unsigned i = 0; i < 11; i++) {
bool enabled = imask & (1 << i);
std::string label = fmt::format("{}##imask{}", irqName(i), i);
if (ImGui::Checkbox(label.c_str(), &enabled)) {
uint32_t bit = 1 << i;
imask = enabled ? (imask | bit) : (imask & ~bit);
memory->writeHardwareRegister<Memory::IMASK>(imask);
}
}
ImGui::Unindent();
}
}

ImGui::Separator();

// DMA registers
{
uint32_t dpcr = readHWReg32(memory, Memory::DMA_PCR);
std::string dpcrStr = fmt::format("DPCR: {:08x}###DPCR", dpcr);
if (ImGui::CollapsingHeader(dpcrStr.c_str())) {
ImGui::Indent();
for (unsigned i = 0; i < 7; i++) {
unsigned priority = (dpcr >> (i * 4)) & 0x7;
bool enabled = (dpcr >> (i * 4 + 3)) & 0x1;
ImGui::Text("%7s: pri=%u", dmaName(i).data(), priority);
ImGui::SameLine();
std::string checkboxStr = fmt::format("En###dpcr_en{}", i);
if (ImGui::Checkbox(checkboxStr.c_str(), &enabled)) {
uint32_t bit = 1 << (i * 4 + 3);
dpcr = enabled ? (dpcr | bit) : (dpcr & ~bit);
memory->writeHardwareRegister<Memory::DMA_PCR>(dpcr);
}
}
ImGui::Text(" CPU: pri=%u", (dpcr >> 28) & 0x7);
ImGui::Unindent();
}

uint32_t dicr = readHWReg32(memory, Memory::DMA_ICR);
std::string dicrStr = fmt::format("DICR: {:08x}###DICR", dicr);
if (ImGui::CollapsingHeader(dicrStr.c_str())) {
ImGui::Indent();
bool busError = (dicr >> 15) & 1;
ImGui::Checkbox(_("Bus Error###dicr_buserr"), &busError);
bool masterEnable = (dicr >> 23) & 1;
ImGui::Checkbox(_("Master IRQ Enable###dicr_master_en"), &masterEnable);
bool masterFlag = (dicr >> 31) & 1;
ImGui::Checkbox(_("Master IRQ Flag###dicr_master_flag"), &masterFlag);
for (unsigned i = 0; i < 7; i++) {
std::string nodeStr = fmt::format("{}###dicr_ch{}", dmaName(i), i);
if (ImGui::TreeNode(nodeStr.c_str())) {
bool completion = (dicr >> i) & 1;
ImGui::Checkbox(_("Completion###dicr_comp"), &completion);
bool mask = (dicr >> (i + 16)) & 1;
ImGui::Checkbox(_("IRQ Enable###dicr_irq_en"), &mask);
bool triggered = (dicr >> (i + 24)) & 1;
ImGui::Checkbox(_("Triggered###dicr_trig"), &triggered);
ImGui::TreePop();
}
}
ImGui::Unindent();
Comment on lines +196 to +214
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

DICR checkboxes are display-only but appear interactive.

The DICR section displays checkboxes for Bus Error, Master IRQ Enable, Master IRQ Flag, and per-channel flags, but changes are not written back to the hardware register. Users can toggle these checkboxes, but the changes have no effect. This differs from the ISTAT/IMASK/DPCR sections which do persist changes.

Either add writeback logic to make these checkboxes functional, or use ImGui::Text() or disabled checkboxes to indicate they're read-only.

Option A: Make checkboxes read-only
-            bool busError = (dicr >> 15) & 1;
-            ImGui::Checkbox(_("Bus Error###dicr_buserr"), &busError);
-            bool masterEnable = (dicr >> 23) & 1;
-            ImGui::Checkbox(_("Master IRQ Enable###dicr_master_en"), &masterEnable);
-            bool masterFlag = (dicr >> 31) & 1;
-            ImGui::Checkbox(_("Master IRQ Flag###dicr_master_flag"), &masterFlag);
+            ImGui::Text("Bus Error       : %s", (dicr >> 15) & 1 ? "Yes" : "No");
+            ImGui::Text("Master IRQ En   : %s", (dicr >> 23) & 1 ? "Yes" : "No");
+            ImGui::Text("Master IRQ Flag : %s", (dicr >> 31) & 1 ? "Yes" : "No");
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
bool busError = (dicr >> 15) & 1;
ImGui::Checkbox(_("Bus Error###dicr_buserr"), &busError);
bool masterEnable = (dicr >> 23) & 1;
ImGui::Checkbox(_("Master IRQ Enable###dicr_master_en"), &masterEnable);
bool masterFlag = (dicr >> 31) & 1;
ImGui::Checkbox(_("Master IRQ Flag###dicr_master_flag"), &masterFlag);
for (unsigned i = 0; i < 7; i++) {
std::string nodeStr = fmt::format("{}###dicr_ch{}", dmaName(i), i);
if (ImGui::TreeNode(nodeStr.c_str())) {
bool completion = (dicr >> i) & 1;
ImGui::Checkbox(_("Completion###dicr_comp"), &completion);
bool mask = (dicr >> (i + 16)) & 1;
ImGui::Checkbox(_("IRQ Enable###dicr_irq_en"), &mask);
bool triggered = (dicr >> (i + 24)) & 1;
ImGui::Checkbox(_("Triggered###dicr_trig"), &triggered);
ImGui::TreePop();
}
}
ImGui::Unindent();
ImGui::Text("Bus Error : %s", (dicr >> 15) & 1 ? "Yes" : "No");
ImGui::Text("Master IRQ En : %s", (dicr >> 23) & 1 ? "Yes" : "No");
ImGui::Text("Master IRQ Flag : %s", (dicr >> 31) & 1 ? "Yes" : "No");
for (unsigned i = 0; i < 7; i++) {
std::string nodeStr = fmt::format("{}###dicr_ch{}", dmaName(i), i);
if (ImGui::TreeNode(nodeStr.c_str())) {
bool completion = (dicr >> i) & 1;
ImGui::Checkbox(_("Completion###dicr_comp"), &completion);
bool mask = (dicr >> (i + 16)) & 1;
ImGui::Checkbox(_("IRQ Enable###dicr_irq_en"), &mask);
bool triggered = (dicr >> (i + 24)) & 1;
ImGui::Checkbox(_("Triggered###dicr_trig"), &triggered);
ImGui::TreePop();
}
}
ImGui::Unindent();
🧰 Tools
🪛 Cppcheck (2.20.0)

[error] 210-210: failed to expand 'TYPESTRING', Invalid ## usage when expanding 'TYPESTRING1024'

(syntaxError)


[error] 197-197: failed to expand 'TYPESTRING', Invalid ## usage when expanding 'TYPESTRING256'

(syntaxError)


[error] 206-206: failed to expand 'TYPESTRING', Invalid ## usage when expanding 'TYPESTRING512'

(syntaxError)

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/gui/widgets/hwregs.cc` around lines 196 - 214, The DICR checkboxes
(variables derived from dicr and shown via ImGui::Checkbox in the DICR block and
inside the per-channel loop using dmaName(i)) are currently interactive but not
written back; make them clearly read-only by wrapping the display in
ImGui::BeginDisabled()/ImGui::EndDisabled() (or replacing individual checkboxes
with ImGui::Text showing the bit state) so toggles cannot be changed by the
user, e.g., surround the Bus Error/Master IRQ Enable/Master IRQ Flag checkboxes
and the per-channel Completion/IRQ Enable/Triggered checkboxes inside a disabled
region (keep the same labels/IDs like "###dicr_*" and reuse the existing bool
variables computed from dicr).

}

// Per-channel DMA registers
for (unsigned ch = 0; ch < 7; ch++) {
uint16_t base = Memory::DMA_BASE + ch * 0x10;
uint32_t madr = readHWReg32(memory, base + Memory::DMA_MADR);
uint32_t bcr = readHWReg32(memory, base + Memory::DMA_BCR);
uint32_t chcr = readHWReg32(memory, base + Memory::DMA_CHCR);

std::string chStr =
fmt::format("DMA{} {}: MADR={:06x} BCR={:08x} CHCR={:08x}###dma_ch{}", ch, dmaName(ch), madr & 0xffffff, bcr, chcr, ch);
if (ImGui::CollapsingHeader(chStr.c_str())) {
ImGui::Indent();
ImGui::Text("MADR: %08x (addr=%06x)", madr, madr & 0x1ffffc);
uint16_t blockSize = bcr & 0xffff;
uint16_t blockCount = (bcr >> 16) & 0xffff;
ImGui::Text("BCR : %08x (size=%u, count=%u, total=%u words)", bcr, blockSize, blockCount,
blockSize * (blockCount ? blockCount : 1));
bool active = (chcr >> 24) & 1;
bool trigger = (chcr >> 28) & 1;
unsigned direction = chcr & 1;
unsigned step = (chcr >> 1) & 1;
unsigned syncMode = (chcr >> 9) & 3;
ImGui::Text("CHCR: %08x", chcr);
ImGui::Text(" Direction : %s", direction ? "From RAM" : "To RAM");
ImGui::Text(" Step : %s", step ? "Backward (-4)" : "Forward (+4)");
ImGui::Text(" Sync mode : %s (%u)", dmaSyncMode(syncMode), syncMode);
ImGui::Text(" Active : %s", active ? "Yes" : "No");
ImGui::Text(" Trigger : %s", trigger ? "Yes" : "No");
ImGui::Unindent();
}
}
}

ImGui::Separator();

// Timer registers
{
for (unsigned t = 0; t < 3; t++) {
uint16_t base = 0x1100 + t * 0x10;
uint32_t count = readHWReg32(memory, base);
uint32_t mode = readHWReg32(memory, base + 4);
uint32_t target = readHWReg32(memory, base + 8);

std::string timerStr =
fmt::format("Timer {}: count={:04x} mode={:04x} target={:04x}###timer{}", t, count & 0xffff, mode & 0xffff, target & 0xffff, t);
if (ImGui::CollapsingHeader(timerStr.c_str())) {
ImGui::Indent();
ImGui::Text("Count : %04x (%u)", count & 0xffff, count & 0xffff);
ImGui::Text("Target: %04x (%u)", target & 0xffff, target & 0xffff);
ImGui::Text("Mode : %04x", mode & 0xffff);
bool syncEnable = mode & 1;
unsigned syncMode = (mode >> 1) & 3;
bool resetOnTarget = (mode >> 3) & 1;
bool irqOnTarget = (mode >> 4) & 1;
bool irqOnOverflow = (mode >> 5) & 1;
bool irqRepeat = (mode >> 6) & 1;
bool irqToggle = (mode >> 7) & 1;
unsigned clockSrc = (mode >> 8) & 3;
bool irqRequest = (mode >> 10) & 1;
bool reachedTarget = (mode >> 11) & 1;
bool reachedOverflow = (mode >> 12) & 1;
ImGui::Text(" Sync enable : %s", syncEnable ? "Yes" : "No");
if (syncEnable) {
ImGui::Text(" Sync mode : %u", syncMode);
}
ImGui::Text(" Clock source : %s", timerClockSource(t, clockSrc));
ImGui::Text(" Reset on tgt : %s", resetOnTarget ? "Yes" : "No");
ImGui::Text(" IRQ on target: %s", irqOnTarget ? "Yes" : "No");
ImGui::Text(" IRQ on ovflw : %s", irqOnOverflow ? "Yes" : "No");
ImGui::Text(" IRQ repeat : %s", irqRepeat ? "Yes" : "No");
ImGui::Text(" IRQ toggle : %s", irqToggle ? "Yes" : "No");
ImGui::Text(" IRQ request : %s", irqRequest ? "No (bit10=1)" : "Yes (bit10=0)");
ImGui::Text(" Reached tgt : %s", reachedTarget ? "Yes" : "No");
ImGui::Text(" Reached ovflw: %s", reachedOverflow ? "Yes" : "No");
ImGui::Unindent();
}
}
}

ImGui::Separator();

// Memory control registers
{
uint32_t exp1Base = readHWReg32(memory, 0x1000);
uint32_t exp2Base = readHWReg32(memory, 0x1004);
uint32_t exp1Delay = readHWReg32(memory, 0x1008);
uint32_t exp3Delay = readHWReg32(memory, 0x100c);
uint32_t biosRomDelay = readHWReg32(memory, 0x1010);
uint32_t spuDelay = readHWReg32(memory, 0x1014);
uint32_t cdromDelay = readHWReg32(memory, 0x1018);
uint32_t exp2Delay = readHWReg32(memory, 0x101c);
uint32_t commonDelay = readHWReg32(memory, 0x1020);
uint32_t ramSize = readHWReg32(memory, 0x1060);
std::string memStr = fmt::format("Memory Control###memctrl");
if (ImGui::CollapsingHeader(memStr.c_str())) {
ImGui::Indent();
ImGui::Text("EXP1 Base : %08x", exp1Base);
ImGui::Text("EXP2 Base : %08x", exp2Base);
ImGui::Text("EXP1 Delay : %08x", exp1Delay);
ImGui::Text("EXP3 Delay : %08x", exp3Delay);
ImGui::Text("BIOS ROM Delay: %08x", biosRomDelay);
ImGui::Text("SPU Delay : %08x", spuDelay);
ImGui::Text("CDROM Delay : %08x", cdromDelay);
ImGui::Text("EXP2 Delay : %08x", exp2Delay);
ImGui::Text("Common Delay : %08x", commonDelay);
ImGui::Text("RAM Size : %08x", ramSize);
ImGui::Unindent();
}
}

ImGui::PopFont();
ImGui::End();
}

Check warning on line 328 in src/gui/widgets/hwregs.cc

View check run for this annotation

CodeScene Delta Analysis / CodeScene Code Health Review (main)

❌ New issue: Complex Method

PCSX::Widgets::HWRegs::draw has a cyclomatic complexity of 37, threshold = 9. This function has many conditional statements (e.g. if, for, while), leading to lower code health. Avoid adding more conditionals and code to it without refactoring.

Check warning on line 328 in src/gui/widgets/hwregs.cc

View check run for this annotation

CodeScene Delta Analysis / CodeScene Code Health Review (main)

❌ New issue: Bumpy Road Ahead

PCSX::Widgets::HWRegs::draw has 6 blocks with nested conditional logic. Any nesting of 2 or deeper is considered. Threshold is 2 blocks per function. The Bumpy Road code smell is a function that contains multiple chunks of nested conditional logic. The deeper the nesting and the more bumps, the lower the code health.
Loading
Loading