mirror of
https://github.com/wheremyfoodat/Panda3DS.git
synced 2025-07-21 06:13:00 +12:00
[APT] Implement new 3DS check, [OS] Fix mem allog bug & impl more of HID
This commit is contained in:
parent
c4cb20f846
commit
0aaf1c317d
14 changed files with 143 additions and 60 deletions
|
@ -20,7 +20,17 @@ namespace KernelHandles {
|
||||||
MinServiceHandle = APT,
|
MinServiceHandle = APT,
|
||||||
MaxServiceHandle = NDM,
|
MaxServiceHandle = NDM,
|
||||||
|
|
||||||
GSPSharedMemHandle = MaxServiceHandle + 1 // Handle for the GSP shared memory
|
GSPSharedMemHandle = MaxServiceHandle + 1, // Handle for the GSP shared memory
|
||||||
|
HIDSharedMemHandle,
|
||||||
|
|
||||||
|
MinSharedMemHandle = GSPSharedMemHandle,
|
||||||
|
MaxSharedMemHandle = HIDSharedMemHandle,
|
||||||
|
|
||||||
|
HIDEvent0,
|
||||||
|
HIDEvent1,
|
||||||
|
HIDEvent2,
|
||||||
|
HIDEvent3,
|
||||||
|
HIDEvent4
|
||||||
};
|
};
|
||||||
|
|
||||||
// Returns whether "handle" belongs to one of the OS services
|
// Returns whether "handle" belongs to one of the OS services
|
||||||
|
@ -28,6 +38,11 @@ namespace KernelHandles {
|
||||||
return handle >= MinServiceHandle && handle <= MaxServiceHandle;
|
return handle >= MinServiceHandle && handle <= MaxServiceHandle;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Returns whether "handle" belongs to one of the OS services' shared memory areas
|
||||||
|
static constexpr bool isSharedMemHandle(Handle handle) {
|
||||||
|
return handle >= MinSharedMemHandle && handle <= MaxSharedMemHandle;
|
||||||
|
}
|
||||||
|
|
||||||
// Returns the name of a handle as a string based on the given handle
|
// Returns the name of a handle as a string based on the given handle
|
||||||
static const char* getServiceName(Handle handle) {
|
static const char* getServiceName(Handle handle) {
|
||||||
switch (handle) {
|
switch (handle) {
|
||||||
|
@ -36,6 +51,7 @@ namespace KernelHandles {
|
||||||
case FS: return "FS";
|
case FS: return "FS";
|
||||||
case GPU: return "GPU";
|
case GPU: return "GPU";
|
||||||
case LCD: return "LCD";
|
case LCD: return "LCD";
|
||||||
|
case NDM: return "NDM";
|
||||||
default: return "Unknown";
|
default: return "Unknown";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -86,6 +86,7 @@ class Kernel {
|
||||||
|
|
||||||
MAKE_LOG_FUNCTION(log, kernelLogger)
|
MAKE_LOG_FUNCTION(log, kernelLogger)
|
||||||
MAKE_LOG_FUNCTION(logSVC, svcLogger)
|
MAKE_LOG_FUNCTION(logSVC, svcLogger)
|
||||||
|
MAKE_LOG_FUNCTION(logDebugString, debugStringLogger)
|
||||||
|
|
||||||
// SVC implementations
|
// SVC implementations
|
||||||
void arbitrateAddress();
|
void arbitrateAddress();
|
||||||
|
|
|
@ -19,6 +19,7 @@ namespace Log {
|
||||||
|
|
||||||
// Our loggers here. Enable/disable by toggling the template param
|
// Our loggers here. Enable/disable by toggling the template param
|
||||||
static Logger<false> kernelLogger;
|
static Logger<false> kernelLogger;
|
||||||
|
static Logger<true> debugStringLogger; // Enables output for the outputDebugString SVC
|
||||||
static Logger<false> svcLogger;
|
static Logger<false> svcLogger;
|
||||||
static Logger<false> gpuLogger;
|
static Logger<false> gpuLogger;
|
||||||
|
|
||||||
|
|
|
@ -1,9 +1,11 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
#include <array>
|
||||||
#include <bitset>
|
#include <bitset>
|
||||||
#include <fstream>
|
#include <fstream>
|
||||||
#include <optional>
|
#include <optional>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include "helpers.hpp"
|
#include "helpers.hpp"
|
||||||
|
#include "handles.hpp"
|
||||||
|
|
||||||
namespace PhysicalAddrs {
|
namespace PhysicalAddrs {
|
||||||
enum : u32 {
|
enum : u32 {
|
||||||
|
@ -68,19 +70,33 @@ namespace KernelMemoryTypes {
|
||||||
MemoryInfo(u32 baseAddr, u32 size, u32 perms, u32 state) : baseAddr(baseAddr), size(size)
|
MemoryInfo(u32 baseAddr, u32 size, u32 perms, u32 state) : baseAddr(baseAddr), size(size)
|
||||||
, perms(perms), state(state) {}
|
, perms(perms), state(state) {}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Shared memory block for HID, GSP:GPU etc
|
||||||
|
struct SharedMemoryBlock {
|
||||||
|
u32 paddr; // Physical address of this block's memory
|
||||||
|
u32 size; // Size of block
|
||||||
|
u32 handle; // The handle of the shared memory block
|
||||||
|
bool mapped; // Has this block been mapped at least once?
|
||||||
|
|
||||||
|
SharedMemoryBlock(u32 paddr, u32 size, u32 handle) : paddr(paddr), size(size), handle(handle), mapped(false) {}
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
class Memory {
|
class Memory {
|
||||||
u8* fcram;
|
u8* fcram;
|
||||||
u64& cpuTicks; // Reference to the CPU tick counter
|
u64& cpuTicks; // Reference to the CPU tick counter
|
||||||
|
using SharedMemoryBlock = KernelMemoryTypes::SharedMemoryBlock;
|
||||||
|
|
||||||
// Our dynarmic core uses page tables for reads and writes with 4096 byte pages
|
// Our dynarmic core uses page tables for reads and writes with 4096 byte pages
|
||||||
std::vector<uintptr_t> readTable, writeTable;
|
std::vector<uintptr_t> readTable, writeTable;
|
||||||
|
|
||||||
// This tracks our OS' memory allocations
|
// This tracks our OS' memory allocations
|
||||||
std::vector<KernelMemoryTypes::MemoryInfo> memoryInfo;
|
std::vector<KernelMemoryTypes::MemoryInfo> memoryInfo;
|
||||||
// This tracks our physical memory reservations when the memory is not actually mapped to a vaddr
|
|
||||||
std::vector<KernelMemoryTypes::MemoryInfo> lockedMemoryInfo;
|
std::array<SharedMemoryBlock, 2> sharedMemBlocks = {
|
||||||
|
SharedMemoryBlock(0, 0x1000, KernelHandles::GSPSharedMemHandle), // GSP shared memory
|
||||||
|
SharedMemoryBlock(0, 0x1000, KernelHandles::HIDSharedMemHandle) // HID shared memory
|
||||||
|
};
|
||||||
|
|
||||||
static constexpr u32 pageShift = 12;
|
static constexpr u32 pageShift = 12;
|
||||||
static constexpr u32 pageSize = 1 << pageShift;
|
static constexpr u32 pageSize = 1 << pageShift;
|
||||||
|
@ -99,7 +115,6 @@ class Memory {
|
||||||
public:
|
public:
|
||||||
u16 kernelVersion = 0;
|
u16 kernelVersion = 0;
|
||||||
u32 usedUserMemory = 0;
|
u32 usedUserMemory = 0;
|
||||||
std::optional<int> gspMemIndex; // Index of GSP shared mem in lockedMemoryInfo or nullopt if it's already reserved
|
|
||||||
|
|
||||||
Memory(u64& cpuTicks);
|
Memory(u64& cpuTicks);
|
||||||
void reset();
|
void reset();
|
||||||
|
@ -139,12 +154,12 @@ public:
|
||||||
// For internal use:
|
// For internal use:
|
||||||
// Reserve FCRAM linearly starting from physical address "paddr" (paddr == 0 is NOT special) with a size of "size"
|
// Reserve FCRAM linearly starting from physical address "paddr" (paddr == 0 is NOT special) with a size of "size"
|
||||||
// Without actually mapping the memory to a vaddr
|
// Without actually mapping the memory to a vaddr
|
||||||
// r, w, x: Permissions for the reserved memory
|
// Returns true if the reservation succeeded and false if not
|
||||||
// Returns the index of the allocation in lockedMemoryInfo if allocation succeeded and nullopt if it failed
|
bool reserveMemory(u32 paddr, u32 size);
|
||||||
std::optional<int> reserveMemory(u32 paddr, u32 size, bool r, bool w, bool x);
|
|
||||||
|
|
||||||
// Map GSP shared memory to virtual address vaddr with permissions "myPerms"
|
// Map a shared memory block to virtual address vaddr with permissions "myPerms"
|
||||||
// The kernel has a second permission parameter in MapMemoryBlock but not sure what's used for
|
// The kernel has a second permission parameter in MapMemoryBlock but not sure what's used for
|
||||||
// TODO: Find out
|
// TODO: Find out
|
||||||
void mapGSPSharedMemory(u32 vaddr, u32 myPerms, u32 otherPerms);
|
// Returns a pointer to the FCRAM block used for the memory if allocation succeeded
|
||||||
|
u8* mapSharedMemory(Handle handle, u32 vaddr, u32 myPerms, u32 otherPerms);
|
||||||
};
|
};
|
|
@ -11,6 +11,7 @@ class APTService {
|
||||||
|
|
||||||
// Service commands
|
// Service commands
|
||||||
void getLockHandle(u32 messagePointer);
|
void getLockHandle(u32 messagePointer);
|
||||||
|
void checkNew3DS(u32 messagePointer);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
APTService(Memory& mem) : mem(mem) {}
|
APTService(Memory& mem) : mem(mem) {}
|
||||||
|
|
|
@ -7,6 +7,8 @@
|
||||||
class HIDService {
|
class HIDService {
|
||||||
Handle handle = KernelHandles::HID;
|
Handle handle = KernelHandles::HID;
|
||||||
Memory& mem;
|
Memory& mem;
|
||||||
|
u8* sharedMem; // Pointer to HID shared memory
|
||||||
|
|
||||||
MAKE_LOG_FUNCTION(log, hidLogger)
|
MAKE_LOG_FUNCTION(log, hidLogger)
|
||||||
|
|
||||||
// Service commands
|
// Service commands
|
||||||
|
@ -16,4 +18,11 @@ public:
|
||||||
HIDService(Memory& mem) : mem(mem) {}
|
HIDService(Memory& mem) : mem(mem) {}
|
||||||
void reset();
|
void reset();
|
||||||
void handleSyncRequest(u32 messagePointer);
|
void handleSyncRequest(u32 messagePointer);
|
||||||
|
|
||||||
|
void setSharedMem(u8* ptr) {
|
||||||
|
sharedMem = ptr;
|
||||||
|
if (ptr != nullptr) { // Zero-fill shared memory in case the process tries to read stale service data or vice versa
|
||||||
|
std::memset(ptr, 0xff, 0x2b0);
|
||||||
|
}
|
||||||
|
}
|
||||||
};
|
};
|
|
@ -34,6 +34,9 @@ public:
|
||||||
|
|
||||||
// Forward a SendSyncRequest IPC message to the service with the respective handle
|
// Forward a SendSyncRequest IPC message to the service with the respective handle
|
||||||
void sendCommandToService(u32 messagePointer, Handle handle);
|
void sendCommandToService(u32 messagePointer, Handle handle);
|
||||||
|
|
||||||
|
// Wrappers for communicating with certain services
|
||||||
void requestGPUInterrupt(GPUInterrupt type) { gsp_gpu.requestInterrupt(type); }
|
void requestGPUInterrupt(GPUInterrupt type) { gsp_gpu.requestInterrupt(type); }
|
||||||
void setGSPSharedMem(u8* ptr) { gsp_gpu.setSharedMem(ptr); }
|
void setGSPSharedMem(u8* ptr) { gsp_gpu.setSharedMem(ptr); }
|
||||||
|
void setHIDSharedMem(u8* ptr) { hid.setSharedMem(ptr); }
|
||||||
};
|
};
|
|
@ -138,7 +138,7 @@ void Kernel::outputDebugString() {
|
||||||
const u32 size = regs[1];
|
const u32 size = regs[1];
|
||||||
|
|
||||||
std::string message = mem.readString(pointer, size);
|
std::string message = mem.readString(pointer, size);
|
||||||
logSVC("[OutputDebugString] %s\n", message.c_str());
|
logDebugString("[OutputDebugString] %s\n", message.c_str());
|
||||||
regs[0] = SVCResult::Success;
|
regs[0] = SVCResult::Success;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -92,15 +92,23 @@ void Kernel::mapMemoryBlock() {
|
||||||
const u32 addr = regs[1];
|
const u32 addr = regs[1];
|
||||||
const u32 myPerms = regs[2];
|
const u32 myPerms = regs[2];
|
||||||
const u32 otherPerms = regs[3];
|
const u32 otherPerms = regs[3];
|
||||||
logSVC("MapMemoryBlock(block = %d, addr = %08X, myPerms = %X, otherPerms = %X\n", block, addr, myPerms, otherPerms);
|
logSVC("MapMemoryBlock(block = %X, addr = %08X, myPerms = %X, otherPerms = %X\n", block, addr, myPerms, otherPerms);
|
||||||
|
|
||||||
if (!isAligned(addr)) [[unlikely]] {
|
if (!isAligned(addr)) [[unlikely]] {
|
||||||
Helpers::panic("MapMemoryBlock: Unaligned address");
|
Helpers::panic("MapMemoryBlock: Unaligned address");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (block == KernelHandles::GSPSharedMemHandle) {
|
if (KernelHandles::isSharedMemHandle(block)) {
|
||||||
mem.mapGSPSharedMemory(addr, myPerms, otherPerms);
|
u8* ptr = mem.mapSharedMemory(block, addr, myPerms, otherPerms); // Map shared memory block
|
||||||
serviceManager.setGSPSharedMem(static_cast<u8*>(mem.getReadPointer(addr)));
|
|
||||||
|
// Pass pointer to shared memory to the appropriate service
|
||||||
|
if (block == KernelHandles::HIDSharedMemHandle) {
|
||||||
|
serviceManager.setHIDSharedMem(ptr);
|
||||||
|
} else if (block == KernelHandles::GSPSharedMemHandle) {
|
||||||
|
serviceManager.setGSPSharedMem(ptr);
|
||||||
|
} else {
|
||||||
|
Helpers::panic("Mapping unknown shared memory block: %X", block);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
Helpers::panic("MapMemoryBlock where the handle does not refer to GSP memory");
|
Helpers::panic("MapMemoryBlock where the handle does not refer to GSP memory");
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,7 +6,6 @@ Handle Kernel::makePort(const char* name) {
|
||||||
portHandles.push_back(ret); // Push the port handle to our cache of port handles
|
portHandles.push_back(ret); // Push the port handle to our cache of port handles
|
||||||
objects[ret].data = new Port(name);
|
objects[ret].data = new Port(name);
|
||||||
|
|
||||||
// printf("Created %s port \"%s\" with handle %d\n", data->isPublic ? "public" : "private", data->name, ret);
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -37,14 +37,18 @@ void Memory::reset() {
|
||||||
allocateMemory(vaddr, basePaddrForTLS, VirtualAddrs::TLSSize, true);
|
allocateMemory(vaddr, basePaddrForTLS, VirtualAddrs::TLSSize, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Reserve 4KB of memory for GSP shared memory
|
// Initialize shared memory blocks and reserve memory for them
|
||||||
constexpr u32 gspMemSize = 0x1000;
|
for (auto& e : sharedMemBlocks) {
|
||||||
const std::optional<u32> gspMemPaddr = findPaddr(gspMemSize);
|
e.mapped = false;
|
||||||
if (!gspMemPaddr.has_value()) Helpers::panic("Couldn't find paddr for GSP shared memory");
|
|
||||||
|
std::optional<u32> possiblePaddr = findPaddr(e.size);
|
||||||
auto temp = reserveMemory(gspMemPaddr.value(), gspMemSize, true, true, false);
|
if (!possiblePaddr.has_value()) Helpers::panic("Failed to find paddr for shared memory block");
|
||||||
if (!temp.has_value()) Helpers::panic("Couldn't reserve FCRAM for GSP shared memory");
|
|
||||||
gspMemIndex = temp.value();
|
e.paddr = possiblePaddr.value();
|
||||||
|
if (!reserveMemory(e.paddr, e.size)) {
|
||||||
|
Helpers::panic("Failed to reserve memory for shared memory block");
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
u8 Memory::read8(u32 vaddr) {
|
u8 Memory::read8(u32 vaddr) {
|
||||||
|
@ -291,7 +295,7 @@ std::optional<u32> Memory::findPaddr(u32 size) {
|
||||||
return std::nullopt;
|
return std::nullopt;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::optional<int> Memory::reserveMemory(u32 paddr, u32 size, bool r, bool w, bool x) {
|
bool Memory::reserveMemory(u32 paddr, u32 size) {
|
||||||
if (!isAligned(paddr) || !isAligned(size)) {
|
if (!isAligned(paddr) || !isAligned(size)) {
|
||||||
Helpers::panic("Memory::reserveMemory: Physical address or size is not page aligned. Paddr: %08X, size: %08X", paddr, size);
|
Helpers::panic("Memory::reserveMemory: Physical address or size is not page aligned. Paddr: %08X, size: %08X", paddr, size);
|
||||||
; }
|
; }
|
||||||
|
@ -303,18 +307,11 @@ std::optional<int> Memory::reserveMemory(u32 paddr, u32 size, bool r, bool w, bo
|
||||||
for (u32 i = 0; i < pageCount; i++) {
|
for (u32 i = 0; i < pageCount; i++) {
|
||||||
if (usedFCRAMPages[startingPage + i])
|
if (usedFCRAMPages[startingPage + i])
|
||||||
Helpers::panic("Memory::reserveMemory: Trying to reserve already reserved memory");
|
Helpers::panic("Memory::reserveMemory: Trying to reserve already reserved memory");
|
||||||
usedFCRAMPages[i] = true;
|
usedFCRAMPages[startingPage + i] = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Back up the info for this allocation in our memoryInfo vector
|
|
||||||
u32 perms = (r ? PERMISSION_R : 0) | (w ? PERMISSION_W : 0) | (x ? PERMISSION_X : 0);
|
|
||||||
u32 ret = lockedMemoryInfo.size();
|
|
||||||
|
|
||||||
// When we reserve but don't map memory, we store the alloc info in lockedMemoryInfo instead of memoryInfo
|
|
||||||
lockedMemoryInfo.push_back(std::move(MemoryInfo(paddr, size, perms, KernelMemoryTypes::Locked)));
|
|
||||||
|
|
||||||
usedUserMemory += size;
|
usedUserMemory += size;
|
||||||
return ret;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// The way I understand how the kernel's QueryMemory is supposed to work is that you give it a vaddr
|
// The way I understand how the kernel's QueryMemory is supposed to work is that you give it a vaddr
|
||||||
|
@ -334,33 +331,42 @@ MemoryInfo Memory::queryMemory(u32 vaddr) {
|
||||||
return MemoryInfo(vaddr, pageSize, 0, KernelMemoryTypes::Free);
|
return MemoryInfo(vaddr, pageSize, 0, KernelMemoryTypes::Free);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Memory::mapGSPSharedMemory(u32 vaddr, u32 myPerms, u32 otherPerms) {
|
u8* Memory::mapSharedMemory(Handle handle, u32 vaddr, u32 myPerms, u32 otherPerms) {
|
||||||
if (!gspMemIndex.has_value())
|
for (auto& e : sharedMemBlocks) {
|
||||||
Helpers::panic("Tried to map already mapped GSP memory");
|
if (e.handle == handle) {
|
||||||
|
if (e.mapped) Helpers::panic("Allocated shared memory block twice. Is this allowed?");
|
||||||
|
|
||||||
const u32 index = gspMemIndex.value(); // Index of GSP shared memory in lockedMemoryInfo
|
const u32 paddr = e.paddr;
|
||||||
const u32 paddr = lockedMemoryInfo[index].baseAddr;
|
const u32 size = e.size;
|
||||||
const u32 size = lockedMemoryInfo[index].size;
|
|
||||||
// This memory was not actually used, we just didn't want QueryMemory, getResourceLimitCurrentValues and such
|
|
||||||
// To report memory sizes wrongly. We subtract the size from the usedUserMemory size so allocateMemory won't break
|
|
||||||
usedUserMemory -= size;
|
|
||||||
|
|
||||||
// Wipe the GSP memory allocation from existence
|
if (myPerms == 0x10000000) {
|
||||||
gspMemIndex = std::nullopt;
|
myPerms = 3;
|
||||||
lockedMemoryInfo.erase(lockedMemoryInfo.begin() + index);
|
Helpers::panic("Memory::mapSharedMemory with DONTCARE perms");
|
||||||
|
}
|
||||||
|
|
||||||
if (myPerms == 0x10000000) {
|
bool r = myPerms & 0b001;
|
||||||
myPerms = 3;
|
bool w = myPerms & 0b010;
|
||||||
Helpers::panic("Memory::mapGSPSharedMemory with DONTCARE perms");
|
bool x = myPerms & 0b100;
|
||||||
|
|
||||||
|
// This memory was not actually used, we just didn't want QueryMemory, getResourceLimitCurrentValues and such
|
||||||
|
// To report memory sizes wrongly. We subtract the size from the usedUserMemory size so
|
||||||
|
// allocateMemory won't break
|
||||||
|
usedUserMemory -= size;
|
||||||
|
|
||||||
|
const auto result = allocateMemory(vaddr, paddr, size, true, r, w, x);
|
||||||
|
e.mapped = true;
|
||||||
|
if (!result.has_value()) {
|
||||||
|
Helpers::panic("Memory::mapSharedMemory: Failed to map shared memory block");
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
return &fcram[paddr];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool r = myPerms & 0b001;
|
// This should be unreachable but better safe than sorry
|
||||||
bool w = myPerms & 0b010;
|
Helpers::panic("Memory::mapSharedMemory: Unknown shared memory handle %08X", handle);
|
||||||
bool x = myPerms & 0b100;
|
return nullptr;
|
||||||
|
|
||||||
const auto result = allocateMemory(vaddr, paddr, size, true, r, w, x);
|
|
||||||
if (!result.has_value())
|
|
||||||
Helpers::panic("Failed to allocated GSP shared memory");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get the number of ms since Jan 1 1900
|
// Get the number of ms since Jan 1 1900
|
||||||
|
|
|
@ -2,7 +2,15 @@
|
||||||
|
|
||||||
namespace APTCommands {
|
namespace APTCommands {
|
||||||
enum : u32 {
|
enum : u32 {
|
||||||
GetLockHandle = 0x00010040
|
GetLockHandle = 0x00010040,
|
||||||
|
CheckNew3DS = 0x01020000
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace Model {
|
||||||
|
enum : u8 {
|
||||||
|
Old3DS = 0,
|
||||||
|
New3DS = 1
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -18,11 +26,17 @@ void APTService::reset() {}
|
||||||
void APTService::handleSyncRequest(u32 messagePointer) {
|
void APTService::handleSyncRequest(u32 messagePointer) {
|
||||||
const u32 command = mem.read32(messagePointer);
|
const u32 command = mem.read32(messagePointer);
|
||||||
switch (command) {
|
switch (command) {
|
||||||
|
case APTCommands::CheckNew3DS: checkNew3DS(messagePointer); break;
|
||||||
case APTCommands::GetLockHandle: getLockHandle(messagePointer); break;
|
case APTCommands::GetLockHandle: getLockHandle(messagePointer); break;
|
||||||
default: Helpers::panic("APT service requested. Command: %08X\n", command);
|
default: Helpers::panic("APT service requested. Command: %08X\n", command);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void APTService::checkNew3DS(u32 messagePointer) {
|
||||||
|
mem.write32(messagePointer + 4, Result::Success);
|
||||||
|
mem.write8(messagePointer + 8, Model::Old3DS); // u8, Status (0 = Old 3DS, 1 = New 3DS)
|
||||||
|
}
|
||||||
|
|
||||||
void APTService::getLockHandle(u32 messagePointer) {
|
void APTService::getLockHandle(u32 messagePointer) {
|
||||||
log("APT::GetLockHandle (Failure)\n");
|
log("APT::GetLockHandle (Failure)\n");
|
||||||
mem.write32(messagePointer + 4, Result::Failure); // Result code
|
mem.write32(messagePointer + 4, Result::Failure); // Result code
|
||||||
|
|
|
@ -10,7 +10,7 @@ namespace FSCommands {
|
||||||
namespace Result {
|
namespace Result {
|
||||||
enum : u32 {
|
enum : u32 {
|
||||||
Success = 0,
|
Success = 0,
|
||||||
Failure = 0xFFFF'FFFF
|
Failure = 0xFFFFFFFF
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -13,7 +13,9 @@ namespace Result {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
void HIDService::reset() {}
|
void HIDService::reset() {
|
||||||
|
sharedMem = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
void HIDService::handleSyncRequest(u32 messagePointer) {
|
void HIDService::handleSyncRequest(u32 messagePointer) {
|
||||||
const u32 command = mem.read32(messagePointer);
|
const u32 command = mem.read32(messagePointer);
|
||||||
|
@ -24,7 +26,15 @@ void HIDService::handleSyncRequest(u32 messagePointer) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void HIDService::getIPCHandles(u32 messagePointer) {
|
void HIDService::getIPCHandles(u32 messagePointer) {
|
||||||
log("HID::GetIPCHandles (Failure)\n");
|
log("HID::GetIPCHandles\n");
|
||||||
mem.write32(messagePointer + 4, Result::Failure); // Result code
|
mem.write32(messagePointer + 4, Result::Success); // Result code
|
||||||
mem.write32(messagePointer + 8, 0x14000000); // Translation descriptor
|
mem.write32(messagePointer + 8, 0x14000000); // Translation descriptor
|
||||||
|
mem.write32(messagePointer + 12, KernelHandles::HIDSharedMemHandle); // Shared memory handle
|
||||||
|
|
||||||
|
// HID event handles
|
||||||
|
mem.write32(messagePointer + 16, KernelHandles::HIDEvent0);
|
||||||
|
mem.write32(messagePointer + 20, KernelHandles::HIDEvent1);
|
||||||
|
mem.write32(messagePointer + 24, KernelHandles::HIDEvent2);
|
||||||
|
mem.write32(messagePointer + 28, KernelHandles::HIDEvent3);
|
||||||
|
mem.write32(messagePointer + 32, KernelHandles::HIDEvent4);
|
||||||
}
|
}
|
Loading…
Add table
Add a link
Reference in a new issue