mirror of
https://github.com/wheremyfoodat/Panda3DS.git
synced 2025-04-08 07:05:40 +12:00
Merge branch 'master' into mii_selector
This commit is contained in:
commit
52304763bb
10 changed files with 141 additions and 26 deletions
9
.github/mac-bundle.sh
vendored
9
.github/mac-bundle.sh
vendored
|
@ -36,6 +36,15 @@ PlistBuddy Alber.app/Contents/Info.plist -c "add CFBundleIconFile string AppIcon
|
|||
PlistBuddy Alber.app/Contents/Info.plist -c "add NSHighResolutionCapable bool true"
|
||||
PlistBuddy Alber.app/Contents/version.plist -c "add ProjectName string Alber"
|
||||
|
||||
PlistBuddy Alber.app/Contents/Info.plist -c "add CFBundleExecutable string Alber"
|
||||
PlistBuddy Alber.app/Contents/Info.plist -c "add CFBundleDevelopmentRegion string en"
|
||||
PlistBuddy Alber.app/Contents/Info.plist -c "add CFBundleInfoDictionaryVersion string 6.0"
|
||||
PlistBuddy Alber.app/Contents/Info.plist -c "add CFBundleName string Panda3DS"
|
||||
PlistBuddy Alber.app/Contents/Info.plist -c "add CFBundlePackageType string APPL"
|
||||
PlistBuddy Alber.app/Contents/Info.plist -c "add NSHumanReadableCopyright string Copyright 2023 Panda3DS Team"
|
||||
|
||||
PlistBuddy Alber.app/Contents/Info.plist -c "add LSMinimumSystemVersion string 10.15"
|
||||
|
||||
# Bundle dylibs
|
||||
dylibbundler -od -b -x Alber.app/Contents/MacOS/Alber -d Alber.app/Contents/Frameworks/ -p @rpath -s /Users/runner/work/Panda3DS/Panda3DS/VULKAN_SDK/lib
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
# We need to be able to use enable_language(OBJC) on Mac, so we need CMake 3.16 vs the 3.10 we use otherwise. Blame Apple.
|
||||
if (APPLE)
|
||||
set(CMAKE_OSX_DEPLOYMENT_TARGET "11.0" CACHE STRING "Minimum OS X deployment version")
|
||||
set(CMAKE_OSX_DEPLOYMENT_TARGET "10.15" CACHE STRING "Minimum OS X deployment version")
|
||||
cmake_minimum_required(VERSION 3.16)
|
||||
else()
|
||||
cmake_minimum_required(VERSION 3.10)
|
||||
|
|
|
@ -1,4 +1,6 @@
|
|||
#pragma once
|
||||
#include <optional>
|
||||
|
||||
#include "helpers.hpp"
|
||||
#include "kernel_types.hpp"
|
||||
#include "logger.hpp"
|
||||
|
@ -15,10 +17,14 @@ class ACService {
|
|||
void closeAsync(u32 messagePointer);
|
||||
void createDefaultConfig(u32 messagePointer);
|
||||
void getLastErrorCode(u32 messagePointer);
|
||||
void isConnected(u32 messagePointer);
|
||||
void registerDisconnectEvent(u32 messagePointer);
|
||||
void setClientVersion(u32 messagePointer);
|
||||
|
||||
public:
|
||||
bool connected = false;
|
||||
std::optional<Handle> disconnectEvent = std::nullopt;
|
||||
|
||||
public:
|
||||
ACService(Memory& mem) : mem(mem) {}
|
||||
void reset();
|
||||
void handleSyncRequest(u32 messagePointer);
|
||||
|
|
|
@ -26,6 +26,7 @@ class FRDService {
|
|||
void getFriendAttributeFlags(u32 messagePointer);
|
||||
void getFriendKeyList(u32 messagePointer);
|
||||
void getFriendPresence(u32 messagePointer);
|
||||
void getFriendProfile(u32 messagePointer);
|
||||
void getMyFriendKey(u32 messagePointer);
|
||||
void getMyMii(u32 messagePointer);
|
||||
void getMyPresence(u32 messagePointer);
|
||||
|
@ -37,6 +38,15 @@ class FRDService {
|
|||
void setNotificationMask(u32 messagePointer);
|
||||
void updateGameModeDescription(u32 messagePointer);
|
||||
|
||||
struct Profile {
|
||||
u8 region;
|
||||
u8 country;
|
||||
u8 area;
|
||||
u8 language;
|
||||
u32 unknown;
|
||||
};
|
||||
static_assert(sizeof(Profile) == 8);
|
||||
|
||||
public:
|
||||
FRDService(Memory& mem) : mem(mem) {}
|
||||
void reset();
|
||||
|
|
|
@ -5,13 +5,19 @@
|
|||
#include "memory.hpp"
|
||||
#include "result/result.hpp"
|
||||
|
||||
// Circular dependencies, yay
|
||||
class Kernel;
|
||||
|
||||
class MICService {
|
||||
Handle handle = KernelHandles::MIC;
|
||||
Memory& mem;
|
||||
Kernel& kernel;
|
||||
MAKE_LOG_FUNCTION(log, micLogger)
|
||||
|
||||
// Service commands
|
||||
void getEventHandle(u32 messagePointer);
|
||||
void getGain(u32 messagePointer);
|
||||
void isSampling(u32 messagePointer);
|
||||
void mapSharedMem(u32 messagePointer);
|
||||
void setClamp(u32 messagePointer);
|
||||
void setGain(u32 messagePointer);
|
||||
|
@ -19,15 +25,18 @@ class MICService {
|
|||
void setPower(u32 messagePointer);
|
||||
void startSampling(u32 messagePointer);
|
||||
void stopSampling(u32 messagePointer);
|
||||
void unmapSharedMem(u32 messagePointer);
|
||||
void theCaptainToadFunction(u32 messagePointer);
|
||||
|
||||
u8 gain = 0; // How loud our microphone input signal is
|
||||
bool micEnabled = false;
|
||||
bool shouldClamp = false;
|
||||
bool isSampling = false;
|
||||
bool currentlySampling = false;
|
||||
|
||||
std::optional<Handle> eventHandle;
|
||||
|
||||
public:
|
||||
MICService(Memory& mem) : mem(mem) {}
|
||||
MICService(Memory& mem, Kernel& kernel) : mem(mem), kernel(kernel) {}
|
||||
void reset();
|
||||
void handleSyncRequest(u32 messagePointer);
|
||||
};
|
|
@ -1,5 +1,5 @@
|
|||
# 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)
|
||||
[](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) [](https://aur.archlinux.org/packages/panda3ds-git)
|
||||
|
||||
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!
|
||||
|
||||
|
|
|
@ -8,11 +8,15 @@ namespace ACCommands {
|
|||
CloseAsync = 0x00080004,
|
||||
GetLastErrorCode = 0x000A0000,
|
||||
RegisterDisconnectEvent = 0x00300004,
|
||||
IsConnected = 0x003E0042,
|
||||
SetClientVersion = 0x00400042,
|
||||
};
|
||||
}
|
||||
|
||||
void ACService::reset() {}
|
||||
void ACService::reset() {
|
||||
connected = false;
|
||||
disconnectEvent = std::nullopt;
|
||||
}
|
||||
|
||||
void ACService::handleSyncRequest(u32 messagePointer) {
|
||||
const u32 command = mem.read32(messagePointer);
|
||||
|
@ -21,6 +25,7 @@ void ACService::handleSyncRequest(u32 messagePointer) {
|
|||
case ACCommands::CloseAsync: closeAsync(messagePointer); break;
|
||||
case ACCommands::CreateDefaultConfig: createDefaultConfig(messagePointer); break;
|
||||
case ACCommands::GetLastErrorCode: getLastErrorCode(messagePointer); break;
|
||||
case ACCommands::IsConnected: isConnected(messagePointer); break;
|
||||
case ACCommands::RegisterDisconnectEvent: registerDisconnectEvent(messagePointer); break;
|
||||
case ACCommands::SetClientVersion: setClientVersion(messagePointer); break;
|
||||
default: Helpers::panic("AC service requested. Command: %08X\n", command);
|
||||
|
@ -37,6 +42,11 @@ void ACService::cancelConnectAsync(u32 messagePointer) {
|
|||
|
||||
void ACService::closeAsync(u32 messagePointer) {
|
||||
log("AC::CloseAsync (stubbed)\n");
|
||||
connected = false;
|
||||
|
||||
if (disconnectEvent.has_value()) {
|
||||
Helpers::warn("AC::DisconnectEvent should be signalled but isn't implemented yet");
|
||||
}
|
||||
|
||||
// TODO: Verify if this response header is correct on hardware
|
||||
mem.write32(messagePointer, IPC::responseHeader(0x8, 1, 0));
|
||||
|
@ -59,6 +69,15 @@ void ACService::getLastErrorCode(u32 messagePointer) {
|
|||
mem.write32(messagePointer + 8, 0); // Hopefully this means no error?
|
||||
}
|
||||
|
||||
void ACService::isConnected(u32 messagePointer) {
|
||||
log("AC::IsConnected\n");
|
||||
// This has parameters according to the command word but it's unknown what they are
|
||||
|
||||
mem.write32(messagePointer, IPC::responseHeader(0x3E, 2, 0));
|
||||
mem.write32(messagePointer + 4, Result::Success);
|
||||
mem.write8(messagePointer + 8, connected ? 1 : 0);
|
||||
}
|
||||
|
||||
void ACService::setClientVersion(u32 messagePointer) {
|
||||
u32 version = mem.read32(messagePointer + 4);
|
||||
log("AC::SetClientVersion (version = %d)\n", version);
|
||||
|
@ -71,9 +90,11 @@ void ACService::registerDisconnectEvent(u32 messagePointer) {
|
|||
log("AC::RegisterDisconnectEvent (stubbed)\n");
|
||||
const u32 pidHeader = mem.read32(messagePointer + 4);
|
||||
const u32 copyHandleHeader = mem.read32(messagePointer + 12);
|
||||
// Event signaled when disconnecting from AC
|
||||
// Event signaled when disconnecting from AC. TODO: Properly implement it.
|
||||
const Handle eventHandle = mem.read32(messagePointer + 16);
|
||||
|
||||
disconnectEvent = eventHandle;
|
||||
|
||||
mem.write32(messagePointer, IPC::responseHeader(0x30, 1, 0));
|
||||
mem.write32(messagePointer + 4, Result::Success);
|
||||
}
|
|
@ -19,6 +19,7 @@ namespace FRDCommands {
|
|||
GetMyMii = 0x000A0000,
|
||||
GetFriendKeyList = 0x00110080,
|
||||
GetFriendPresence = 0x00120042,
|
||||
GetFriendProfile = 0x00150042,
|
||||
GetFriendAttributeFlags = 0x00170042,
|
||||
UpdateGameModeDescription = 0x001D0002,
|
||||
};
|
||||
|
@ -33,6 +34,7 @@ void FRDService::handleSyncRequest(u32 messagePointer) {
|
|||
case FRDCommands::GetFriendAttributeFlags: getFriendAttributeFlags(messagePointer); break;
|
||||
case FRDCommands::GetFriendKeyList: getFriendKeyList(messagePointer); break;
|
||||
case FRDCommands::GetFriendPresence: getFriendPresence(messagePointer); break;
|
||||
case FRDCommands::GetFriendProfile: getFriendProfile(messagePointer); break;
|
||||
case FRDCommands::GetMyFriendKey: getMyFriendKey(messagePointer); break;
|
||||
case FRDCommands::GetMyMii: getMyMii(messagePointer); break;
|
||||
case FRDCommands::GetMyPresence: getMyPresence(messagePointer); break;
|
||||
|
@ -87,6 +89,41 @@ void FRDService::getFriendKeyList(u32 messagePointer) {
|
|||
}
|
||||
}
|
||||
|
||||
void FRDService::getFriendProfile(u32 messagePointer) {
|
||||
log("FRD::GetFriendProfile\n");
|
||||
|
||||
const u32 count = mem.read32(messagePointer + 4);
|
||||
const u32 friendKeyList = mem.read32(messagePointer + 12); // Pointer to list of friend keys
|
||||
const u32 profile = mem.read32(messagePointer + 0x104); // Pointer to friend profile where we'll write info to
|
||||
|
||||
mem.write32(messagePointer, IPC::responseHeader(0x15, 1, 2));
|
||||
mem.write32(messagePointer + 4, Result::Success);
|
||||
|
||||
// Clear all profiles
|
||||
for (u32 i = 0; i < count; i++) {
|
||||
const u32 pointer = profile + (i * sizeof(Profile));
|
||||
for (u32 j = 0; j < sizeof(Profile); j++) {
|
||||
mem.write8(pointer + j, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void FRDService::getFriendAttributeFlags(u32 messagePointer) {
|
||||
log("FRD::GetFriendAttributeFlags\n");
|
||||
|
||||
const u32 count = mem.read32(messagePointer + 4);
|
||||
const u32 friendKeyList = mem.read32(messagePointer + 12); // Pointer to list of friend keys
|
||||
const u32 profile = mem.read32(messagePointer + 0x104); // Pointer to friend profile where we'll write info to
|
||||
|
||||
mem.write32(messagePointer, IPC::responseHeader(0x17, 1, 2));
|
||||
mem.write32(messagePointer + 4, Result::Success);
|
||||
|
||||
// Clear flags
|
||||
for (u32 i = 0; i < count; i++) {
|
||||
mem.write8(profile + i, 0);
|
||||
}
|
||||
}
|
||||
|
||||
void FRDService::getMyPresence(u32 messagePointer) {
|
||||
static constexpr u32 presenceSize = 0x12C; // A presence seems to be 12C bytes of data, not sure what it contains
|
||||
log("FRD::GetMyPresence\n");
|
||||
|
@ -100,21 +137,6 @@ void FRDService::getMyPresence(u32 messagePointer) {
|
|||
mem.write32(messagePointer + 4, Result::Success);
|
||||
}
|
||||
|
||||
void FRDService::getFriendAttributeFlags(u32 messagePointer) {
|
||||
log("FRD::GetFriendAttributeFlags\n");
|
||||
const u32 count = mem.read32(messagePointer + 4);
|
||||
const u32 buffer = mem.read32(messagePointer + 0x104); // Buffer to write flag info to.
|
||||
|
||||
|
||||
// Clear all flags. Assume one flag == 1 byte (u8) for now.
|
||||
for (u32 i = 0; i < count; i++) {
|
||||
const u32 pointer = buffer + (i * sizeof(u8));
|
||||
for (u32 j = 0; j < sizeof(u8); j++) {
|
||||
mem.write8(pointer + j, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void FRDService::getFriendPresence(u32 messagePointer) {
|
||||
Helpers::warn("FRD::GetFriendPresence (stubbed)");
|
||||
|
||||
|
|
|
@ -1,11 +1,15 @@
|
|||
#include "services/mic.hpp"
|
||||
#include "ipc.hpp"
|
||||
#include "kernel/kernel.hpp"
|
||||
|
||||
namespace MICCommands {
|
||||
enum : u32 {
|
||||
MapSharedMem = 0x00010042,
|
||||
UnmapSharedMem = 0x00020000,
|
||||
StartSampling = 0x00030140,
|
||||
StopSampling = 0x00050000,
|
||||
IsSampling = 0x00060000,
|
||||
GetEventHandle = 0x00070000,
|
||||
SetGain = 0x00080040,
|
||||
GetGain = 0x00090000,
|
||||
SetPower = 0x000A0040,
|
||||
|
@ -18,14 +22,18 @@ namespace MICCommands {
|
|||
void MICService::reset() {
|
||||
micEnabled = false;
|
||||
shouldClamp = false;
|
||||
isSampling = false;
|
||||
currentlySampling = false;
|
||||
gain = 0;
|
||||
|
||||
eventHandle = std::nullopt;
|
||||
}
|
||||
|
||||
void MICService::handleSyncRequest(u32 messagePointer) {
|
||||
const u32 command = mem.read32(messagePointer);
|
||||
switch (command) {
|
||||
case MICCommands::GetEventHandle: getEventHandle(messagePointer); break;
|
||||
case MICCommands::GetGain: getGain(messagePointer); break;
|
||||
case MICCommands::IsSampling: isSampling(messagePointer); break;
|
||||
case MICCommands::MapSharedMem: mapSharedMem(messagePointer); break;
|
||||
case MICCommands::SetClamp: setClamp(messagePointer); break;
|
||||
case MICCommands::SetGain: setGain(messagePointer); break;
|
||||
|
@ -33,6 +41,7 @@ void MICService::handleSyncRequest(u32 messagePointer) {
|
|||
case MICCommands::SetPower: setPower(messagePointer); break;
|
||||
case MICCommands::StartSampling: startSampling(messagePointer); break;
|
||||
case MICCommands::StopSampling: stopSampling(messagePointer); break;
|
||||
case MICCommands::UnmapSharedMem: unmapSharedMem(messagePointer); break;
|
||||
case MICCommands::CaptainToadFunction: theCaptainToadFunction(messagePointer); break;
|
||||
default: Helpers::panic("MIC service requested. Command: %08X\n", command);
|
||||
}
|
||||
|
@ -47,6 +56,27 @@ void MICService::mapSharedMem(u32 messagePointer) {
|
|||
mem.write32(messagePointer + 4, Result::Success);
|
||||
}
|
||||
|
||||
void MICService::unmapSharedMem(u32 messagePointer) {
|
||||
log("MIC::UnmapSharedMem (stubbed)\n");
|
||||
|
||||
mem.write32(messagePointer, IPC::responseHeader(0x2, 1, 0));
|
||||
mem.write32(messagePointer + 4, Result::Success);
|
||||
}
|
||||
|
||||
void MICService::getEventHandle(u32 messagePointer) {
|
||||
log("MIC::GetEventHandle\n");
|
||||
Helpers::warn("Acquire MIC event handle");
|
||||
|
||||
if (!eventHandle.has_value()) {
|
||||
eventHandle = kernel.makeEvent(ResetType::OneShot);
|
||||
}
|
||||
|
||||
mem.write32(messagePointer, IPC::responseHeader(0x7, 1, 2));
|
||||
mem.write32(messagePointer + 4, Result::Success);
|
||||
// TODO: Translation descriptor
|
||||
mem.write32(messagePointer + 12, eventHandle.value());
|
||||
}
|
||||
|
||||
void MICService::getGain(u32 messagePointer) {
|
||||
log("MIC::GetGain\n");
|
||||
mem.write32(messagePointer, IPC::responseHeader(0x9, 2, 0));
|
||||
|
@ -91,19 +121,27 @@ void MICService::startSampling(u32 messagePointer) {
|
|||
encoding, sampleRate, offset, dataSize, loop ? "yes" : "no"
|
||||
);
|
||||
|
||||
isSampling = true;
|
||||
currentlySampling = true;
|
||||
mem.write32(messagePointer, IPC::responseHeader(0x3, 1, 0));
|
||||
mem.write32(messagePointer + 4, Result::Success);
|
||||
}
|
||||
|
||||
void MICService::stopSampling(u32 messagePointer) {
|
||||
log("MIC::StopSampling\n");
|
||||
isSampling = false;
|
||||
currentlySampling = false;
|
||||
|
||||
mem.write32(messagePointer, IPC::responseHeader(0x5, 1, 0));
|
||||
mem.write32(messagePointer + 4, Result::Success);
|
||||
}
|
||||
|
||||
void MICService::isSampling(u32 messagePointer) {
|
||||
log("MIC::IsSampling");
|
||||
|
||||
mem.write32(messagePointer, IPC::responseHeader(0x6, 2, 0));
|
||||
mem.write32(messagePointer + 4, Result::Success);
|
||||
mem.write8(messagePointer + 8, currentlySampling ? 1 : 0);
|
||||
}
|
||||
|
||||
void MICService::setIirFilter(u32 messagePointer) {
|
||||
const u32 size = mem.read32(messagePointer + 4);
|
||||
const u32 pointer = mem.read32(messagePointer + 12);
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
ServiceManager::ServiceManager(std::span<u32, 16> regs, Memory& mem, GPU& gpu, u32& currentPID, Kernel& kernel, const EmulatorConfig& config)
|
||||
: regs(regs), mem(mem), kernel(kernel), ac(mem), am(mem), boss(mem), act(mem), apt(mem, kernel), cam(mem, kernel), cecd(mem, kernel), cfg(mem),
|
||||
dlp_srvr(mem), dsp(mem, kernel), hid(mem, kernel), http(mem), ir_user(mem, kernel), frd(mem), fs(mem, kernel),
|
||||
gsp_gpu(mem, gpu, kernel, currentPID), gsp_lcd(mem), ldr(mem), mcu_hwc(mem, config), mic(mem), nfc(mem, kernel), nim(mem), ndm(mem),
|
||||
gsp_gpu(mem, gpu, kernel, currentPID), gsp_lcd(mem), ldr(mem), mcu_hwc(mem, config), mic(mem, kernel), nfc(mem, kernel), nim(mem), ndm(mem),
|
||||
news_u(mem), ptm(mem, config), soc(mem), ssl(mem), y2r(mem, kernel) {}
|
||||
|
||||
static constexpr int MAX_NOTIFICATION_COUNT = 16;
|
||||
|
|
Loading…
Add table
Reference in a new issue