mirror of
https://github.com/wheremyfoodat/Panda3DS.git
synced 2025-04-08 23:25:40 +12:00
Merge branch 'bottom-screen' of github.com:fleroviux/Panda3DS into pica-tev-emulation
This commit is contained in:
commit
3aeef23b2e
14 changed files with 160 additions and 62 deletions
14
.clang-format
Normal file
14
.clang-format
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
BasedOnStyle: Google
|
||||||
|
IndentWidth: 4
|
||||||
|
ColumnLimit: 150
|
||||||
|
AccessModifierOffset: -2
|
||||||
|
TabWidth: 4
|
||||||
|
NamespaceIndentation: All
|
||||||
|
UseTab: ForContinuationAndIndentation
|
||||||
|
AllowShortEnumsOnASingleLine: true
|
||||||
|
AllowShortCaseLabelsOnASingleLine: true
|
||||||
|
AllowShortFunctionsOnASingleLine: true
|
||||||
|
AllowShortIfStatementsOnASingleLine: true
|
||||||
|
Cpp11BracedListStyle: true
|
||||||
|
PackConstructorInitializers: BinPack
|
||||||
|
AlignAfterOpenBracket: BlockIndent
|
39
.github/workflows/Windows_Build.yml
vendored
Normal file
39
.github/workflows/Windows_Build.yml
vendored
Normal file
|
@ -0,0 +1,39 @@
|
||||||
|
name: Windows Build
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches:
|
||||||
|
- master
|
||||||
|
pull_request:
|
||||||
|
|
||||||
|
env:
|
||||||
|
# Customize the CMake build type here (Release, Debug, RelWithDebInfo, etc.)
|
||||||
|
BUILD_TYPE: Release
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
build:
|
||||||
|
# The CMake configure and build commands are platform agnostic and should work equally
|
||||||
|
# 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: windows-latest
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v2
|
||||||
|
- name: Fetch submodules
|
||||||
|
run: git submodule update --init --recursive
|
||||||
|
|
||||||
|
- name: Configure CMake
|
||||||
|
# Configure CMake in a 'build' subdirectory. `CMAKE_BUILD_TYPE` is only required if you are using a single-configuration generator such as make.
|
||||||
|
# See https://cmake.org/cmake/help/latest/variable/CMAKE_BUILD_TYPE.html?highlight=cmake_build_type
|
||||||
|
run: cmake -B ${{github.workspace}}/build -DCMAKE_BUILD_TYPE=${{env.BUILD_TYPE}}
|
||||||
|
|
||||||
|
- name: Build
|
||||||
|
# Build your program with the given configuration
|
||||||
|
run: cmake --build ${{github.workspace}}/build --config ${{env.BUILD_TYPE}}
|
||||||
|
|
||||||
|
- name: Upload executable
|
||||||
|
uses: actions/upload-artifact@v2
|
||||||
|
with:
|
||||||
|
name: Windows executable
|
||||||
|
path: './build/Release/Alber.exe'
|
|
@ -1,4 +1,5 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
#include "helpers.hpp"
|
||||||
|
|
||||||
namespace PICAInternalRegs {
|
namespace PICAInternalRegs {
|
||||||
enum : u32 {
|
enum : u32 {
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include <span>
|
||||||
|
|
||||||
#include "dynarmic/interface/A32/a32.h"
|
#include "dynarmic/interface/A32/a32.h"
|
||||||
#include "dynarmic/interface/A32/config.h"
|
#include "dynarmic/interface/A32/config.h"
|
||||||
#include "dynarmic/interface/exclusive_monitor.h"
|
#include "dynarmic/interface/exclusive_monitor.h"
|
||||||
|
@ -132,17 +134,11 @@ public:
|
||||||
return jit->Regs()[index];
|
return jit->Regs()[index];
|
||||||
}
|
}
|
||||||
|
|
||||||
std::array<u32, 16>& regs() {
|
std::span<u32, 16> regs() { return jit->Regs(); }
|
||||||
return jit->Regs();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get reference to array of FPRs. This array consists of the FPRs as single precision values
|
// Get reference to array of FPRs. This array consists of the FPRs as single precision values
|
||||||
// Hence why its base type is u32
|
// Hence why its base type is u32
|
||||||
// Note: Dynarmic keeps 64 VFP registers as VFPv3 extends the VFP register set to 64 registers.
|
std::span<u32, 32> fprs() { return std::span(jit->ExtRegs()).first<32>(); }
|
||||||
// However the 3DS ARM11 is an ARMv6k processor with VFPv2, so only the first 32 registers are actually used
|
|
||||||
std::array<u32, 64>& fprs() {
|
|
||||||
return jit->ExtRegs();
|
|
||||||
}
|
|
||||||
|
|
||||||
void setCPSR(u32 value) {
|
void setCPSR(u32 value) {
|
||||||
jit->SetCpsr(value);
|
jit->SetCpsr(value);
|
||||||
|
|
|
@ -2,10 +2,12 @@
|
||||||
#include <array>
|
#include <array>
|
||||||
#include <cassert>
|
#include <cassert>
|
||||||
#include <limits>
|
#include <limits>
|
||||||
|
#include <span>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include "kernel_types.hpp"
|
|
||||||
#include "helpers.hpp"
|
#include "helpers.hpp"
|
||||||
|
#include "kernel_types.hpp"
|
||||||
#include "logger.hpp"
|
#include "logger.hpp"
|
||||||
#include "memory.hpp"
|
#include "memory.hpp"
|
||||||
#include "resource_limits.hpp"
|
#include "resource_limits.hpp"
|
||||||
|
@ -14,7 +16,7 @@
|
||||||
class CPU;
|
class CPU;
|
||||||
|
|
||||||
class Kernel {
|
class Kernel {
|
||||||
std::array<u32, 16>& regs;
|
std::span<u32, 16> regs;
|
||||||
CPU& cpu;
|
CPU& cpu;
|
||||||
Memory& mem;
|
Memory& mem;
|
||||||
|
|
||||||
|
|
|
@ -30,6 +30,19 @@
|
||||||
|
|
||||||
#include "gl3w.h"
|
#include "gl3w.h"
|
||||||
|
|
||||||
|
// Check if we have C++20. If yes, we can add C++20 std::span support
|
||||||
|
#ifdef _MSVC_LANG // MSVC does not properly define __cplusplus without a compiler flag...
|
||||||
|
#if _MSVC_LANG >= 202002L
|
||||||
|
#define OPENGL_HAVE_CPP20
|
||||||
|
#endif
|
||||||
|
#elif __cplusplus >= 202002L
|
||||||
|
#define OPENGL_HAVE_CPP20
|
||||||
|
#endif // MSVC_LANG
|
||||||
|
|
||||||
|
#ifdef OPENGL_HAVE_CPP20
|
||||||
|
#include <span>
|
||||||
|
#endif
|
||||||
|
|
||||||
// Uncomment the following define if you want GL objects to automatically free themselves when their lifetime ends
|
// Uncomment the following define if you want GL objects to automatically free themselves when their lifetime ends
|
||||||
// #define OPENGL_DESTRUCTORS
|
// #define OPENGL_DESTRUCTORS
|
||||||
|
|
||||||
|
@ -399,6 +412,19 @@ namespace OpenGL {
|
||||||
void bufferVertsSub(VertType* vertices, int vertCount, GLintptr offset = 0) {
|
void bufferVertsSub(VertType* vertices, int vertCount, GLintptr offset = 0) {
|
||||||
glBufferSubData(GL_ARRAY_BUFFER, offset, sizeof(VertType) * vertCount, vertices);
|
glBufferSubData(GL_ARRAY_BUFFER, offset, sizeof(VertType) * vertCount, vertices);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// If C++20 is available, add overloads that take std::span instead of raw pointers
|
||||||
|
#ifdef OPENGL_HAVE_CPP20
|
||||||
|
template <typename VertType>
|
||||||
|
void bufferVerts(std::span<const VertType> vertices, GLenum usage = GL_DYNAMIC_DRAW) {
|
||||||
|
glBufferData(GL_ARRAY_BUFFER, sizeof(VertType) * vertices.size(), vertices.data(), usage);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename VertType>
|
||||||
|
void bufferVertsSub(std::span<const VertType> vertices, GLintptr offset = 0) {
|
||||||
|
glBufferSubData(GL_ARRAY_BUFFER, offset, sizeof(VertType) * vertices.size(), vertices.data());
|
||||||
|
}
|
||||||
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
enum DepthFunc {
|
enum DepthFunc {
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
#include <array>
|
#include <array>
|
||||||
|
#include <span>
|
||||||
|
|
||||||
#include "helpers.hpp"
|
#include "helpers.hpp"
|
||||||
#include "logger.hpp"
|
#include "logger.hpp"
|
||||||
#include "opengl.hpp"
|
#include "opengl.hpp"
|
||||||
|
@ -77,7 +79,7 @@ class Renderer {
|
||||||
void bindDepthBuffer();
|
void bindDepthBuffer();
|
||||||
void setupTextureEnvState();
|
void setupTextureEnvState();
|
||||||
|
|
||||||
public:
|
public:
|
||||||
Renderer(GPU& gpu, const std::array<u32, regNum>& internalRegs) : gpu(gpu), regs(internalRegs) {}
|
Renderer(GPU& gpu, const std::array<u32, regNum>& internalRegs) : gpu(gpu), regs(internalRegs) {}
|
||||||
|
|
||||||
void reset();
|
void reset();
|
||||||
|
@ -86,7 +88,7 @@ public:
|
||||||
void getGraphicsContext(); // Set up graphics context for rendering
|
void getGraphicsContext(); // Set up graphics context for rendering
|
||||||
void clearBuffer(u32 startAddress, u32 endAddress, u32 value, u32 control); // Clear a GPU buffer in VRAM
|
void clearBuffer(u32 startAddress, u32 endAddress, u32 value, u32 control); // Clear a GPU buffer in VRAM
|
||||||
void displayTransfer(u32 inputAddr, u32 outputAddr, u32 inputSize, u32 outputSize, u32 flags); // Perform display transfer
|
void displayTransfer(u32 inputAddr, u32 outputAddr, u32 inputSize, u32 outputSize, u32 flags); // Perform display transfer
|
||||||
void drawVertices(OpenGL::Primitives primType, Vertex* vertices, u32 count); // Draw the given vertices
|
void drawVertices(OpenGL::Primitives primType, std::span<const Vertex> vertices); // Draw the given vertices
|
||||||
|
|
||||||
void setFBSize(u32 width, u32 height) {
|
void setFBSize(u32 width, u32 height) {
|
||||||
fbSize.x() = width;
|
fbSize.x() = width;
|
||||||
|
|
|
@ -1,6 +1,8 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
#include <array>
|
#include <array>
|
||||||
#include <optional>
|
#include <optional>
|
||||||
|
#include <span>
|
||||||
|
|
||||||
#include "kernel_types.hpp"
|
#include "kernel_types.hpp"
|
||||||
#include "logger.hpp"
|
#include "logger.hpp"
|
||||||
#include "memory.hpp"
|
#include "memory.hpp"
|
||||||
|
@ -14,16 +16,16 @@
|
||||||
#include "services/cfg.hpp"
|
#include "services/cfg.hpp"
|
||||||
#include "services/dlp_srvr.hpp"
|
#include "services/dlp_srvr.hpp"
|
||||||
#include "services/dsp.hpp"
|
#include "services/dsp.hpp"
|
||||||
#include "services/hid.hpp"
|
|
||||||
#include "services/frd.hpp"
|
#include "services/frd.hpp"
|
||||||
#include "services/fs.hpp"
|
#include "services/fs.hpp"
|
||||||
#include "services/gsp_gpu.hpp"
|
#include "services/gsp_gpu.hpp"
|
||||||
#include "services/gsp_lcd.hpp"
|
#include "services/gsp_lcd.hpp"
|
||||||
|
#include "services/hid.hpp"
|
||||||
#include "services/ldr_ro.hpp"
|
#include "services/ldr_ro.hpp"
|
||||||
#include "services/mic.hpp"
|
#include "services/mic.hpp"
|
||||||
|
#include "services/ndm.hpp"
|
||||||
#include "services/nfc.hpp"
|
#include "services/nfc.hpp"
|
||||||
#include "services/nim.hpp"
|
#include "services/nim.hpp"
|
||||||
#include "services/ndm.hpp"
|
|
||||||
#include "services/ptm.hpp"
|
#include "services/ptm.hpp"
|
||||||
#include "services/y2r.hpp"
|
#include "services/y2r.hpp"
|
||||||
|
|
||||||
|
@ -31,7 +33,7 @@
|
||||||
class Kernel;
|
class Kernel;
|
||||||
|
|
||||||
class ServiceManager {
|
class ServiceManager {
|
||||||
std::array<u32, 16>& regs;
|
std::span<u32, 16> regs;
|
||||||
Memory& mem;
|
Memory& mem;
|
||||||
Kernel& kernel;
|
Kernel& kernel;
|
||||||
|
|
||||||
|
@ -69,8 +71,8 @@ class ServiceManager {
|
||||||
void registerClient(u32 messagePointer);
|
void registerClient(u32 messagePointer);
|
||||||
void subscribe(u32 messagePointer);
|
void subscribe(u32 messagePointer);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
ServiceManager(std::array<u32, 16>& regs, Memory& mem, GPU& gpu, u32& currentPID, Kernel& kernel);
|
ServiceManager(std::span<u32, 16> regs, Memory& mem, GPU& gpu, u32& currentPID, Kernel& kernel);
|
||||||
void reset();
|
void reset();
|
||||||
void initializeFS() { fs.initializeFilesystem(); }
|
void initializeFS() { fs.initializeFilesystem(); }
|
||||||
void handleSyncRequest(u32 messagePointer);
|
void handleSyncRequest(u32 messagePointer);
|
||||||
|
|
|
@ -1,7 +1,13 @@
|
||||||
# Panda3DS
|
# Panda3DS
|
||||||
|
[](https://github.com/wheremyfoodat/Panda3DS/actions/workflows/Windows_Build.yml) [](https://github.com/wheremyfoodat/Panda3DS/actions/workflows/MacOS_Build.yml) [](https://github.com/wheremyfoodat/Panda3DS/actions/workflows/Linux_Build.yml)
|
||||||
|
|
||||||
Panda3DS is an HLE, red-panda-themed Nintendo 3DS emulator written in C++ which started out as a fun project out of curiosity, but evolved into something that can sort of play games!
|
Panda3DS is an HLE, red-panda-themed Nintendo 3DS emulator written in C++ which started out as a fun project out of curiosity, but evolved into something that can sort of play games!
|
||||||
|
|
||||||
|
# Discussion
|
||||||
|
Join our Discord server by pressing on the banner below!
|
||||||
|
|
||||||
|
[](https://discord.gg/ZYbugsEmsw)
|
||||||
|
|
||||||
  
|
  
|
||||||
|
|
||||||
# Compatibility
|
# Compatibility
|
||||||
|
|
|
@ -1,7 +1,10 @@
|
||||||
#include "PICA/gpu.hpp"
|
#include "PICA/gpu.hpp"
|
||||||
|
|
||||||
|
#include <array>
|
||||||
|
#include <cstdio>
|
||||||
|
|
||||||
#include "PICA/float_types.hpp"
|
#include "PICA/float_types.hpp"
|
||||||
#include "PICA/regs.hpp"
|
#include "PICA/regs.hpp"
|
||||||
#include <cstdio>
|
|
||||||
|
|
||||||
using namespace Floats;
|
using namespace Floats;
|
||||||
|
|
||||||
|
@ -41,7 +44,7 @@ void GPU::drawArrays(bool indexed) {
|
||||||
drawArrays<false>();
|
drawArrays<false>();
|
||||||
}
|
}
|
||||||
|
|
||||||
Vertex* vertices = new Vertex[Renderer::vertexBufferSize];
|
static std::array<Vertex, Renderer::vertexBufferSize> vertices;
|
||||||
|
|
||||||
template <bool indexed>
|
template <bool indexed>
|
||||||
void GPU::drawArrays() {
|
void GPU::drawArrays() {
|
||||||
|
@ -205,7 +208,7 @@ void GPU::drawArrays() {
|
||||||
OpenGL::Triangle, OpenGL::TriangleStrip, OpenGL::TriangleFan, OpenGL::Triangle
|
OpenGL::Triangle, OpenGL::TriangleStrip, OpenGL::TriangleFan, OpenGL::Triangle
|
||||||
};
|
};
|
||||||
const auto shape = primTypes[primType];
|
const auto shape = primTypes[primType];
|
||||||
renderer.drawVertices(shape, vertices, vertexCount);
|
renderer.drawVertices(shape, std::span(vertices).first(vertexCount));
|
||||||
}
|
}
|
||||||
|
|
||||||
Vertex GPU::getImmediateModeVertex() {
|
Vertex GPU::getImmediateModeVertex() {
|
||||||
|
|
|
@ -157,7 +157,7 @@ void GPU::writeInternalReg(u32 index, u32 value, u32 mask) {
|
||||||
// If we've reached 3 verts, issue a draw call
|
// If we've reached 3 verts, issue a draw call
|
||||||
// Handle rendering depending on the primitive type
|
// Handle rendering depending on the primitive type
|
||||||
if (immediateModeVertIndex == 3) {
|
if (immediateModeVertIndex == 3) {
|
||||||
renderer.drawVertices(OpenGL::Triangle, &immediateModeVertices[0], 3);
|
renderer.drawVertices(OpenGL::Triangle, immediateModeVertices);
|
||||||
|
|
||||||
switch (primType) {
|
switch (primType) {
|
||||||
// Triangle or geometry primitive. Draw a triangle and discard all vertices
|
// Triangle or geometry primitive. Draw a triangle and discard all vertices
|
||||||
|
|
|
@ -1,8 +1,10 @@
|
||||||
#include <cassert>
|
#include <cassert>
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
#include "kernel.hpp"
|
|
||||||
#include "arm_defs.hpp"
|
#include "arm_defs.hpp"
|
||||||
// This header needs to be included because I did stupid forward decl hack so the kernel and CPU can both access each other
|
#include "kernel.hpp"
|
||||||
|
// This header needs to be included because I did stupid forward decl hack so the kernel and CPU can both access each
|
||||||
|
// other
|
||||||
#include "cpu.hpp"
|
#include "cpu.hpp"
|
||||||
#include "resource_limits.hpp"
|
#include "resource_limits.hpp"
|
||||||
|
|
||||||
|
@ -20,14 +22,14 @@ void Kernel::switchThread(int newThreadIndex) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Backup context
|
// Backup context
|
||||||
std::memcpy(&oldThread.gprs[0], &cpu.regs()[0], 16 * sizeof(u32)); // Backup the 16 GPRs
|
std::memcpy(oldThread.gprs.data(), cpu.regs().data(), cpu.regs().size_bytes()); // Backup the 16 GPRs
|
||||||
std::memcpy(&oldThread.fprs[0], &cpu.fprs()[0], 32 * sizeof(u32)); // Backup the 32 FPRs
|
std::memcpy(oldThread.fprs.data(), cpu.fprs().data(), cpu.fprs().size_bytes()); // Backup the 32 FPRs
|
||||||
oldThread.cpsr = cpu.getCPSR(); // Backup CPSR
|
oldThread.cpsr = cpu.getCPSR(); // Backup CPSR
|
||||||
oldThread.fpscr = cpu.getFPSCR(); // Backup FPSCR
|
oldThread.fpscr = cpu.getFPSCR(); // Backup FPSCR
|
||||||
|
|
||||||
// Load new context
|
// Load new context
|
||||||
std::memcpy(&cpu.regs()[0], &newThread.gprs[0], 16 * sizeof(u32)); // Load 16 GPRs
|
std::memcpy(cpu.regs().data(), newThread.gprs.data(), cpu.regs().size_bytes()); // Load 16 GPRs
|
||||||
std::memcpy(&cpu.fprs()[0], &newThread.fprs[0], 32 * sizeof(u32)); // Load 32 FPRs
|
std::memcpy(cpu.fprs().data(), newThread.fprs.data(), cpu.fprs().size_bytes()); // Load 32 FPRs
|
||||||
cpu.setCPSR(newThread.cpsr); // Load CPSR
|
cpu.setCPSR(newThread.cpsr); // Load CPSR
|
||||||
cpu.setFPSCR(newThread.fpscr); // Load FPSCR
|
cpu.setFPSCR(newThread.fpscr); // Load FPSCR
|
||||||
cpu.setTLSBase(newThread.tlsBase); // Load CP15 thread-local-storage pointer register
|
cpu.setTLSBase(newThread.tlsBase); // Load CP15 thread-local-storage pointer register
|
||||||
|
|
|
@ -475,7 +475,10 @@ void Renderer::setupTextureEnvState() {
|
||||||
glUniform4f(textureEnvBufferColorLoc, r, g, b, a);
|
glUniform4f(textureEnvBufferColorLoc, r, g, b, a);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Renderer::drawVertices(OpenGL::Primitives primType, Vertex* vertices, u32 count) {
|
void Renderer::drawVertices(OpenGL::Primitives primType, std::span<const Vertex> vertices) {
|
||||||
|
// TODO: We should implement a GL state tracker that tracks settings like scissor, blending, bound program, etc
|
||||||
|
// This way if we attempt to eg do multiple glEnable(GL_BLEND) calls in a row, it will say "Oh blending is already enabled"
|
||||||
|
// And not actually perform the very expensive driver call for it
|
||||||
OpenGL::disableScissor();
|
OpenGL::disableScissor();
|
||||||
|
|
||||||
vbo.bind();
|
vbo.bind();
|
||||||
|
@ -570,8 +573,8 @@ void Renderer::drawVertices(OpenGL::Primitives primType, Vertex* vertices, u32 c
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
vbo.bufferVertsSub(vertices, count);
|
vbo.bufferVertsSub(vertices);
|
||||||
OpenGL::draw(primType, count);
|
OpenGL::draw(primType, vertices.size());
|
||||||
}
|
}
|
||||||
|
|
||||||
constexpr u32 topScreenBuffer = 0x1f000000;
|
constexpr u32 topScreenBuffer = 0x1f000000;
|
||||||
|
|
|
@ -1,9 +1,11 @@
|
||||||
#include "services/service_manager.hpp"
|
#include "services/service_manager.hpp"
|
||||||
|
|
||||||
#include <map>
|
#include <map>
|
||||||
|
|
||||||
#include "ipc.hpp"
|
#include "ipc.hpp"
|
||||||
#include "kernel.hpp"
|
#include "kernel.hpp"
|
||||||
|
|
||||||
ServiceManager::ServiceManager(std::array<u32, 16>& regs, Memory& mem, GPU& gpu, u32& currentPID, Kernel& kernel)
|
ServiceManager::ServiceManager(std::span<u32, 16> regs, Memory& mem, GPU& gpu, u32& currentPID, Kernel& kernel)
|
||||||
: regs(regs), mem(mem), kernel(kernel), ac(mem), am(mem), boss(mem), act(mem), apt(mem, kernel), cam(mem),
|
: regs(regs), mem(mem), kernel(kernel), ac(mem), am(mem), boss(mem), act(mem), apt(mem, kernel), cam(mem),
|
||||||
cecd(mem, kernel), cfg(mem), dlp_srvr(mem), dsp(mem, kernel), hid(mem, kernel), frd(mem), fs(mem, kernel),
|
cecd(mem, kernel), cfg(mem), dlp_srvr(mem), dsp(mem, kernel), hid(mem, kernel), frd(mem), fs(mem, kernel),
|
||||||
gsp_gpu(mem, gpu, kernel, currentPID), gsp_lcd(mem), ldr(mem), mic(mem), nfc(mem, kernel), nim(mem), ndm(mem),
|
gsp_gpu(mem, gpu, kernel, currentPID), gsp_lcd(mem), ldr(mem), mic(mem), nfc(mem, kernel), nim(mem), ndm(mem),
|
||||||
|
|
Loading…
Add table
Reference in a new issue