Skip to content

Commit

Permalink
debug: added timers debug window
Browse files Browse the repository at this point in the history
slight timer device refactor (not templated anymore)
  • Loading branch information
JaCzekanski committed Aug 11, 2019
1 parent 80494d6 commit 2a7f248
Show file tree
Hide file tree
Showing 9 changed files with 255 additions and 81 deletions.
19 changes: 5 additions & 14 deletions src/device/timer.cpp
Expand Up @@ -3,11 +3,9 @@

using namespace timer;

template <int which>
Timer<which>::Timer(System* sys) : sys(sys) {}
Timer::Timer(System* sys, int which) : which(which), sys(sys) {}

template <int which>
void Timer<which>::step(int cycles) {
void Timer::step(int cycles) {
if (paused) return;
cnt += cycles;

Expand Down Expand Up @@ -66,8 +64,7 @@ void Timer<which>::step(int cycles) {
current._reg = (uint16_t)tval;
}

template <int which>
void Timer<which>::checkIrq() {
void Timer::checkIrq() {
if (mode.irqPulseMode == CounterMode::IrqPulseMode::toggle) {
mode.interruptRequest = !mode.interruptRequest;
} else {
Expand All @@ -83,8 +80,7 @@ void Timer<which>::checkIrq() {
mode.interruptRequest = true; // low only for few cycles
}

template <int which>
uint8_t Timer<which>::read(uint32_t address) {
uint8_t Timer::read(uint32_t address) {
if (address < 2) {
return current.read(address);
}
Expand All @@ -102,8 +98,7 @@ uint8_t Timer<which>::read(uint32_t address) {
return 0;
}

template <int which>
void Timer<which>::write(uint32_t address, uint8_t data) {
void Timer::write(uint32_t address, uint8_t data) {
if (address < 2) {
current.write(address, data);
} else if (address >= 4 && address < 6) {
Expand Down Expand Up @@ -142,7 +137,3 @@ void Timer<which>::write(uint32_t address, uint8_t data) {
target.write(address - 8, data);
}
}

template class Timer<0>;
template class Timer<1>;
template class Timer<2>;
6 changes: 3 additions & 3 deletions src/device/timer.h
Expand Up @@ -65,11 +65,11 @@ union CounterMode {
};
} // namespace timer

template <int which>
class Timer {
public:
const int baseAddress = 0x1f801100;

public:
int which;
Reg16 current;
timer::CounterMode mode;
Reg16 target;
Expand All @@ -92,7 +92,7 @@ class Timer {
}

public:
Timer(System* sys);
Timer(System* sys, int which);
void step() { step(1); }
void step(int cycles);
uint8_t read(uint32_t address);
Expand Down
33 changes: 0 additions & 33 deletions src/platform/windows/gui/debug.cpp
Expand Up @@ -402,39 +402,6 @@ void gpuLogWindow(System *sys) {
}
}

void ioWindow(System *sys) {
if (!showIo) {
return;
}
ImGui::Begin("IO", &showIo, ImVec2(300, 200));

ImGui::Columns(1, nullptr, false);
ImGui::Text("Timer 0");

ImGui::Columns(2, nullptr, false);
dumpRegister("current", sys->timer0->current._reg);
dumpRegister("target", sys->timer0->target._reg);
dumpRegister("mode", sys->timer0->mode._reg);

ImGui::Columns(1, nullptr, false);
ImGui::Text("Timer 1");

ImGui::Columns(2, nullptr, false);
dumpRegister("current", sys->timer1->current._reg);
dumpRegister("target", sys->timer1->target._reg);
dumpRegister("mode", sys->timer1->mode._reg);

ImGui::Columns(1, nullptr, false);
ImGui::Text("Timer 2");

ImGui::Columns(2, nullptr, false);
dumpRegister("current", sys->timer2->current._reg);
dumpRegister("target", sys->timer2->target._reg);
dumpRegister("mode", sys->timer2->mode._reg);

ImGui::End();
}

void ioLogWindow(System *sys) {
#ifdef ENABLE_IO_LOG
if (!ioLogEnabled) {
Expand Down
200 changes: 200 additions & 0 deletions src/platform/windows/gui/debug/timers/timers.cpp
@@ -0,0 +1,200 @@
#include "timers.h"
#include <imgui.h>
#include <numeric>
#include "platform/windows/gui/tools.h"
#include "system.h"
#include "utils/string.h"

namespace gui::debug::timers {

std::string getSyncMode(Timer* timer) {
int which = timer->which;
timer::CounterMode mode = timer->mode;

if (which == 0) {
using modes = timer::CounterMode::SyncMode0;
auto mode0 = static_cast<modes>(mode.syncMode);

switch (mode0) {
case modes::pauseDuringHblank: return "pauseDuringHblank";
case modes::resetAtHblank: return "resetAtHblank";
case modes::resetAtHblankAndPauseOutside: return "resetAtHblankAndPauseOutside";
case modes::pauseUntilHblankAndFreerun: return "pauseUntilHblankAndFreerun";
}
}
if (which == 1) {
using modes = timer::CounterMode::SyncMode1;
auto mode1 = static_cast<modes>(mode.syncMode);

switch (mode1) {
case modes::pauseDuringVblank: return "pauseDuringVblank";
case modes::resetAtVblank: return "resetAtVblank";
case modes::resetAtVblankAndPauseOutside: return "resetAtVblankAndPauseOutside";
case modes::pauseUntilVblankAndFreerun: return "pauseUntilVblankAndFreerun";
}
}
if (which == 2) {
using modes = timer::CounterMode::SyncMode2;
auto mode2 = static_cast<modes>(mode.syncMode);

switch (mode2) {
case modes::stopCounter:
case modes::stopCounter_: return "stopCounter";
case modes::freeRun:
case modes::freeRun_: return "freeRun";
}
}
return "";
}

std::string getClockSource(Timer* timer) {
int which = timer->which;
timer::CounterMode mode = timer->mode;
if (which == 0) {
using modes = timer::CounterMode::ClockSource0;
auto clock = static_cast<modes>(mode.clockSource & 1);

if (clock == modes::dotClock) {
return "Dotclock";
} else {
return "Sysclock";
}
} else if (which == 1) {
using modes = timer::CounterMode::ClockSource1;
auto clock = static_cast<modes>(mode.clockSource & 1);

if (clock == modes::hblank) {
return "HBlank";
} else {
return "Sysclock";
}
} else if (which == 2) {
using modes = timer::CounterMode::ClockSource2;
auto clock = static_cast<modes>((mode.clockSource >> 1) & 1);

if (clock == modes::systemClock_8) {
return "Sysclock/8";
} else {
return "Sysclock";
}
}
return "";
}

struct Field {
std::string bits;
std::string name;
std::string value;
};

void drawRegisterFields(const char* name, const std::vector<Field>& fields) {
const int colNum = 3;
ImVec2 charSize = ImGui::CalcTextSize("_");
std::vector<int> columnsWidth(colNum);

for (int i = 0; i < fields.size(); i++) {
auto& f = fields[i];
if (f.bits.size() > columnsWidth[0]) {
columnsWidth[0] = f.bits.size();
}
if (f.name.size() > columnsWidth[1]) {
columnsWidth[1] = f.name.size();
}
if (f.value.size() > columnsWidth[2]) {
columnsWidth[2] = f.value.size();
}
}

ImVec2 padding(2, 2);
ImVec2 spacing(4, 0);

int width = 0;
for (auto w : columnsWidth) {
width += w * charSize.x + spacing.x;
}
ImVec2 windowSize(width, fields.size() * charSize.y + padding.y * 2);

ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, padding);
ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(0, 0));
ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, spacing);
if (ImGui::BeginChild(name, windowSize, true)) {
ImGui::Columns(3, name, true);

for (int i = 0; i < colNum; i++) {
ImGui::SetColumnWidth(i, columnsWidth[i] * charSize.x + spacing.x);
}

for (auto& f : fields) {
ImGui::TextUnformatted(f.bits.c_str());
ImGui::NextColumn();

ImGui::TextUnformatted(f.name.c_str());
ImGui::NextColumn();

ImGui::TextUnformatted(f.value.c_str());
ImGui::NextColumn();
}

ImGui::Columns(1);
}
ImGui::EndChild();
ImGui::PopStyleVar(3);
}

void Timers::timersWindow(System* sys) {
ImGui::Begin("Timers", &timersWindowOpen, ImVec2(600, 300), ImGuiWindowFlags_NoScrollbar);

ImGui::PushFont(ImGui::GetIO().Fonts->Fonts[1]);

std::array<Timer*, 3> timers = {sys->timer[0].get(), sys->timer[1].get(), sys->timer[2].get()};

ImGui::Columns(3);
for (auto* timer : timers) {
int which = timer->which;
ImGui::Text("Timer%d", which);
ImGui::Text("Value: 0x%04x", timer->current._reg);
if (ImGui::IsItemHovered()) {
ImGui::SetTooltip("0x%08x", timer->baseAddress + which * 0x10 + 0);
}

ImGui::Text("Target: 0x%04x", timer->target._reg);
if (ImGui::IsItemHovered()) {
ImGui::SetTooltip("0x%08x", timer->baseAddress + which * 0x10 + 8);
}

ImGui::Text("Mode: 0x%04x", timer->mode._reg);
if (ImGui::IsItemHovered()) {
ImGui::SetTooltip("0x%08x", timer->baseAddress + which * 0x10 + 4);
}

const std::vector<Field> fields = {
{"0", "Sync", timer->mode.syncEnabled ? "On" : "Off"},
{"1-2", "SyncMode", getSyncMode(timer)},
{"3", "Reset counter", timer->mode.resetToZero == timer::CounterMode::ResetToZero::whenFFFF ? "after 0xffff" : "after target"},
{"4", "IRQ on target", timer->mode.irqWhenTarget ? "On" : "Off"},
{"5", "IRQ on 0xFFFF", timer->mode.irqWhenFFFF ? "On" : "Off"},
{"6", "IRQ repeat mode",
timer->mode.irqRepeatMode == timer::CounterMode::IrqRepeatMode::repeatedly ? "Repeatedly" : "One-shot"},
{"7", "IRQ pulse mode", timer->mode.irqPulseMode == timer::CounterMode::IrqPulseMode::toggle ? "Toggle bit10" : "Pulse bit10"},
{"8-9", "Clock source", getClockSource(timer)},
{"10", "IRQ request", timer->mode.interruptRequest ? "No" : "Pending"},
{"11", "Reached target", timer->mode.reachedTarget ? "Yes" : "No"},
{"12", "Reached 0xFFFF", timer->mode.reachedFFFF ? "Yes" : "No"},
};

drawRegisterFields(string_format("flags##timer%d", which).c_str(), fields);

ImGui::NextColumn();
}

ImGui::Columns(1);

ImGui::PopFont();

ImGui::End();
}

void Timers::displayWindows(System* sys) {
if (timersWindowOpen) timersWindow(sys);
}
} // namespace gui::debug::timers
16 changes: 16 additions & 0 deletions src/platform/windows/gui/debug/timers/timers.h
@@ -0,0 +1,16 @@
#pragma once
#include <array>
#include <cstdint>
#include <string>

struct System;

namespace gui::debug::timers {
class Timers {
void timersWindow(System* sys);

public:
bool timersWindowOpen = false;
void displayWindows(System* sys);
};
} // namespace gui::debug::timers
9 changes: 5 additions & 4 deletions src/platform/windows/gui/gui.cpp
Expand Up @@ -5,6 +5,7 @@
#include "debug/cpu/cpu.h"
#include "debug/gpu/gpu.h"
#include "debug/kernel/kernel.h"
#include "debug/timers/timers.h"
#include "imgui/imgui_impl_sdl_gl3.h"
#include "options.h"
#include "platform/windows/input/key.h"
Expand All @@ -16,7 +17,6 @@ void gteRegistersWindow(GTE& gte);
void ioLogWindow(System* sys);
void gteLogWindow(System* sys);
void gpuLogWindow(System* sys);
void ioWindow(System* sys);
void vramWindow(gpu::GPU* gpu);
void watchWindow(System* sys);
void ramWindow(System* sys);
Expand All @@ -30,7 +30,6 @@ bool ioLogEnabled = false;
bool gteLogEnabled = false;
bool gpuLogEnabled = false;
bool singleFrame = false;
bool showIo = false;

bool notInitializedWindowShown = false;
bool showVramWindow = false;
Expand All @@ -42,6 +41,7 @@ bool showSpuWindow = false;
bool showAboutWindow = false;

gui::debug::cpu::CPU cpuDebug;
gui::debug::timers::Timers timersDebug;

void aboutWindow() {
ImGui::Begin("About", &showAboutWindow);
Expand Down Expand Up @@ -112,7 +112,8 @@ void renderImgui(System* sys) {
ImGui::Separator();

ImGui::MenuItem("GTE registers", nullptr, &gteRegistersEnabled);
ImGui::MenuItem("IO", nullptr, &showIo);
ImGui::MenuItem("Timers", nullptr, &timersDebug.timersWindowOpen);
;
ImGui::MenuItem("Memory", nullptr, &showRamWindow);
ImGui::MenuItem("VRAM", nullptr, &showVramWindow);
ImGui::MenuItem("Debugger", nullptr, &cpuDebug.debuggerWindowOpen);
Expand Down Expand Up @@ -145,7 +146,6 @@ void renderImgui(System* sys) {
if (ioLogEnabled) ioLogWindow(sys);
if (gteLogEnabled) gteLogWindow(sys);
if (gpuLogEnabled) gpuLogWindow(sys);
if (showIo) ioWindow(sys);
if (showRamWindow) ramWindow(sys);
if (showVramWindow) vramWindow(sys->gpu.get());
if (showWatchWindow) watchWindow(sys);
Expand All @@ -154,6 +154,7 @@ void renderImgui(System* sys) {
if (showGpuWindow) gpuWindow(sys);
if (showSpuWindow) spuWindow(sys->spu.get());

timersDebug.displayWindows(sys);
cpuDebug.displayWindows(sys);

// Options
Expand Down

0 comments on commit 2a7f248

Please sign in to comment.