mirror of
https://github.com/wheremyfoodat/Panda3DS.git
synced 2025-05-23 20:16:25 +12:00
Merge branch 'master' into extdata
This commit is contained in:
commit
701fd0f446
30 changed files with 286 additions and 58 deletions
9
include/audio/audio_device.hpp
Normal file
9
include/audio/audio_device.hpp
Normal file
|
@ -0,0 +1,9 @@
|
|||
#pragma once
|
||||
|
||||
#if defined(__LIBRETRO__) && defined(USE_LIBRETRO_AUDIO_DEVICE)
|
||||
#include "audio/libretro_audio_device.hpp"
|
||||
using AudioDevice = LibretroAudioDevice;
|
||||
#else
|
||||
#include "audio/miniaudio_device.hpp"
|
||||
using AudioDevice = MiniAudioDevice;
|
||||
#endif
|
36
include/audio/audio_device_interface.hpp
Normal file
36
include/audio/audio_device_interface.hpp
Normal file
|
@ -0,0 +1,36 @@
|
|||
#pragma once
|
||||
#include <array>
|
||||
|
||||
#include "config.hpp"
|
||||
#include "helpers.hpp"
|
||||
#include "ring_buffer.hpp"
|
||||
|
||||
class AudioDeviceInterface {
|
||||
protected:
|
||||
static constexpr usize maxFrameCount = 0x2000;
|
||||
|
||||
using Samples = Common::RingBuffer<s16, maxFrameCount * 2>;
|
||||
using RenderBatchCallback = usize (*)(const s16*, usize);
|
||||
|
||||
Samples* samples = nullptr;
|
||||
|
||||
const AudioDeviceConfig& audioSettings;
|
||||
// Store the last stereo sample we output. We play this when underruning to avoid pops.
|
||||
std::array<s16, 2> lastStereoSample{};
|
||||
|
||||
public:
|
||||
AudioDeviceInterface(Samples* samples, const AudioDeviceConfig& audioSettings) : samples(samples), audioSettings(audioSettings) {}
|
||||
|
||||
bool running = false;
|
||||
Samples* getSamples() { return samples; }
|
||||
|
||||
// If safe is on, we create a null audio device
|
||||
virtual void init(Samples& samples, bool safe = false) = 0;
|
||||
virtual void close() = 0;
|
||||
|
||||
virtual void start() = 0;
|
||||
virtual void stop() = 0;
|
||||
|
||||
// Only used for audio devices that render multiple audio frames in one go, eg the libretro audio device.
|
||||
virtual void renderBatch(RenderBatchCallback callback) {}
|
||||
};
|
61
include/audio/libretro_audio_device.hpp
Normal file
61
include/audio/libretro_audio_device.hpp
Normal file
|
@ -0,0 +1,61 @@
|
|||
#pragma once
|
||||
#include <cstring>
|
||||
|
||||
#include "audio/audio_device_interface.hpp"
|
||||
|
||||
class LibretroAudioDevice final : public AudioDeviceInterface {
|
||||
bool initialized = false;
|
||||
|
||||
public:
|
||||
LibretroAudioDevice(const AudioDeviceConfig& audioSettings) : AudioDeviceInterface(nullptr, audioSettings), initialized(false) {
|
||||
running = false;
|
||||
}
|
||||
|
||||
void init(Samples& samples, bool safe = false) override {
|
||||
this->samples = &samples;
|
||||
|
||||
initialized = true;
|
||||
running = false;
|
||||
}
|
||||
|
||||
void close() override {
|
||||
initialized = false;
|
||||
running = false;
|
||||
};
|
||||
|
||||
void start() override { running = true; }
|
||||
void stop() override { running = false; };
|
||||
|
||||
void renderBatch(RenderBatchCallback callback) override {
|
||||
if (running) {
|
||||
static constexpr usize sampleRate = 32768; // 3DS samples per second
|
||||
static constexpr usize frameCount = sampleRate / 60; // 3DS samples per video frame
|
||||
static constexpr usize channelCount = 2;
|
||||
static s16 audioBuffer[frameCount * channelCount];
|
||||
|
||||
usize samplesWritten = 0;
|
||||
samplesWritten += samples->pop(audioBuffer, frameCount * channelCount);
|
||||
|
||||
// Get the last sample for underrun handling
|
||||
if (samplesWritten != 0) {
|
||||
std::memcpy(&lastStereoSample[0], &audioBuffer[(samplesWritten - 1) * 2], sizeof(lastStereoSample));
|
||||
}
|
||||
|
||||
// If underruning, copy the last output sample
|
||||
{
|
||||
s16* pointer = &audioBuffer[samplesWritten * 2];
|
||||
s16 l = lastStereoSample[0];
|
||||
s16 r = lastStereoSample[1];
|
||||
|
||||
for (usize i = samplesWritten; i < frameCount; i++) {
|
||||
*pointer++ = l;
|
||||
*pointer++ = r;
|
||||
}
|
||||
}
|
||||
|
||||
callback(audioBuffer, sizeof(audioBuffer) / (channelCount * sizeof(s16)));
|
||||
}
|
||||
}
|
||||
|
||||
bool isInitialized() const { return initialized; }
|
||||
};
|
|
@ -3,39 +3,31 @@
|
|||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "config.hpp"
|
||||
#include "helpers.hpp"
|
||||
#include "audio/audio_device_interface.hpp"
|
||||
#include "miniaudio.h"
|
||||
#include "ring_buffer.hpp"
|
||||
|
||||
class MiniAudioDevice {
|
||||
using Samples = Common::RingBuffer<ma_int16, 0x2000 * 2>;
|
||||
class MiniAudioDevice final : public AudioDeviceInterface {
|
||||
static constexpr ma_uint32 sampleRate = 32768; // 3DS sample rate
|
||||
static constexpr ma_uint32 channelCount = 2; // Audio output is stereo
|
||||
|
||||
bool initialized = false;
|
||||
|
||||
ma_device device;
|
||||
ma_context context;
|
||||
ma_device_config deviceConfig;
|
||||
Samples* samples = nullptr;
|
||||
|
||||
const AudioDeviceConfig& audioSettings;
|
||||
|
||||
bool initialized = false;
|
||||
bool running = false;
|
||||
|
||||
// Store the last stereo sample we output. We play this when underruning to avoid pops.
|
||||
std::array<s16, 2> lastStereoSample;
|
||||
std::vector<std::string> audioDevices;
|
||||
|
||||
public:
|
||||
MiniAudioDevice(const AudioDeviceConfig& audioSettings);
|
||||
|
||||
// If safe is on, we create a null audio device
|
||||
void init(Samples& samples, bool safe = false);
|
||||
void close();
|
||||
void init(Samples& samples, bool safe = false) override;
|
||||
void close() override;
|
||||
|
||||
void start();
|
||||
void stop();
|
||||
void start() override;
|
||||
void stop() override;
|
||||
|
||||
bool isInitialized() const { return initialized; }
|
||||
};
|
|
@ -181,5 +181,7 @@ class CPU {
|
|||
void addTicks(u64 ticks) { env.AddTicks(ticks); }
|
||||
|
||||
void clearCache() { jit->ClearCache(); }
|
||||
void clearCacheRange(u32 start, u32 size) { jit->InvalidateCacheRange(start, size); }
|
||||
|
||||
void runFrame();
|
||||
};
|
|
@ -7,8 +7,8 @@
|
|||
#include <span>
|
||||
|
||||
#include "PICA/gpu.hpp"
|
||||
#include "audio/audio_device.hpp"
|
||||
#include "audio/dsp_core.hpp"
|
||||
#include "audio/miniaudio_device.hpp"
|
||||
#include "cheats.hpp"
|
||||
#include "config.hpp"
|
||||
#include "cpu.hpp"
|
||||
|
@ -48,14 +48,14 @@ class Emulator {
|
|||
Scheduler scheduler;
|
||||
|
||||
Crypto::AESEngine aesEngine;
|
||||
MiniAudioDevice audioDevice;
|
||||
AudioDevice audioDevice;
|
||||
Cheats cheats;
|
||||
|
||||
public:
|
||||
static constexpr u32 width = 400;
|
||||
static constexpr u32 height = 240 * 2; // * 2 because 2 screens
|
||||
ROMType romType = ROMType::None;
|
||||
bool running = false; // Is the emulator running a game?
|
||||
bool running = false; // Is the emulator running a game?
|
||||
|
||||
private:
|
||||
#ifdef PANDA3DS_ENABLE_HTTP_SERVER
|
||||
|
@ -126,6 +126,7 @@ class Emulator {
|
|||
LuaManager& getLua() { return lua; }
|
||||
Scheduler& getScheduler() { return scheduler; }
|
||||
Memory& getMemory() { return memory; }
|
||||
AudioDeviceInterface& getAudioDevice() { return audioDevice; }
|
||||
|
||||
RendererType getRendererType() const { return config.rendererType; }
|
||||
Renderer* getRenderer() { return gpu.getRenderer(); }
|
||||
|
|
|
@ -175,6 +175,8 @@ public:
|
|||
void svcSignalEvent();
|
||||
void svcSetTimer();
|
||||
void svcSleepThread();
|
||||
void svcInvalidateInstructionCacheRange();
|
||||
void svcInvalidateEntireInstructionCache();
|
||||
void connectToPort();
|
||||
void outputDebugString();
|
||||
void waitSynchronization1();
|
||||
|
@ -250,4 +252,6 @@ public:
|
|||
|
||||
void sendGPUInterrupt(GPUInterrupt type) { serviceManager.sendGPUInterrupt(type); }
|
||||
void clearInstructionCache();
|
||||
void clearInstructionCacheRange(u32 start, u32 size);
|
||||
u32 getSharedFontVaddr();
|
||||
};
|
|
@ -19,7 +19,7 @@ struct ResourceLimitValues {
|
|||
// APPLICATION resource limit
|
||||
static constexpr ResourceLimitValues appResourceLimits = {
|
||||
.maxPriority = 0x18,
|
||||
.maxCommit = 0x4000000,
|
||||
.maxCommit = 64_MB + 16_MB, // We're currently giving 80MB to all apps. TODO: Implement extended memory properly
|
||||
.maxThreads = 0x20,
|
||||
.maxEvents = 0x20,
|
||||
.maxMutexes = 0x20,
|
||||
|
@ -33,7 +33,7 @@ static constexpr ResourceLimitValues appResourceLimits = {
|
|||
// SYS_APPLET resource limit
|
||||
static constexpr ResourceLimitValues sysAppletResourceLimits = {
|
||||
.maxPriority = 0x4,
|
||||
.maxCommit = 0x5E00000,
|
||||
.maxCommit = 0x5E00000 - 16_MB,
|
||||
.maxThreads = 0x1D,
|
||||
.maxEvents = 0xB,
|
||||
.maxMutexes = 0x8,
|
||||
|
|
|
@ -132,7 +132,7 @@ public:
|
|||
static constexpr u32 totalPageCount = 1 << (32 - pageShift);
|
||||
|
||||
static constexpr u32 FCRAM_SIZE = u32(128_MB);
|
||||
static constexpr u32 FCRAM_APPLICATION_SIZE = u32(64_MB);
|
||||
static constexpr u32 FCRAM_APPLICATION_SIZE = u32(80_MB);
|
||||
static constexpr u32 FCRAM_PAGE_COUNT = FCRAM_SIZE / pageSize;
|
||||
static constexpr u32 FCRAM_APPLICATION_PAGE_COUNT = FCRAM_APPLICATION_SIZE / pageSize;
|
||||
|
||||
|
|
|
@ -53,6 +53,7 @@ class Renderer {
|
|||
|
||||
EmulatorConfig* emulatorConfig = nullptr;
|
||||
|
||||
void doSoftwareTextureCopy(u32 inputAddr, u32 outputAddr, u32 copySize, u32 inputWidth, u32 inputGap, u32 outputWidth, u32 outputGap);
|
||||
public:
|
||||
Renderer(GPU& gpu, const std::array<u32, regNum>& internalRegs, const std::array<u32, extRegNum>& externalRegs);
|
||||
virtual ~Renderer();
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue