4 //#define KHAX_DEBUG_DUMP_DATA
\r
7 #define KHAX_printf(...) printf(__VA_ARGS__), gspWaitForVBlank(), gfxFlushBuffers(), gfxSwapBuffers()
\r
9 #define KHAX_printf static_cast<void>
\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
16 #define ALIGN(x) __declspec(align(x))
\r
18 #define alignof __alignof
\r
20 #define KHAX_ATTRIBUTE(...)
\r
22 #define KHAX_ATTRIBUTE(...) __VA_ARGS__
\r
25 #define KHAX_lengthof(...) (sizeof(__VA_ARGS__) / sizeof((__VA_ARGS__)[0]))
\r
27 //------------------------------------------------------------------------------------------------
\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
35 //------------------------------------------------------------------------------------------------
\r
36 // General linked list node kernel object.
\r
37 struct KLinkedListNode
\r
39 KLinkedListNode *next;
\r
40 KLinkedListNode *prev;
\r
43 static_assert(sizeof(KLinkedListNode) == 0x00C, "KLinkedListNode isn't the expected size.");
\r
45 //------------------------------------------------------------------------------------------------
\r
46 // Base class of reference-counted kernel objects.
\r
50 u32 m_refCount; // +004
\r
53 virtual ~KAutoObject() {}
\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
58 //------------------------------------------------------------------------------------------------
\r
59 // Base class of synchronizable objects.
\r
60 class KSynchronizationObject : public KAutoObject
\r
63 u32 m_threadSyncCount; // +008
\r
64 KLinkedListNode *m_threadSyncFirst; // +00C
\r
65 KLinkedListNode *m_threadSyncLast; // +010
\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
71 //------------------------------------------------------------------------------------------------
\r
72 struct KDebugThread;
\r
73 struct KThreadLocalPage;
\r
76 //------------------------------------------------------------------------------------------------
\r
78 typedef u8 KSVCACL[0x80 / 8];
\r
80 //------------------------------------------------------------------------------------------------
\r
82 union KHAX_ATTRIBUTE(__attribute__((__aligned__(4))) __attribute__((__packed__))) VFPRegister
\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
92 //------------------------------------------------------------------------------------------------
\r
93 // SVC-mode register save area.
\r
94 // http://3dbrew.org/wiki/Memory_layout#0xFF4XX000
\r
95 struct SVCRegisterState
\r
108 static_assert(sizeof(SVCRegisterState) == 0x028,
\r
109 "SVCRegisterState isn't the expected size.");
\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
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
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
130 //------------------------------------------------------------------------------------------------
\r
131 // Kernel's internal structure of a thread object.
\r
132 class KThread : public KSynchronizationObject
\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
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
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
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
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
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
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
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
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
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
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
336 //------------------------------------------------------------------------------------------------
\r
337 // Done using illegal offsetof
\r
338 #pragma GCC diagnostic pop
\r