From 415bf7b0a4756be550afda146b1bb49ca73f75ef Mon Sep 17 00:00:00 2001 From: wheremyfoodat <44909372+wheremyfoodat@users.noreply.github.com> Date: Tue, 8 Jul 2025 01:35:53 +0300 Subject: [PATCH 1/6] Initial DSP debugger work --- CMakeLists.txt | 11 +- include/audio/dsp_core.hpp | 2 + include/audio/teakra_core.hpp | 1 + include/emulator.hpp | 1 + include/panda_qt/dsp_debugger.hpp | 45 ++++++ include/panda_qt/main_window.hpp | 2 + src/core/audio/teakra_core.cpp | 6 + src/panda_qt/dsp_debugger.cpp | 242 ++++++++++++++++++++++++++++++ src/panda_qt/main_window.cpp | 4 + 9 files changed, 309 insertions(+), 5 deletions(-) create mode 100644 include/panda_qt/dsp_debugger.hpp create mode 100644 src/panda_qt/dsp_debugger.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index a0de7271..f0acd3bc 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -314,7 +314,7 @@ else() message(FATAL_ERROR "Currently unsupported CPU architecture") endif() -add_subdirectory(third_party/teakra EXCLUDE_FROM_ALL) +add_subdirectory(third_party/teakra) add_subdirectory(third_party/fdk-aac) set(CAPSTONE_ARCHITECTURE_DEFAULT OFF) @@ -686,8 +686,8 @@ set(ALL_SOURCES ${SOURCE_FILES} ${FS_SOURCE_FILES} ${CRYPTO_SOURCE_FILES} ${KERN ${AUDIO_SOURCE_FILES} ${HEADER_FILES} ${FRONTEND_HEADER_FILES}) target_sources(AlberCore PRIVATE ${ALL_SOURCES}) -target_link_libraries(AlberCore PRIVATE dynarmic glad resources_console_fonts teakra fdk-aac) -target_link_libraries(AlberCore PUBLIC glad capstone fmt::fmt) +target_link_libraries(AlberCore PRIVATE dynarmic glad resources_console_fonts fdk-aac) +target_link_libraries(AlberCore PUBLIC glad capstone fmt::fmt teakra) if(ENABLE_DISCORD_RPC AND NOT ANDROID) target_compile_definitions(AlberCore PUBLIC "PANDA3DS_ENABLE_DISCORD_RPC=1") @@ -733,12 +733,13 @@ if(NOT BUILD_HYDRA_CORE AND NOT BUILD_LIBRETRO_CORE) set(FRONTEND_SOURCE_FILES src/panda_qt/main.cpp src/panda_qt/screen.cpp src/panda_qt/main_window.cpp src/panda_qt/about_window.cpp src/panda_qt/config_window.cpp src/panda_qt/zep.cpp src/panda_qt/text_editor.cpp src/panda_qt/cheats_window.cpp src/panda_qt/mappings.cpp src/panda_qt/patch_window.cpp src/panda_qt/elided_label.cpp src/panda_qt/shader_editor.cpp src/panda_qt/translations.cpp - src/panda_qt/thread_debugger.cpp src/panda_qt/cpu_debugger.cpp + src/panda_qt/thread_debugger.cpp src/panda_qt/cpu_debugger.cpp src/panda_qt/dsp_debugger.cpp ) set(FRONTEND_HEADER_FILES include/panda_qt/screen.hpp include/panda_qt/main_window.hpp include/panda_qt/about_window.hpp include/panda_qt/config_window.hpp include/panda_qt/text_editor.hpp include/panda_qt/cheats_window.hpp include/panda_qt/patch_window.hpp include/panda_qt/elided_label.hpp include/panda_qt/shader_editor.hpp - include/panda_qt/thread_debugger.hpp include/panda_qt/cpu_debugger.hpp include/panda_qt/disabled_widget_overlay.hpp + include/panda_qt/thread_debugger.hpp include/panda_qt/cpu_debugger.hpp include/panda_qt/dsp_debugger.hpp + include/panda_qt/disabled_widget_overlay.hpp ) source_group("Source Files\\Qt" FILES ${FRONTEND_SOURCE_FILES}) diff --git a/include/audio/dsp_core.hpp b/include/audio/dsp_core.hpp index f180e717..00c45527 100644 --- a/include/audio/dsp_core.hpp +++ b/include/audio/dsp_core.hpp @@ -63,6 +63,8 @@ namespace Audio { Samples& getSamples() { return sampleBuffer; } virtual void setAudioEnabled(bool enable) { audioEnabled = enable; } + + virtual u32 getPC() { return 0; } }; std::unique_ptr makeDSPCore(EmulatorConfig& config, Memory& mem, Scheduler& scheduler, DSPService& dspService); diff --git a/include/audio/teakra_core.hpp b/include/audio/teakra_core.hpp index a9d39414..5b4c2f8c 100644 --- a/include/audio/teakra_core.hpp +++ b/include/audio/teakra_core.hpp @@ -90,6 +90,7 @@ namespace Audio { void setAudioEnabled(bool enable) override; u8* getDspMemory() override { return teakra.GetDspMemory().data(); } + u32 getPC() override; u16 recvData(u32 regId) override { return teakra.RecvData(regId); } bool recvDataIsReady(u32 regId) override { return teakra.RecvDataIsReady(regId); } diff --git a/include/emulator.hpp b/include/emulator.hpp index 51242494..bed01937 100644 --- a/include/emulator.hpp +++ b/include/emulator.hpp @@ -126,6 +126,7 @@ class Emulator { Memory& getMemory() { return memory; } Kernel& getKernel() { return kernel; } Scheduler& getScheduler() { return scheduler; } + Audio::DSPCore* getDSP() { return dsp.get(); } EmulatorConfig& getConfig() { return config; } Cheats& getCheats() { return cheats; } diff --git a/include/panda_qt/dsp_debugger.hpp b/include/panda_qt/dsp_debugger.hpp new file mode 100644 index 00000000..10f3acb1 --- /dev/null +++ b/include/panda_qt/dsp_debugger.hpp @@ -0,0 +1,45 @@ +#pragma once +#include +#include +#include +#include +#include + +#include "capstone.hpp" +#include "emulator.hpp" +#include "panda_qt/disabled_widget_overlay.hpp" + +class DSPDebugger : public QWidget { + Q_OBJECT + Emulator* emu; + + QListWidget* disasmListWidget; + QScrollBar* verticalScrollBar; + QPlainTextEdit* registerTextEdit; + QTimer* updateTimer; + QLineEdit* addressInput; + + DisabledWidgetOverlay* disabledOverlay; + + bool enabled = false; + bool followPC = false; + Common::CapstoneDisassembler disassembler; + + public: + DSPDebugger(Emulator* emulator, QWidget* parent = nullptr); + void enable(); + void disable(); + + private: + // Update the state of the disassembler. Qt events should always call update, not updateDisasm/updateRegister + // As update properly handles thread safety + void update(); + void updateDisasm(); + void updateRegisters(); + void scrollToPC(); + + bool eventFilter(QObject* obj, QEvent* event) override; + void showEvent(QShowEvent* event) override; + void resizeEvent(QResizeEvent* event) override; + void keyPressEvent(QKeyEvent* event) override; +}; diff --git a/include/panda_qt/main_window.hpp b/include/panda_qt/main_window.hpp index c5032a87..80b4a7f1 100644 --- a/include/panda_qt/main_window.hpp +++ b/include/panda_qt/main_window.hpp @@ -18,6 +18,7 @@ #include "panda_qt/cheats_window.hpp" #include "panda_qt/config_window.hpp" #include "panda_qt/cpu_debugger.hpp" +#include "panda_qt/dsp_debugger.hpp" #include "panda_qt/patch_window.hpp" #include "panda_qt/screen.hpp" #include "panda_qt/shader_editor.hpp" @@ -112,6 +113,7 @@ class MainWindow : public QMainWindow { PatchWindow* patchWindow; ShaderEditorWindow* shaderEditor; CPUDebugger* cpuDebugger; + DSPDebugger* dspDebugger; ThreadDebugger* threadDebugger; // We use SDL's game controller API since it's the sanest API that supports as many controllers as possible diff --git a/src/core/audio/teakra_core.cpp b/src/core/audio/teakra_core.cpp index c9c92902..7b73d5cd 100644 --- a/src/core/audio/teakra_core.cpp +++ b/src/core/audio/teakra_core.cpp @@ -7,6 +7,10 @@ #include "services/dsp.hpp" +#undef Assert +#undef UNREACHABLE +#include "teakra/impl/register.h" + using namespace Audio; struct Dsp1 { @@ -343,3 +347,5 @@ void TeakraDSP::unloadComponent() { teakra.RecvData(2); running = false; } + +u32 TeakraDSP::getPC() { return teakra.GetRegisterState().pc; } \ No newline at end of file diff --git a/src/panda_qt/dsp_debugger.cpp b/src/panda_qt/dsp_debugger.cpp new file mode 100644 index 00000000..326c8a2b --- /dev/null +++ b/src/panda_qt/dsp_debugger.cpp @@ -0,0 +1,242 @@ +#include "panda_qt/dsp_debugger.hpp" + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "teakra/disassembler.h" + +// TODO: Make this actually thread-safe by having it only work when paused +static int getLinesInViewport(QListWidget* listWidget) { + auto viewportHeight = listWidget->viewport()->height(); + QFontMetrics fm = QFontMetrics(listWidget->font()); + auto lineHeight = fm.height(); + + return int(viewportHeight / lineHeight); +} + +static std::pair getVisibleLineRange(QListWidget* listWidget, QScrollBar* scrollBar) { + int firstLine = scrollBar->value(); + int lineCount = getLinesInViewport(listWidget); + + return {firstLine, lineCount}; +} + +DSPDebugger::DSPDebugger(Emulator* emulator, QWidget* parent) : emu(emulator), disassembler(CS_ARCH_ARM, CS_MODE_ARM), QWidget(parent, Qt::Window) { + setWindowTitle(tr("DSP debugger")); + resize(1000, 600); + + QGridLayout* gridLayout = new QGridLayout(this); + QHBoxLayout* horizontalLayout = new QHBoxLayout(); + + // Set up the top line widgets + QPushButton* goToAddressButton = new QPushButton(tr("Go to address"), this); + QPushButton* goToPCButton = new QPushButton(tr("Go to PC"), this); + QCheckBox* followPCCheckBox = new QCheckBox(tr("Follow PC"), this); + addressInput = new QLineEdit(this); + + horizontalLayout->addWidget(goToAddressButton); + horizontalLayout->addWidget(goToPCButton); + horizontalLayout->addWidget(followPCCheckBox); + horizontalLayout->addWidget(addressInput); + + followPCCheckBox->setChecked(followPC); + connect(followPCCheckBox, &QCheckBox::toggled, this, [&](bool checked) { followPC = checked; }); + + addressInput->setPlaceholderText(tr("Address to jump to")); + addressInput->setMaximumWidth(150); + + gridLayout->addLayout(horizontalLayout, 0, 0); + + // Disassembly list on the left, scrollbar in the middle, register view on the right + disasmListWidget = new QListWidget(this); + gridLayout->addWidget(disasmListWidget, 1, 0); + + verticalScrollBar = new QScrollBar(Qt::Vertical, this); + gridLayout->addWidget(verticalScrollBar, 1, 1); + + registerTextEdit = new QPlainTextEdit(this); + registerTextEdit->setEnabled(true); + registerTextEdit->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); + registerTextEdit->setMaximumWidth(800); + gridLayout->addWidget(registerTextEdit, 1, 2); + + // Setup overlay for when the widget is disabled + disabledOverlay = new DisabledWidgetOverlay(this, tr("Pause the emulator to use the DSP Debugger")); + disabledOverlay->resize(size()); // Fill the whole screen + disabledOverlay->raise(); + disabledOverlay->hide(); + + // Use a monospace font for the disassembly to align it + QFont mono_font = QFont("Courier New"); + mono_font.setStyleHint(QFont::Monospace); + disasmListWidget->setFont(mono_font); + registerTextEdit->setFont(mono_font); + + // Forward scrolling from the list widget to our scrollbar + disasmListWidget->installEventFilter(this); + + // Annoyingly, due to a Qt limitation we can't set it to U32_MAX + verticalScrollBar->setRange(0, std::numeric_limits::max()); + verticalScrollBar->setSingleStep(8); + verticalScrollBar->setPageStep(getLinesInViewport(disasmListWidget)); + verticalScrollBar->show(); + connect(verticalScrollBar, &QScrollBar::valueChanged, this, &DSPDebugger::updateDisasm); + registerTextEdit->setReadOnly(true); + + connect(goToPCButton, &QPushButton::clicked, this, [&]() { scrollToPC(); }); + + // We have a QTimer that triggers every 500ms to update our widget when it's active + updateTimer = new QTimer(this); + connect(updateTimer, &QTimer::timeout, this, &DSPDebugger::update); + + // Go to address when the "Go to address" button is pressed, or when we press enter inside the address input box + connect(goToAddressButton, &QPushButton::clicked, this, [&]() { + QString text = addressInput->text().trimmed(); + + bool validAddr = false; + u32 addr = text.toUInt(&validAddr, 16); // Parse address as hex + if (validAddr) { + verticalScrollBar->setValue(addr); + } else { + addressInput->setText(tr("Invalid hexadecimal address")); + } + }); + connect(addressInput, &QLineEdit::returnPressed, goToAddressButton, &QPushButton::click); + + disable(); + hide(); +} + +void DSPDebugger::enable() { + enabled = true; + + disabledOverlay->hide(); + scrollToPC(); + + // Update the widget every 500ms + updateTimer->start(500); + update(); +} + +void DSPDebugger::disable() { + enabled = false; + + updateTimer->stop(); + disabledOverlay->show(); +} + +void DSPDebugger::update() { + if (enabled) { + if (followPC) { + scrollToPC(); + } + + updateDisasm(); + updateRegisters(); + } +} + +void DSPDebugger::updateDisasm() { + int currentRow = disasmListWidget->currentRow(); + disasmListWidget->clear(); + + auto [firstLine, lineCount] = getVisibleLineRange(disasmListWidget, verticalScrollBar); + const u32 startPC = (firstLine + 1) & ~1; // Align PC to 2 bytes + + auto DSP = emu->getDSP(); + 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(); + u32 pc = DSP->getPC(); + + std::string disassembly; + + for (u32 addr = startPC, instructionCount = 0; instructionCount < lineCount; instructionCount++) { + const u16 instruction = readWord(addr); + const bool needExpansion = Teakra::Disassembler::NeedExpansion(instruction); + + const u16 expansion = needExpansion ? readWord(addr + 2) : u16(0); + addr += needExpansion ? sizeof(u32) : sizeof(u16); + + std::string disassembly = Teakra::Disassembler::Do(instruction, expansion); + disassembly = fmt::format("{:08X} | {}", addr, disassembly); + + QListWidgetItem* item = new QListWidgetItem(QString::fromStdString(disassembly)); + if (addr == pc) { + item->setBackground(Qt::darkGreen); + } + disasmListWidget->addItem(item); + } + + disasmListWidget->setCurrentRow(currentRow); +} + +void DSPDebugger::scrollToPC() { + u32 pc = emu->getDSP()->getPC(); + verticalScrollBar->setValue(pc); +} + +void DSPDebugger::updateRegisters() { registerTextEdit->setPlainText(QString::fromStdString("")); } + +bool DSPDebugger::eventFilter(QObject* obj, QEvent* event) { + // Forward scroll events from the list widget to the scrollbar + if (obj == disasmListWidget && event->type() == QEvent::Wheel) { + QWheelEvent* wheelEvent = (QWheelEvent*)event; + + int wheelSteps = wheelEvent->angleDelta().y() / 60; + int newScrollValue = verticalScrollBar->value() - wheelSteps; + newScrollValue = qBound(verticalScrollBar->minimum(), newScrollValue, verticalScrollBar->maximum()); + verticalScrollBar->setValue(newScrollValue); + + return true; + } + + return QWidget::eventFilter(obj, event); +} + +void DSPDebugger::showEvent(QShowEvent* event) { + QWidget::showEvent(event); + + enable(); +} + +// Scroll 1 instruction up or down when the arrow keys are pressed and we're at the edge of the disassembly list +void DSPDebugger::keyPressEvent(QKeyEvent* event) { + constexpr usize instructionSize = sizeof(u16); + + if (event->key() == Qt::Key_Up) { + verticalScrollBar->setValue(verticalScrollBar->value() - instructionSize); + } else if (event->key() == Qt::Key_Down) { + verticalScrollBar->setValue(verticalScrollBar->value() + instructionSize); + } else { + QWidget::keyPressEvent(event); + } +} + +void DSPDebugger::resizeEvent(QResizeEvent* event) { + QWidget::resizeEvent(event); + disabledOverlay->resize(event->size()); + verticalScrollBar->setPageStep(getLinesInViewport(disasmListWidget)); + + update(); +} \ No newline at end of file diff --git a/src/panda_qt/main_window.cpp b/src/panda_qt/main_window.cpp index e5a2795d..e8971878 100644 --- a/src/panda_qt/main_window.cpp +++ b/src/panda_qt/main_window.cpp @@ -9,6 +9,7 @@ #include "cheats.hpp" #include "input_mappings.hpp" +#include "panda_qt/dsp_debugger.hpp" #include "sdl_sensors.hpp" #include "services/dsp.hpp" #include "version.hpp" @@ -67,6 +68,7 @@ MainWindow::MainWindow(QApplication* app, QWidget* parent) : QMainWindow(parent) auto patchWindowAction = toolsMenu->addAction(tr("Open Patch Window")); auto shaderEditorAction = toolsMenu->addAction(tr("Open Shader Editor")); auto cpuDebuggerAction = toolsMenu->addAction(tr("Open CPU Debugger")); + auto dspDebuggerAction = toolsMenu->addAction(tr("Open DSP Debugger")); auto threadDebuggerAction = toolsMenu->addAction(tr("Open Thread Debugger")); auto dumpDspFirmware = toolsMenu->addAction(tr("Dump loaded DSP firmware")); @@ -76,6 +78,7 @@ MainWindow::MainWindow(QApplication* app, QWidget* parent) : QMainWindow(parent) connect(cheatsEditorAction, &QAction::triggered, this, [this]() { cheatsEditor->show(); }); connect(patchWindowAction, &QAction::triggered, this, [this]() { patchWindow->show(); }); connect(cpuDebuggerAction, &QAction::triggered, this, [this]() { cpuDebugger->show(); }); + connect(dspDebuggerAction, &QAction::triggered, this, [this]() { dspDebugger->show(); }); connect(threadDebuggerAction, &QAction::triggered, this, [this]() { threadDebugger->show(); }); connect(dumpDspFirmware, &QAction::triggered, this, &MainWindow::dumpDspFirmware); @@ -97,6 +100,7 @@ MainWindow::MainWindow(QApplication* app, QWidget* parent) : QMainWindow(parent) shaderEditor = new ShaderEditorWindow(this, "shader.glsl", ""); threadDebugger = new ThreadDebugger(emu, this); cpuDebugger = new CPUDebugger(emu, this); + dspDebugger = new DSPDebugger(emu, this); shaderEditor->setEnable(emu->getRenderer()->supportsShaderReload()); if (shaderEditor->supported) { From c872cfb507e984afd32c202a7964438a835dace2 Mon Sep 17 00:00:00 2001 From: wheremyfoodat <44909372+wheremyfoodat@users.noreply.github.com> Date: Tue, 8 Jul 2025 02:57:57 +0300 Subject: [PATCH 2/6] Fix PC in disassembly --- src/panda_qt/dsp_debugger.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/panda_qt/dsp_debugger.cpp b/src/panda_qt/dsp_debugger.cpp index 326c8a2b..46aa5b8a 100644 --- a/src/panda_qt/dsp_debugger.cpp +++ b/src/panda_qt/dsp_debugger.cpp @@ -176,7 +176,6 @@ void DSPDebugger::updateDisasm() { const bool needExpansion = Teakra::Disassembler::NeedExpansion(instruction); const u16 expansion = needExpansion ? readWord(addr + 2) : u16(0); - addr += needExpansion ? sizeof(u32) : sizeof(u16); std::string disassembly = Teakra::Disassembler::Do(instruction, expansion); disassembly = fmt::format("{:08X} | {}", addr, disassembly); @@ -185,7 +184,9 @@ void DSPDebugger::updateDisasm() { if (addr == pc) { item->setBackground(Qt::darkGreen); } + disasmListWidget->addItem(item); + addr += needExpansion ? sizeof(u32) : sizeof(u16); } disasmListWidget->setCurrentRow(currentRow); From 69bbb13d5d8846c7ee8a54cda387a389641c5956 Mon Sep 17 00:00:00 2001 From: wheremyfoodat <44909372+wheremyfoodat@users.noreply.github.com> Date: Tue, 8 Jul 2025 17:42:58 +0300 Subject: [PATCH 3/6] Make HLE DSP load binaries too --- CMakeLists.txt | 2 +- include/audio/dsp_binary.hpp | 29 +++++++++++++++++++++++++++++ src/core/audio/hle_core.cpp | 31 +++++++++++++++++++++++++++++++ src/core/audio/teakra_core.cpp | 28 +--------------------------- 4 files changed, 62 insertions(+), 28 deletions(-) create mode 100644 include/audio/dsp_binary.hpp diff --git a/CMakeLists.txt b/CMakeLists.txt index f0acd3bc..9d8aba7e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -416,7 +416,7 @@ set(HEADER_FILES include/emulator.hpp include/helpers.hpp include/termcolor.hpp include/fs/archive_twl_sound.hpp include/fs/archive_card_spi.hpp include/services/ns.hpp include/audio/audio_device.hpp include/audio/audio_device_interface.hpp include/audio/libretro_audio_device.hpp include/services/ir/ir_types.hpp include/services/ir/ir_device.hpp include/services/ir/circlepad_pro.hpp include/services/service_intercept.hpp - include/screen_layout.hpp include/services/service_map.hpp + include/screen_layout.hpp include/services/service_map.hpp include/audio/dsp_binary.hpp ) if(IOS) diff --git a/include/audio/dsp_binary.hpp b/include/audio/dsp_binary.hpp new file mode 100644 index 00000000..6345903a --- /dev/null +++ b/include/audio/dsp_binary.hpp @@ -0,0 +1,29 @@ +#pragma once +#include "helpers.hpp" + +struct Dsp1 { + // All sizes are in bytes unless otherwise specified + u8 signature[0x100]; + u8 magic[4]; + u32 size; + u8 codeMemLayout; + u8 dataMemLayout; + u8 pad[3]; + u8 specialType; + u8 segmentCount; + u8 flags; + u32 specialStart; + u32 specialSize; + u64 zeroBits; + + struct Segment { + u32 offs; // Offset of the segment data + u32 dspAddr; // Start of the segment in 16-bit units + u32 size; + u8 pad[3]; + u8 type; + u8 hash[0x20]; + }; + + Segment segments[10]; +}; diff --git a/src/core/audio/hle_core.cpp b/src/core/audio/hle_core.cpp index 73d39adb..97a6211e 100644 --- a/src/core/audio/hle_core.cpp +++ b/src/core/audio/hle_core.cpp @@ -7,6 +7,7 @@ #include #include "audio/aac_decoder.hpp" +#include "audio/dsp_binary.hpp" #include "audio/dsp_simd.hpp" #include "config.hpp" #include "services/dsp.hpp" @@ -89,6 +90,36 @@ namespace Audio { Helpers::warn("Loading DSP component when already loaded"); } + // We load the DSP binary into DSP memory even though we don't use it in HLE, so that we can + // still see the DSP code in the DSP debugger + u8* dspCode = dspRam.rawMemory.data(); + u8* dspData = dspCode + 0x40000; + + Dsp1 dsp1; + std::memcpy(&dsp1, data.data(), sizeof(dsp1)); + + // TODO: verify DSP1 signature & hashes + // Load DSP segments to DSP RAM + for (uint i = 0; i < dsp1.segmentCount; i++) { + auto& segment = dsp1.segments[i]; + u32 addr = segment.dspAddr << 1; + u8* src = data.data() + segment.offs; + u8* dst = nullptr; + + switch (segment.type) { + case 0: + case 1: dst = dspCode + addr; break; + default: dst = dspData + addr; break; + } + + std::memcpy(dst, src, segment.size); + } + + bool loadSpecialSegment = (dsp1.flags >> 1) & 0x1; + if (loadSpecialSegment) { + log("LoadComponent: special segment not supported"); + } + loaded = true; scheduler.addEvent(Scheduler::EventType::RunDSP, scheduler.currentTimestamp + Audio::cyclesPerFrame); } diff --git a/src/core/audio/teakra_core.cpp b/src/core/audio/teakra_core.cpp index 7b73d5cd..e1476b83 100644 --- a/src/core/audio/teakra_core.cpp +++ b/src/core/audio/teakra_core.cpp @@ -5,6 +5,7 @@ #include #include +#include "audio/dsp_binary.hpp" #include "services/dsp.hpp" #undef Assert @@ -13,33 +14,6 @@ using namespace Audio; -struct Dsp1 { - // All sizes are in bytes unless otherwise specified - u8 signature[0x100]; - u8 magic[4]; - u32 size; - u8 codeMemLayout; - u8 dataMemLayout; - u8 pad[3]; - u8 specialType; - u8 segmentCount; - u8 flags; - u32 specialStart; - u32 specialSize; - u64 zeroBits; - - struct Segment { - u32 offs; // Offset of the segment data - u32 dspAddr; // Start of the segment in 16-bit units - u32 size; - u8 pad[3]; - u8 type; - u8 hash[0x20]; - }; - - Segment segments[10]; -}; - TeakraDSP::TeakraDSP(Memory& mem, Scheduler& scheduler, DSPService& dspService, EmulatorConfig& config) : DSPCore(mem, scheduler, dspService, config), pipeBaseAddr(0), running(false) { // Set up callbacks for Teakra From 518b27913948aa341388a148fd20562f1bc9a902 Mon Sep 17 00:00:00 2001 From: wheremyfoodat <44909372+wheremyfoodat@users.noreply.github.com> Date: Tue, 8 Jul 2025 18:10:57 +0300 Subject: [PATCH 4/6] DSP debugger: Fix prpage --- include/audio/dsp_core.hpp | 3 ++- include/audio/hle_core.hpp | 1 + include/audio/null_core.hpp | 1 + include/audio/teakra_core.hpp | 3 ++- include/panda_qt/dsp_debugger.hpp | 3 +++ src/core/audio/teakra_core.cpp | 6 +----- src/panda_qt/dsp_debugger.cpp | 22 ++++++++++++++++++++-- 7 files changed, 30 insertions(+), 9 deletions(-) diff --git a/include/audio/dsp_core.hpp b/include/audio/dsp_core.hpp index 00c45527..27a660d3 100644 --- a/include/audio/dsp_core.hpp +++ b/include/audio/dsp_core.hpp @@ -64,7 +64,8 @@ namespace Audio { Samples& getSamples() { return sampleBuffer; } virtual void setAudioEnabled(bool enable) { audioEnabled = enable; } - virtual u32 getPC() { return 0; } + virtual Type getType() = 0; + virtual void* getRegisters() { return nullptr; } }; std::unique_ptr makeDSPCore(EmulatorConfig& config, Memory& mem, Scheduler& scheduler, DSPService& dspService); diff --git a/include/audio/hle_core.hpp b/include/audio/hle_core.hpp index 0e3b8636..d374e304 100644 --- a/include/audio/hle_core.hpp +++ b/include/audio/hle_core.hpp @@ -213,6 +213,7 @@ namespace Audio { void runAudioFrame(u64 eventTimestamp) override; u8* getDspMemory() override { return dspRam.rawMemory.data(); } + DSPCore::Type getType() override { return DSPCore::Type::HLE; } u16 recvData(u32 regId) override; bool recvDataIsReady(u32 regId) override { return true; } // Treat data as always ready diff --git a/include/audio/null_core.hpp b/include/audio/null_core.hpp index e7ae12dc..a67c1d9d 100644 --- a/include/audio/null_core.hpp +++ b/include/audio/null_core.hpp @@ -30,6 +30,7 @@ namespace Audio { void runAudioFrame(u64 eventTimestamp) override; u8* getDspMemory() override { return dspRam.data(); } + DSPCore::Type getType() override { return DSPCore::Type::Null; } u16 recvData(u32 regId) override; bool recvDataIsReady(u32 regId) override { return true; } // Treat data as always ready diff --git a/include/audio/teakra_core.hpp b/include/audio/teakra_core.hpp index 5b4c2f8c..9fd6a02c 100644 --- a/include/audio/teakra_core.hpp +++ b/include/audio/teakra_core.hpp @@ -90,7 +90,8 @@ namespace Audio { void setAudioEnabled(bool enable) override; u8* getDspMemory() override { return teakra.GetDspMemory().data(); } - u32 getPC() override; + void* getRegisters() override; + DSPCore::Type getType() override { return DSPCore::Type::Teakra; } u16 recvData(u32 regId) override { return teakra.RecvData(regId); } bool recvDataIsReady(u32 regId) override { return teakra.RecvDataIsReady(regId); } diff --git a/include/panda_qt/dsp_debugger.hpp b/include/panda_qt/dsp_debugger.hpp index 10f3acb1..72b4f884 100644 --- a/include/panda_qt/dsp_debugger.hpp +++ b/include/panda_qt/dsp_debugger.hpp @@ -31,6 +31,9 @@ class DSPDebugger : public QWidget { void disable(); private: + // Get the full PC value of the DSP, including the current progrma page value + u32 getPC(); + // Update the state of the disassembler. Qt events should always call update, not updateDisasm/updateRegister // As update properly handles thread safety void update(); diff --git a/src/core/audio/teakra_core.cpp b/src/core/audio/teakra_core.cpp index e1476b83..05d39487 100644 --- a/src/core/audio/teakra_core.cpp +++ b/src/core/audio/teakra_core.cpp @@ -8,10 +8,6 @@ #include "audio/dsp_binary.hpp" #include "services/dsp.hpp" -#undef Assert -#undef UNREACHABLE -#include "teakra/impl/register.h" - using namespace Audio; TeakraDSP::TeakraDSP(Memory& mem, Scheduler& scheduler, DSPService& dspService, EmulatorConfig& config) @@ -322,4 +318,4 @@ void TeakraDSP::unloadComponent() { running = false; } -u32 TeakraDSP::getPC() { return teakra.GetRegisterState().pc; } \ No newline at end of file +void* TeakraDSP::getRegisters() { return &teakra.GetRegisterState(); } \ No newline at end of file diff --git a/src/panda_qt/dsp_debugger.cpp b/src/panda_qt/dsp_debugger.cpp index 46aa5b8a..7d44cc1c 100644 --- a/src/panda_qt/dsp_debugger.cpp +++ b/src/panda_qt/dsp_debugger.cpp @@ -12,8 +12,13 @@ #include #include +#include "audio/dsp_core.hpp" #include "teakra/disassembler.h" +#undef Assert +#undef UNREACHABLE +#include "teakra/impl/register.h" + // TODO: Make this actually thread-safe by having it only work when paused static int getLinesInViewport(QListWidget* listWidget) { auto viewportHeight = listWidget->viewport()->height(); @@ -167,7 +172,7 @@ void DSPDebugger::updateDisasm() { }; auto& mem = emu->getMemory(); - u32 pc = DSP->getPC(); + u32 pc = getPC(); std::string disassembly; @@ -192,8 +197,21 @@ void DSPDebugger::updateDisasm() { disasmListWidget->setCurrentRow(currentRow); } +// This is only supported on the Teakra core, as other cores don't actually have a register contexts +u32 DSPDebugger::getPC() { + auto DSP = emu->getDSP(); + auto dspType = DSP->getType(); + + if (dspType == Audio::DSPCore::Type::Teakra) { + auto regs = (Teakra::RegisterState*)DSP->getRegisters(); + return regs->pc | (u32(regs->prpage) << 18); + } else { + return 0; + } +} + void DSPDebugger::scrollToPC() { - u32 pc = emu->getDSP()->getPC(); + u32 pc = getPC(); verticalScrollBar->setValue(pc); } From 9ef7db63ef73dd9182896bacda5b881bd298d08e Mon Sep 17 00:00:00 2001 From: wheremyfoodat <44909372+wheremyfoodat@users.noreply.github.com> Date: Tue, 8 Jul 2025 20:28:21 +0300 Subject: [PATCH 5/6] Update teakra --- include/audio/dsp_core.hpp | 15 ++++++ include/audio/teakra_core.hpp | 1 + include/panda_qt/dsp_debugger.hpp | 3 +- src/panda_qt/cpu_debugger.cpp | 2 +- src/panda_qt/dsp_debugger.cpp | 90 ++++++++++++++++++++++--------- third_party/teakra | 2 +- 6 files changed, 84 insertions(+), 29 deletions(-) diff --git a/include/audio/dsp_core.hpp b/include/audio/dsp_core.hpp index 27a660d3..b15a64da 100644 --- a/include/audio/dsp_core.hpp +++ b/include/audio/dsp_core.hpp @@ -66,6 +66,21 @@ namespace Audio { virtual Type getType() = 0; 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 makeDSPCore(EmulatorConfig& config, Memory& mem, Scheduler& scheduler, DSPService& dspService); diff --git a/include/audio/teakra_core.hpp b/include/audio/teakra_core.hpp index 9fd6a02c..46cf7c00 100644 --- a/include/audio/teakra_core.hpp +++ b/include/audio/teakra_core.hpp @@ -92,6 +92,7 @@ namespace Audio { u8* getDspMemory() override { return teakra.GetDspMemory().data(); } void* getRegisters() override; 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); } bool recvDataIsReady(u32 regId) override { return teakra.RecvDataIsReady(regId); } diff --git a/include/panda_qt/dsp_debugger.hpp b/include/panda_qt/dsp_debugger.hpp index 72b4f884..e0067690 100644 --- a/include/panda_qt/dsp_debugger.hpp +++ b/include/panda_qt/dsp_debugger.hpp @@ -5,7 +5,6 @@ #include #include -#include "capstone.hpp" #include "emulator.hpp" #include "panda_qt/disabled_widget_overlay.hpp" @@ -20,10 +19,10 @@ class DSPDebugger : public QWidget { QLineEdit* addressInput; DisabledWidgetOverlay* disabledOverlay; + DisabledWidgetOverlay* disabledRegisterEditOverlay; bool enabled = false; bool followPC = false; - Common::CapstoneDisassembler disassembler; public: DSPDebugger(Emulator* emulator, QWidget* parent = nullptr); diff --git a/src/panda_qt/cpu_debugger.cpp b/src/panda_qt/cpu_debugger.cpp index 6a2aebab..61730c53 100644 --- a/src/panda_qt/cpu_debugger.cpp +++ b/src/panda_qt/cpu_debugger.cpp @@ -69,7 +69,7 @@ CPUDebugger::CPUDebugger(Emulator* emulator, QWidget* parent) : emu(emulator), d // Setup overlay for when the widget is disabled 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->hide(); diff --git a/src/panda_qt/dsp_debugger.cpp b/src/panda_qt/dsp_debugger.cpp index 7d44cc1c..3cb1c0fa 100644 --- a/src/panda_qt/dsp_debugger.cpp +++ b/src/panda_qt/dsp_debugger.cpp @@ -9,7 +9,6 @@ #include #include #include -#include #include #include "audio/dsp_core.hpp" @@ -35,7 +34,7 @@ static std::pair getVisibleLineRange(QListWidget* listWidget, QScrollB 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")); resize(1000, 600); @@ -74,12 +73,18 @@ DSPDebugger::DSPDebugger(Emulator* emulator, QWidget* parent) : emu(emulator), d registerTextEdit->setMaximumWidth(800); 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->resize(size()); // Fill the whole screen + disabledOverlay->resize(size()); // Fill the whole widget disabledOverlay->raise(); 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 QFont mono_font = QFont("Courier New"); mono_font.setStyleHint(QFont::Monospace); @@ -155,21 +160,10 @@ void DSPDebugger::updateDisasm() { disasmListWidget->clear(); 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 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 dsp = emu->getDSP(); + auto dspRam = dsp->getDspMemory(); auto& mem = emu->getMemory(); u32 pc = getPC(); @@ -177,10 +171,10 @@ void DSPDebugger::updateDisasm() { std::string disassembly; 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 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); 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 u32 DSPDebugger::getPC() { - auto DSP = emu->getDSP(); - auto dspType = DSP->getType(); + auto dsp = emu->getDSP(); + auto dspType = dsp->getType(); 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); } else { return 0; @@ -215,7 +209,52 @@ void DSPDebugger::scrollToPC() { 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) { // Forward scroll events from the list widget to the scrollbar @@ -255,7 +294,8 @@ void DSPDebugger::keyPressEvent(QKeyEvent* event) { void DSPDebugger::resizeEvent(QResizeEvent* event) { QWidget::resizeEvent(event); disabledOverlay->resize(event->size()); - verticalScrollBar->setPageStep(getLinesInViewport(disasmListWidget)); + disabledRegisterEditOverlay->resize(registerTextEdit->size()); + verticalScrollBar->setPageStep(getLinesInViewport(disasmListWidget)); update(); } \ No newline at end of file diff --git a/third_party/teakra b/third_party/teakra index 01db7cdd..e34a8679 160000 --- a/third_party/teakra +++ b/third_party/teakra @@ -1 +1 @@ -Subproject commit 01db7cdd00aabcce559a8dddce8798dabb71949b +Subproject commit e34a86799efd65e3c44b915a4d65b3514d34df4f From d126cf1ac6e1ad400f31b116f3435bb778c2716b Mon Sep 17 00:00:00 2001 From: wheremyfoodat <44909372+wheremyfoodat@users.noreply.github.com> Date: Wed, 9 Jul 2025 00:13:53 +0300 Subject: [PATCH 6/6] Reduce global namespace bloat --- .../PICA/dynapica/shader_rec_emitter_x64.hpp | 12 +++--- include/PICA/dynapica/x64_regs.hpp | 42 +++++++++---------- include/audio/dsp_core.hpp | 3 -- 3 files changed, 26 insertions(+), 31 deletions(-) diff --git a/include/PICA/dynapica/shader_rec_emitter_x64.hpp b/include/PICA/dynapica/shader_rec_emitter_x64.hpp index a43bd2dc..85c85bf8 100644 --- a/include/PICA/dynapica/shader_rec_emitter_x64.hpp +++ b/include/PICA/dynapica/shader_rec_emitter_x64.hpp @@ -29,11 +29,11 @@ class ShaderEmitter : public Xbyak::CodeGenerator { std::vector returnPCs; // Vector value of (-0.0, -0.0, -0.0, -0.0) for negating vectors via pxor - Label negateVector; + Xbyak::Label negateVector; // Vector value of (1.0, 1.0, 1.0, 1.0) for SLT(i)/SGE(i) - Label onesVector; + Xbyak::Label onesVector; // Vector value of (0xFF, 0xFF, 0xFF, 0) for setting the w component to 0 in DP3 - Label dp3Vector; + Xbyak::Label dp3Vector; u32 recompilerPC = 0; // PC the recompiler is currently recompiling @ u32 loopLevel = 0; // The current loop nesting level (0 = not in a loop) @@ -47,7 +47,7 @@ class ShaderEmitter : public Xbyak::CodeGenerator { bool codeHasExp2 = false; // Whether to compile this shader using accurate, safe, non-IEEE multiplication (slow) or faster but less accurate mul bool useSafeMUL = false; - + Xbyak::Label log2Func, exp2Func; Xbyak::Label emitLog2Func(); Xbyak::Label emitExp2Func(); @@ -72,8 +72,8 @@ class ShaderEmitter : public Xbyak::CodeGenerator { // Load register with number "srcReg" indexed by index "idx" into the xmm register "reg" template - void loadRegister(Xmm dest, const PICAShader& shader, u32 src, u32 idx, u32 operandDescriptor); - void storeRegister(Xmm source, const PICAShader& shader, u32 dest, u32 operandDescriptor); + void loadRegister(Xbyak::Xmm dest, const PICAShader& shader, u32 src, u32 idx, u32 operandDescriptor); + void storeRegister(Xbyak::Xmm source, const PICAShader& shader, u32 dest, u32 operandDescriptor); const vec4f& getSourceRef(const PICAShader& shader, u32 src); const vec4f& getDestRef(const PICAShader& shader, u32 dest); diff --git a/include/PICA/dynapica/x64_regs.hpp b/include/PICA/dynapica/x64_regs.hpp index 16bc7ca3..e4450870 100644 --- a/include/PICA/dynapica/x64_regs.hpp +++ b/include/PICA/dynapica/x64_regs.hpp @@ -2,39 +2,37 @@ #ifdef PANDA3DS_X64_HOST #include "xbyak/xbyak.h" -using namespace Xbyak; -using namespace Xbyak::util; #if defined(WIN32) || defined(_WIN32) || defined(__WIN32) && !defined(__CYGWIN__) #define PANDA3DS_MS_ABI -constexpr Reg32 arg1 = ecx; // register where first arg is stored -constexpr Reg32 arg2 = edx; // register where second arg is stored -constexpr Reg32 arg3 = r8d; // register where third arg is stored -constexpr Reg32 arg4 = r9d; // register where fourth arg is stored +constexpr Xbyak::Reg32 arg1 = Xbyak::util::ecx; // register where first arg is stored +constexpr Xbyak::Reg32 arg2 = Xbyak::util::edx; // register where second arg is stored +constexpr Xbyak::Reg32 arg3 = Xbyak::util::r8d; // register where third arg is stored +constexpr Xbyak::Reg32 arg4 = Xbyak::util::r9d; // register where fourth arg is stored // Similar for floating point and vector arguemnts. -constexpr Xmm arg1f = xmm0; -constexpr Xmm arg2f = xmm1; -constexpr Xmm arg3f = xmm2; -constexpr Xmm arg4f = xmm3; +constexpr Xbyak::Xmm arg1f = Xbyak::util::xmm0; +constexpr Xbyak::Xmm arg2f = Xbyak::util::xmm1; +constexpr Xbyak::Xmm arg3f = Xbyak::util::xmm2; +constexpr Xbyak::Xmm arg4f = Xbyak::util::xmm3; constexpr bool isWindows() { return true; } #else // System V calling convention #define PANDA3DS_SYSV_ABI -constexpr Reg32 arg1 = edi; -constexpr Reg32 arg2 = esi; -constexpr Reg32 arg3 = edx; -constexpr Reg32 arg4 = ecx; +constexpr Xbyak::Reg32 arg1 = Xbyak::util::edi; +constexpr Xbyak::Reg32 arg2 = Xbyak::util::esi; +constexpr Xbyak::Reg32 arg3 = Xbyak::util::edx; +constexpr Xbyak::Reg32 arg4 = Xbyak::util::ecx; -constexpr Xmm arg1f = xmm0; -constexpr Xmm arg2f = xmm1; -constexpr Xmm arg3f = xmm2; -constexpr Xmm arg4f = xmm3; -constexpr Xmm arg5f = xmm4; -constexpr Xmm arg6f = xmm5; -constexpr Xmm arg7f = xmm6; -constexpr Xmm arg8f = xmm7; +constexpr Xbyak::Xmm arg1f = Xbyak::util::xmm0; +constexpr Xbyak::Xmm arg2f = Xbyak::util::xmm1; +constexpr Xbyak::Xmm arg3f = Xbyak::util::xmm2; +constexpr Xbyak::Xmm arg4f = Xbyak::util::xmm3; +constexpr Xbyak::Xmm arg5f = Xbyak::util::xmm4; +constexpr Xbyak::Xmm arg6f = Xbyak::util::xmm5; +constexpr Xbyak::Xmm arg7f = Xbyak::util::xmm6; +constexpr Xbyak::Xmm arg8f = Xbyak::util::xmm7; constexpr bool isWindows() { return false; } #endif diff --git a/include/audio/dsp_core.hpp b/include/audio/dsp_core.hpp index b15a64da..c2016569 100644 --- a/include/audio/dsp_core.hpp +++ b/include/audio/dsp_core.hpp @@ -1,8 +1,5 @@ #pragma once -#include -#include #include -#include #include #include