Merge branch 'master' into metal2

This commit is contained in:
SamoZ256 2024-09-24 09:22:17 +02:00 committed by GitHub
commit 779e30e3e5
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
48 changed files with 1691 additions and 242 deletions

View file

@ -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;
};
};

View 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

View file

@ -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?

View file

@ -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

View file

@ -135,4 +135,7 @@ class Emulator {
std::filesystem::path getAppDataRoot();
std::span<u8> getSMDH();
private:
void loadRenderdoc();
};

View file

@ -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;
};

View file

@ -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
View 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

View file

@ -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
View 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

View file

@ -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) {