Skip to content

Commit

Permalink
Merge pull request #498 from wheremyfoodat/hle-dsp
Browse files Browse the repository at this point in the history
Qt: Add support for dumping DSP firmware
  • Loading branch information
wheremyfoodat authored Apr 25, 2024
2 parents 000dc09 + 01875e0 commit 2fc66fd
Show file tree
Hide file tree
Showing 7 changed files with 87 additions and 10 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/Hydra_Build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ jobs:


MacOS:
runs-on: macos-latest
runs-on: macos-13

steps:
- uses: actions/checkout@v2
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/MacOS_Build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ jobs:
# well on Windows or Mac. You can convert this to a matrix build if you need
# cross-platform coverage.
# See: https://docs.github.com/en/free-pro-team@latest/actions/learn-github-actions/managing-complex-workflows#using-a-build-matrix
runs-on: macos-latest
runs-on: macos-13

steps:
- uses: actions/checkout@v2
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/Qt_Build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ jobs:
path: upload

MacOS:
runs-on: macos-latest
runs-on: macos-13

steps:
- uses: actions/checkout@v2
Expand Down
1 change: 1 addition & 0 deletions include/panda_qt/main_window.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,7 @@ class MainWindow : public QMainWindow {
void emuThreadMainLoop();
void selectLuaFile();
void selectROM();
void dumpDspFirmware();
void dumpRomFS();
void openLuaEditor();
void openCheatsEditor();
Expand Down
20 changes: 16 additions & 4 deletions include/services/dsp.hpp
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
#pragma once
#include <array>
#include <filesystem>
#include <optional>
#include <vector>

#include "audio/dsp_core.hpp"
#include "helpers.hpp"
#include "logger.hpp"
Expand Down Expand Up @@ -34,9 +37,10 @@ class DSPService {

// Total number of DSP service events registered with registerInterruptEvents
size_t totalEventCount;
std::vector<u8> loadedComponent;

// Service functions
void convertProcessAddressFromDspDram(u32 messagePointer); // Nice function name
void convertProcessAddressFromDspDram(u32 messagePointer); // Nice function name
void flushDataCache(u32 messagePointer);
void getHeadphoneStatus(u32 messagePointer);
void getSemaphoreEventHandle(u32 messagePointer);
Expand All @@ -51,23 +55,31 @@ class DSPService {
void unloadComponent(u32 messagePointer);
void writeProcessPipe(u32 messagePointer);

public:
public:
DSPService(Memory& mem, Kernel& kernel) : mem(mem), kernel(kernel) {}
void reset();
void handleSyncRequest(u32 messagePointer);
void setDSPCore(Audio::DSPCore* pointer) { dsp = pointer; }

// Special callback that's ran when the semaphore event is signalled
void onSemaphoreEventSignal() { dsp->setSemaphore(semaphoreMask); }

enum class SoundOutputMode : u8 {
Mono = 0,
Stereo = 1,
Surround = 2
Surround = 2,
};

enum class ComponentDumpResult : u8 {
Success = 0,
NotLoaded,
FileFailure,
};

void triggerPipeEvent(int index);
void triggerSemaphoreEvent();
void triggerInterrupt0();
void triggerInterrupt1();

ComponentDumpResult dumpComponent(const std::filesystem::path& path);
};
25 changes: 22 additions & 3 deletions src/core/services/dsp.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
#include "kernel.hpp"

#include <algorithm>
#include <fstream>

namespace DSPCommands {
enum : u32 {
Expand Down Expand Up @@ -41,6 +42,8 @@ void DSPService::reset() {
for (DSPEvent& e : pipeEvents) {
e = std::nullopt;
}

loadedComponent.clear();
}

void DSPService::handleSyncRequest(u32 messagePointer) {
Expand Down Expand Up @@ -80,13 +83,14 @@ void DSPService::loadComponent(u32 messagePointer) {
u32 dataMask = mem.read32(messagePointer + 12);
u32 buffer = mem.read32(messagePointer + 20);

std::vector<u8> data(size);
loadedComponent.resize(size);

for (u32 i = 0; i < size; i++) {
data[i] = mem.read8(buffer + i);
loadedComponent[i] = mem.read8(buffer + i);
}

log("DSP::LoadComponent (size = %08X, program mask = %X, data mask = %X\n", size, programMask, dataMask);
dsp->loadComponent(data, programMask, dataMask);
dsp->loadComponent(loadedComponent, programMask, dataMask);

mem.write32(messagePointer, IPC::responseHeader(0x11, 2, 2));
mem.write32(messagePointer + 4, Result::Success);
Expand Down Expand Up @@ -262,6 +266,21 @@ void DSPService::invalidateDCache(u32 messagePointer) {
mem.write32(messagePointer + 4, Result::Success);
}

DSPService::ComponentDumpResult DSPService::dumpComponent(const std::filesystem::path& path) {
if (loadedComponent.empty()) {
return ComponentDumpResult::NotLoaded;
}

std::ofstream file(path, std::ios::out | std::ios::binary);
if (file.bad()) {
return ComponentDumpResult::FileFailure;
}

file.write((char*)&loadedComponent[0], loadedComponent.size() * sizeof(u8));
file.close();
return ComponentDumpResult::Success;
}

void DSPService::triggerPipeEvent(int index) {
if (index < pipeCount && pipeEvents[index].has_value()) {
kernel.signalEvent(*pipeEvents[index]);
Expand Down
45 changes: 45 additions & 0 deletions src/panda_qt/main_window.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@

#include "cheats.hpp"
#include "input_mappings.hpp"
#include "services/dsp.hpp"

MainWindow::MainWindow(QApplication* app, QWidget* parent) : QMainWindow(parent), keyboardMappings(InputMappings::defaultKeyboardMappings()), screen(this) {
setWindowTitle("Alber");
Expand Down Expand Up @@ -53,9 +54,12 @@ MainWindow::MainWindow(QApplication* app, QWidget* parent) : QMainWindow(parent)
auto dumpRomFSAction = toolsMenu->addAction(tr("Dump RomFS"));
auto luaEditorAction = toolsMenu->addAction(tr("Open Lua Editor"));
auto cheatsEditorAction = toolsMenu->addAction(tr("Open Cheats Editor"));
auto dumpDspFirmware = toolsMenu->addAction(tr("Dump loaded DSP firmware"));

connect(dumpRomFSAction, &QAction::triggered, this, &MainWindow::dumpRomFS);
connect(luaEditorAction, &QAction::triggered, this, &MainWindow::openLuaEditor);
connect(cheatsEditorAction, &QAction::triggered, this, &MainWindow::openCheatsEditor);
connect(dumpDspFirmware, &QAction::triggered, this, &MainWindow::dumpDspFirmware);

auto aboutAction = aboutMenu->addAction(tr("About Panda3DS"));
connect(aboutAction, &QAction::triggered, this, &MainWindow::showAboutMenu);
Expand Down Expand Up @@ -241,6 +245,47 @@ void MainWindow::dumpRomFS() {
}
}

void MainWindow::dumpDspFirmware() {
auto file = QFileDialog::getSaveFileName(this, tr("Select file"), "", tr("DSP firmware file (*.cdc)"));

if (file.isEmpty()) {
return;
}
std::filesystem::path path(file.toStdU16String());

messageQueueMutex.lock();
auto res = emu->getServiceManager().getDSP().dumpComponent(path);
messageQueueMutex.unlock();

switch (res) {
case DSPService::ComponentDumpResult::Success: break;
case DSPService::ComponentDumpResult::NotLoaded: {
QMessageBox messageBox(
QMessageBox::Icon::Warning, tr("No DSP firmware loaded"),
tr("The currently loaded app has not uploaded a firmware to the DSP")
);

QAbstractButton* button = messageBox.addButton(tr("OK"), QMessageBox::ButtonRole::YesRole);
button->setIcon(QIcon(":/docs/img/rsob_icon.png"));
messageBox.exec();
break;
}

case DSPService::ComponentDumpResult::FileFailure: {
QMessageBox messageBox(
QMessageBox::Icon::Warning, tr("Failed to open output file"),
tr("The currently loaded DSP firmware could not be written to the selected file. Please make sure you have permission to access this "
"file")
);

QAbstractButton* button = messageBox.addButton(tr("OK"), QMessageBox::ButtonRole::YesRole);
button->setIcon(QIcon(":/docs/img/rstarstruck_icon.png"));
messageBox.exec();
break;
}
}
}

void MainWindow::showAboutMenu() {
AboutWindow about(this);
about.exec();
Expand Down

0 comments on commit 2fc66fd

Please sign in to comment.