mirror of
https://github.com/wheremyfoodat/Panda3DS.git
synced 2025-07-14 03:07:08 +12:00
* Fix typo (#680) Co-authored-by: Noumi <139501014+noumidev@users.noreply.github.com> * More PTM stuff Co-Authored-By: Noumi <139501014+noumidev@users.noreply.github.com> * Make system language configurable * Fix building crypto++ for x64 target on Apple silicon MacOS * Attempt to switch to M1 runners again * Prevent selecting Vulkan renderer in Qt frontend and present a message * Libretro: Add system language option * Only enable audio by default on libretro for now * CMake: Bump version * Store configuration file in AppData root if not in working directory (#693) * Store configuration file in AppData root if not in working directory This fixes MacOS app bundles, as the emulator cannot write the config file into the app bundle. * Remove duplicate fs calls * I'm an idiot sandwich --------- Co-authored-by: wheremyfoodat <44909372+wheremyfoodat@users.noreply.github.com> * GL: Add usingGLES to driverInfo struct (#694) * Wayland fixes part 1 * Support GLES on desktop * Qt: Fix Wayland support Qt will only create a Wayland surface when show() is called on the main window and on the ScreenWidget. Thus, call the function before creating the GL context. Doesn't cause regressions on XWayland, untested in other platforms. Fixes #586 * No need to call screen->show() twice * Fix disabling Wayland & building on some distros (#700) * GLES: Properly stub out logic ops * Fix git versioning * Android_Build: Implement ccache (#703) * Android_Build: Implement ccache * Update Android_Build.yml * Update Android_Build.yml --------- Co-authored-by: wheremyfoodat <44909372+wheremyfoodat@users.noreply.github.com> * Removed dead Citra link in readme (#706) * CRO: Lighter icache flushes * Implement Luma icache SVCs * Add missing SVC logs * GPU: Add sw texture copies * Use vk::detail::DynamicLoader instead of vk::DynamicLoader (#710) * Use vk::detail::DynamicLoader instead of vk::DynamicLoader * Update renderer_vk.cpp * Vk: Fix typo * Vk: Lock CI runners to SDK version 1.3.301 temporarily * Vk: Fixing CI pt 2 * Vulkan: Fixing CI pt 3 * Vk: Fix typo * Temporarily give 80MB to all processes (#715) * Try to cross-compile Libretro core for arm64 (#717) * Try to cross-compile Libretro core for arm64 * Bonk * Update Hydra_Build.yml * [WIP] Libretro: Add audio support (#714) * Libretro: Add audio support * Adding audio interface part 1 * Audio device pt 2 * More audio device * More audio device * Morea uudi odevice * More audio device * More audio device * More audio device --------- Co-authored-by: wheremyfoodat <44909372+wheremyfoodat@users.noreply.github.com> * Libretro audio device: Fix frame count * Mark audio devices as final * Add toggle for libretro audio device (#719) * Very important work (#720) * Very important work * Most important fix * Add more HLE service calls for eshop (#721) * CI: Fix Vulkan SDK action (#723) * GPU registers: Fix writes to some registers ignoring the mask (#725) Co-authored-by: henry <23128103+atem2069@users.noreply.github.com> * OLED theme * OLED theme config fix (#736) Co-authored-by: smiRaphi <neogt404@gmail.com> * Adding Swedish translation * Fix Metal renderer compilation on iOS * [Core] Improve iOS compilation workflow * [Qt] Hook Swedish to UI * AppDataDocumentProvider: Typo (#740) * More iOS work * More iOS progress * More iOS work * AppDataDocumentProvider: Add missing ``COLUMN_FLAGS`` in the default document projectation (#741) Fixes unable to copy files from device to app's internal storage problem * More iOS work * ios: Simplify MTKView interface (still doesn't work though) * ios: Pass CAMetalLayer instead of void* to Obj-C++ bridging header * Fix bridging cast * FINALLY IOS GRAPHICS * ios: Remove printf spam * Metal: Reimplement some texture formats on iOS * metal: implement texture decoder * metal: check for format support * metal: implement texture swizzling * metal: remove unused texture functions * Shadergen types: Add Metal & MSL * Format * Undo submodule changes * Readme: Add Chonkystation 3 * Metal: Use std::unique_ptr for texture decode * AppDataDocumentProvider: Allow to remove documents (#744) * AppDataDocumentProvider: Allow to remove documents * Typo * Metal renderer fixes for iOS * iOS driver: Add doc comments * iOS: Add frontend & frontend build files (#746) * iOS: Add SwiftUI part to repo * Add iOS build script * Update SDL2 submodule * Fix iOS build script * CI: Update xcode tools for iOS * Update iOS_Build.yml * Update iOS build * Lower XCode version * A * Update project.pbxproj * Update iOS_Build.yml * Update iOS_Build.yml * Update build.sh * iOS: Fail on build error * iOS: Add file picker (#747) * iOS: Add file picker * Fix lock placement * Qt: Add runpog icon (#752) * Update discord-rpc submodule (#753) * Remove cryptoppwin submodule (#754) * Add optional texture hashing * Fix build on new Vk SDK (#757) Co-authored-by: Nadia Holmquist Pedersen <893884+nadiaholmquist@users.noreply.github.com> * CI: Use new Vulkan SDK --------- Co-authored-by: Noumi <139501014+noumidev@users.noreply.github.com> Co-authored-by: Thomas <thomas@thomasw.dev> Co-authored-by: Thomas <twvd@users.noreply.github.com> Co-authored-by: Daniel López Guimaraes <danielectra@outlook.com> Co-authored-by: Jonian Guveli <jonian@hardpixel.eu> Co-authored-by: Ishan09811 <156402647+Ishan09811@users.noreply.github.com> Co-authored-by: Auxy6858 <71662994+Auxy6858@users.noreply.github.com> Co-authored-by: Paris Oplopoios <parisoplop@gmail.com> Co-authored-by: henry <23128103+atem2069@users.noreply.github.com> Co-authored-by: smiRaphi <neogt404@gmail.com> Co-authored-by: smiRaphi <87574679+smiRaphi@users.noreply.github.com> Co-authored-by: Daniel Nylander <po@danielnylander.se> Co-authored-by: Samuliak <samuliak77@gmail.com> Co-authored-by: Albert <45282415+ggrtk@users.noreply.github.com> Co-authored-by: Nadia Holmquist Pedersen <893884+nadiaholmquist@users.noreply.github.com>
257 lines
No EOL
8.5 KiB
C++
257 lines
No EOL
8.5 KiB
C++
#pragma once
|
|
#include <array>
|
|
#include <cassert>
|
|
#include <limits>
|
|
#include <span>
|
|
#include <string>
|
|
#include <vector>
|
|
|
|
#include "config.hpp"
|
|
#include "helpers.hpp"
|
|
#include "kernel_types.hpp"
|
|
#include "logger.hpp"
|
|
#include "memory.hpp"
|
|
#include "resource_limits.hpp"
|
|
#include "services/service_manager.hpp"
|
|
|
|
class CPU;
|
|
struct Scheduler;
|
|
|
|
class Kernel {
|
|
using Handle = HorizonHandle;
|
|
|
|
std::span<u32, 16> regs;
|
|
CPU& cpu;
|
|
Memory& mem;
|
|
|
|
// The handle number for the next kernel object to be created
|
|
u32 handleCounter;
|
|
// A list of our OS threads, the max number of which depends on the resource limit (hardcoded 32 per process on retail it seems).
|
|
// We have an extra thread for when no thread is capable of running. This thread is called the "idle thread" in our code
|
|
// This thread is set up in setupIdleThread and just yields in a loop to see if any other thread has woken up
|
|
std::array<Thread, appResourceLimits.maxThreads + 1> threads;
|
|
static constexpr int idleThreadIndex = appResourceLimits.maxThreads;
|
|
// Our waitlist system uses a bitfield of 64 bits to show which threads are waiting on an object.
|
|
// That means we can have a maximum of 63 threads + 1 idle thread. This assert should never trigger because the max thread # is 32
|
|
// But we have it here for safety purposes
|
|
static_assert(appResourceLimits.maxThreads <= 63, "The waitlist system is built on the premise that <= 63 threads max can be active");
|
|
|
|
std::vector<KernelObject> objects;
|
|
std::vector<Handle> portHandles;
|
|
std::vector<Handle> mutexHandles;
|
|
std::vector<Handle> timerHandles;
|
|
|
|
// Thread indices, sorted by priority
|
|
std::vector<int> threadIndices;
|
|
|
|
Handle currentProcess;
|
|
Handle mainThread;
|
|
int currentThreadIndex;
|
|
Handle srvHandle; // Handle for the special service manager port "srv:"
|
|
Handle errorPortHandle; // Handle for the err:f port used for displaying errors
|
|
|
|
u32 arbiterCount;
|
|
u32 threadCount; // How many threads in our thread pool have been used as of now (Up to 32)
|
|
u32 aliveThreadCount; // How many of these threads are actually alive?
|
|
ServiceManager serviceManager;
|
|
|
|
// Top 8 bits are the major version, bottom 8 are the minor version
|
|
u16 kernelVersion = 0;
|
|
|
|
// Shows whether a reschedule will be need
|
|
bool needReschedule = false;
|
|
|
|
Handle makeArbiter();
|
|
Handle makeProcess(u32 id);
|
|
Handle makePort(const char* name);
|
|
Handle makeSession(Handle port);
|
|
Handle makeThread(u32 entrypoint, u32 initialSP, u32 priority, ProcessorID id, u32 arg,ThreadStatus status = ThreadStatus::Dormant);
|
|
Handle makeMemoryBlock(u32 addr, u32 size, u32 myPermission, u32 otherPermission);
|
|
|
|
public:
|
|
// 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) {
|
|
object->getData<Event>()->fired = false;
|
|
}
|
|
}
|
|
|
|
private:
|
|
void signalArbiter(u32 waitingAddress, s32 threadCount);
|
|
void sleepThread(s64 ns);
|
|
void sleepThreadOnArbiter(u32 waitingAddress);
|
|
void switchThread(int newThreadIndex);
|
|
void sortThreads();
|
|
std::optional<int> getNextThread();
|
|
void rescheduleThreads();
|
|
bool canThreadRun(const Thread& t);
|
|
bool shouldWaitOnObject(KernelObject* object);
|
|
void releaseMutex(Mutex* moo);
|
|
void cancelTimer(Timer* timer);
|
|
void signalTimer(Handle timerHandle, Timer* timer);
|
|
u64 getWakeupTick(s64 ns);
|
|
|
|
// Wake up the thread with the highest priority out of all threads in the waitlist
|
|
// Returns the index of the woken up thread
|
|
// Do not call this function with an empty waitlist!!!
|
|
int wakeupOneThread(u64 waitlist, Handle handle);
|
|
void wakeupAllThreads(u64 waitlist, Handle handle);
|
|
|
|
std::optional<Handle> getPortHandle(const char* name);
|
|
void deleteObjectData(KernelObject& object);
|
|
|
|
KernelObject* getProcessFromPID(Handle handle);
|
|
s32 getCurrentResourceValue(const KernelObject* limit, u32 resourceName);
|
|
u32 getMaxForResource(const KernelObject* limit, u32 resourceName);
|
|
u32 getTLSPointer();
|
|
void setupIdleThread();
|
|
|
|
void acquireSyncObject(KernelObject* object, const Thread& thread);
|
|
bool isWaitable(const KernelObject* object);
|
|
|
|
// Functions for the err:f port
|
|
void handleErrorSyncRequest(u32 messagePointer);
|
|
void throwError(u32 messagePointer);
|
|
|
|
std::string getProcessName(u32 pid);
|
|
const char* resetTypeToString(u32 type);
|
|
|
|
MAKE_LOG_FUNCTION(log, kernelLogger)
|
|
MAKE_LOG_FUNCTION(logSVC, svcLogger)
|
|
MAKE_LOG_FUNCTION(logThread, threadLogger)
|
|
MAKE_LOG_FUNCTION(logError, errorLogger)
|
|
MAKE_LOG_FUNCTION(logFileIO, fileIOLogger)
|
|
MAKE_LOG_FUNCTION_USER(logDebugString, debugStringLogger)
|
|
|
|
// SVC implementations
|
|
void arbitrateAddress();
|
|
void createAddressArbiter();
|
|
void createMemoryBlock();
|
|
void createThread();
|
|
void controlMemory();
|
|
void duplicateHandle();
|
|
void exitThread();
|
|
void mapMemoryBlock();
|
|
void unmapMemoryBlock();
|
|
void queryMemory();
|
|
void getCurrentProcessorNumber();
|
|
void getProcessID();
|
|
void getProcessInfo();
|
|
void getResourceLimit();
|
|
void getResourceLimitLimitValues();
|
|
void getResourceLimitCurrentValues();
|
|
void getSystemInfo();
|
|
void getSystemTick();
|
|
void getThreadContext();
|
|
void getThreadID();
|
|
void getThreadIdealProcessor();
|
|
void getThreadPriority();
|
|
void sendSyncRequest();
|
|
void setThreadPriority();
|
|
void svcCancelTimer();
|
|
void svcClearEvent();
|
|
void svcClearTimer();
|
|
void svcCloseHandle();
|
|
void svcCreateEvent();
|
|
void svcCreateMutex();
|
|
void svcCreateSemaphore();
|
|
void svcCreateTimer();
|
|
void svcReleaseMutex();
|
|
void svcReleaseSemaphore();
|
|
void svcSignalEvent();
|
|
void svcSetTimer();
|
|
void svcSleepThread();
|
|
void svcInvalidateInstructionCacheRange();
|
|
void svcInvalidateEntireInstructionCache();
|
|
void connectToPort();
|
|
void outputDebugString();
|
|
void waitSynchronization1();
|
|
void waitSynchronizationN();
|
|
|
|
// File operations
|
|
void handleFileOperation(u32 messagePointer, Handle file);
|
|
void closeFile(u32 messagePointer, Handle file);
|
|
void flushFile(u32 messagePointer, Handle file);
|
|
void readFile(u32 messagePointer, Handle file);
|
|
void writeFile(u32 messagePointer, Handle file);
|
|
void getFileSize(u32 messagePointer, Handle file);
|
|
void openLinkFile(u32 messagePointer, Handle file);
|
|
void setFileSize(u32 messagePointer, Handle file);
|
|
void setFilePriority(u32 messagePointer, Handle file);
|
|
|
|
// Directory operations
|
|
void handleDirectoryOperation(u32 messagePointer, Handle directory);
|
|
void closeDirectory(u32 messagePointer, Handle directory);
|
|
void readDirectory(u32 messagePointer, Handle directory);
|
|
|
|
public:
|
|
Kernel(CPU& cpu, Memory& mem, GPU& gpu, const EmulatorConfig& config);
|
|
void initializeFS() { return serviceManager.initializeFS(); }
|
|
void setVersion(u8 major, u8 minor);
|
|
void serviceSVC(u32 svc);
|
|
void reset();
|
|
|
|
void requireReschedule() { needReschedule = true; }
|
|
|
|
void evalReschedule() {
|
|
if (needReschedule) {
|
|
needReschedule = false;
|
|
rescheduleThreads();
|
|
}
|
|
}
|
|
|
|
Handle makeObject(KernelObjectType type) {
|
|
if (handleCounter > KernelHandles::Max) [[unlikely]] {
|
|
Helpers::panic("Hlep we somehow created enough kernel objects to overflow this thing");
|
|
}
|
|
|
|
objects.push_back(KernelObject(handleCounter, type));
|
|
log("Created %s object with handle %d\n", kernelObjectTypeToString(type), handleCounter);
|
|
return handleCounter++;
|
|
}
|
|
|
|
std::vector<KernelObject>& getObjects() {
|
|
return objects;
|
|
}
|
|
|
|
// Get pointer to the object with the specified handle
|
|
KernelObject* getObject(Handle handle) {
|
|
// Accessing an object that has not been created
|
|
if (handle >= objects.size()) [[unlikely]] {
|
|
return nullptr;
|
|
}
|
|
|
|
return &objects[handle];
|
|
}
|
|
|
|
// Get pointer to the object with the specified handle and type
|
|
KernelObject* getObject(Handle handle, KernelObjectType type) {
|
|
if (handle >= objects.size() || objects[handle].type != type) [[unlikely]] {
|
|
return nullptr;
|
|
}
|
|
|
|
return &objects[handle];
|
|
}
|
|
|
|
ServiceManager& getServiceManager() { return serviceManager; }
|
|
Scheduler& getScheduler();
|
|
|
|
void sendGPUInterrupt(GPUInterrupt type) { serviceManager.sendGPUInterrupt(type); }
|
|
void clearInstructionCache();
|
|
void clearInstructionCacheRange(u32 start, u32 size);
|
|
u32 getSharedFontVaddr();
|
|
}; |