Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Proper proguard rules #32

Closed
wants to merge 15 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .gitmodules
Original file line number Diff line number Diff line change
Expand Up @@ -55,3 +55,6 @@
[submodule "third_party/libuv"]
path = third_party/libuv
url = https://github.com/libuv/libuv
[submodule "third_party/teakra"]
path = third_party/teakra
url = https://github.com/wwylele/teakra
8 changes: 6 additions & 2 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -149,6 +149,7 @@ if(HOST_X64 OR HOST_ARM64)
else()
message(FATAL_ERROR "Currently unsupported CPU architecture")
endif()
add_subdirectory(third_party/teakra EXCLUDE_FROM_ALL)

set(SOURCE_FILES src/emulator.cpp src/io_file.cpp src/config.cpp
src/core/CPU/cpu_dynarmic.cpp src/core/CPU/dynarmic_cycles.cpp
Expand Down Expand Up @@ -191,6 +192,7 @@ set(FS_SOURCE_FILES src/core/fs/archive_self_ncch.cpp src/core/fs/archive_save_d
set(APPLET_SOURCE_FILES src/core/applets/applet.cpp src/core/applets/mii_selector.cpp src/core/applets/software_keyboard.cpp src/core/applets/applet_manager.cpp
src/core/applets/error_applet.cpp
)
set(AUDIO_SOURCE_FILES src/core/audio/dsp_core.cpp src/core/audio/null_core.cpp src/core/audio/teakra_core.cpp)
set(RENDERER_SW_SOURCE_FILES src/core/renderer_sw/renderer_sw.cpp)

# Frontend source files
Expand Down Expand Up @@ -247,6 +249,7 @@ set(HEADER_FILES include/emulator.hpp include/helpers.hpp include/termcolor.hpp
include/services/amiibo_device.hpp include/services/nfc_types.hpp include/swap.hpp include/services/csnd.hpp include/services/nwm_uds.hpp
include/fs/archive_system_save_data.hpp include/lua_manager.hpp include/memory_mapped_file.hpp include/hydra_icon.hpp
include/PICA/dynapica/shader_rec_emitter_arm64.hpp include/scheduler.hpp include/applets/error_applet.hpp
include/audio/dsp_core.hpp include/audio/null_core.hpp include/audio/teakra_core.hpp
)

cmrc_add_resource_library(
Expand Down Expand Up @@ -299,6 +302,7 @@ source_group("Source Files\\Core\\Loader" FILES ${LOADER_SOURCE_FILES})
source_group("Source Files\\Core\\Services" FILES ${SERVICE_SOURCE_FILES})
source_group("Source Files\\Core\\Applets" FILES ${APPLET_SOURCE_FILES})
source_group("Source Files\\Core\\PICA" FILES ${PICA_SOURCE_FILES})
source_group("Source Files\\Core\\Audio" FILES ${AUDIO_SOURCE_FILES})
source_group("Source Files\\Core\\Software Renderer" FILES ${RENDERER_SW_SOURCE_FILES})
source_group("Source Files\\Third Party" FILES ${THIRD_PARTY_SOURCE_FILES})

Expand Down Expand Up @@ -397,7 +401,7 @@ endif()
source_group("Header Files\\Core" FILES ${HEADER_FILES})
set(ALL_SOURCES ${SOURCE_FILES} ${FRONTEND_SOURCE_FILES} ${FS_SOURCE_FILES} ${CRYPTO_SOURCE_FILES} ${KERNEL_SOURCE_FILES}
${LOADER_SOURCE_FILES} ${SERVICE_SOURCE_FILES} ${APPLET_SOURCE_FILES} ${RENDERER_SW_SOURCE_FILES} ${PICA_SOURCE_FILES} ${THIRD_PARTY_SOURCE_FILES}
${HEADER_FILES} ${FRONTEND_HEADER_FILES})
${AUDIO_SOURCE_FILES} ${HEADER_FILES} ${FRONTEND_HEADER_FILES})

if(ENABLE_OPENGL)
# Add the OpenGL source files to ALL_SOURCES
Expand Down Expand Up @@ -429,7 +433,7 @@ if(ENABLE_LTO OR ENABLE_USER_BUILD)
set_target_properties(Alber PROPERTIES INTERPROCEDURAL_OPTIMIZATION TRUE)
endif()

target_link_libraries(Alber PRIVATE dynarmic cryptopp glad resources_console_fonts)
target_link_libraries(Alber PRIVATE dynarmic cryptopp glad resources_console_fonts teakra)

if(NOT ANDROID)
target_link_libraries(Alber PRIVATE SDL2-static)
Expand Down
55 changes: 55 additions & 0 deletions include/audio/dsp_core.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
#pragma once
#include <array>
#include <functional>
#include <memory>
#include <optional>
#include <string>
#include <vector>

#include "helpers.hpp"
#include "logger.hpp"
#include "scheduler.hpp"

// The DSP core must have access to the DSP service to be able to trigger interrupts properly
class DSPService;
class Memory;

namespace Audio {
// There are 160 stereo samples in 1 audio frame, so 320 samples total
static constexpr u64 samplesInFrame = 160;
// 1 frame = 4096 DSP cycles = 8192 ARM11 cycles
static constexpr u64 cyclesPerFrame = samplesInFrame * 8192;
// For LLE DSP cores, we run the DSP for N cycles at a time, every N*2 arm11 cycles since the ARM11 runs twice as fast
static constexpr u64 lleSlice = 16384;

class DSPCore {
protected:
Memory& mem;
Scheduler& scheduler;
DSPService& dspService;

MAKE_LOG_FUNCTION(log, dspLogger)

public:
enum class Type { Null, Teakra };
DSPCore(Memory& mem, Scheduler& scheduler, DSPService& dspService) : mem(mem), scheduler(scheduler), dspService(dspService) {}

virtual void reset() = 0;
virtual void runAudioFrame() = 0;
virtual u8* getDspMemory() = 0;

virtual u16 recvData(u32 regId) = 0;
virtual bool recvDataIsReady(u32 regId) = 0;
virtual void setSemaphore(u16 value) = 0;
virtual void writeProcessPipe(u32 channel, u32 size, u32 buffer) = 0;
virtual std::vector<u8> readPipe(u32 channel, u32 peer, u32 size, u32 buffer) = 0;
virtual void loadComponent(std::vector<u8>& data, u32 programMask, u32 dataMask) = 0;
virtual void unloadComponent() = 0;
virtual void setSemaphoreMask(u16 value) = 0;

static Audio::DSPCore::Type typeFromString(std::string inString);
static const char* typeToString(Audio::DSPCore::Type type);
};

std::unique_ptr<DSPCore> makeDSPCore(DSPCore::Type type, Memory& mem, Scheduler& scheduler, DSPService& dspService);
} // namespace Audio
45 changes: 45 additions & 0 deletions include/audio/null_core.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
#pragma once
#include <array>

#include "audio/dsp_core.hpp"
#include "memory.hpp"

namespace Audio {
class NullDSP : public DSPCore {
enum class DSPState : u32 {
Off,
On,
Slep,
};

// Number of DSP pipes
static constexpr size_t pipeCount = 8;
DSPState dspState;

std::array<std::vector<u8>, pipeCount> pipeData; // The data of each pipe
std::array<u8, Memory::DSP_RAM_SIZE> dspRam;

void resetAudioPipe();
bool loaded = false; // Have we loaded a component?

public:
NullDSP(Memory& mem, Scheduler& scheduler, DSPService& dspService) : DSPCore(mem, scheduler, dspService) {}

void reset() override;
void runAudioFrame() override;

u8* getDspMemory() override { return dspRam.data(); }

u16 recvData(u32 regId) override;
bool recvDataIsReady(u32 regId) override { return true; } // Treat data as always ready
void writeProcessPipe(u32 channel, u32 size, u32 buffer) override;
std::vector<u8> readPipe(u32 channel, u32 peer, u32 size, u32 buffer) override;

// NOPs for null DSP core
void loadComponent(std::vector<u8>& data, u32 programMask, u32 dataMask) override;
void unloadComponent() override;
void setSemaphore(u16 value) override {}
void setSemaphoreMask(u16 value) override {}
};

} // namespace Audio
99 changes: 99 additions & 0 deletions include/audio/teakra_core.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
#pragma once
#include "audio/dsp_core.hpp"
#include "memory.hpp"
#include "swap.hpp"
#include "teakra/teakra.h"

namespace Audio {
class TeakraDSP : public DSPCore {
Teakra::Teakra teakra;
u32 pipeBaseAddr;
bool running; // Is the DSP running?
bool loaded; // Have we finished loading a binary with LoadComponent?

// Get a pointer to a data memory address
u8* getDataPointer(u32 address) { return getDspMemory() + Memory::DSP_DATA_MEMORY_OFFSET + address; }

enum class PipeDirection {
DSPtoCPU = 0,
CPUtoDSP = 1,
};

// A lot of Teakra integration code, especially pipe stuff is based on Citra's integration here:
// https://github.com/citra-emu/citra/blob/master/src/audio_core/lle/lle.cpp
struct PipeStatus {
// All addresses and sizes here refer to byte values, NOT 16-bit values.
u16_le address;
u16_le byteSize;
u16_le readPointer;
u16_le writePointer;
u8 slot;
u8 flags;

static constexpr u16 wrapBit = 0x8000;
static constexpr u16 pointerMask = 0x7FFF;

bool isFull() const { return (readPointer ^ writePointer) == wrapBit; }
bool isEmpty() const { return (readPointer ^ writePointer) == 0; }

// isWrapped: Are read and write pointers in different memory passes.
// true: xxxx]----[xxxx (data is wrapping around the end of memory)
// false: ----[xxxx]----
bool isWrapped() const { return (readPointer ^ writePointer) >= wrapBit; }
};
static_assert(sizeof(PipeStatus) == 10, "Teakra: Pipe Status size is wrong");
static constexpr u8 pipeToSlotIndex(u8 pipe, PipeDirection direction) { return (pipe * 2) + u8(direction); }

PipeStatus getPipeStatus(u8 pipe, PipeDirection direction) {
PipeStatus ret;
const u8 index = pipeToSlotIndex(pipe, direction);

std::memcpy(&ret, getDataPointer(pipeBaseAddr * 2 + index * sizeof(PipeStatus)), sizeof(PipeStatus));
return ret;
}

void updatePipeStatus(const PipeStatus& status) {
u8 slot = status.slot;
u8* statusAddress = getDataPointer(pipeBaseAddr * 2 + slot * sizeof(PipeStatus));

if (slot % 2 == 0) {
std::memcpy(statusAddress + 4, &status.readPointer, sizeof(u16));
} else {
std::memcpy(statusAddress + 6, &status.writePointer, sizeof(u16));
}
}

bool signalledData;
bool signalledSemaphore;

// Run 1 slice of DSP instructions
void runSlice() {
if (running) {
teakra.Run(Audio::lleSlice);
}
}

public:
TeakraDSP(Memory& mem, Scheduler& scheduler, DSPService& dspService);

void reset() override;

// Run 1 slice of DSP instructions and schedule the next audio frame
void runAudioFrame() override {
runSlice();
scheduler.addEvent(Scheduler::EventType::RunDSP, scheduler.currentTimestamp + Audio::lleSlice * 2);
}

u8* getDspMemory() override { return teakra.GetDspMemory().data(); }

u16 recvData(u32 regId) override { return teakra.RecvData(regId); }
bool recvDataIsReady(u32 regId) override { return teakra.RecvDataIsReady(regId); }
void setSemaphore(u16 value) override { teakra.SetSemaphore(value); }
void setSemaphoreMask(u16 value) override { teakra.MaskSemaphore(value); }

void writeProcessPipe(u32 channel, u32 size, u32 buffer) override;
std::vector<u8> readPipe(u32 channel, u32 peer, u32 size, u32 buffer) override;
void loadComponent(std::vector<u8>& data, u32 programMask, u32 dataMask) override;
void unloadComponent() override;
};
} // namespace Audio
2 changes: 2 additions & 0 deletions include/config.hpp
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
#pragma once
#include <filesystem>

#include "audio/dsp_core.hpp"
#include "renderer.hpp"

// Remember to initialize every field here to its default value otherwise bad things will happen
Expand All @@ -15,6 +16,7 @@ struct EmulatorConfig {
bool shaderJitEnabled = shaderJitDefault;
bool discordRpcEnabled = false;
RendererType rendererType = RendererType::OpenGL;
Audio::DSPCore::Type dspType = Audio::DSPCore::Type::Null;

bool sdCardInserted = true;
bool sdWriteProtected = false;
Expand Down
6 changes: 5 additions & 1 deletion include/emulator.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,12 @@

#include <filesystem>
#include <fstream>
#include <memory>
#include <optional>
#include <span>

#include "PICA/gpu.hpp"
#include "audio/dsp_core.hpp"
#include "cheats.hpp"
#include "config.hpp"
#include "cpu.hpp"
Expand Down Expand Up @@ -41,9 +43,11 @@ class Emulator {
GPU gpu;
Memory memory;
Kernel kernel;
std::unique_ptr<Audio::DSPCore> dsp;
Scheduler scheduler;

Crypto::AESEngine aesEngine;
Cheats cheats;
Scheduler scheduler;

// Variables to keep track of whether the user is controlling the 3DS analog stick with their keyboard
// This is done so when a gamepad is connected, we won't automatically override the 3DS analog stick settings with the gamepad's state
Expand Down
14 changes: 9 additions & 5 deletions include/kernel/kernel.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -66,15 +66,20 @@ class Kernel {
Handle makeMemoryBlock(u32 addr, u32 size, u32 myPermission, u32 otherPermission);

public:
Handle makeEvent(ResetType resetType); // Needs to be public to be accessible to the APT/HID services
Handle makeMutex(bool locked = false); // Needs to be public to be accessible to the APT/DSP services
Handle makeSemaphore(u32 initialCount, u32 maximumCount); // Needs to be public to be accessible to the service manager port
// Needs to be public to be accessible to the APT/HID services
Handle makeEvent(ResetType resetType, Event::CallbackType callback = Event::CallbackType::None);
// Needs to be public to be accessible to the APT/DSP services
Handle makeMutex(bool locked = false);
// Needs to be public to be accessible to the service manager port
Handle makeSemaphore(u32 initialCount, u32 maximumCount);
Handle makeTimer(ResetType resetType);
void pollTimers();

// Signals an event, returns true on success or false if the event does not exist
bool signalEvent(Handle e);

// Run the callback for "special" events that have callbacks
void runEventCallback(Event::CallbackType callback);

void clearEvent(Handle e) {
KernelObject* object = getObject(e, KernelObjectType::Event);
if (object != nullptr) {
Expand Down Expand Up @@ -240,6 +245,5 @@ class Kernel {
ServiceManager& getServiceManager() { return serviceManager; }

void sendGPUInterrupt(GPUInterrupt type) { serviceManager.sendGPUInterrupt(type); }
void signalDSPEvents() { serviceManager.signalDSPEvents(); }
void clearInstructionCache();
};
8 changes: 8 additions & 0 deletions include/kernel/kernel_types.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -62,11 +62,19 @@ struct Process {
};

struct Event {
// Some events (for now, only the DSP semaphore events) need to execute a callback when signalled
// This enum stores what kind of callback they should execute
enum class CallbackType : u32 {
None, DSPSemaphore,
};

u64 waitlist; // A bitfield where each bit symbolizes if the thread with thread with the corresponding index is waiting on the event
ResetType resetType = ResetType::OneShot;
CallbackType callback = CallbackType::None;
bool fired = false;

Event(ResetType resetType) : resetType(resetType), waitlist(0) {}
Event(ResetType resetType, CallbackType cb) : resetType(resetType), waitlist(0), callback(cb) {}
};

struct Port {
Expand Down
1 change: 1 addition & 0 deletions include/logger.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ namespace Log {
static Logger<false> gpuLogger;
static Logger<false> rendererLogger;
static Logger<false> shaderJITLogger;
static Logger<false> dspLogger;

// Service loggers
static Logger<false> acLogger;
Expand Down
6 changes: 4 additions & 2 deletions include/memory.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -100,8 +100,8 @@ namespace KernelMemoryTypes {

class Memory {
u8* fcram;
u8* dspRam;
u8* vram; // Provided to the memory class by the GPU class
u8* dspRam; // Provided to us by Audio
u8* vram; // Provided to the memory class by the GPU class

u64& cpuTicks; // Reference to the CPU tick counter
using SharedMemoryBlock = KernelMemoryTypes::SharedMemoryBlock;
Expand Down Expand Up @@ -281,6 +281,8 @@ class Memory {
u32 getUsedUserMem() { return usedUserMemory; }

void setVRAM(u8* pointer) { vram = pointer; }
void setDSPMem(u8* pointer) { dspRam = pointer; }

bool allocateMainThreadStack(u32 size);
Regions getConsoleRegion();
void copySharedFont(u8* ptr);
Expand Down
3 changes: 2 additions & 1 deletion include/scheduler.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,8 @@ struct Scheduler {
enum class EventType {
VBlank = 0, // End of frame event
UpdateTimers = 1, // Update kernel timer objects
Panic = 2, // Dummy event that is always pending and should never be triggered (Timestamp = UINT64_MAX)
RunDSP = 2, // Make the emulated DSP run for one audio frame
Panic = 3, // Dummy event that is always pending and should never be triggered (Timestamp = UINT64_MAX)
TotalNumberOfEvents // How many event types do we have in total?
};
static constexpr usize totalNumberOfEvents = static_cast<usize>(EventType::TotalNumberOfEvents);
Expand Down
Loading
Loading