fc99395c |
1 | #pragma once\r |
2 | \r |
3 | #define KHAX_DEBUG\r |
4 | //#define KHAX_DEBUG_DUMP_DATA\r |
5 | \r |
6 | #ifdef KHAX_DEBUG\r |
7 | #define KHAX_printf(...) printf(__VA_ARGS__), gspWaitForVBlank(), gfxFlushBuffers(), gfxSwapBuffers()\r |
8 | #else\r |
9 | #define KHAX_printf static_cast<void>\r |
10 | #endif\r |
11 | \r |
12 | // Shut up IntelliSense warnings when using MSVC as an IDE, even though MSVC will obviously never\r |
13 | // actually compile this program.\r |
14 | #ifdef _MSC_VER\r |
15 | #undef ALIGN\r |
16 | #define ALIGN(x) __declspec(align(x))\r |
17 | #if _MSC_VER < 1900\r |
18 | #define alignof __alignof\r |
19 | #endif\r |
20 | #define KHAX_ATTRIBUTE(...)\r |
21 | #else\r |
22 | #define KHAX_ATTRIBUTE(...) __VA_ARGS__\r |
23 | #endif\r |
24 | \r |
25 | #define KHAX_lengthof(...) (sizeof(__VA_ARGS__) / sizeof((__VA_ARGS__)[0]))\r |
26 | \r |
27 | //------------------------------------------------------------------------------------------------\r |
28 | namespace KHAX\r |
29 | {\r |
30 | //------------------------------------------------------------------------------------------------\r |
31 | // This code uses offsetof illegally (i.e. on polymorphic classes).\r |
32 | #pragma GCC diagnostic push\r |
33 | #pragma GCC diagnostic ignored "-Winvalid-offsetof"\r |
34 | \r |
35 | //------------------------------------------------------------------------------------------------\r |
36 | // General linked list node kernel object.\r |
37 | struct KLinkedListNode\r |
38 | {\r |
39 | KLinkedListNode *next;\r |
40 | KLinkedListNode *prev;\r |
41 | void *data;\r |
42 | };\r |
43 | static_assert(sizeof(KLinkedListNode) == 0x00C, "KLinkedListNode isn't the expected size.");\r |
44 | \r |
45 | //------------------------------------------------------------------------------------------------\r |
46 | // Base class of reference-counted kernel objects.\r |
47 | class KAutoObject\r |
48 | {\r |
49 | public:\r |
50 | u32 m_refCount; // +004\r |
51 | \r |
52 | protected:\r |
53 | virtual ~KAutoObject() {}\r |
54 | };\r |
55 | static_assert(sizeof(KAutoObject) == 0x008, "KAutoObject isn't the expected size.");\r |
56 | static_assert(offsetof(KAutoObject, m_refCount) == 0x004, "KAutoObject isn't the expected layout.");\r |
57 | \r |
58 | //------------------------------------------------------------------------------------------------\r |
59 | // Base class of synchronizable objects.\r |
60 | class KSynchronizationObject : public KAutoObject\r |
61 | {\r |
62 | public:\r |
63 | u32 m_threadSyncCount; // +008\r |
64 | KLinkedListNode *m_threadSyncFirst; // +00C\r |
65 | KLinkedListNode *m_threadSyncLast; // +010\r |
66 | };\r |
67 | static_assert(sizeof(KSynchronizationObject) == 0x014, "KSynchronizationObject isn't the expected size.");\r |
68 | static_assert(offsetof(KSynchronizationObject, m_threadSyncCount) == 0x008,\r |
69 | "KSynchronizationObject isn't the expected layout.");\r |
70 | \r |
71 | //------------------------------------------------------------------------------------------------\r |
72 | struct KDebugThread;\r |
73 | struct KThreadLocalPage;\r |
74 | class KCodeSet;\r |
75 | \r |
76 | //------------------------------------------------------------------------------------------------\r |
77 | // Unofficial name\r |
78 | typedef u8 KSVCACL[0x80 / 8];\r |
79 | \r |
80 | //------------------------------------------------------------------------------------------------\r |
81 | // ARM VFP register\r |
82 | union KHAX_ATTRIBUTE(__attribute__((__aligned__(4))) __attribute__((__packed__))) VFPRegister\r |
83 | {\r |
84 | float m_single[2];\r |
85 | double m_double;\r |
86 | };\r |
87 | static_assert(alignof(VFPRegister) == 0x004,\r |
88 | "VFPRegister isn't the expected alignment.");\r |
89 | static_assert(sizeof(VFPRegister) == 0x008,\r |
90 | "VFPRegister isn't the expected size.");\r |
91 | \r |
92 | //------------------------------------------------------------------------------------------------\r |
93 | // SVC-mode register save area.\r |
94 | // http://3dbrew.org/wiki/Memory_layout#0xFF4XX000\r |
95 | struct SVCRegisterState\r |
96 | {\r |
97 | u32 m_r4; // +000\r |
98 | u32 m_r5; // +004\r |
99 | u32 m_r6; // +008\r |
100 | u32 m_r7; // +00C\r |
101 | u32 m_r8; // +010\r |
102 | u32 m_r9; // +014\r |
103 | u32 m_sl; // +018\r |
104 | u32 m_fp; // +01C\r |
105 | u32 m_sp; // +020\r |
106 | u32 m_lr; // +024\r |
107 | };\r |
108 | static_assert(sizeof(SVCRegisterState) == 0x028,\r |
109 | "SVCRegisterState isn't the expected size.");\r |
110 | \r |
111 | //------------------------------------------------------------------------------------------------\r |
112 | // SVC-mode thread state structure. This is the last part of the per-\r |
113 | // thread page allocated in 0xFF4XX000.\r |
114 | // http://3dbrew.org/wiki/Memory_layout#0xFF4XX000\r |
115 | struct SVCThreadArea\r |
116 | {\r |
117 | KSVCACL m_svcAccessControl; // +000\r |
118 | u32 m_unknown010; // +010\r |
119 | u32 m_unknown014; // +014\r |
120 | SVCRegisterState m_svcRegisterState; // +018\r |
121 | VFPRegister m_vfpRegisters[16]; // +040\r |
122 | u32 m_unknown0C4; // +0C0\r |
123 | u32 m_fpexc; // +0C4\r |
124 | };\r |
125 | static_assert(offsetof(SVCThreadArea, m_svcRegisterState) == 0x018,\r |
126 | "ThreadSVCArea isn't the expected layout.");\r |
127 | static_assert(sizeof(SVCThreadArea) == 0x0C8,\r |
128 | "ThreadSVCArea isn't the expected size.");\r |
129 | \r |
130 | //------------------------------------------------------------------------------------------------\r |
131 | // Kernel's internal structure of a thread object.\r |
132 | class KThread : public KSynchronizationObject\r |
133 | {\r |
134 | public:\r |
135 | u32 m_unknown014; // +014\r |
136 | u32 m_unknown018; // +018\r |
137 | u32 m_unknown01C; // +01C\r |
138 | u32 m_unknown020; // +020\r |
139 | u32 m_unknown024; // +024\r |
140 | u32 m_unknown028; // +028\r |
141 | u32 m_unknown02C; // +02C\r |
142 | u32 m_unknown030; // +030\r |
143 | u32 m_unknown034; // +034\r |
144 | KDebugThread *m_debugThread; // +038\r |
145 | s32 m_threadPriority; // +03C\r |
146 | void *m_waitingOnObject; // +040\r |
147 | u32 m_unknown044; // +044\r |
148 | KThread **m_schedulerUnknown048; // +048\r |
149 | void *m_arbitrationAddress; // +04C\r |
150 | u32 m_unknown050; // +050\r |
151 | u32 m_unknown054; // +054\r |
152 | u32 m_unknown058; // +058\r |
153 | KLinkedListNode *m_waitingOnList; // +05C\r |
154 | u32 m_unknownListCount; // +060\r |
155 | KLinkedListNode *m_unknownListHead; // +064\r |
156 | KLinkedListNode *m_unknownListTail; // +068\r |
157 | s32 m_threadPriority2; // +06C\r |
158 | s32 m_creatingProcessor; // +070\r |
159 | u32 m_unknown074; // +074\r |
160 | u32 m_unknown078; // +078\r |
161 | u16 m_unknown07C; // +07C\r |
162 | u8 m_threadType; // +07E\r |
163 | u8 m_padding07F; // +07F\r |
164 | void *m_process; // +080\r |
165 | u32 m_threadID; // +084\r |
166 | SVCRegisterState *m_svcRegisterState; // +088\r |
167 | void *m_svcPageEnd; // +08C\r |
168 | s32 m_idealProcessor; // +090\r |
169 | void *m_tlsUserMode; // +094\r |
170 | void *m_tlsKernelMode; // +098\r |
171 | u32 m_unknown09C; // +09C\r |
172 | KThread *m_prev; // +0A0\r |
173 | KThread *m_next; // +0A4\r |
174 | KThread **m_temporaryLinkedList; // +0A8\r |
175 | u32 m_unknown0AC; // +0B0\r |
176 | };\r |
177 | static_assert(sizeof(KThread) == 0x0B0,\r |
178 | "KThread isn't the expected size.");\r |
179 | static_assert(offsetof(KThread, m_svcRegisterState) == 0x088,\r |
180 | "KThread isn't the expected layout.");\r |
181 | \r |
182 | //------------------------------------------------------------------------------------------------\r |
183 | // Kernel's internal structure of a process object.\r |
184 | // Version 1.0.0(?) - 7.2.0\r |
185 | class KProcess_1_0_0_Old : public KSynchronizationObject\r |
186 | {\r |
187 | public:\r |
188 | u32 m_unknown014; // +014\r |
189 | u32 m_unknown018; // +018\r |
190 | KThread *volatile m_interactingThread; // +01C\r |
191 | u16 m_unknown020; // +020\r |
192 | u16 m_unknown022; // +022\r |
193 | u32 m_unknown024; // +024\r |
194 | u32 m_unknown028; // +028\r |
195 | u32 m_memoryBlockCount; // +02C\r |
196 | KLinkedListNode *m_memoryBlockFirst; // +030\r |
197 | KLinkedListNode *m_memoryBlockLast; // +034\r |
198 | u32 m_unknown038; // +038\r |
199 | u32 m_unknown03C; // +03C\r |
200 | void *m_translationTableBase; // +040\r |
201 | u8 m_contextID; // +044\r |
202 | u32 m_unknown048; // +048\r |
203 | u32 m_unknown04C; // +04C\r |
204 | u32 m_mmuTableSize; // +050\r |
205 | void *m_mmuTableAddress; // +054\r |
206 | u32 m_threadContextPagesSize; // +058\r |
207 | u32 m_threadLocalPageCount; // +05C\r |
208 | KLinkedListNode *m_threadLocalPageFirst; // +060\r |
209 | KLinkedListNode *m_threadLocalPageLast; // +064\r |
210 | u32 m_unknown068; // +068\r |
211 | s32 m_idealProcessor; // +06C\r |
212 | u32 m_unknown070; // +070\r |
213 | void *m_resourceLimits; // +074\r |
214 | u8 m_unknown078; // +078\r |
215 | u8 m_affinityMask; // +079\r |
216 | u32 m_threadCount; // +07C\r |
217 | KSVCACL m_svcAccessControl; // +080\r |
218 | u32 m_interruptFlags[0x80 / 32]; // +090\r |
219 | u32 m_kernelFlags; // +0A0\r |
220 | u16 m_handleTableSize; // +0A4\r |
221 | u16 m_kernelReleaseVersion; // +0A6\r |
222 | KCodeSet *m_codeSet; // +0A8\r |
223 | u32 m_processID; // +0AC\r |
224 | u32 m_kernelFlags2; // +0B0\r |
225 | u32 m_unknown0B4; // +0B4\r |
226 | KThread *m_mainThread; // +0B8\r |
227 | //...more...\r |
228 | };\r |
229 | static_assert(offsetof(KProcess_1_0_0_Old, m_svcAccessControl) == 0x080,\r |
230 | "KProcess_1_0_0_Old isn't the expected layout.");\r |
231 | \r |
232 | //------------------------------------------------------------------------------------------------\r |
233 | // Kernel's internal structure of a process object.\r |
234 | // Old 3DS Version 8.0.0 - 9.5.0...\r |
235 | class KProcess_8_0_0_Old : public KSynchronizationObject\r |
236 | {\r |
237 | public:\r |
238 | u32 m_unknown014; // +014\r |
239 | u32 m_unknown018; // +018\r |
240 | KThread *volatile m_interactingThread; // +01C\r |
241 | u16 m_unknown020; // +020\r |
242 | u16 m_unknown022; // +022\r |
243 | u32 m_unknown024; // +024\r |
244 | u32 m_unknown028; // +028\r |
245 | u32 m_memoryBlockCount; // +02C\r |
246 | KLinkedListNode *m_memoryBlockFirst; // +030\r |
247 | KLinkedListNode *m_memoryBlockLast; // +034\r |
248 | u32 m_unknown038; // +038\r |
249 | u32 m_unknown03C; // +03C\r |
250 | void *m_translationTableBase; // +040\r |
251 | u8 m_contextID; // +044\r |
252 | u32 m_unknown048; // +048\r |
253 | void *m_userVirtualMemoryEnd; // +04C\r |
254 | void *m_userLinearVirtualBase; // +050\r |
255 | u32 m_unknown054; // +054\r |
256 | u32 m_mmuTableSize; // +058\r |
257 | void *m_mmuTableAddress; // +05C\r |
258 | u32 m_threadContextPagesSize; // +060\r |
259 | u32 m_threadLocalPageCount; // +064\r |
260 | KLinkedListNode *m_threadLocalPageFirst; // +068\r |
261 | KLinkedListNode *m_threadLocalPageLast; // +06C\r |
262 | u32 m_unknown070; // +070\r |
263 | s32 m_idealProcessor; // +074\r |
264 | u32 m_unknown078; // +078\r |
265 | void *m_resourceLimits; // +07C\r |
266 | u32 m_unknown080; // +080\r |
267 | u32 m_threadCount; // +084\r |
268 | u8 m_svcAccessControl[0x80 / 8]; // +088\r |
269 | u32 m_interruptFlags[0x80 / 32]; // +098\r |
270 | u32 m_kernelFlags; // +0A8\r |
271 | u16 m_handleTableSize; // +0AC\r |
272 | u16 m_kernelReleaseVersion; // +0AE\r |
273 | KCodeSet *m_codeSet; // +0B0\r |
274 | u32 m_processID; // +0B4\r |
275 | u32 m_unknown0B8; // +0B8\r |
276 | u32 m_unknown0BC; // +0BC\r |
277 | KThread *m_mainThread; // +0C0\r |
278 | //...more...\r |
279 | };\r |
280 | static_assert(offsetof(KProcess_8_0_0_Old, m_svcAccessControl) == 0x088,\r |
281 | "KProcess_8_0_0_Old isn't the expected layout.");\r |
282 | \r |
283 | //------------------------------------------------------------------------------------------------\r |
284 | // Kernel's internal structure of a process object.\r |
285 | // New 3DS Version 8.0.0 - 9.5.0...\r |
286 | class KProcess_8_0_0_New : public KSynchronizationObject\r |
287 | {\r |
288 | public:\r |
289 | u32 m_unknown014; // +014\r |
290 | u32 m_unknown018; // +018\r |
291 | KThread *volatile m_interactingThread; // +01C\r |
292 | u16 m_unknown020; // +020\r |
293 | u16 m_unknown022; // +022\r |
294 | u32 m_unknown024; // +024\r |
295 | u32 m_unknown028; // +028\r |
296 | u32 m_unknown02C; // +02C new to New 3DS\r |
297 | u32 m_unknown030; // +030 new to New 3DS\r |
298 | u32 m_memoryBlockCount; // +034\r |
299 | KLinkedListNode *m_memoryBlockFirst; // +038\r |
300 | KLinkedListNode *m_memoryBlockLast; // +03C\r |
301 | u32 m_unknown040; // +040\r |
302 | u32 m_unknown044; // +044\r |
303 | void *m_translationTableBase; // +048\r |
304 | u8 m_contextID; // +04C\r |
305 | u32 m_unknown050; // +050\r |
306 | void *m_userVirtualMemoryEnd; // +054\r |
307 | void *m_userLinearVirtualBase; // +058\r |
308 | u32 m_unknown05C; // +05C\r |
309 | u32 m_mmuTableSize; // +060\r |
310 | void *m_mmuTableAddress; // +064\r |
311 | u32 m_threadContextPagesSize; // +068\r |
312 | u32 m_threadLocalPageCount; // +06C\r |
313 | KLinkedListNode *m_threadLocalPageFirst; // +070\r |
314 | KLinkedListNode *m_threadLocalPageLast; // +074\r |
315 | u32 m_unknown078; // +078\r |
316 | s32 m_idealProcessor; // +07C\r |
317 | u32 m_unknown080; // +080\r |
318 | void *m_resourceLimits; // +084\r |
319 | u32 m_unknown088; // +088\r |
320 | u32 m_threadCount; // +08C\r |
321 | u8 m_svcAccessControl[0x80 / 8]; // +090\r |
322 | u32 m_interruptFlags[0x80 / 32]; // +0A0\r |
323 | u32 m_kernelFlags; // +0B0\r |
324 | u16 m_handleTableSize; // +0B4\r |
325 | u16 m_kernelReleaseVersion; // +0B6\r |
326 | KCodeSet *m_codeSet; // +0B8\r |
327 | u32 m_processID; // +0BC\r |
328 | u32 m_unknown0C0; // +0C0\r |
329 | u32 m_unknown0C4; // +0C4\r |
330 | KThread *m_mainThread; // +0C8\r |
331 | //...more...\r |
332 | };\r |
333 | static_assert(offsetof(KProcess_8_0_0_New, m_svcAccessControl) == 0x090,\r |
334 | "KProcess_8_0_0_New isn't the expected layout.");\r |
335 | \r |
336 | //------------------------------------------------------------------------------------------------\r |
337 | // Done using illegal offsetof\r |
338 | #pragma GCC diagnostic pop\r |
339 | }\r |