mirror of
https://github.com/wheremyfoodat/Panda3DS.git
synced 2025-06-03 12:27:21 +12:00
Merge branch 'master' into metal2
This commit is contained in:
commit
779e30e3e5
48 changed files with 1691 additions and 242 deletions
|
@ -54,6 +54,15 @@ namespace Audio::AAC {
|
|||
u32_le sampleCount;
|
||||
};
|
||||
|
||||
struct DecodeRequest {
|
||||
u32_le address; // Address of input AAC stream
|
||||
u32_le size; // Size of input AAC stream
|
||||
u32_le destAddrLeft; // Output address for left channel samples
|
||||
u32_le destAddrRight; // Output address for right channel samples
|
||||
u32_le unknown1;
|
||||
u32_le unknown2;
|
||||
};
|
||||
|
||||
struct Message {
|
||||
u16_le mode = Mode::None; // Encode or decode AAC?
|
||||
u16_le command = Command::Init;
|
||||
|
@ -62,7 +71,9 @@ namespace Audio::AAC {
|
|||
// Info on the AAC request
|
||||
union {
|
||||
std::array<u8, 24> commandData{};
|
||||
|
||||
DecodeResponse decodeResponse;
|
||||
DecodeRequest decodeRequest;
|
||||
};
|
||||
};
|
||||
|
||||
|
|
24
include/audio/aac_decoder.hpp
Normal file
24
include/audio/aac_decoder.hpp
Normal file
|
@ -0,0 +1,24 @@
|
|||
#pragma once
|
||||
#include <functional>
|
||||
|
||||
#include "audio/aac.hpp"
|
||||
#include "helpers.hpp"
|
||||
|
||||
struct AAC_DECODER_INSTANCE;
|
||||
|
||||
namespace Audio::AAC {
|
||||
class Decoder {
|
||||
using DecoderHandle = AAC_DECODER_INSTANCE*;
|
||||
using PaddrCallback = std::function<u8*(u32)>;
|
||||
|
||||
DecoderHandle decoderHandle = nullptr;
|
||||
|
||||
bool isInitialized() { return decoderHandle != nullptr; }
|
||||
void initialize();
|
||||
|
||||
public:
|
||||
// Decode function. Takes in a reference to the AAC response & request, and a callback for paddr -> pointer conversions
|
||||
void decode(AAC::Message& response, const AAC::Message& request, PaddrCallback paddrCallback);
|
||||
~Decoder();
|
||||
};
|
||||
} // namespace Audio::AAC
|
|
@ -2,10 +2,12 @@
|
|||
#include <array>
|
||||
#include <cassert>
|
||||
#include <deque>
|
||||
#include <memory>
|
||||
#include <queue>
|
||||
#include <vector>
|
||||
|
||||
#include "audio/aac.hpp"
|
||||
#include "audio/aac_decoder.hpp"
|
||||
#include "audio/dsp_core.hpp"
|
||||
#include "audio/dsp_shared_mem.hpp"
|
||||
#include "memory.hpp"
|
||||
|
@ -33,8 +35,8 @@ namespace Audio {
|
|||
SampleFormat format;
|
||||
SourceType sourceType;
|
||||
|
||||
bool fromQueue = false; // Is this buffer from the buffer queue or an embedded buffer?
|
||||
bool hasPlayedOnce = false; // Has the buffer been played at least once before?
|
||||
bool fromQueue = false; // Is this buffer from the buffer queue or an embedded buffer?
|
||||
bool hasPlayedOnce = false; // Has the buffer been played at least once before?
|
||||
|
||||
bool operator<(const Buffer& other) const {
|
||||
// Lower ID = Higher priority
|
||||
|
@ -129,6 +131,8 @@ namespace Audio {
|
|||
std::array<Source, Audio::HLE::sourceCount> sources; // DSP voices
|
||||
Audio::HLE::DspMemory dspRam;
|
||||
|
||||
std::unique_ptr<Audio::AAC::Decoder> aacDecoder;
|
||||
|
||||
void resetAudioPipe();
|
||||
bool loaded = false; // Have we loaded a component?
|
||||
|
||||
|
|
|
@ -39,6 +39,10 @@ struct EmulatorConfig {
|
|||
|
||||
bool audioEnabled = false;
|
||||
bool vsyncEnabled = true;
|
||||
|
||||
bool enableRenderdoc = false;
|
||||
bool printAppVersion = true;
|
||||
bool appVersionOnWindow = false;
|
||||
|
||||
bool chargerPlugged = true;
|
||||
// Default to 3% battery to make users suffer
|
||||
|
|
|
@ -135,4 +135,7 @@ class Emulator {
|
|||
std::filesystem::path getAppDataRoot();
|
||||
|
||||
std::span<u8> getSMDH();
|
||||
|
||||
private:
|
||||
void loadRenderdoc();
|
||||
};
|
||||
|
|
|
@ -1,6 +1,13 @@
|
|||
#pragma once
|
||||
|
||||
#include <QAction>
|
||||
#include <QCheckBox>
|
||||
#include <QDialog>
|
||||
#include <QLabel>
|
||||
#include <QLineEdit>
|
||||
#include <QListWidget>
|
||||
#include <QPushButton>
|
||||
#include <QTextEdit>
|
||||
#include <QWidget>
|
||||
#include <filesystem>
|
||||
#include <memory>
|
||||
|
@ -24,3 +31,60 @@ class CheatsWindow final : public QWidget {
|
|||
std::filesystem::path cheatPath;
|
||||
Emulator* emu;
|
||||
};
|
||||
|
||||
struct CheatMetadata {
|
||||
u32 handle = Cheats::badCheatHandle;
|
||||
std::string name = "New cheat";
|
||||
std::string code;
|
||||
bool enabled = true;
|
||||
};
|
||||
|
||||
class CheatEntryWidget : public QWidget {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
CheatEntryWidget(Emulator* emu, CheatMetadata metadata, QListWidget* parent);
|
||||
|
||||
void Update() {
|
||||
name->setText(metadata.name.c_str());
|
||||
enabled->setChecked(metadata.enabled);
|
||||
update();
|
||||
}
|
||||
|
||||
void Remove() {
|
||||
emu->getCheats().removeCheat(metadata.handle);
|
||||
cheatList->takeItem(cheatList->row(listItem));
|
||||
deleteLater();
|
||||
}
|
||||
|
||||
const CheatMetadata& getMetadata() { return metadata; }
|
||||
void setMetadata(const CheatMetadata& metadata) { this->metadata = metadata; }
|
||||
|
||||
private:
|
||||
void checkboxChanged(int state);
|
||||
void editClicked();
|
||||
|
||||
Emulator* emu;
|
||||
CheatMetadata metadata;
|
||||
u32 handle;
|
||||
QLabel* name;
|
||||
QCheckBox* enabled;
|
||||
QListWidget* cheatList;
|
||||
QListWidgetItem* listItem;
|
||||
};
|
||||
|
||||
class CheatEditDialog : public QDialog {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
CheatEditDialog(Emulator* emu, CheatEntryWidget& cheatEntry);
|
||||
|
||||
void accepted();
|
||||
void rejected();
|
||||
|
||||
private:
|
||||
Emulator* emu;
|
||||
CheatEntryWidget& cheatEntry;
|
||||
QTextEdit* codeEdit;
|
||||
QLineEdit* nameEdit;
|
||||
};
|
|
@ -141,7 +141,7 @@ class MainWindow : public QMainWindow {
|
|||
MainWindow(QApplication* app, QWidget* parent = nullptr);
|
||||
~MainWindow();
|
||||
|
||||
void closeEvent(QCloseEvent *event) override;
|
||||
void closeEvent(QCloseEvent* event) override;
|
||||
void keyPressEvent(QKeyEvent* event) override;
|
||||
void keyReleaseEvent(QKeyEvent* event) override;
|
||||
void mousePressEvent(QMouseEvent* event) override;
|
||||
|
|
38
include/renderdoc.hpp
Normal file
38
include/renderdoc.hpp
Normal file
|
@ -0,0 +1,38 @@
|
|||
// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#pragma once
|
||||
#include <string>
|
||||
|
||||
#include "helpers.hpp"
|
||||
|
||||
#ifdef PANDA3DS_ENABLE_RENDERDOC
|
||||
namespace Renderdoc {
|
||||
// Loads renderdoc dynamic library module.
|
||||
void loadRenderdoc();
|
||||
|
||||
// Begins a capture if a renderdoc instance is attached.
|
||||
void startCapture();
|
||||
|
||||
// Ends current renderdoc capture.
|
||||
void endCapture();
|
||||
|
||||
// Triggers capturing process.
|
||||
void triggerCapture();
|
||||
|
||||
// Sets output directory for captures
|
||||
void setOutputDir(const std::string& path, const std::string& prefix);
|
||||
|
||||
// Returns whether we've compiled with Renderdoc support
|
||||
static constexpr bool isSupported() { return true; }
|
||||
} // namespace Renderdoc
|
||||
#else
|
||||
namespace Renderdoc {
|
||||
static void loadRenderdoc() {}
|
||||
static void startCapture() { Helpers::panic("Tried to start a Renderdoc capture while support for renderdoc is disabled") }
|
||||
static void endCapture() { Helpers::panic("Tried to end a Renderdoc capture while support for renderdoc is disabled") }
|
||||
static void triggerCapture() { Helpers::panic("Tried to trigger a Renderdoc capture while support for renderdoc is disabled") }
|
||||
static void setOutputDir(const std::string& path, const std::string& prefix) {}
|
||||
static constexpr bool isSupported() { return false; }
|
||||
} // namespace Renderdoc
|
||||
#endif
|
|
@ -1,17 +0,0 @@
|
|||
#pragma once
|
||||
|
||||
#include <glm/glm.hpp>
|
||||
#include <numbers>
|
||||
|
||||
#include "services/hid.hpp"
|
||||
|
||||
namespace Gyro::SDL {
|
||||
// Convert the rotation data we get from SDL sensor events to rotation data we can feed right to HID
|
||||
// Returns [pitch, roll, yaw]
|
||||
static glm::vec3 convertRotation(glm::vec3 rotation) {
|
||||
// Convert the rotation from rad/s to deg/s and scale by the gyroscope coefficient in HID
|
||||
constexpr float scale = 180.f / std::numbers::pi * HIDService::gyroscopeCoeff;
|
||||
// The axes are also inverted, so invert scale before the multiplication.
|
||||
return rotation * -scale;
|
||||
}
|
||||
} // namespace Gyro::SDL
|
32
include/sdl_sensors.hpp
Normal file
32
include/sdl_sensors.hpp
Normal file
|
@ -0,0 +1,32 @@
|
|||
#pragma once
|
||||
|
||||
#include <cmath>
|
||||
#include <glm/glm.hpp>
|
||||
#include <numbers>
|
||||
|
||||
#include "helpers.hpp"
|
||||
#include "services/hid.hpp"
|
||||
|
||||
namespace Sensors::SDL {
|
||||
// Convert the rotation data we get from SDL sensor events to rotation data we can feed right to HID
|
||||
// Returns [pitch, roll, yaw]
|
||||
static glm::vec3 convertRotation(glm::vec3 rotation) {
|
||||
// Convert the rotation from rad/s to deg/s and scale by the gyroscope coefficient in HID
|
||||
constexpr float scale = 180.f / std::numbers::pi * HIDService::gyroscopeCoeff;
|
||||
// The axes are also inverted, so invert scale before the multiplication.
|
||||
return rotation * -scale;
|
||||
}
|
||||
|
||||
static glm::vec3 convertAcceleration(float* data) {
|
||||
// Set our cap to ~9 m/s^2. The 3DS sensors cap at -930 and +930, so values above this value will get clamped to 930
|
||||
// At rest (3DS laid flat on table), hardware reads around ~0 for x and z axis, and around ~480 for y axis due to gravity.
|
||||
// This code tries to mimic this approximately, with offsets based on measurements from my DualShock 4.
|
||||
static constexpr float accelMax = 9.f;
|
||||
|
||||
s16 x = std::clamp<s16>(s16(data[0] / accelMax * 930.f), -930, +930);
|
||||
s16 y = std::clamp<s16>(s16(data[1] / (SDL_STANDARD_GRAVITY * accelMax) * 930.f - 350.f), -930, +930);
|
||||
s16 z = std::clamp<s16>(s16((data[2] - 2.1f) / accelMax * 930.f), -930, +930);
|
||||
|
||||
return glm::vec3(x, y, z);
|
||||
}
|
||||
} // namespace Sensors::SDL
|
|
@ -56,6 +56,7 @@ class HIDService {
|
|||
s16 circlePadX, circlePadY; // Circlepad state
|
||||
s16 touchScreenX, touchScreenY; // Touchscreen state
|
||||
s16 roll, pitch, yaw; // Gyroscope state
|
||||
s16 accelX, accelY, accelZ; // Accelerometer state
|
||||
|
||||
bool accelerometerEnabled;
|
||||
bool eventsInitialized;
|
||||
|
@ -87,6 +88,11 @@ class HIDService {
|
|||
*(T*)&sharedMem[offset] = value;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
T* getSharedMemPointer(size_t offset) {
|
||||
return (T*)&sharedMem[offset];
|
||||
}
|
||||
|
||||
public:
|
||||
static constexpr float gyroscopeCoeff = 14.375f; // Same as retail 3DS
|
||||
|
||||
|
@ -130,6 +136,12 @@ class HIDService {
|
|||
void setPitch(s16 value) { pitch = value; }
|
||||
void setYaw(s16 value) { yaw = value; }
|
||||
|
||||
void setAccel(s16 x, s16 y, s16 z) {
|
||||
accelX = x;
|
||||
accelY = y;
|
||||
accelZ = z;
|
||||
}
|
||||
|
||||
void updateInputs(u64 currentTimestamp);
|
||||
|
||||
void setSharedMem(u8* ptr) {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue