mirror of
https://github.com/wheremyfoodat/Panda3DS.git
synced 2025-07-11 01:28:41 +12:00
Update teakra
This commit is contained in:
parent
518b279139
commit
9ef7db63ef
6 changed files with 84 additions and 29 deletions
|
@ -66,6 +66,21 @@ namespace Audio {
|
||||||
|
|
||||||
virtual Type getType() = 0;
|
virtual Type getType() = 0;
|
||||||
virtual void* getRegisters() { return nullptr; }
|
virtual void* getRegisters() { return nullptr; }
|
||||||
|
|
||||||
|
// Read a word from program memory. By default, just perform a regular DSP RAM read for the HLE cores
|
||||||
|
// The LLE cores translate the address, accounting for the way Teak memory is mapped
|
||||||
|
virtual u16 readProgramWord(u32 address) {
|
||||||
|
u8* dspRam = getDspMemory();
|
||||||
|
|
||||||
|
auto readByte = [&](u32 addr) {
|
||||||
|
if (addr >= 256_KB) return u8(0);
|
||||||
|
return dspRam[addr];
|
||||||
|
};
|
||||||
|
|
||||||
|
u16 lsb = u16(readByte(address));
|
||||||
|
u16 msb = u16(readByte(address + 1));
|
||||||
|
return u16(lsb | (msb << 8));
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
std::unique_ptr<DSPCore> makeDSPCore(EmulatorConfig& config, Memory& mem, Scheduler& scheduler, DSPService& dspService);
|
std::unique_ptr<DSPCore> makeDSPCore(EmulatorConfig& config, Memory& mem, Scheduler& scheduler, DSPService& dspService);
|
||||||
|
|
|
@ -92,6 +92,7 @@ namespace Audio {
|
||||||
u8* getDspMemory() override { return teakra.GetDspMemory().data(); }
|
u8* getDspMemory() override { return teakra.GetDspMemory().data(); }
|
||||||
void* getRegisters() override;
|
void* getRegisters() override;
|
||||||
DSPCore::Type getType() override { return DSPCore::Type::Teakra; }
|
DSPCore::Type getType() override { return DSPCore::Type::Teakra; }
|
||||||
|
u16 readProgramWord(u32 address) override { return teakra.ProgramRead(address); }
|
||||||
|
|
||||||
u16 recvData(u32 regId) override { return teakra.RecvData(regId); }
|
u16 recvData(u32 regId) override { return teakra.RecvData(regId); }
|
||||||
bool recvDataIsReady(u32 regId) override { return teakra.RecvDataIsReady(regId); }
|
bool recvDataIsReady(u32 regId) override { return teakra.RecvDataIsReady(regId); }
|
||||||
|
|
|
@ -5,7 +5,6 @@
|
||||||
#include <QScrollBar>
|
#include <QScrollBar>
|
||||||
#include <QWidget>
|
#include <QWidget>
|
||||||
|
|
||||||
#include "capstone.hpp"
|
|
||||||
#include "emulator.hpp"
|
#include "emulator.hpp"
|
||||||
#include "panda_qt/disabled_widget_overlay.hpp"
|
#include "panda_qt/disabled_widget_overlay.hpp"
|
||||||
|
|
||||||
|
@ -20,10 +19,10 @@ class DSPDebugger : public QWidget {
|
||||||
QLineEdit* addressInput;
|
QLineEdit* addressInput;
|
||||||
|
|
||||||
DisabledWidgetOverlay* disabledOverlay;
|
DisabledWidgetOverlay* disabledOverlay;
|
||||||
|
DisabledWidgetOverlay* disabledRegisterEditOverlay;
|
||||||
|
|
||||||
bool enabled = false;
|
bool enabled = false;
|
||||||
bool followPC = false;
|
bool followPC = false;
|
||||||
Common::CapstoneDisassembler disassembler;
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
DSPDebugger(Emulator* emulator, QWidget* parent = nullptr);
|
DSPDebugger(Emulator* emulator, QWidget* parent = nullptr);
|
||||||
|
|
|
@ -69,7 +69,7 @@ CPUDebugger::CPUDebugger(Emulator* emulator, QWidget* parent) : emu(emulator), d
|
||||||
|
|
||||||
// Setup overlay for when the widget is disabled
|
// Setup overlay for when the widget is disabled
|
||||||
disabledOverlay = new DisabledWidgetOverlay(this, tr("Pause the emulator to use the CPU Debugger"));
|
disabledOverlay = new DisabledWidgetOverlay(this, tr("Pause the emulator to use the CPU Debugger"));
|
||||||
disabledOverlay->resize(size()); // Fill the whole screen
|
disabledOverlay->resize(size()); // Fill the whole widget
|
||||||
disabledOverlay->raise();
|
disabledOverlay->raise();
|
||||||
disabledOverlay->hide();
|
disabledOverlay->hide();
|
||||||
|
|
||||||
|
|
|
@ -9,7 +9,6 @@
|
||||||
#include <QPlainTextEdit>
|
#include <QPlainTextEdit>
|
||||||
#include <QPushButton>
|
#include <QPushButton>
|
||||||
#include <limits>
|
#include <limits>
|
||||||
#include <span>
|
|
||||||
#include <utility>
|
#include <utility>
|
||||||
|
|
||||||
#include "audio/dsp_core.hpp"
|
#include "audio/dsp_core.hpp"
|
||||||
|
@ -35,7 +34,7 @@ static std::pair<int, int> getVisibleLineRange(QListWidget* listWidget, QScrollB
|
||||||
return {firstLine, lineCount};
|
return {firstLine, lineCount};
|
||||||
}
|
}
|
||||||
|
|
||||||
DSPDebugger::DSPDebugger(Emulator* emulator, QWidget* parent) : emu(emulator), disassembler(CS_ARCH_ARM, CS_MODE_ARM), QWidget(parent, Qt::Window) {
|
DSPDebugger::DSPDebugger(Emulator* emulator, QWidget* parent) : emu(emulator), QWidget(parent, Qt::Window) {
|
||||||
setWindowTitle(tr("DSP debugger"));
|
setWindowTitle(tr("DSP debugger"));
|
||||||
resize(1000, 600);
|
resize(1000, 600);
|
||||||
|
|
||||||
|
@ -74,12 +73,18 @@ DSPDebugger::DSPDebugger(Emulator* emulator, QWidget* parent) : emu(emulator), d
|
||||||
registerTextEdit->setMaximumWidth(800);
|
registerTextEdit->setMaximumWidth(800);
|
||||||
gridLayout->addWidget(registerTextEdit, 1, 2);
|
gridLayout->addWidget(registerTextEdit, 1, 2);
|
||||||
|
|
||||||
// Setup overlay for when the widget is disabled
|
// Setup overlay for when the debugger is disabled
|
||||||
disabledOverlay = new DisabledWidgetOverlay(this, tr("Pause the emulator to use the DSP Debugger"));
|
disabledOverlay = new DisabledWidgetOverlay(this, tr("Pause the emulator to use the DSP Debugger"));
|
||||||
disabledOverlay->resize(size()); // Fill the whole screen
|
disabledOverlay->resize(size()); // Fill the whole widget
|
||||||
disabledOverlay->raise();
|
disabledOverlay->raise();
|
||||||
disabledOverlay->hide();
|
disabledOverlay->hide();
|
||||||
|
|
||||||
|
// Setup overlay for when the register widget is disabled
|
||||||
|
disabledRegisterEditOverlay = new DisabledWidgetOverlay(registerTextEdit, tr("Register view is only supported\nwith LLE DSP"));
|
||||||
|
disabledRegisterEditOverlay->resize(registerTextEdit->size());
|
||||||
|
disabledRegisterEditOverlay->raise();
|
||||||
|
disabledRegisterEditOverlay->hide();
|
||||||
|
|
||||||
// Use a monospace font for the disassembly to align it
|
// Use a monospace font for the disassembly to align it
|
||||||
QFont mono_font = QFont("Courier New");
|
QFont mono_font = QFont("Courier New");
|
||||||
mono_font.setStyleHint(QFont::Monospace);
|
mono_font.setStyleHint(QFont::Monospace);
|
||||||
|
@ -155,21 +160,10 @@ void DSPDebugger::updateDisasm() {
|
||||||
disasmListWidget->clear();
|
disasmListWidget->clear();
|
||||||
|
|
||||||
auto [firstLine, lineCount] = getVisibleLineRange(disasmListWidget, verticalScrollBar);
|
auto [firstLine, lineCount] = getVisibleLineRange(disasmListWidget, verticalScrollBar);
|
||||||
const u32 startPC = (firstLine + 1) & ~1; // Align PC to 2 bytes
|
const u32 startPC = firstLine;
|
||||||
|
|
||||||
auto DSP = emu->getDSP();
|
auto dsp = emu->getDSP();
|
||||||
auto dspRam = DSP->getDspMemory();
|
auto dspRam = dsp->getDspMemory();
|
||||||
auto readByte = [&](u32 addr) {
|
|
||||||
if (addr >= 256_KB) return u8(0);
|
|
||||||
|
|
||||||
return dspRam[addr];
|
|
||||||
};
|
|
||||||
|
|
||||||
auto readWord = [&](u32 addr) {
|
|
||||||
u16 lsb = u16(readByte(addr));
|
|
||||||
u16 msb = u16(readByte(addr + 1));
|
|
||||||
return u16(lsb | (msb << 8));
|
|
||||||
};
|
|
||||||
|
|
||||||
auto& mem = emu->getMemory();
|
auto& mem = emu->getMemory();
|
||||||
u32 pc = getPC();
|
u32 pc = getPC();
|
||||||
|
@ -177,10 +171,10 @@ void DSPDebugger::updateDisasm() {
|
||||||
std::string disassembly;
|
std::string disassembly;
|
||||||
|
|
||||||
for (u32 addr = startPC, instructionCount = 0; instructionCount < lineCount; instructionCount++) {
|
for (u32 addr = startPC, instructionCount = 0; instructionCount < lineCount; instructionCount++) {
|
||||||
const u16 instruction = readWord(addr);
|
const u16 instruction = dsp->readProgramWord(addr);
|
||||||
const bool needExpansion = Teakra::Disassembler::NeedExpansion(instruction);
|
const bool needExpansion = Teakra::Disassembler::NeedExpansion(instruction);
|
||||||
|
|
||||||
const u16 expansion = needExpansion ? readWord(addr + 2) : u16(0);
|
const u16 expansion = needExpansion ? dsp->readProgramWord(addr + 2) : u16(0);
|
||||||
|
|
||||||
std::string disassembly = Teakra::Disassembler::Do(instruction, expansion);
|
std::string disassembly = Teakra::Disassembler::Do(instruction, expansion);
|
||||||
disassembly = fmt::format("{:08X} | {}", addr, disassembly);
|
disassembly = fmt::format("{:08X} | {}", addr, disassembly);
|
||||||
|
@ -199,11 +193,11 @@ void DSPDebugger::updateDisasm() {
|
||||||
|
|
||||||
// This is only supported on the Teakra core, as other cores don't actually have a register contexts
|
// This is only supported on the Teakra core, as other cores don't actually have a register contexts
|
||||||
u32 DSPDebugger::getPC() {
|
u32 DSPDebugger::getPC() {
|
||||||
auto DSP = emu->getDSP();
|
auto dsp = emu->getDSP();
|
||||||
auto dspType = DSP->getType();
|
auto dspType = dsp->getType();
|
||||||
|
|
||||||
if (dspType == Audio::DSPCore::Type::Teakra) {
|
if (dspType == Audio::DSPCore::Type::Teakra) {
|
||||||
auto regs = (Teakra::RegisterState*)DSP->getRegisters();
|
auto regs = (Teakra::RegisterState*)dsp->getRegisters();
|
||||||
return regs->pc | (u32(regs->prpage) << 18);
|
return regs->pc | (u32(regs->prpage) << 18);
|
||||||
} else {
|
} else {
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -215,7 +209,52 @@ void DSPDebugger::scrollToPC() {
|
||||||
verticalScrollBar->setValue(pc);
|
verticalScrollBar->setValue(pc);
|
||||||
}
|
}
|
||||||
|
|
||||||
void DSPDebugger::updateRegisters() { registerTextEdit->setPlainText(QString::fromStdString("")); }
|
void DSPDebugger::updateRegisters() {
|
||||||
|
auto dsp = emu->getDSP();
|
||||||
|
auto dspType = dsp->getType();
|
||||||
|
|
||||||
|
if (dspType == Audio::DSPCore::Type::Teakra) {
|
||||||
|
std::string text = "";
|
||||||
|
text.reserve(4096);
|
||||||
|
|
||||||
|
auto regs = (Teakra::RegisterState*)dsp->getRegisters();
|
||||||
|
text += fmt::format(
|
||||||
|
"PC: 0x{:05X}\nProgram Page: 0x{:01X}\nStack Pointer: 0x{:04X}\n", regs->pc & 0x3FFFF, regs->prpage & 0xF, regs->sp
|
||||||
|
);
|
||||||
|
|
||||||
|
text += "\nGeneral Purpose Registers\n";
|
||||||
|
for (int i = 0; i < 8; i++) {
|
||||||
|
text += fmt::format("r{:01d}: 0x{:08X}\n", i, regs->r[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
text += "\nAccumulators (40-bit)\n";
|
||||||
|
text += fmt::format("a0: 0x{:010X}\n", regs->a[0] & 0xFFFFFFFFFFull);
|
||||||
|
text += fmt::format("a1: 0x{:010X}\n", regs->a[1] & 0xFFFFFFFFFFull);
|
||||||
|
text += fmt::format("b0: 0x{:010X}\n", regs->b[0] & 0xFFFFFFFFFFull);
|
||||||
|
text += fmt::format("b1: 0x{:010X}\n", regs->b[1] & 0xFFFFFFFFFFull);
|
||||||
|
text += fmt::format("a1s: 0x{:010X}\n", regs->a1s & 0xFFFFFFFFFFull);
|
||||||
|
text += fmt::format("b1s: 0x{:010X}\n", regs->b1s & 0xFFFFFFFFFFull);
|
||||||
|
|
||||||
|
text += "\nMultiplication Unit\n";
|
||||||
|
text += fmt::format("x0: 0x{:04X}\n", regs->x[0]);
|
||||||
|
text += fmt::format("x1: 0x{:04X}\n", regs->x[1]);
|
||||||
|
text += fmt::format("y0: 0x{:04X}\n", regs->y[0]);
|
||||||
|
text += fmt::format("y1: 0x{:04X}\n", regs->y[1]);
|
||||||
|
text += fmt::format("p0: 0x{:08X}\n", regs->p[0]);
|
||||||
|
text += fmt::format("p1: 0x{:08X}\n", regs->p[1]);
|
||||||
|
|
||||||
|
text += "\nOther Registers\n";
|
||||||
|
text += fmt::format("mixp: 0x{:04X}\n", regs->mixp);
|
||||||
|
text += fmt::format("sv: 0x{:04X}\n", regs->sv);
|
||||||
|
text += fmt::format("Shift mode: {}\n", regs->s ? "Logic" : "Arithmetic");
|
||||||
|
|
||||||
|
registerTextEdit->setPlainText(QString::fromStdString(text));
|
||||||
|
disabledRegisterEditOverlay->hide();
|
||||||
|
} else {
|
||||||
|
registerTextEdit->setPlainText(QString::fromStdString(""));
|
||||||
|
disabledRegisterEditOverlay->show();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
bool DSPDebugger::eventFilter(QObject* obj, QEvent* event) {
|
bool DSPDebugger::eventFilter(QObject* obj, QEvent* event) {
|
||||||
// Forward scroll events from the list widget to the scrollbar
|
// Forward scroll events from the list widget to the scrollbar
|
||||||
|
@ -255,7 +294,8 @@ void DSPDebugger::keyPressEvent(QKeyEvent* event) {
|
||||||
void DSPDebugger::resizeEvent(QResizeEvent* event) {
|
void DSPDebugger::resizeEvent(QResizeEvent* event) {
|
||||||
QWidget::resizeEvent(event);
|
QWidget::resizeEvent(event);
|
||||||
disabledOverlay->resize(event->size());
|
disabledOverlay->resize(event->size());
|
||||||
verticalScrollBar->setPageStep(getLinesInViewport(disasmListWidget));
|
disabledRegisterEditOverlay->resize(registerTextEdit->size());
|
||||||
|
|
||||||
|
verticalScrollBar->setPageStep(getLinesInViewport(disasmListWidget));
|
||||||
update();
|
update();
|
||||||
}
|
}
|
2
third_party/teakra
vendored
2
third_party/teakra
vendored
|
@ -1 +1 @@
|
||||||
Subproject commit 01db7cdd00aabcce559a8dddce8798dabb71949b
|
Subproject commit e34a86799efd65e3c44b915a4d65b3514d34df4f
|
Loading…
Add table
Add a link
Reference in a new issue