--- /dev/null
+// Shamelessly stolen from ctrtool.
+typedef struct {
+ u8 signature[0x100];
+ u8 magic[4];
+ u8 contentsize[4];
+ u8 partitionid[8];
+ u8 makercode[2];
+ u8 version[2];
+ u8 reserved0[4];
+ u8 programid[8];
+ u8 tempflag;
+ u8 reserved1[0x2f];
+ u8 productcode[0x10];
+ u8 extendedheaderhash[0x20];
+ u8 extendedheadersize[4];
+ u8 reserved2[4];
+ u8 flags[8];
+ u8 plainregionoffset[4];
+ u8 plainregionsize[4];
+ u8 reserved3[8];
+ u8 exefsoffset[4];
+ u8 exefssize[4];
+ u8 exefshashregionsize[4];
+ u8 reserved4[4];
+ u8 romfsoffset[4];
+ u8 romfssize[4];
+ u8 romfshashregionsize[4];
+ u8 reserved5[4];
+ u8 exefssuperblockhash[0x20];
+ u8 romfssuperblockhash[0x20];
+} ctr_ncchheader;
+
+// Exheader
+typedef struct {
+ u8 reserved[5];
+ u8 flag;
+ u8 remasterversion[2];
+} exheader_systeminfoflags;
+
+typedef struct {
+ u8 address[4];
+ u8 nummaxpages[4];
+ u8 codesize[4];
+} exheader_codesegmentinfo;
+
+typedef struct {
+ u8 name[8];
+ exheader_systeminfoflags flags;
+ exheader_codesegmentinfo text;
+ u8 stacksize[4];
+ exheader_codesegmentinfo ro;
+ u8 reserved[4];
+ exheader_codesegmentinfo data;
+ u8 bsssize[4];
+} exheader_codesetinfo;
+
+typedef struct {
+ u8 programid[0x30][8];
+} exheader_dependencylist;
+
+typedef struct {
+ u8 savedatasize[4];
+ u8 reserved[4];
+ u8 jumpid[8];
+ u8 reserved2[0x30];
+} exheader_systeminfo;
+
+typedef struct {
+ u8 extsavedataid[8];
+ u8 systemsavedataid[8];
+ u8 reserved[8];
+ u8 accessinfo[7];
+ u8 otherattributes;
+} exheader_storageinfo;
+
+typedef struct {
+ u8 programid[8];
+ u8 flags[8];
+ u8 resourcelimitdescriptor[0x10][2];
+ exheader_storageinfo storageinfo;
+ u8 serviceaccesscontrol[0x20][8];
+ u8 reserved[0x1f];
+ u8 resourcelimitcategory;
+} exheader_arm11systemlocalcaps;
+
+typedef struct {
+ u8 descriptors[28][4];
+ u8 reserved[0x10];
+} exheader_arm11kernelcapabilities;
+
+typedef struct {
+ u8 descriptors[15];
+ u8 descversion;
+} exheader_arm9accesscontrol;
+
+typedef struct {
+ // systemcontrol info {
+ // coreinfo {
+ exheader_codesetinfo codesetinfo;
+ exheader_dependencylist deplist;
+ // }
+ exheader_systeminfo systeminfo;
+ // }
+ // accesscontrolinfo {
+ exheader_arm11systemlocalcaps arm11systemlocalcaps;
+ exheader_arm11kernelcapabilities arm11kernelcaps;
+ exheader_arm9accesscontrol arm9accesscontrol;
+ // }
+ struct {
+ u8 signature[0x100];
+ u8 ncchpubkeymodulus[0x100];
+ exheader_arm11systemlocalcaps arm11systemlocalcaps;
+ exheader_arm11kernelcapabilities arm11kernelcaps;
+ exheader_arm9accesscontrol arm9accesscontrol;
+ } accessdesc;
+} exheader_header;
+
+// ExeFS
+typedef struct {
+ u8 name[8];
+ u8 offset[4];
+ u8 size[4];
+} exefs_sectionheader;
+
+typedef struct {
+ exefs_sectionheader section[8];
+ u8 reserved[0x80];
+ u8 hashes[8][0x20];
+} exefs_header;
+
+int Boot(KKernel* kernel);
--- /dev/null
+#ifndef _COMMON_H
+#define _COMMON_H
+
+#include <string>
+#include <stdlib.h>
+#include <string.h>
+#include <stddef.h>
+#include <stdint.h>
+#include <inttypes.h>
+#include "Platform.h"
+
+typedef uint8_t u8;
+typedef uint16_t u16;
+typedef uint32_t u32;
+typedef uint64_t u64;
+
+typedef int8_t s8;
+typedef int16_t s16;
+typedef int32_t s32;
+typedef int64_t s64;
+
+typedef unsigned int uint;
+typedef signed int sint;
+
+typedef uint8_t bit8;
+typedef uint16_t bit16;
+typedef uint32_t bit32;
+typedef uint64_t bit64;
+
+
+
+
+#ifdef __GNUC__
+#define likely(x) __builtin_expect(!!(x), 1)
+#define unlikely(x) __builtin_expect(!!(x), 0)
+#else
+#define likely(x) (x)
+#define unlikely(x) (x)
+#endif
+
+#define notcritical(x) (x)
+
+#include "Log.h"
+
+#endif
--- /dev/null
+#include "../external/gl3w/include/GL/gl3w.h"
+#define GLFW_INCLUDE_GLU
+#include <GLFW/glfw3.h>
+
+#include "../external/imgui/imgui.h"
+#include "../external/imgui/examples/opengl3_example/imgui_impl_glfw_gl3.h"
+
+#include "gui/MainWindow.h"
--- /dev/null
+#pragma once
+#include "hardware/IO.h"
+#include "hardware/IPC.h"
+#include "hardware/HASH.h"
+#include "hardware/I2C.h"
+#include "hardware/GPIO.h"
+#include "hardware/PDN.h"
+#include "hardware/SPI.h"
+#include "hardware/DSP.h"
+#include "hardware/GPU.h"
+#include "hardware/HID.h"
+#include "hardware/MIC.h"
\ No newline at end of file
--- /dev/null
+#include "Common.h"
+#include <unordered_map>
+
+typedef s32 Result;
+const Result Success = 0;
+
+typedef u32 Handle;
+
+enum ClassName {
+ KAutoObject_Class,
+ KSynchronizationObject_Class,
+ KProcess_Class,
+ KThread_Class,
+ KTimer_Class,
+ KMutex_Class,
+ KSemaphore_Class,
+ KAddressArbiter_Class,
+ KClientPort_Class,
+ KClientSession_Class,
+ KServerPort_Class,
+ KServerSession_Class,
+ KMemoryBlock_Class,
+ KResourceLimit_Class,
+ KCodeSet_Class,
+ KEvent_Class,
+ KInterrupt_Class,
+ KPort_Class,
+ KSession_Class,
+ KSharedMemory_Class,
+ KDmaObject_Class
+};
+
+
+#include "Util.h"
+
+class KProcess;
+
+struct ThreadContext {
+ u32 cpu_registers[13];
+ u32 sp;
+ u32 lr;
+ u32 pc;
+ u32 cpsr;
+ u32 fpu_registers[32];
+ u32 fpscr;
+ u32 fpexc;
+ // These are not part of native ThreadContext, but needed by emu
+ u32 reg_15;
+ u32 mode;
+
+ KProcess* m_pro;
+
+ u32 NFlag, ZFlag, CFlag, VFlag, IFFlags;
+};
+
+#include "kernel/TimedEvent.h"
+#include "kernel/AutoObject.h"
+#include "kernel/AutoObjectRef.h"
+#include "kernel/LinkedList.h"
+#include "kernel/SynchronizationObject.h"
+#include "kernel/HandleTable.h"
+#include "kernel/MemoryMap.h"
+#include "kernel/CodeSet.h"
+#include "kernel/ResourceLimit.h"
+#include "kernel/Thread.h"
+#include "arm/interpreter/arm_interpreter.h"
+#include "arm/dyncom/arm_dyncom.h"
+#include "kernel/Process.h"
+#include "arm/ArmCore.h"
+#include "kernel/Kernel.h"
+#include "kernel/Scheduler.h"
+#include "kernel/Memory.h"
+#include "kernel/AddressArbiter.h"
+#include "kernel/Swi.h"
+#include "kernel/Event.h"
+#include "kernel/Semaphore.h"
+#include "kernel/Mutex.h"
+#include "kernel/Interrupt.h"
+#include "kernel/ClientSession.h"
+#include "kernel/ServerSession.h"
+#include "kernel/Session.h"
+#include "kernel/ClientPort.h"
+#include "kernel/ServerPort.h"
+#include "kernel/Port.h"
+#include "kernel/SharedMemory.h"
+#include "kernel/DmaObject.h"
+#include "kernel/Timer.h"
+
+
+extern KThread* current_thread; // 0xFFFF9000
+extern KProcess* current_process; // 0xFFFF9004
+extern KScheduler* current_scheduler; // 0xFFFF9008
+extern KThread* current_core_first_thread; // *0xFFFF900C + 0xC- first thread spawned on a given core, i think 0x2F0-0x2FC are arguments or something
+
+extern SwitchContext* sc; // 0xFFF2D0A8 (can change occasionally)
--- /dev/null
+#define LOG(...) do { \
+ printf(__VA_ARGS__); \
+ printf("\n"); \
+ } while(0);
+#define XDSERROR(...) do { \
+ printf(__VA_ARGS__); \
+ printf("\n"); \
+ } while(0);
--- /dev/null
+#pragma once
+
+////////////////////////////////////////////////////////////////////////////////////////////////////
+// Platform definitions
+/// Enumeration for defining the supported platforms
+#define PLATFORM_NULL 0
+#define PLATFORM_WINDOWS 1
+#define PLATFORM_LINUX 2
+
+////////////////////////////////////////////////////////////////////////////////////////////////////
+// Platform detection
+#ifndef EMU_PLATFORM
+#if defined( __WIN32__ ) || defined( _WIN32 )
+#define EMU_PLATFORM PLATFORM_WINDOWS
+#elif defined(__linux__)
+#define EMU_PLATFORM PLATFORM_LINUX
+#else
+#error unsupported platform
+#endif
+#endif
+#if defined(__x86_64__) || defined(_M_X64) || defined(__alpha__) || defined(__ia64__)
+#define EMU_ARCHITECTURE_X64
+#else
+#define EMU_ARCHITECTURE_X86
+#endif
+
+
+#ifndef __func__
+#define __func__ __FUNCTION__
+#endif
--- /dev/null
+#include "process9/file.h"
+#include "process9/p9fs.h"
+#include "process9/pm.h"
+#include "process9/ps.h"
+#include "process9/mc.h"
+#include "process9/am.h"
+#include "process9/PXI.h"
--- /dev/null
+#include <stdio.h>
+
+#define TEST_START(test_name) \
+ u32 __num_passed = 0; \
+ u32 __num_failed = 0; \
+ const char* __test_name = test_name;
+
+#define TEST_END() \
+ printf("Total: %d, Passed: %d, Failed: %d\n", \
+ __num_passed+__num_failed, __num_passed, __num_failed); \
+ return __num_failed != 0;
+
+#define EXPECT(statement, desc) \
+ if(!(statement)) { \
+ fprintf(stderr, "%s::" desc " FAIL\n", __test_name); \
+ __num_failed++; \
+ } \
+ else { \
+ fprintf(stderr, "%s::" desc " PASS\n", __test_name); \
+ __num_passed++; \
+ }
--- /dev/null
+#pragma once
+
+#include "util/Mutex.h"
+#include "util/Common.h"
+#include "util/LowPath.h"
+
+#ifdef _WIN32
+#include <direct.h>
+#include <io.h>
+#else
+#include <unistd.h>
+#endif
+
+#define strcpy_s(a,b,c) strncpy(a,c,b)
+
+#ifdef _WIN32
+
+#ifndef snprintf
+#define snprintf sprintf_s
+#endif
+
+#ifndef fseek64
+#define fseek64 _fseeki64
+#endif
+
+#ifndef ftell64
+#define ftell64 _ftelli64
+#endif
+
+#ifndef ftruncate
+#define ftruncate _chsize_s
+#endif
+
+#define open _open
+#define close _close
+#define fileno _fileno
+
+#define O_EXCL _O_EXCL
+#define O_WRONLY _O_WRONLY
+
+#else
+#ifndef fseek64
+#define fseek64 fseeko
+#endif
+
+#ifndef ftell64
+#define ftell64 ftello
+#endif
+#endif
\ No newline at end of file
--- /dev/null
+enum ArmCoreState {
+ STOPPED=0,
+ RUNNING=1,
+ UNHANDLED_EXCEPTION=2,
+ KERNEL_PANIC=3,
+ PAUSED_DEBUG=4
+};
+
+class KKernel;
+
+class KArmCore {
+public:
+ KArmCore(KKernel* kernel);
+
+ u64 RunCycles(uint cycles);
+ ArmCoreState GetState();
+ u32 GetRegister(uint id);
+ void SetRegister(uint id,uint data);
+ void SetThread(KThread* thread);
+ void ReSchedule();
+ void Addticks(int ticks);
+ s64 Getticks();
+
+private:
+ ARM_DynCom m_cpu;
+ KKernel* m_kernel;
+ KThread* m_thread;
+};
--- /dev/null
+class MainWindow {
+public:
+ MainWindow();
+};
--- /dev/null
+class DSP : public IOHW {
+
+public:
+ DSP::DSP(KKernel * kernel);
+ u8 Read8(u32 addr);
+ u16 Read16(u32 addr);
+ u32 Read32(u32 addr);
+ void Write8(u32 addr, u8 data);
+ void Write16(u32 addr, u16 data);
+ void Write32(u32 addr, u32 data);
+protected:
+ KKernel * m_kernel;
+private:
+ //HW stuff
+ u16 m_DSP_PDATA, m_DSP_PADR, m_DSP_PCFG, m_DSP_PSTS, m_DSP_PSEM, m_DSP_PMASK, m_DSP_PCLEAR, m_DSP_SEM;
+ u16 m_DSP_CMD[3], m_DSP_REP[3];
+
+ u16 DSPreadCMD(u8 numb);
+ void DSPwriteRES(u16 data ,u8 numb);
+ //HLE software stuff
+ u32 m_phase;
+ void Reset();
+ void REPread(u8 id);
+ void CMDwrite(u8 id);
+};
\ No newline at end of file
--- /dev/null
+class GPIO : public IOHW {
+
+public:
+ GPIO::GPIO(KKernel * kernel);
+ u8 Read8(u32 addr);
+ u16 Read16(u32 addr);
+ u32 Read32(u32 addr);
+ void Write8(u32 addr, u8 data);
+ void Write16(u32 addr, u16 data);
+ void Write32(u32 addr, u32 data);
+protected:
+ u32 m_IO, m_DIR;
+ KKernel * m_kernel;
+};
\ No newline at end of file
--- /dev/null
+#include "hardware/GPU/Syn.h"
+
+class GPUHW : public IOHW {
+
+public:
+ GPUHW(KKernel * kernel);
+ u8 Read8(u32 addr);
+ u16 Read16(u32 addr);
+ u32 Read32(u32 addr);
+ void Write8(u32 addr, u8 data);
+ void Write16(u32 addr, u16 data);
+ void Write32(u32 addr, u32 data);
+ KKernel * m_kernel;
+protected:
+ u32 m_data[0x8000];
+ Syncer * top;
+ Syncer * bot;
+};
\ No newline at end of file
--- /dev/null
+class GPUHW;
+
+class Syncer : public KTimeedEvent
+{
+public:
+ Syncer(GPUHW *owner, bool bottom);
+ ~Syncer();
+ virtual void trigger_event();
+
+private:
+ GPUHW *m_owner;
+ bool m_bottom;
+};
+
+
--- /dev/null
+class HWHASH2;
+
+static const unsigned int SHA256_BLOCK_SIZE = (512 / 8);
+
+class HWHASH : public IOHW {
+
+public:
+ HWHASH(KKernel * kernel);
+ u8 Read8(u32 addr);
+ u16 Read16(u32 addr);
+ u32 Read32(u32 addr);
+ void Write8(u32 addr, u8 data);
+ void Write16(u32 addr, u16 data);
+ void Write32(u32 addr, u32 data);
+ void finalise();
+ void transform(const u8 *message, u32 block_nb);
+ void update(const u8 *message, u32 len);
+ KKernel * m_kernel;
+private:
+ u32 HASH_CNT;
+ u32 m_total_len;
+ u32 m_len;
+ u8 m_block[2 * SHA256_BLOCK_SIZE];
+ u32 m_h[8];
+ HWHASH2* m_HASH2;
+ friend class HWHASH2;
+};
+class HWHASH2 : public IOHW {
+
+public:
+ HWHASH2(KKernel * kernel, HWHASH * hash1);
+ u8 Read8(u32 addr);
+ u16 Read16(u32 addr);
+ u32 Read32(u32 addr);
+ void Write8(u32 addr, u8 data);
+ void Write16(u32 addr, u16 data);
+ void Write32(u32 addr, u32 data);
+ void flush();
+
+ KKernel * m_kernel;
+ HWHASH * m_hash1;
+private:
+ u8 m_buffer[0x40];
+ u32 m_curret;
+};
\ No newline at end of file
--- /dev/null
+class HID : public IOHW {
+
+public:
+ HID::HID(KKernel * kernel);
+ u8 Read8(u32 addr);
+ u16 Read16(u32 addr);
+ u32 Read32(u32 addr);
+ void Write8(u32 addr, u8 data);
+ void Write16(u32 addr, u16 data);
+ void Write32(u32 addr, u32 data);
+protected:
+ u32 m_IO, m_DIR;
+ KKernel * m_kernel;
+};
\ No newline at end of file
--- /dev/null
+class IOI2C : public IOHW {
+
+public:
+ IOI2C::IOI2C(KKernel * kernel);
+ u8 Read8(u32 addr);
+ u16 Read16(u32 addr);
+ u32 Read32(u32 addr);
+ void Write8(u32 addr, u8 data);
+ void Write16(u32 addr, u16 data);
+ void Write32(u32 addr, u32 data);
+protected:
+ virtual bool Read(u8 &data, u8 device, bool end, bool& noack) = 0;
+ virtual bool Write(u8 &data, u8 device, bool end, bool& noack) = 0;
+ KKernel* m_kernel;
+ u8 m_buffer[0x10000];
+ int m_index;
+ u8 m_CNT;
+ u8 m_data;
+ u8 m_deviceID;
+};
+
+#include "i2c/Bus1.h"
+#include "i2c/Bus2.h"
+#include "i2c/Bus3.h"
\ No newline at end of file
--- /dev/null
+class IOHW {
+
+public:
+ virtual u8 Read8(u32 addr) = 0;
+ virtual u16 Read16(u32 addr) = 0;
+ virtual u32 Read32(u32 addr) = 0;
+ virtual void Write8(u32 addr, u8 data) = 0;
+ virtual void Write16(u32 addr, u16 data) = 0;
+ virtual void Write32(u32 addr, u32 data) = 0;
+
+};
\ No newline at end of file
--- /dev/null
+#define FIFOSIZE 0x10
+struct FIFO {
+ u32 data[FIFOSIZE];
+ int nextwrite;
+ int nextread;
+ int size;
+};
+
+//IRQ 50 "new 3DS IRQ interrupt from IPCSYNC"
+//IRQ 51 "maybe the old IRQ stuff but not sure"
+//IRQ 52 "Receive Fifo Not Empty"
+//IRQ 53 "Send Fifo Empty IRQ"
+
+class HWIPC : public IOHW {
+
+public:
+ HWIPC(KKernel * kernel);
+ u8 Read8(u32 addr);
+ u16 Read16(u32 addr);
+ u32 Read32(u32 addr);
+ void Write8(u32 addr, u8 data);
+ void Write16(u32 addr, u16 data);
+ void Write32(u32 addr, u32 data);
+
+ u32 FIFOp9read();
+ void FIFOp9write(u32 data);
+
+ u8 m_IPCSYNCP9;
+ u8 m_IPCSYNCP11;
+ u8 m_IPCIRQ;
+ u8 m_SENDFIFOSTAT;
+ u8 m_RECVFIFOSTAT_ERROR;
+
+ virtual void FIFOReadBackCall() = 0; //everything even flash
+ virtual void FIFOWriteBackCall() = 0; //everything even flash
+ virtual void FIFOIRQ() = 0;
+ virtual void FIFOIRQOLD() = 0; //this is unused on the 3DS
+ KKernel * m_kernel;
+private:
+
+ u32 FIFOget(struct FIFO* FIFO);
+ void FIFOset(struct FIFO* FIFO, u32 data);
+ struct FIFO m_recvarm9;
+ struct FIFO m_sendarm9;
+};
\ No newline at end of file
--- /dev/null
+class MIC : public IOHW {
+
+public:
+ MIC::MIC(KKernel * kernel);
+ u8 Read8(u32 addr);
+ u16 Read16(u32 addr);
+ u32 Read32(u32 addr);
+ void Write8(u32 addr, u8 data);
+ void Write16(u32 addr, u16 data);
+ void Write32(u32 addr, u32 data);
+protected:
+ u16 m_CNT;
+ /*
+ Bit15 running
+ Bit14 unknown set at starting mic clear while pause
+ Bit13 unknown set at starting mic clear while pause
+ Bit12 clear error or clear fifo full flag?
+ Bit11 error or fifo full flag
+ Bit8 Fifo not empty
+ Bit2-3 sample_rate
+ Bit1 unknown set at at starting mic
+ */
+ KKernel * m_kernel;
+};
\ No newline at end of file
--- /dev/null
+class PDN : public IOHW {
+
+public:
+ PDN::PDN(KKernel * kernel);
+ u8 Read8(u32 addr);
+ u16 Read16(u32 addr);
+ u32 Read32(u32 addr);
+ void Write8(u32 addr, u8 data);
+ void Write16(u32 addr, u16 data);
+ void Write32(u32 addr, u32 data);
+ u16 m_SPI_CNT;
+protected:
+ KKernel * m_kernel;
+};
\ No newline at end of file
--- /dev/null
+class SPI : public IOHW {
+
+public:
+ SPI::SPI(KKernel * kernel);
+ u8 Read8(u32 addr);
+ u16 Read16(u32 addr);
+ u32 Read32(u32 addr);
+ void Write8(u32 addr, u8 data);
+ void Write16(u32 addr, u16 data);
+ void Write32(u32 addr, u32 data);
+protected:
+ KKernel * m_kernel;
+private:
+ u32 SPI_NEW_CNT;
+};
\ No newline at end of file
--- /dev/null
+class HWBUS1 : public IOI2C {
+public:
+ HWBUS1(KKernel * k);
+protected:
+ virtual bool Read(u8 &data, u8 device, bool end, bool &noack);
+ virtual bool Write(u8 &data, u8 device, bool end, bool &noack);
+private:
+ u32 m_register;
+ bool m_active;
+};
\ No newline at end of file
--- /dev/null
+class HWBUS2 : public IOI2C {
+public:
+ HWBUS2(KKernel * k);
+protected:
+ virtual bool Read(u8 &data, u8 device, bool end, bool& noack);
+ virtual bool Write(u8 &data, u8 device, bool end, bool& noack);
+private:
+ u32 m_register;
+ bool m_active;
+};
\ No newline at end of file
--- /dev/null
+class HWBUS3 : public IOI2C {
+public:
+ HWBUS3(KKernel * k);
+protected:
+ virtual bool Read(u8 &data, u8 device, bool end, bool& noack);
+ virtual bool Write(u8 &data, u8 device, bool end, bool& noack);
+private:
+ u32 m_register;
+ bool m_active;
+};
\ No newline at end of file
--- /dev/null
+
+
+class KAddressArbiter : public KAutoObject
+{
+public:
+ typedef KAutoObject super;
+
+ KAddressArbiter(KProcess* owner);
+ ~KAddressArbiter();
+
+ Result ArbitrateAddress(u32 addr, u32 type, s32 val, s64 time, KThread * caller);
+
+
+
+ bool IsInstanceOf(ClassName name);
+ static const ClassName name = KAddressArbiter_Class;
+
+private:
+ KProcess* m_owner;
+ KLinkedList<KThread> arbiterlist;
+ PMutex m_Mutex;
+};
\ No newline at end of file
--- /dev/null
+class KAutoObject {
+public:
+ KAutoObject();
+ void AcquireReference();
+ void ReleaseReference();
+
+ virtual bool IsInstanceOf(ClassName name);
+ virtual void Destroy();
+
+ static const ClassName name = KAutoObject_Class;
+
+private:
+ u32 m_refcount;
+};
--- /dev/null
+class KAutoObjectRef {
+public:
+ KAutoObjectRef::KAutoObjectRef(const KAutoObjectRef &obj);
+ KAutoObjectRef();
+ KAutoObjectRef(KAutoObject* object);
+ ~KAutoObjectRef();
+ void SetObject(KAutoObject* object);
+ KAutoObject* operator*();
+private:
+ KAutoObject* m_object;
+};
--- /dev/null
+class KPort;
+
+class KClientPort : public KSynchronizationObject
+{
+public:
+
+ typedef KSynchronizationObject super;
+
+
+ KClientPort(char* name, u32 maxconnection, KPort *owner);
+ bool Synchronization(KThread* thread, u32 &error);
+ virtual bool IsInstanceOf(ClassName name);
+
+ s32 connect(KClientSession* &sesion);
+
+ static const ClassName name = KClientPort_Class;
+
+
+private:
+ KPort *m_owner;
+ s16 m_maxConnection;
+ s16 m_CurrentConnection;
+};
--- /dev/null
+class KPort;
+
+class KSession;
+class KClientSession : public KSynchronizationObject
+{
+public:
+
+ typedef KSynchronizationObject super;
+
+
+ KClientSession(KSession *owner);
+ bool Synchronization(KThread* thread, u32 &error);
+ virtual bool IsInstanceOf(ClassName name);
+
+ static const ClassName name = KClientSession_Class;
+
+ virtual void Destroy();
+private:
+ KSession *m_owner;
+ u32 m_unk;
+};
--- /dev/null
+// File layout:
+// - File header
+// - Code, rodata and data relocation table headers
+// - Code segment
+// - Rodata segment
+// - Loadable (non-BSS) part of the data segment
+// - Code relocation table
+// - Rodata relocation table
+// - Data relocation table
+
+// Memory layout before relocations are applied:
+// [0..codeSegSize) -> code segment
+// [codeSegSize..rodataSegSize) -> rodata segment
+// [rodataSegSize..dataSegSize) -> data segment
+
+// Memory layout after relocations are applied: well, however the loader sets it up :)
+// The entrypoint is always the start of the code segment.
+// The BSS section must be cleared manually by the application.
+
+// File header
+#define _3DSX_MAGIC 0x58534433 // '3DSX'
+typedef struct {
+ u32 magic;
+ u16 headerSize, relocHdrSize;
+ u32 formatVer;
+ u32 flags;
+
+ // Sizes of the code, rodata and data segments +
+ // size of the BSS section (uninitialized latter half of the data segment)
+ u32 codeSegSize, rodataSegSize, dataSegSize, bssSize;
+} _3DSX_Header;
+
+// Relocation header: all fields (even extra unknown fields) are guaranteed to be relocation counts.
+typedef struct {
+ u32 cAbsolute; // # of absolute relocations (that is, fix address to post-relocation memory layout)
+ u32 cRelative; // # of cross-segment relative relocations (that is, 32bit signed offsets that need to be patched)
+ // more?
+
+ // Relocations are written in this order:
+ // - Absolute relocs
+ // - Relative relocs
+} _3DSX_RelocHdr;
+
+// Relocation entry: from the current pointer, skip X words and patch Y words
+typedef struct {
+ u16 skip, patch;
+} _3DSX_Reloc;
+
+#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
+#define be_word(a) __builtin_bswap32(a)
+#define be_hword(a) __builtin_bswap16(a)
+#define le_word(a) (a)
+#define le_hword(a) (a)
+#elif __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
+#define be_word(a) (a)
+#define be_hword(a) (a)
+#define le_word(a) __builtin_bswap32(a)
+#define le_hword(a) __builtin_bswap16(a)
+#else
+#error "What's the endianness of the platform you're targeting?"
+#endif
+
+struct _3DSX_LoadInfo {
+ void* segPtrs[3]; // code, rodata & data
+ u32 segAddrs[3];
+ u32 segSizes[3];
+};
+
+
+
+class KCodeSet : public KAutoObject
+{
+public:
+ typedef KAutoObject super;
+
+ KCodeSet(u8* code_buf, u32 code_pages, u8* rodata_buf, u32 rodata_pages,
+ u8* data_buf, u32 data_pages, u32 bss_pages, u64 TitleID, const char* name);
+ ~KCodeSet();
+ Result MapInto(KMemoryMap * map, bool spezialmem);
+ const char* GetName();
+
+ static const ClassName name = KCodeSet_Class;
+ virtual bool IsInstanceOf(ClassName name);
+private:
+ bool Patch();
+ void LoadElfFile(u8 *addr);
+ int Load3DSXFile(FILE* f, u32 baseAddr);
+ u8* m_code;
+ u32 m_code_pages;
+ u8* m_rodata;
+ u32 m_rodata_pages;
+ u8* m_data;
+ u32 m_data_pages;
+ u32 m_bss_pages;
+ u64 m_TitleID;
+ const char* m_name;
+};
--- /dev/null
+#pragma once
+
+
+
+class KDmaObject : public KSynchronizationObject
+{
+public:
+
+ typedef KSynchronizationObject super;
+
+
+ KDmaObject(u8 channel, u8 started, KProcess *owner);
+ ~KDmaObject();
+ bool Synchronization(KThread* thread,u32 &error);
+ virtual bool IsInstanceOf(ClassName name);
+
+ static const ClassName name = KDmaObject_Class;
+
+ u8 GetState() { return m_started; }
+
+private:
+ KProcess *m_owner;
+ u8 m_channel;
+ u8 m_started;
+};
+
+
--- /dev/null
+#pragma once
+
+
+
+class KEvent : public KSynchronizationObject
+{
+public:
+
+ typedef KSynchronizationObject super;
+
+
+ KEvent(u32 priority, bool manual, KProcess *owner);
+ ~KEvent();
+ bool Synchronization(KThread* thread, u32 &error);
+ void Clear();
+ virtual bool IsInstanceOf(ClassName name);
+
+ void Triggerevent();
+
+ static const ClassName name = KEvent_Class;
+
+ bool m_open;
+private:
+ KProcess *m_owner;
+ bool m_manual;
+ u32 m_priority;
+ PMutex m_Mutex;
+};
+
+
--- /dev/null
+class KProcess;
+
+struct HandleEntry {
+ u32 handle; // 0 if free.
+
+ union {
+ HandleEntry* next_free;
+ KAutoObject* object;
+ } ptr;
+};
+
+class KHandleTable {
+public:
+ KHandleTable(KProcess* process, u32 size);
+
+ template<class T> KAutoObjectRef GetHandle(Handle h) {
+ KAutoObjectRef ref;
+ s32 ret = GetHandleObject(ref, h);
+ if (ret != Success)
+ {
+ return NULL;
+ }
+
+ KAutoObject* obj = *ref;
+ if (obj == NULL) return NULL;
+ if (!obj->IsInstanceOf(T::name)) return NULL;
+ return ref;
+ }
+
+ Result CreateHandle(Handle& handle_out, KAutoObject* obj);
+ Result GetHandleObject(KAutoObjectRef& obj_out, Handle handle);
+ Result CloseHandle(Handle handle);
+private:
+ KProcess* m_process;
+ HandleEntry* m_handles;
+ HandleEntry* m_next_free;
+ u32 m_counter;
+ u32 m_size;
+};
--- /dev/null
+
+
+class KInterrupt : public KAutoObject
+{
+public:
+ typedef KAutoObject super;
+
+ KInterrupt(KSynchronizationObject* syncObject, s32 priority, bool isManualClear);
+ KAutoObjectRef* GetObjRef();
+ ~KInterrupt();
+ void fire();
+
+
+ bool IsInstanceOf(ClassName name);
+ static const ClassName name = KInterrupt_Class;
+
+private:
+ KAutoObjectRef m_syncObject;
+ s32 m_priority;
+ bool m_isManualClear;
+};
\ No newline at end of file
--- /dev/null
+#include <array>
+#include "Hardware.h"
+
+#define SERVICECORE 1
+
+
+class Process9;
+class KPort;
+class KInterrupt;
+
+class KKernel {
+public:
+ KKernel();
+ void AddQuickCodeProcess(u8* buf, size_t size); // TEMP
+ void AddProcess(KProcess* p, bool is_firm_process);
+ void StartThread(KThread* p);
+ void StopThread(KThread* p);
+ void ReScheduler();
+ void ThreadsRunTemp();
+ u32 GetNextThreadID();
+ u32 GetNextProcessID();
+ s32 RegisterInterrupt(u32 name, KSynchronizationObject* syncObject, s32 priority, bool isManualClear);
+ s32 UnRegisterInterrupt(u32 name, KSynchronizationObject* syncObject);
+ void FireInterrupt(u32 name);
+ void FireNextTimeEvent(KTimeedEvent* eve, u64 ticks);
+ u32 m_numbFirmProcess;
+ KLinkedList<KPort> m_Portlist;
+ KLinkedRefList<KProcess> m_processes;
+ KMemoryMap* m_IPCFIFOAdresses[0xF];
+ bool m_IPCFIFOAdressesRO[0xF];
+ u8 m_FIRM_Launch_Parameters[0x1000];
+
+ Process9* m_p9;
+ HWHASH* m_hash1;
+ HWHASH2* m_hash2;
+ IOI2C * m_I2C1;
+ IOI2C * m_I2C2;
+ IOI2C * m_I2C3;
+ GPIO * m_GPIO;
+ PDN * m_PDN;
+ SPI * m_SPI0;
+ SPI * m_SPI1;
+ SPI * m_SPI2;
+ DSP * m_DSP;
+ GPUHW * m_GPU;
+ HID * m_HID;
+ MIC * m_MIC;
+ KLinkedList<KTimeedEvent> m_Timedevent;
+
+
+private:
+ u64 FindTimedEventWithSmallestCyclesRemaining();
+ KArmCore m_core0;
+ KArmCore m_core1;
+ KArmCore m_core2;
+ KArmCore m_core3;
+ KLinkedList<KThread> tempsh;
+ u32 m_NextProcessID;
+ u32 m_NextThreadID;
+ KLinkedList<KInterrupt> *m_Interrupt[0x80];
+};
--- /dev/null
+template<class T> struct KLinkedListNode {
+ KLinkedListNode<T>* next;
+ KLinkedListNode<T>* prev;
+ T* data;
+};
+
+template<class T> class KLinkedList {
+public:
+ KLinkedList() {
+ list = NULL;
+ }
+
+ int AddItem(T* item) {
+ KLinkedListNode<T>* node = (KLinkedListNode<T>*)
+ malloc(sizeof(KLinkedListNode<T>));
+
+ if(node == NULL)
+ return 1;
+
+ node->prev = NULL;
+ node->next = list;
+ node->data = item;
+
+ if(list != NULL)
+ list->prev = node;
+
+ list = node;
+ return 0;
+ }
+
+ int RemoveItem(KLinkedListNode<T>* item) {
+ KLinkedListNode<T>* prev = item->prev;
+ KLinkedListNode<T>* next = item->next;
+
+ if(prev != NULL)
+ prev->next = next;
+ else
+ list = next;
+
+ if(next != NULL)
+ next->prev = prev;
+
+ return 0;
+ }
+
+ ~KLinkedList() {
+ KLinkedListNode<T>* p = list;
+
+ while(p != NULL) {
+ KLinkedListNode<T>* next = p->next;
+ free(p); p = next;
+ }
+ }
+
+ KLinkedListNode<T>* list;
+};
+
+// Keeps reference counting for KAutoObj's.
+template<class T> class KLinkedRefList : public KLinkedList<T> {
+public:
+ typedef KLinkedList<T> super;
+
+ int AddItem(T* item) {
+ item->AcquireReference();
+ return super::AddItem(item);
+ }
+
+ int RemoveItem(KLinkedListNode<T>* item) {
+ item->data->ReleaseReference();
+ return super::RemoveItem(item);
+ }
+
+ ~KLinkedRefList() {
+ KLinkedListNode<T>* p = super::list;
+
+ while(p != NULL) {
+ KLinkedListNode<T>* next = p->next;
+
+ p->data->ReleaseReference();
+ free(p); p = next;
+ }
+ }
+};
--- /dev/null
+
+
+extern u8* Mem_VRAM;
+extern u8* Mem_DSP;
+extern u8* Mem_FCRAM;
+extern u8* Mem_Configuration;
+extern u8* Mem_Shared;
+extern MemChunk* chunk_Configuration;
+extern MemChunk* chunk_Shared;
+extern bool* MEM_FCRAM_Used;
+void Mem_Init(bool new3ds);
+
+void Mem_SharedMemInit();
+
+u8* Mem_GetPhysicalPointer(u32 addr);
--- /dev/null
+class IOHW;
+
+/* MemoryPermissions */
+typedef u8 MemoryPermissions;
+
+#define PERMISSION_NONE 0
+#define PERMISSION_R 1
+#define PERMISSION_W 2
+#define PERMISSION_RW 3
+#define PERMISSION_X 4
+#define PERMISSION_RX 5
+#define PERMISSION_WX 6
+#define PERMISSION_RWX 7
+
+/* MemoryOperation */
+typedef u32 MemoryOperation;
+
+#define OPERATION_FREE 1
+#define OPERATION_RESERVE 2
+#define OPERATION_COMMIT 3
+#define OPERATION_MAP 4
+#define OPERATION_UNMAP 5
+#define OPERATION_PROTECT 6
+#define OPERATION_LINEAR (1 << 16)
+
+#define TLS_OFFSET 0x1FF82000
+
+/* MemoryState */
+typedef u16 MemoryState;
+
+#define STATE_FREE 0
+#define STATE_RESERVED 1
+#define STATE_IO 2
+#define STATE_STATIC 3
+#define STATE_CODE 4
+#define STATE_PRIVATE 5
+#define STATE_SHARED 6
+#define STATE_CONTINOUS 7
+#define STATE_ALIASED 8
+#define STATE_ALIAS 9
+#define STATE_ALIASCODE 10
+#define STATE_LOCKED 11
+
+// Internal flags.
+#define STATE_FREE_ALLOWED 0x100
+#define STATE_PROTECT_ALLOWED 0x200
+#define STATE_DEBUGSVCS_ALLOWED 0x400
+#define STATE_IPC_ALLOWED 0x800
+#define STATE_DMASVCS_ALLOWED 0x1000
+#define STATE_UNKNOWN1 0x2000
+#define STATE_UNKNOWN2 0x4000
+#define STATE_UNKNOWN3 0x8000
+
+//// Normal heap - 0xBB05
+#define MEMTYPE_HEAP \
+ (STATE_PRIVATE|STATE_FREE_ALLOWED|STATE_PROTECT_ALLOWED| \
+ STATE_IPC_ALLOWED|STATE_DMASVCS_ALLOWED|STATE_UNKNOWN1| \
+ STATE_UNKNOWN3)
+
+//// Linear heap - 0x3907
+#define MEMTYPE_LINEARHEAP \
+ (STATE_CONTINOUS|STATE_FREE_ALLOWED|STATE_IPC_ALLOWED| \
+ STATE_DMASVCS_ALLOWED|STATE_UNKNOWN1)
+
+//// Mirror mem - 0x1A09
+#define MEMTYPE_MIRROR \
+ (STATE_ALIAS|STATE_PROTECT_ALLOWED|STATE_IPC_ALLOWED| \
+ STATE_DMASVCS_ALLOWED)
+
+//// Mirrored mem - 0x3A08
+#define MEMTYPE_MIRRORED \
+ (STATE_ALIASED|STATE_PROTECT_ALLOWED|STATE_IPC_ALLOWED| \
+ STATE_DMASVCS_ALLOWED|STATE_UNKNOWN1)
+
+//// Code segment - 0xBC04
+#define MEMTYPE_CODE \
+ (STATE_CODE|STATE_DEBUGSVCS_ALLOWED|STATE_IPC_ALLOWED| \
+ STATE_DMASVCS_ALLOWED|STATE_UNKNOWN1|STATE_UNKNOWN3)
+
+// Tls: has 0x380B
+#define MEMTYPE_TLS \
+ (STATE_LOCKED|STATE_IPC_ALLOWED| \
+ STATE_DMASVCS_ALLOWED|STATE_UNKNOWN1)
+// Alias-code has 0xBC0A (MapProcessMemory)
+// SharedMemory has 0x5806
+#define MEMTYPE_SHAREDMEMORY \
+ (STATE_SHARED|STATE_IPC_ALLOWED| \
+ STATE_DMASVCS_ALLOWED|STATE_UNKNOWN3)
+// Vram has 0x1003
+// IO mapping has 0x1002
+#define MEMTYPE_IO \
+ (STATE_IO| \
+ STATE_DMASVCS_ALLOWED)
+
+/* PageFlags */
+typedef u8 PageFlags;
+
+struct MemoryInfo {
+ u32 base_address;
+ u32 size;
+ u32 perm;
+ u32 state;
+};
+
+struct PageInfo {
+ u32 flags;
+};
+
+struct MemChunk {
+ u32 size;
+ u8* data;
+ u32 ref_count;
+};
+
+struct MemPage {
+ u8* data;
+ MemChunk* chunk;
+ MemoryState state;
+ MemoryPermissions perm;
+ PageFlags flags;
+ u32 mirrored; // If mirror-page, then this is original addr.
+ IOHW *HW;
+};
+
+class KProcess;
+class KMemoryBlock;
+
+#define NUM_PAGES 0x40000
+#define PAGE_SIZE 0x1000
+#define PAGE_MASK 0xFFF
+#define HEAP_VA_START 0x08000000
+
+class KMemoryMap {
+public:
+ KMemoryMap(KProcess* process);
+
+ Result Read8 (u32 addr, u8& out);
+ Result Read16(u32 addr, u16& out);
+ Result Read32(u32 addr, u32& out);
+ Result Read64(u32 addr, u64& out);
+ Result ReadN(u32 addr, u8* out, u32 size);
+ Result Write8 (u32 addr, u8 val);
+ Result Write16(u32 addr, u16 val);
+ Result Write32(u32 addr, u32 val);
+ Result Write64(u32 addr, u64 val);
+
+ Result IPCMap(u32 addr0, u32 addr1, u32 size, MemoryPermissions perm, KMemoryMap * mapto);
+
+ Result ControlMemory(u32* addr_out, u32 addr0, u32 addr1, u32 size,
+ MemoryOperation op, MemoryPermissions perm);
+ Result QueryMemory(MemoryInfo* mem_out, PageInfo* page_out, u32 addr);
+ Result MapMemoryBlock(KMemoryBlock& block, u32 addr,
+ MemoryPermissions local_perms, MemoryPermissions remote_perms);
+ Result UnmapMemoryBlock(KMemoryBlock& block, u32 addr);
+
+ Result AddCodeSegment(u32 addr, u32 size, u8* data,
+ MemoryPermissions perm);
+ Result AddIOMem(u32 address, u32 size, MemoryPermissions perm);
+
+ Result AddPages(u32 addr, u32 size, u8* data, MemChunk* chunk,
+ MemoryPermissions perm, MemoryState state, IOHW *HW);
+
+ Result AddTLS(u32* out_3DSAddr,u8** out_TLSpointer);
+ Result RemoveTLS(u32 DSAddr);
+ Result MapIOobj(u32 address, u32 size, IOHW* obj, MemoryPermissions perm);
+ Result RemovePages(u32 addr, u32 size);
+ s32 AllocFreeGSP(bool new3DS, u32 size);
+ Result MapIOData(u32 address, u32 size,u8*data, MemoryPermissions perm);
+ KProcess* m_process;
+#ifndef XDS_TEST
+private:
+#endif
+ Result VerifyRegionState(u32 addr, u32 size, MemoryState state);
+ Result VerifyRegionMaskState(u32 addr, u32 size, MemoryState state);
+ Result Reprotect(u32 addr, u32 size, MemoryPermissions perm);
+ Result CreateChunk(MemChunk** chunk_out, u32 size);
+
+ Result AddMirror(u32 mirror, u32 mirrored, u32 size,
+ MemoryPermissions perm);
+ Result AddMirror(u32 mirror, u32 mirrored, u32 size,
+ MemoryPermissions perm, KMemoryMap * mapto);
+ Result RemoveMirror(u32 mirror, u32 mirrored, u32 size);
+
+ MemPage m_pages[NUM_PAGES];
+ bool m_TLSused[0x100]; //the maximum number of TLS that are possible because of the ResourceLimit
+ u8* m_TLSpointer[0x100/8];
+};
+
+// TODO: Free chunks when ref_count == 0.
--- /dev/null
+#pragma once
+
+
+
+class KMutex : public KSynchronizationObject
+{
+public:
+
+ typedef KSynchronizationObject super;
+
+
+ KMutex(KProcess *owner,bool locked);
+ ~KMutex();
+ bool Synchronization(KThread* thread, u32 &error);
+ virtual bool IsInstanceOf(ClassName name);
+
+ void Release();
+
+ static const ClassName name = KEvent_Class;
+
+
+private:
+ KProcess *m_owner;
+ KThread *m_lockedThread;
+ bool m_locked;
+ PMutex m_Mutex;
+};
+
+
--- /dev/null
+
+class KPort : public KAutoObject
+{
+public:
+
+ typedef KAutoObject super;
+
+
+ KPort(char* name, u32 maxconnection);
+ ~KPort();
+ virtual bool IsInstanceOf(ClassName name);
+
+ static const ClassName name = KPort_Class;
+
+ KClientPort m_Client;
+ KServerPort m_Server;
+ char m_Name[9]; //this is not like on the 3DS but we use it like that for debugging
+private:
+};
+
+
--- /dev/null
+
+class KKernel;
+#define bb_map std::unordered_map<u32, int>
+
+class KProcess : public KSynchronizationObject
+{
+public:
+ typedef KSynchronizationObject super;
+
+ bool Synchronization(KThread* thread, u32 &error);
+
+ KProcess::~KProcess();
+
+ KProcess(KCodeSet* code, u32 capabilities_num, u32* capabilities_ptr, KKernel* Kernel,bool );
+
+ KMemoryMap* getMemoryMap();
+
+ void AddQuickCode(u8* buf, size_t size);
+
+ void AddThread(KThread * thread);
+
+ const char* GetName();
+ u32 GetProcessID();
+ KResourceLimit* GetResourceLimit();
+ void SetResourceLimit(KResourceLimit* lim);
+ KHandleTable* GetHandleTable();
+
+ virtual Result WaitSynchronization(s64 timeout);
+ virtual bool IsInstanceOf(ClassName name);
+ virtual void Destroy();
+ bool m_systemcallmask[0x80];
+ u32 m_exheader_flags;
+ KMemoryMap m_memory;
+
+ u32 LINEAR_memory_virtual_address_userland;
+
+ static const ClassName name = KProcess_Class;
+ KKernel* m_Kernel;
+ u32 m_ProcessID;
+
+ //Dyncore stuff
+ char* repretBuffer;
+ int repretBuffersize;
+ int repretBuffertop;
+ bb_map *CreamCache;
+
+private:
+ u32 static Read32(uint8_t p[4]);
+ void ParseArm11KernelCaps(u32 capabilities_num, u32* capabilities_ptr);
+ KLinkedList<KThread> m_Threads;
+ KAutoObjectRef m_limit;
+ KAutoObjectRef m_codeset;
+ KHandleTable* m_handles;
+ bool m_AllowedInterrupt[0x7E];
+ /*
+ Bit(0) Allow debug
+ Bit(1) Force debug
+ Bit(2) Allow non-alphanum
+ Bit(3) Shared page writing
+ Bit(4) Privilege priority
+ Bit(5) Allow main() args <-- is ignored anyway
+ Bit(6) Shared device mem <-- TODO what dose that mean??
+ Bit(7) Runnable on sleep
+ Bit(8-11) Memory type(0 = APPLICATION 1 = SYSTEM 2 = BASE)
+ Bit(12) Special memory (map to 0x14000000 insted of 0x00100000)
+ Bit(23-31) 1111 1111 0
+ */
+};
--- /dev/null
+#pragma once
+
+#define RESOURCE_PRIORITY 0x0
+#define RESOURCE_COMMIT 0x1
+#define RESOURCE_THREAD 0x2
+#define RESOURCE_EVENT 0x3
+#define RESOURCE_MUTEX 0x4
+#define RESOURCE_SEMAPHORE 0x5
+#define RESOURCE_TIMER 0x6
+#define RESOURCE_SHARED_MEMORY 0x7
+#define RESOURCE_ADDRESS_ARBITER 0x8
+#define RESOURCE_CPU_TIME 0x9
+
+#define NUMBER_OF_RESOURCES 0xA
+
+/* Normal Values are some of them are bytes so check that if you mess with them TODO check if they are still correct reversed from FIRM 4.X (Process Manager Services in emulator)
+
+APPLICATION
+0000000000000018
+<Configmem-APPMEMTYPE Value> //APPMEMALLOC
+0:0x04000000
+1:0x04000000
+2:0x06000000
+3:0x05000000
+4:0x04800000
+5:0x02000000
+6:0x07C00000 //New_3DS
+7:0x0B200000 //New_3DS
+0000000000000020
+0000000000000020
+0000000000000020
+0000000000000008
+0000000000000008
+0000000000000010
+0000000000000002
+0000000000000000
+
+SYS_APPLET
+0000000000000004
+<Configmem-APPMEMTYPE Value> //calculated from SYSMEMALLOC
+0:0x02600000
+1:0x02600000
+2:0x00600000
+3:0x01600000
+4:0x00600000
+5:0x03E00000
+6:0x05000000 //New_3DS
+7:0x02780000 //New_3DS
+000000000000000E
+0000000000000008
+0000000000000008
+0000000000000004
+0000000000000004
+0000000000000008
+0000000000000002
+0000000000002710
+
+LIB_APPLET
+0000000000000004
+<Configmem-APPMEMTYPE Value> //calculated from SYSMEMALLOC
+0:0x00600000
+1:0x00600000
+2:0x00000000 <-- TODO this looks wrong check it
+3:0x00600000
+4:0x00600000
+5:0x00E00000
+6:0x01400000 //New_3DS
+7:0x00680000 //New_3DS
+000000000000000E
+0000000000000008
+0000000000000008
+0000000000000004
+0000000000000004
+0000000000000008
+0000000000000001
+0000000000002710
+
+OTHER
+0000000000000004
+<Configmem-APPMEMTYPE Value> //calculated from SYSMEMALLOC
+0:0x01680000
+1:0x01680000
+2:0x01680000
+3:0x01680000
+4:0x01680000
+5:0x02000000
+6:0x02480000 //New_3DS
+7:0x01700000 //New_3DS
+00000000000000C5
+00000000000000F5
+0000000000000023
+000000000000003F
+000000000000002B
+000000000000001D
+000000000000002A
+00000000000003E8
+*/
+
+class KResourceLimit : public KAutoObject
+{
+public:
+
+ typedef KAutoObject super;
+
+ KResourceLimit();
+ ~KResourceLimit();
+
+ bool UseResource(u32 resource_id, u32 num);
+ void FreeResource(u32 resource_id, u32 num);
+ s64 GetCurrentValue(u32 resource_id);
+ s64 GetMaxValue(u32 resource_id);
+ void SetMaxValue(u32 resource_id, s64 number);
+
+ static const ClassName name = KResourceLimit_Class;
+ virtual bool IsInstanceOf(ClassName name);
+
+private:
+ PMutex m_Mutex;
+ s32 m_MaxResource[NUMBER_OF_RESOURCES];
+ s32 m_CurrentUsedResource[NUMBER_OF_RESOURCES];
+};
--- /dev/null
+#pragma once
+
+
+#define PRIO_FIELD_COUNT 0x20
+#define PRIO_FIELD_MASK 0x1F
+#define PRIO_TYPE_MASK 0x20
+#define PRIO_COUNT 0x40
+#define PRIO_MAX PRIO_COUNT - 1
+#define PRIO_HIGH 0
+#define PRIO_LOW PRIO_MAX
+#define PRIO_TYPE_LOW 1
+#define PRIO_TYPE_HIGH 0
+
+
+struct SwitchContext {
+
+ KThread* current_thread_on_switch;
+ u32 running_thread_switch_count;
+};
+
+struct ThreadScheduleList {
+
+ KThread* prev; // this may be first/last, not prev/next
+ KThread* next;
+
+};
+
+class KScheduler
+{
+public:
+ KScheduler();
+ ~KScheduler();
+
+ void AddToScheduler(KThread* add_thread);
+ void RemoveFromScheduler(KThread* sub_thread);
+ void AdjustScheduler(KThread* schedule_thread, bit8 scheduling_mask);
+ KThread* ScheduleThreads(int z);
+ void Reschedule(KThread* schedule_thread, bit8 lower_scheduling_mask);
+
+ void SwitchKernelContext(int z);
+ void SwitchThreadContext(SwitchContext* c); // switchA
+ void ReturnThreadContext(SwitchContext* c); // switchB
+ void SoftContextSwitch(SwitchContext* c); // switchC
+
+ inline s32 GetPrioType(s32 prio) { return (prio & PRIO_TYPE_MASK) >> 5; }
+ inline s32 GetPrioField(s32 prio) { return prio & PRIO_FIELD_MASK; }
+
+ void OtherCoreTriggerIntr8();
+
+private:
+
+ u32 m_scheduler_count; //used in the 3 context switch functions
+ bool m_switch_context;
+ bool m_intr_thread_in_progress;
+ bool m_swap_intr_core;
+ bool m_need_post_intr_reschedule;
+ s16 m_core_num;
+ u16 m_scheduler_thread_count;
+ bit32 m_thread_high_prio; // high priority thread mask (0x0-0x1F)
+ bit32 m_thread_low_prio; // low priority thread mask (0x20-0x3F)
+ KThread* m_scheduler_thread;
+ u32 m_unknown2;
+ u32 m_unknown3;
+ ThreadScheduleList m_schedule_entries[64]; // 1 per prio, 0-3F
+
+};
+
+/*
+priority is handled from most significant bit to least significant bit:
+
+ex.
+m_thread_high_prio: bit31, prio 0 bit 0, prio 31
+ | |
+ 00000000000000000000000000000000
+
+highest bit of priority determines between high and low priority:
+
+ex.
+prio 0x11 vs prio 0x31: prio 0x11 is high prio bit 14, prio 0x31 is low prio bit 14
+*/
\ No newline at end of file
--- /dev/null
+#pragma once
+
+
+
+class KSemaphore : public KSynchronizationObject
+{
+public:
+
+ typedef KSynchronizationObject super;
+
+
+ KSemaphore(u32 count,u32 maxcount , KProcess *owner);
+ ~KSemaphore();
+ bool Synchronization(KThread* thread,u32 &error);
+ virtual bool IsInstanceOf(ClassName name);
+
+ s32 ReleaseSemaphore(u32 releaseCount, u32 &count);
+
+ static const ClassName name = KSemaphore_Class;
+
+
+private:
+ KProcess *m_owner;
+ volatile u32 m_count;
+ u32 m_maxcount;
+ PMutex m_Mutex;
+};
+
+
--- /dev/null
+class KPort;
+
+class KServerPort : public KSynchronizationObject
+{
+public:
+
+ typedef KSynchronizationObject super;
+
+
+ KServerPort(char* name, u32 maxconnection, KPort *owner);
+ ~KServerPort();
+ bool Synchronization(KThread* thread, u32 &error);
+ virtual bool IsInstanceOf(ClassName name);
+
+ KServerSession * AcceptSesion();
+
+ static const ClassName name = KServerPort_Class;
+
+ KLinkedList<KSession> m_sessionToTake;
+private:
+ KPort *m_owner;
+ KLinkedList<KSession> m_sessions;
+};
--- /dev/null
+class KSession;
+
+class KServerSession : public KSynchronizationObject
+{
+public:
+
+ typedef KSynchronizationObject super;
+
+
+ KServerSession(KSession *owner);
+ ~KServerSession();
+ bool Synchronization(KThread* thread, u32 &error);
+ virtual bool IsInstanceOf(ClassName name);
+
+ static const ClassName name = KServerSession_Class;
+
+ s32 reply(KThread * sender);
+ void Destroy();
+ KThread* m_processingCmd;
+ KThread* m_waitingForCmdResp;
+
+private:
+ KSession *m_owner;
+};
--- /dev/null
+
+class KSession : public KAutoObject
+{
+public:
+
+ typedef KAutoObject super;
+
+
+ KSession(KPort * owner = NULL);
+ ~KSession();
+ virtual bool IsInstanceOf(ClassName name);
+
+ s32 Communicate(KThread* sender, KThread* recver,bool IsResponse);
+
+ static const ClassName name = KSession_Class;
+
+ KServerSession m_Server;
+ KClientSession m_Client;
+ KPort * m_owner; //this is for debugging
+ KLinkedList<u32> m_openMemAddr;
+ KLinkedList<u32> m_openMemSize;
+private:
+};
+
+
--- /dev/null
+#pragma once
+
+
+
+class KSharedMemory : public KAutoObject
+{
+public:
+
+ typedef KAutoObject super;
+
+
+ KSharedMemory(u32 addr, u32 size,u32 myperm,u32 otherpem, KProcess *owner);
+ ~KSharedMemory();
+ virtual bool IsInstanceOf(ClassName name);
+ s32 map(u32 addr, u32 myperm, u32 otherpem, KProcess *caller);
+
+ static const ClassName name = KSharedMemory_Class;
+
+private:
+ KProcess *m_owner;
+ u32 m_addr;
+ u32 m_size;
+ u32 m_myperm;
+ u32 m_otherpem;
+ bool m_IsGSP;
+};
+
+
--- /dev/null
+//error codes
+#define SVCERROR_INVALID_OPERATION 0xE0E01BEE
+#define SVCERROR_OUT_OF_RANGE 0xE0E01BFD
+#define SVCERROR_INVALID_HANDLE 0xD9001BF7
+#define SVCERROR_INVALID_PARAMS 0xE0E01BF5
+#define SVCERROR_INVALID_SIZE 0xE0E01BF2
+#define SVCERROR_ALIGN_ADDR 0xE0E01BF1
+#define SVCERROR_INVALID_POINTER 0xD8E007F6
+#define SVCERROR_INVALID_ENUM_VALUE 0xD8E007ED
+#define SVCERROR_CREATE_HANLE 0xD8A093F8
+#define SVCERROR_RESOURCE_LIMIT 0xC860180A
+
+void ProcessSwi(u8 swi, u32* Reg, KThread * currentThread);
+u32 ControlMemory_swi(u32* address, u32 addr0, u32 addr1, u32 size, u32 op, u32 permissions, KThread * currentThread);
--- /dev/null
+
+class KThread;
+
+class KSynchronizationObject : public KAutoObject
+{
+public:
+ typedef KAutoObject super;
+
+ KSynchronizationObject();
+
+ virtual bool Synchronization(KThread* thread,u32 &error) = 0;
+
+ virtual bool IsInstanceOf(ClassName name);
+ bool Syn(KThread* thread, u32 &error);
+ void SynRemove(KThread* thread);
+
+ static const ClassName name = KAutoObject_Class;
+ void SynFree(u32 errorCode, KThread* thread);
+ KThread* SynGetNextPrio();
+ void SynFreeAll(u32 errorCode);
+
+ bool m_killed;
+
+private:
+ KLinkedList<KThread> waiting;
+
+};
--- /dev/null
+#pragma once
+
+class KArmCore;
+
+enum SchedulingTask : bit8 {
+
+ TASK_PERFORM = 1,
+ TASK_IGNORE = 2 // TASK_ABANDON?
+
+};
+
+class KThread : public KSynchronizationObject,public KTimeedEvent
+{
+public:
+
+ typedef KSynchronizationObject super;
+
+
+ KThread(s32 core,KProcess *owner);
+ ~KThread();
+
+ bool Synchronization(KThread* thread, u32 &error);
+ void SyncFree(s32 errorCode, KSynchronizationObject* obj);
+ void SyncStall(KLinkedList<KSynchronizationObject>* objects, bool waitAll);
+ void stop();
+ void trigger_event();
+ bool m_waitAll;
+ KLinkedList<KSynchronizationObject> *Threadwaitlist; //if there is nothing inside the thread is freed
+
+ virtual bool IsInstanceOf(ClassName name);
+ virtual void Destroy();
+
+
+ bool m_running;
+
+ bit8 m_scheduling_task;
+ s32 m_thread_prio;
+ s32 m_creator_core;
+ s32 m_corenumb;
+ KArmCore* m_core;
+ u32 m_thread_id;
+
+ KThread* m_prev;
+ KThread* m_next;
+
+ u32 m_TSL3DS;
+ u8* m_TSLpointer;
+ KProcess* m_owner;
+
+ u32 arb_addr;
+
+ ThreadContext m_context;
+
+ static const ClassName name = KThread_Class;
+
+
+private:
+
+};
+
+
--- /dev/null
+#pragma once
+
+
+
+class KTimeedEvent
+{
+public:
+ KTimeedEvent(){ num_cycles_remaining = 0; }
+ ~KTimeedEvent(){ }
+ s64 num_cycles_remaining;
+ virtual void trigger_event() = 0;
+
+
+private:
+};
+
+
--- /dev/null
+#pragma once
+
+
+
+class KTimer : public KSynchronizationObject, public KTimeedEvent
+{
+public:
+
+ typedef KSynchronizationObject super;
+
+
+ KTimer(KProcess *owner, u32 resettype);
+ ~KTimer();
+ bool Synchronization(KThread* thread, u32 &error);
+ virtual bool IsInstanceOf(ClassName name);
+ Result SetTimer(s64 initial, s64 interval);
+ void Release();
+ void Cancel();
+ virtual void trigger_event();
+
+ static const ClassName name = KTimer_Class;
+
+
+private:
+ KProcess *m_owner;
+ bool m_Enabled;
+ u32 m_ResetType;
+ s64 m_Interval;
+ s64 m_Initial;
+ bool m_locked;
+};
+
+
--- /dev/null
+
+class Process9 : public HWIPC
+{
+public:
+ Process9(KKernel* kernel);
+ ~Process9();
+ void FIFOReadBackCall(); //everything even flash
+ void FIFOWriteBackCall(); //everything even flash
+ void FIFOIRQ();
+ void FIFOIRQOLD(); //this is unused on the 3DS
+ void Sendresponds(u32 myid,u32 data[]);
+ u64 GetTitleFromPM(u64 handle);
+private:
+ P9MC m_MC;
+ P9FS m_FS;
+ P9PM m_PM;
+ P9PS m_PS;
+ P9AM m_AM;
+ u32 m_datarecved;
+ u32 m_datasended;
+ u32 m_datarecv[0x200]; //this is more than enough
+ u32 m_datasend[0x200]; //this is more than enough
+ bool m_IntiHadData;
+};
+
+
--- /dev/null
+class P9AM
+{
+public:
+ P9AM(Process9* owner);
+ ~P9AM();
+ void Command(u32 data[],u32 numb);
+private:
+ Process9* m_owner;
+};
+
+
--- /dev/null
+#include "archive/archivep.h"
+#include "archive/archive1234567b.h"
+#include "archive/archive1234567c.h"
+#include "archive/archive1234567d.h"
+#include "archive/archive1234567e.h"
+#include "archive/archive2345678e.h"
+#include "archive/archive567890b0.h"
+#include "archive/archive2345678a.h"
\ No newline at end of file
--- /dev/null
+
+class Archive1234567b : public Archive
+{
+public:
+ Archive1234567b(Process9* owner, LowPath *lowpath);
+ P9File* OpenFile(LowPath* lowpath, u32 flags, u32 attributes, u32* result);
+ ~Archive1234567b();
+};
+
+
--- /dev/null
+
+class Archive1234567c : public Archive
+{
+public:
+ Archive1234567c(Process9* owner, LowPath *lowpath);
+ ~Archive1234567c();
+ P9File* OpenFile(LowPath* lowpath, u32 flags, u32 attributes, u32* result) override;
+ void DeleteFile(LowPath* lowpath, u32* result) override;
+};
+
+
--- /dev/null
+
+class Archive1234567d : public Archive
+{
+public:
+ Archive1234567d(Process9* owner, LowPath *lowpath);
+ P9File* OpenFile(LowPath* lowpath, u32 flags, u32 attributes, u32* result);
+ ~Archive1234567d();
+};
+
+
--- /dev/null
+
+class Archive1234567e : public Archive
+{
+public:
+ Archive1234567e(Process9* owner, LowPath *lowpath);
+ P9File* OpenFile(LowPath* lowpath, u32 flags, u32 attributes, u32* result);
+ ~Archive1234567e();
+};
+
+
--- /dev/null
+
+class Archive2345678a : public Archive
+{
+public:
+ Archive2345678a(Process9* owner, LowPath *lowpath);
+ ~Archive2345678a();
+ P9File* OpenFile(LowPath* lowpath, u32 flags, u32 attributes, u32* result) override;
+};
+
+
--- /dev/null
+
+class Archive2345678e : public Archive
+{
+public:
+ Archive2345678e(Process9* owner, LowPath *lowpath);
+ ~Archive2345678e();
+ P9File* OpenFile(LowPath* lowpath, u32 flags, u32 attributes, u32* result) override;
+private:
+ u64 m_title;
+};
+
+
--- /dev/null
+
+class Archive567890b0 : public Archive
+{
+public:
+ Archive567890b0(Process9* owner, LowPath *lowpath);
+ ~Archive567890b0();
+};
+
+
--- /dev/null
+#undef DeleteFile
+
+class Archive
+{
+public:
+ Archive(Process9* owner, LowPath *lowpath);
+ virtual char* init() {
+ LOG("Archive stub");
+ return NULL;
+ };
+ virtual P9File* OpenFile(LowPath* lowpath, u32 flags, u32 attributes, u32* result) {
+ LOG("OpenFile stub");
+ return NULL;
+ };
+ virtual void CloseFile() {
+ LOG("CloseFile stub");
+ };
+ virtual void DeleteFile(LowPath* lowpath, u32* result) {
+ LOG("DeleteFile stub");
+ };
+ virtual void RenameFile() {
+ LOG("RenameFile stub");
+ };
+ ~Archive();
+protected:
+ LowPath m_lowpath;
+ Process9* m_owner;
+private:
+};
+
+
--- /dev/null
+
+class P9File
+{
+public:
+ P9File(Process9* owner, LowPath lowpath, LowPath highpath, u32 achivetype);
+ P9File(Process9* owner, LowPath lowpath, LowPath highpath, FILE* fs, u64 offset, u64 size, u8 *hash, u32 achivetype);
+ ~P9File();
+
+ virtual u64 getsize();
+ virtual s32 setsize(u64 size);
+ virtual s32 read(u8 *buffer, u32 size, u64 file_offset, u32 &out_sizeread);
+ virtual s32 write(u8 *buffer, u32 size, u64 file_offset, u32 &out_sizewritten);
+ virtual u8* GetHashPtr();
+
+ enum {
+ OPEN_READ = 1,
+ OPEN_WRITE = 2,
+ OPEN_CREATE = 4
+ };
+
+ static const char* FlagsToMode(u32 flags, char *buf_out)
+ {
+ switch (flags)
+ {
+ case 1: //R
+ strcpy(buf_out, "rb");
+ break;
+ case 2: //W
+ case 3: //RW
+ strcpy(buf_out, "rb+");
+ break;
+ case 4: //C
+ case 6: //W+C
+ strcpy(buf_out, "wb+");
+ break;
+ default:
+ buf_out[0] = '\0';
+ break;
+ }
+ return buf_out;
+ }
+
+ static const char* FlagsToString(u32 flags, char* buf_out)
+ {
+ buf_out[0] = '\0';
+
+ // Convert flags to string representation.
+ if (flags & OPEN_READ)
+ strcat(buf_out, "R");
+ if (flags & OPEN_WRITE)
+ strcat(buf_out, "W");
+ if (flags & OPEN_CREATE)
+ strcat(buf_out, "C");
+
+ return buf_out;
+ }
+
+private:
+ LowPath m_lowpath;
+ LowPath m_highpath;
+ char m_realpath[0x400];
+ u64 m_offset;
+ u64 m_size;
+ Process9* m_owner;
+ FILE* m_fs;
+ u8 *m_hash;
+ u32 m_achivetype;
+};
+
+
--- /dev/null
+class P9MC
+{
+public:
+ P9MC(Process9* owner);
+ ~P9MC();
+ void Command(u32 data[],u32 numb);
+private:
+ Process9* m_owner;
+};
+
+
--- /dev/null
+
+class Archive;
+struct fsArchiveentry
+{
+ Archive * Archobj;
+ u64 id;
+};
+
+struct fsFileentry
+{
+ P9File * Archobj;
+ u64 id;
+};
+
+typedef fsArchiveentry s_fsArchiveEntry;
+typedef fsFileentry s_fsFileentry;
+
+class P9FS
+{
+public:
+ P9FS(Process9* owner);
+ ~P9FS();
+ void Command(u32 data[],u32 numb);
+private:
+ Process9* m_owner;
+ u64 lastID = 0x110000001;
+ KLinkedList<s_fsArchiveEntry> m_open;
+ KLinkedList<s_fsFileentry> m_fopen;
+};
+
+
--- /dev/null
+
+struct PMOpenprocess
+{
+ u64 title;
+ u64 handle; //the most uppern bit should be cleared
+};
+
+class P9PM
+{
+public:
+ P9PM(Process9* owner);
+ ~P9PM();
+ void Command(u32 data[],u32 numb);
+ u64 GetTitle(u64 handle);
+private:
+ Process9* m_owner;
+ u64 handlecount;
+ KLinkedList <PMOpenprocess> m_open;
+};
+
+
--- /dev/null
+class P9PS
+{
+public:
+ P9PS(Process9* owner);
+ ~P9PS();
+ void Command(u32 data[],u32 numb);
+private:
+ Process9* m_owner;
+};
+
+
--- /dev/null
+// This file shouldn't exist. It has STL.
+#include <string>
+
+
+namespace Common {
+ std::string StringFromFormat(const char* format, ...);
+ // Cheap!
+ bool CharArrayFromFormatV(char* out, int outsize, const char* format, va_list args);
+ unsigned int CountLeadingZeros(unsigned int num);
+ FILE* fopen_mkdir(const char* name, const char* mode);
+ char * U16ToASCII(char* data);
+}
+
--- /dev/null
+
+#include "../Common.h"
+
+static u64 LowPathRead64(uint8_t p[8])
+{
+ u64 temp = p[4] | p[5] << 8 | p[6] << 16 | p[7] << 24 | (u64)(p[0]) << 32 | (u64)(p[1]) << 40 | (u64)(p[2]) << 48 | (u64)(p[3]) << 56;
+ return temp;
+}
+
+class LowPath {
+public:
+ LowPath(u32 type, u32 size, u32 desc, u8 *ptr);
+ LowPath(LowPath &pat);
+ ~LowPath();
+
+ enum {
+ PATH_INVALID,
+ PATH_EMPTY,
+ PATH_BINARY,
+ PATH_CHAR,
+ PATH_WCHAR
+ };
+
+ const char* TypeToString()
+ {
+ // Convert type to string representation.
+ switch(m_type) {
+ case PATH_INVALID:
+ return "INVALID";
+ case PATH_EMPTY:
+ return "EMPTY";
+ case PATH_BINARY:
+ return "BINARY";
+ case PATH_CHAR:
+ return "CHAR";
+ case PATH_WCHAR:
+ return "WCHAR";
+ default:
+ return "UNKNOWN";
+ }
+ }
+
+ const std::string GetPath()
+ {
+ static const char* hex_digits = "0123456789abcdef";
+ u32 i;
+
+ std::string str;
+
+ str.resize(512); //TODO: fix this
+
+ switch(m_type) {
+ case PATH_BINARY:
+ // Dump binary paths in hex.
+ for(i = 0; i < m_size; i++) {
+ u8 b = m_ptr[i];
+ str[2 * i] = hex_digits[(b >> 4) & 0xF];
+ str[2 * i + 1] = hex_digits[b & 0xF];
+ }
+ return str;
+
+ case PATH_CHAR:
+ return std::string((char*)m_ptr);
+
+ case PATH_WCHAR:
+ for(i = 0; i < m_size; i++) {
+ // TODO: Do this conversion properly
+ // Convert unicode -> ascii.
+ // If it fails, use question marks.
+ if(m_ptr[(2 * i) + 1])
+ str[i] = '?';
+ else
+ str[i] = m_ptr[2 * i] & 0xFF;
+ }
+ return str;
+
+ default:
+ return "";
+ }
+ }
+
+ const u32 GetSize()
+ {
+ return m_size;
+ }
+
+ const u64 GetHandle()
+ {
+ return LowPathRead64(m_ptr);
+ }
+ const u8* getraw()
+ {
+ return m_ptr;
+ }
+private:
+ u32 m_type;
+ u32 m_size;
+ u32 m_desc;
+ u8 *m_ptr;
+};
--- /dev/null
+#include "Platform.h"
+
+#if EMU_PLATFORM == PLATFORM_LINUX
+#include <pthread.h>
+#elif EMU_PLATFORM == PLATFORM_WINDOWS
+#include <windows.h>
+#endif
+
+class PMutex {
+public:
+ PMutex();
+ ~PMutex();
+
+ void Lock();
+ bool IsLocked();
+ void Unlock();
+private:
+ bool m_locked;
+
+#if EMU_PLATFORM == PLATFORM_LINUX
+ pthread_mutex_t m_mutex;
+#elif EMU_PLATFORM == PLATFORM_WINDOWS
+ HANDLE m_mutex;
+#endif
+};