Browse code

* Fixes for gcc and clang (while they can compile the code, the DLLs made aren't functional, but oh well).

* [2SF] Used more up-to-date asmjit, despite the ugly looking code.

Naram Qashat authored on 2014/09/17 19:51:45
Showing 1 changed files
1 1
deleted file mode 100644
... ...
@@ -1,410 +0,0 @@
1
-/*  Copyright (C) 2008 Guillaume Duhamel
2
-	Copyright (C) 2009-2010 DeSmuME team
3
-
4
-    This file is part of DeSmuME
5
-
6
-    DeSmuME is free software; you can redistribute it and/or modify
7
-    it under the terms of the GNU General Public License as published by
8
-    the Free Software Foundation; either version 2 of the License, or
9
-    (at your option) any later version.
10
-
11
-    DeSmuME is distributed in the hope that it will be useful,
12
-    but WITHOUT ANY WARRANTY; without even the implied warranty of
13
-    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14
-    GNU General Public License for more details.
15
-
16
-    You should have received a copy of the GNU General Public License
17
-    along with DeSmuME; if not, write to the Free Software
18
-    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19
-*/
20
-
21
-#include <algorithm>
22
-#include <cstdarg>
23
-#include <cstdio>
24
-
25
-#include "debug.h"
26
-#include "MMU.h"
27
-#include "armcpu.h"
28
-#include "arm_instructions.h"
29
-#include "thumb_instructions.h"
30
-#include "cp15.h"
31
-#include "NDSSystem.h"
32
-#include "utils/xstring.h"
33
-//#include "movie.h"
34
-
35
-#ifdef HAVE_LUA
36
-#include "lua-engine.h"
37
-#endif
38
-
39
-armcpu_t* TDebugEventData::cpu() { return procnum==0?&NDS_ARM9:&NDS_ARM7; }
40
-
41
-TDebugEventData DebugEventData;
42
-uint32_t debugFlag;
43
-
44
-//DEBUG CONFIGURATION
45
-const bool debug_acl = false;
46
-
47
-static bool acl_check_access(uint32_t adr, uint32_t access) {
48
-
49
-	//non-user modes get separate access handling, so check that here
50
-	if(NDS_ARM9.CPSR.bits.mode != USR)
51
-		access |= 1;
52
-
53
-	if (armcp15_isAccessAllowed((armcp15_t *)NDS_ARM9.coproc[15],adr,access)==false) {
54
-		HandleDebugEvent(DEBUG_EVENT_ACL_EXCEPTION);
55
-	}
56
-	return true;
57
-}
58
-
59
-void HandleDebugEvent_ACL_Exception()
60
-{
61
-	printf("ACL EXCEPTION!\n");
62
-	if(DebugEventData.memAccessType == MMU_AT_CODE)
63
-		armcpu_exception(DebugEventData.cpu(),EXCEPTION_PREFETCH_ABORT);
64
-	else if(DebugEventData.memAccessType == MMU_AT_DATA)
65
-		armcpu_exception(DebugEventData.cpu(),EXCEPTION_DATA_ABORT);
66
-}
67
-
68
-
69
-/*static bool CheckRange(uint32_t adr, uint32_t min, uint32_t len)
70
-{
71
-	return (adr>=min && adr<min+len);
72
-}*/
73
-
74
-void HandleDebugEvent_Read()
75
-{
76
-	if(!debug_acl) return;
77
-	if(DebugEventData.procnum != ARMCPU_ARM9) return; //acl only valid on arm9
78
-	acl_check_access(DebugEventData.addr,CP15_ACCESS_READ);
79
-}
80
-
81
-void HandleDebugEvent_Write()
82
-{
83
-	if(!debug_acl) return;
84
-	if(DebugEventData.procnum != ARMCPU_ARM9) return; //acl only valid on arm9
85
-	acl_check_access(DebugEventData.addr,CP15_ACCESS_WRITE);
86
-}
87
-
88
-void HandleDebugEvent_Execute()
89
-{
90
-	//HACKY BREAKPOINTS!
91
-	//extern bool nds_debug_continuing[2];
92
-	//if(!nds_debug_continuing[DebugEventData.procnum]) //dont keep hitting the same breakpoint
93
-	//{
94
-	//	if((DebugEventData.addr & 0xFFFFFFF0) == 0x02000000)
95
-	//	{
96
-	//		void NDS_debug_break();
97
-	//		NDS_debug_break();
98
-	//	}
99
-	//}
100
-	if(!debug_acl) return;
101
-	if(DebugEventData.procnum != ARMCPU_ARM9) return; //acl only valid on arm9
102
-	acl_check_access(DebugEventData.addr,CP15_ACCESS_EXECUTE);
103
-}
104
-
105
-//------------------------------------------------
106
-DebugStatistics DEBUG_statistics;
107
-
108
-DebugStatistics::DebugStatistics()
109
-{
110
-}
111
-
112
-DebugStatistics::InstructionHits::InstructionHits()
113
-{
114
-	memset(&arm,0,sizeof(arm));
115
-	memset(&thumb,0,sizeof(thumb));
116
-}
117
-
118
-
119
-static DebugStatistics::InstructionHits combinedHits[2];
120
-
121
-template<int proc, int which>
122
-static bool debugStatsSort(int num1, int num2) {
123
-	if(which==0) {
124
-		if(combinedHits[proc].arm[num2] == combinedHits[proc].arm[num1]) return false;
125
-		if(combinedHits[proc].arm[num1] == 0xFFFFFFFF) return false;
126
-		if(combinedHits[proc].arm[num2] == 0xFFFFFFFF) return true;
127
-		return combinedHits[proc].arm[num2] < combinedHits[proc].arm[num1];
128
-	}
129
-	else {
130
-		if(combinedHits[proc].thumb[num2] == combinedHits[proc].thumb[num1]) return false;
131
-		if(combinedHits[proc].thumb[num1] == 0xFFFFFFFF) return false;
132
-		if(combinedHits[proc].thumb[num2] == 0xFFFFFFFF) return true;
133
-		return combinedHits[proc].thumb[num2] < combinedHits[proc].thumb[num1];
134
-	}
135
-}
136
-
137
-void DebugStatistics::print()
138
-{
139
-	//consolidate opcodes with the same names
140
-	for(int i=0;i<2;i++) {
141
-		combinedHits[i] = DEBUG_statistics.instructionHits[i];
142
-
143
-		for(int j=0;j<4096;j++) {
144
-			if(combinedHits[i].arm[j] == 0xFFFFFFFF)
145
-				continue;
146
-			std::string name = arm_instruction_names[j];
147
-			for(int k=j+1;k<4096;k++) {
148
-				if(combinedHits[i].arm[k] == 0xFFFFFFFF)
149
-					continue;
150
-				if(name == arm_instruction_names[k]) {
151
-					//printf("combining %s with %d and %d\n",name.c_str(),combinedHits[i].arm[j],combinedHits[i].arm[k]);
152
-					combinedHits[i].arm[j] += combinedHits[i].arm[k];
153
-					combinedHits[i].arm[k] = 0xFFFFFFFF;
154
-				}
155
-
156
-			}
157
-		}
158
-
159
-		for(int j=0;j<1024;j++) {
160
-			if(combinedHits[i].thumb[j] == 0xFFFFFFFF)
161
-				continue;
162
-			std::string name = thumb_instruction_names[j];
163
-			for(int k=j+1;k<1024;k++) {
164
-				if(combinedHits[i].thumb[k] == 0xFFFFFFFF)
165
-					continue;
166
-				if(name == thumb_instruction_names[k]) {
167
-					//printf("combining %s with %d and %d\n",name.c_str(),combinedHits[i].arm[j],combinedHits[i].arm[k]);
168
-					combinedHits[i].thumb[j] += combinedHits[i].thumb[k];
169
-					combinedHits[i].thumb[k] = 0xFFFFFFFF;
170
-				}
171
-
172
-			}
173
-		}
174
-	}
175
-
176
-	InstructionHits sorts[2];
177
-	for(int i=0;i<2;i++) {
178
-		for(int j=0;j<4096;j++) sorts[i].arm[j] = j;
179
-		for(int j=0;j<1024;j++) sorts[i].thumb[j] = j;
180
-	}
181
-	std::sort(sorts[0].arm, sorts[0].arm+4096, debugStatsSort<0,0>);
182
-	std::sort(sorts[0].thumb, sorts[0].thumb+1024, debugStatsSort<0,1>);
183
-	std::sort(sorts[1].arm, sorts[1].arm+4096, debugStatsSort<1,0>);
184
-	std::sort(sorts[1].thumb, sorts[1].thumb+1024, debugStatsSort<1,1>);
185
-
186
-	for(int i=0;i<2;i++) {
187
-		printf("Top arm instructions for ARM%d:\n",7+i*2);
188
-		for(int j=0;j<10;j++) {
189
-			int val = sorts[i].arm[j];
190
-			printf("%08d: %s\n", combinedHits[i].arm[val], arm_instruction_names[val]);
191
-		}
192
-		printf("Top thumb instructions for ARM%d:\n",7+i*2);
193
-		for(int j=0;j<10;j++) {
194
-			int val = sorts[i].thumb[j];
195
-			printf("%08d: %s\n", combinedHits[i].thumb[val], thumb_instruction_names[val]);
196
-		}
197
-	}
198
-}
199
-
200
-void DebugStatistics::printSequencerExecutionCounters()
201
-{
202
-	for(int i=0;i<21;i++) printf("%06d ",sequencerExecutionCounters[i]);
203
-	printf("\n");
204
-}
205
-
206
-void DEBUG_reset()
207
-{
208
-	//for now, just enable all debugging in developer builds
209
-#ifdef DEVELOPER
210
-	debugFlag = 1;
211
-#endif
212
-
213
-	DEBUG_Notify = DebugNotify();
214
-	DEBUG_statistics = DebugStatistics();
215
-	printf("DEBUG_reset: %08X\n",&DebugStatistics::print); //force a reference to this function
216
-}
217
-
218
-/*static void DEBUG_dumpMemory_fill(EMUFILE *fp, uint32_t size)
219
-{
220
-	static std::vector<uint8_t> buf;
221
-	buf.resize(size);
222
-	memset(&buf[0],0,size);
223
-	fp->fwrite(&buf[0],size);
224
-}*/
225
-
226
-void DEBUG_dumpMemory(EMUFILE* fp)
227
-{
228
-	fp->fseek(0x000000,SEEK_SET); fp->fwrite(MMU.MAIN_MEM,0x800000); //arm9 main mem (8192K)
229
-	fp->fseek(0x900000,SEEK_SET); fp->fwrite(MMU.ARM9_DTCM,0x4000); //arm9 DTCM (16K)
230
-	fp->fseek(0xA00000,SEEK_SET); fp->fwrite(MMU.ARM9_ITCM,0x8000); //arm9 ITCM (32K)
231
-	fp->fseek(0xB00000,SEEK_SET); fp->fwrite(MMU.ARM9_LCD,0xA4000); //LCD mem 656K
232
-	fp->fseek(0xC00000,SEEK_SET); fp->fwrite(MMU.ARM9_VMEM,0x800); //OAM
233
-	fp->fseek(0xD00000,SEEK_SET); fp->fwrite(MMU.ARM7_ERAM,0x10000); //arm7 WRAM (64K)
234
-	fp->fseek(0xE00000,SEEK_SET); fp->fwrite(MMU.ARM7_WIRAM,0x10000); //arm7 wifi RAM ?
235
-	fp->fseek(0xF00000,SEEK_SET); fp->fwrite(MMU.SWIRAM,0x8000); //arm9/arm7 shared WRAM (32KB)
236
-}
237
-
238
-//----------------------------------------------------
239
-
240
-std::vector<Logger *> Logger::channels;
241
-
242
-
243
-static void defaultCallback(const Logger& logger, const char * message) {
244
-	logger.getOutput() << message;
245
-}
246
-
247
-Logger::Logger() {
248
-	out = &std::cout;
249
-	callback = defaultCallback;
250
-	flags = 0;
251
-}
252
-
253
-Logger::~Logger() {
254
-	for(int i=0;i<(int)channels.size();i++)
255
-		delete channels[i];
256
-}
257
-
258
-void Logger::vprintf(const char * format, va_list l, const char * file, unsigned int line) {
259
-	char buffer[1024];
260
-	char * cur = buffer;
261
-
262
-	if (flags & Logger::FILE) cur += sprintf(cur, "%s:", file);
263
-	if (flags & Logger::LINE) cur += sprintf(cur, "%d:", line);
264
-	if (flags) cur += sprintf(cur, " ");
265
-
266
-	::vsnprintf(cur, 1024, format, l);
267
-	callback(*this, buffer);
268
-}
269
-
270
-void Logger::setOutput(std::ostream * o) {
271
-	out = o;
272
-}
273
-
274
-void Logger::setCallback(void (*cback)(const Logger& logger, const char * message)) {
275
-	callback = cback;
276
-}
277
-
278
-void Logger::setFlag(unsigned int flag) {
279
-	this->flags = flag;
280
-}
281
-
282
-void Logger::fixSize(unsigned int channel) {
283
-	while(channel >= channels.size()) {
284
-		channels.push_back(new Logger());
285
-	}
286
-}
287
-
288
-std::ostream& Logger::getOutput() const {
289
-	return *out;
290
-}
291
-
292
-void Logger::log(unsigned int channel, const char * file, unsigned int line, const char * format, ...) {
293
-	fixSize(channel);
294
-
295
-	va_list l;
296
-	va_start(l, format);
297
-	channels[channel]->vprintf(format, l, file, line);
298
-	va_end(l);
299
-}
300
-
301
-void Logger::log(unsigned int channel, const char *, unsigned int, std::ostream& os) {
302
-	fixSize(channel);
303
-
304
-	channels[channel]->setOutput(&os);
305
-}
306
-
307
-void Logger::log(unsigned int channel, const char *, unsigned int, unsigned int flag) {
308
-	fixSize(channel);
309
-
310
-	channels[channel]->setFlag(flag);
311
-}
312
-
313
-void Logger::log(unsigned int channel, const char *, unsigned int, void (*callback)(const Logger& logger, const char * message)) {
314
-	fixSize(channel);
315
-
316
-	channels[channel]->setCallback(callback);
317
-}
318
-
319
-void IdeasLog(armcpu_t* cpu)
320
-{
321
-	uint32_t adr = cpu->R[0];
322
-	for(;;) {
323
-		uint8_t c = _MMU_read08(cpu->proc_ID, MMU_AT_DEBUG, adr);
324
-		adr++;
325
-		if(!c) break;
326
-		printf("%c",c);
327
-	}
328
-	//don't emit a newline. that is a pain in the butt.
329
-}
330
-
331
-void NocashMessage(armcpu_t* cpu)
332
-{
333
-	uint32_t adr = cpu->instruct_adr + 6;
334
-
335
-	std::string todo;
336
-	for(;;) {
337
-		uint8_t c = _MMU_read08(cpu->proc_ID, MMU_AT_DEBUG, adr);
338
-		adr++;
339
-		if(!c) break;
340
-		todo.push_back(c);
341
-	}
342
-
343
-	//r0,r1,r2,...,r15  show register content (displayed as 32bit Hex number)
344
-	//sp,lr,pc          alias for r13,r14,r15
345
-	//scanline          show current scanline number
346
-	//frame             show total number of frames since coldboot
347
-	//totalclks         show total number of clock cycles since coldboot
348
-	//lastclks          show number of cycles since previous lastclks (or zeroclks)
349
-	//zeroclks          resets the 'lastclks' counter
350
-
351
-	//this is very inefficiently coded!
352
-	char tmp[100];
353
-	todo = mass_replace(todo,"%sp%","%r13%");
354
-	todo = mass_replace(todo,"%lr%","%r14%");
355
-	todo = mass_replace(todo,"%pc%","%r15%");
356
-	sprintf(tmp,"%08X",cpu->R[0]); todo = mass_replace(todo,"%r0%",tmp);
357
-	sprintf(tmp,"%08X",cpu->R[1]); todo = mass_replace(todo,"%r1%",tmp);
358
-	sprintf(tmp,"%08X",cpu->R[2]); todo = mass_replace(todo,"%r2%",tmp);
359
-	sprintf(tmp,"%08X",cpu->R[3]); todo = mass_replace(todo,"%r3%",tmp);
360
-	sprintf(tmp,"%08X",cpu->R[4]); todo = mass_replace(todo,"%r4%",tmp);
361
-	sprintf(tmp,"%08X",cpu->R[5]); todo = mass_replace(todo,"%r5%",tmp);
362
-	sprintf(tmp,"%08X",cpu->R[6]); todo = mass_replace(todo,"%r6%",tmp);
363
-	sprintf(tmp,"%08X",cpu->R[7]); todo = mass_replace(todo,"%r7%",tmp);
364
-	sprintf(tmp,"%08X",cpu->R[8]); todo = mass_replace(todo,"%r8%",tmp);
365
-	sprintf(tmp,"%08X",cpu->R[9]); todo = mass_replace(todo,"%r9%",tmp);
366
-	sprintf(tmp,"%08X",cpu->R[10]); todo = mass_replace(todo,"%r10%",tmp);
367
-	sprintf(tmp,"%08X",cpu->R[11]); todo = mass_replace(todo,"%r11%",tmp);
368
-	sprintf(tmp,"%08X",cpu->R[12]); todo = mass_replace(todo,"%r12%",tmp);
369
-	sprintf(tmp,"%08X",cpu->R[13]); todo = mass_replace(todo,"%r13%",tmp);
370
-	sprintf(tmp,"%08X",cpu->R[14]); todo = mass_replace(todo,"%r14%",tmp);
371
-	sprintf(tmp,"%08X",cpu->R[15]); todo = mass_replace(todo,"%r15%",tmp);
372
-	sprintf(tmp,"%d",nds.VCount); todo = mass_replace(todo,"%scanline%",tmp);
373
-	/*sprintf(tmp,"%d",currFrameCounter); */todo = mass_replace(todo,"%frame%",tmp);
374
-	sprintf(tmp,"%lld",nds_timer); todo = mass_replace(todo,"%totalclks%",tmp);
375
-
376
-	printf("%s",todo.c_str());
377
-}
378
-
379
-//-------
380
-DebugNotify DEBUG_Notify;
381
-
382
-//enable bits arent being used right now.
383
-//if you want exhaustive logging, move the print before the early return (or comment the early return)
384
-
385
-//the intent of this system is to provide a compact dialog box showing which debug notifies have been
386
-//triggered in this frame (with a glowing LED!) and which debug notifies have been triggered EVER
387
-//which can be cleared, like a clip indicator in an audio tool.
388
-//obviously all this isnt implemented yet.
389
-
390
-void DebugNotify::NextFrame()
391
-{
392
-#ifdef DEVELOPER
393
-	pingBits.reset();
394
-#endif
395
-}
396
-
397
-void DebugNotify::ReadBeyondEndOfCart(uint32_t addr, uint32_t romsize)
398
-{
399
-#ifdef DEVELOPER
400
-	if(!ping(DEBUG_NOTIFY_READ_BEYOND_END_OF_CART)) return;
401
-	INFO("Reading beyond end of cart! ... %08X >= %08X\n",addr,romsize);
402
-#endif
403
-}
404
-
405
-bool DebugNotify::ping(EDEBUG_NOTIFY which)
406
-{
407
-	bool wasPinged = pingBits[(int)which];
408
-	pingBits[(int)which] = true;
409
-	return !wasPinged;
410
-}
Browse code

Import actual code.

Naram Qashat authored on 2013/03/26 02:41:19
Showing 1 changed files
1 1
new file mode 100644
... ...
@@ -0,0 +1,410 @@
1
+/*  Copyright (C) 2008 Guillaume Duhamel
2
+	Copyright (C) 2009-2010 DeSmuME team
3
+
4
+    This file is part of DeSmuME
5
+
6
+    DeSmuME is free software; you can redistribute it and/or modify
7
+    it under the terms of the GNU General Public License as published by
8
+    the Free Software Foundation; either version 2 of the License, or
9
+    (at your option) any later version.
10
+
11
+    DeSmuME is distributed in the hope that it will be useful,
12
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
13
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14
+    GNU General Public License for more details.
15
+
16
+    You should have received a copy of the GNU General Public License
17
+    along with DeSmuME; if not, write to the Free Software
18
+    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19
+*/
20
+
21
+#include <algorithm>
22
+#include <cstdarg>
23
+#include <cstdio>
24
+
25
+#include "debug.h"
26
+#include "MMU.h"
27
+#include "armcpu.h"
28
+#include "arm_instructions.h"
29
+#include "thumb_instructions.h"
30
+#include "cp15.h"
31
+#include "NDSSystem.h"
32
+#include "utils/xstring.h"
33
+//#include "movie.h"
34
+
35
+#ifdef HAVE_LUA
36
+#include "lua-engine.h"
37
+#endif
38
+
39
+armcpu_t* TDebugEventData::cpu() { return procnum==0?&NDS_ARM9:&NDS_ARM7; }
40
+
41
+TDebugEventData DebugEventData;
42
+uint32_t debugFlag;
43
+
44
+//DEBUG CONFIGURATION
45
+const bool debug_acl = false;
46
+
47
+static bool acl_check_access(uint32_t adr, uint32_t access) {
48
+
49
+	//non-user modes get separate access handling, so check that here
50
+	if(NDS_ARM9.CPSR.bits.mode != USR)
51
+		access |= 1;
52
+
53
+	if (armcp15_isAccessAllowed((armcp15_t *)NDS_ARM9.coproc[15],adr,access)==false) {
54
+		HandleDebugEvent(DEBUG_EVENT_ACL_EXCEPTION);
55
+	}
56
+	return true;
57
+}
58
+
59
+void HandleDebugEvent_ACL_Exception()
60
+{
61
+	printf("ACL EXCEPTION!\n");
62
+	if(DebugEventData.memAccessType == MMU_AT_CODE)
63
+		armcpu_exception(DebugEventData.cpu(),EXCEPTION_PREFETCH_ABORT);
64
+	else if(DebugEventData.memAccessType == MMU_AT_DATA)
65
+		armcpu_exception(DebugEventData.cpu(),EXCEPTION_DATA_ABORT);
66
+}
67
+
68
+
69
+/*static bool CheckRange(uint32_t adr, uint32_t min, uint32_t len)
70
+{
71
+	return (adr>=min && adr<min+len);
72
+}*/
73
+
74
+void HandleDebugEvent_Read()
75
+{
76
+	if(!debug_acl) return;
77
+	if(DebugEventData.procnum != ARMCPU_ARM9) return; //acl only valid on arm9
78
+	acl_check_access(DebugEventData.addr,CP15_ACCESS_READ);
79
+}
80
+
81
+void HandleDebugEvent_Write()
82
+{
83
+	if(!debug_acl) return;
84
+	if(DebugEventData.procnum != ARMCPU_ARM9) return; //acl only valid on arm9
85
+	acl_check_access(DebugEventData.addr,CP15_ACCESS_WRITE);
86
+}
87
+
88
+void HandleDebugEvent_Execute()
89
+{
90
+	//HACKY BREAKPOINTS!
91
+	//extern bool nds_debug_continuing[2];
92
+	//if(!nds_debug_continuing[DebugEventData.procnum]) //dont keep hitting the same breakpoint
93
+	//{
94
+	//	if((DebugEventData.addr & 0xFFFFFFF0) == 0x02000000)
95
+	//	{
96
+	//		void NDS_debug_break();
97
+	//		NDS_debug_break();
98
+	//	}
99
+	//}
100
+	if(!debug_acl) return;
101
+	if(DebugEventData.procnum != ARMCPU_ARM9) return; //acl only valid on arm9
102
+	acl_check_access(DebugEventData.addr,CP15_ACCESS_EXECUTE);
103
+}
104
+
105
+//------------------------------------------------
106
+DebugStatistics DEBUG_statistics;
107
+
108
+DebugStatistics::DebugStatistics()
109
+{
110
+}
111
+
112
+DebugStatistics::InstructionHits::InstructionHits()
113
+{
114
+	memset(&arm,0,sizeof(arm));
115
+	memset(&thumb,0,sizeof(thumb));
116
+}
117
+
118
+
119
+static DebugStatistics::InstructionHits combinedHits[2];
120
+
121
+template<int proc, int which>
122
+static bool debugStatsSort(int num1, int num2) {
123
+	if(which==0) {
124
+		if(combinedHits[proc].arm[num2] == combinedHits[proc].arm[num1]) return false;
125
+		if(combinedHits[proc].arm[num1] == 0xFFFFFFFF) return false;
126
+		if(combinedHits[proc].arm[num2] == 0xFFFFFFFF) return true;
127
+		return combinedHits[proc].arm[num2] < combinedHits[proc].arm[num1];
128
+	}
129
+	else {
130
+		if(combinedHits[proc].thumb[num2] == combinedHits[proc].thumb[num1]) return false;
131
+		if(combinedHits[proc].thumb[num1] == 0xFFFFFFFF) return false;
132
+		if(combinedHits[proc].thumb[num2] == 0xFFFFFFFF) return true;
133
+		return combinedHits[proc].thumb[num2] < combinedHits[proc].thumb[num1];
134
+	}
135
+}
136
+
137
+void DebugStatistics::print()
138
+{
139
+	//consolidate opcodes with the same names
140
+	for(int i=0;i<2;i++) {
141
+		combinedHits[i] = DEBUG_statistics.instructionHits[i];
142
+
143
+		for(int j=0;j<4096;j++) {
144
+			if(combinedHits[i].arm[j] == 0xFFFFFFFF)
145
+				continue;
146
+			std::string name = arm_instruction_names[j];
147
+			for(int k=j+1;k<4096;k++) {
148
+				if(combinedHits[i].arm[k] == 0xFFFFFFFF)
149
+					continue;
150
+				if(name == arm_instruction_names[k]) {
151
+					//printf("combining %s with %d and %d\n",name.c_str(),combinedHits[i].arm[j],combinedHits[i].arm[k]);
152
+					combinedHits[i].arm[j] += combinedHits[i].arm[k];
153
+					combinedHits[i].arm[k] = 0xFFFFFFFF;
154
+				}
155
+
156
+			}
157
+		}
158
+
159
+		for(int j=0;j<1024;j++) {
160
+			if(combinedHits[i].thumb[j] == 0xFFFFFFFF)
161
+				continue;
162
+			std::string name = thumb_instruction_names[j];
163
+			for(int k=j+1;k<1024;k++) {
164
+				if(combinedHits[i].thumb[k] == 0xFFFFFFFF)
165
+					continue;
166
+				if(name == thumb_instruction_names[k]) {
167
+					//printf("combining %s with %d and %d\n",name.c_str(),combinedHits[i].arm[j],combinedHits[i].arm[k]);
168
+					combinedHits[i].thumb[j] += combinedHits[i].thumb[k];
169
+					combinedHits[i].thumb[k] = 0xFFFFFFFF;
170
+				}
171
+
172
+			}
173
+		}
174
+	}
175
+
176
+	InstructionHits sorts[2];
177
+	for(int i=0;i<2;i++) {
178
+		for(int j=0;j<4096;j++) sorts[i].arm[j] = j;
179
+		for(int j=0;j<1024;j++) sorts[i].thumb[j] = j;
180
+	}
181
+	std::sort(sorts[0].arm, sorts[0].arm+4096, debugStatsSort<0,0>);
182
+	std::sort(sorts[0].thumb, sorts[0].thumb+1024, debugStatsSort<0,1>);
183
+	std::sort(sorts[1].arm, sorts[1].arm+4096, debugStatsSort<1,0>);
184
+	std::sort(sorts[1].thumb, sorts[1].thumb+1024, debugStatsSort<1,1>);
185
+
186
+	for(int i=0;i<2;i++) {
187
+		printf("Top arm instructions for ARM%d:\n",7+i*2);
188
+		for(int j=0;j<10;j++) {
189
+			int val = sorts[i].arm[j];
190
+			printf("%08d: %s\n", combinedHits[i].arm[val], arm_instruction_names[val]);
191
+		}
192
+		printf("Top thumb instructions for ARM%d:\n",7+i*2);
193
+		for(int j=0;j<10;j++) {
194
+			int val = sorts[i].thumb[j];
195
+			printf("%08d: %s\n", combinedHits[i].thumb[val], thumb_instruction_names[val]);
196
+		}
197
+	}
198
+}
199
+
200
+void DebugStatistics::printSequencerExecutionCounters()
201
+{
202
+	for(int i=0;i<21;i++) printf("%06d ",sequencerExecutionCounters[i]);
203
+	printf("\n");
204
+}
205
+
206
+void DEBUG_reset()
207
+{
208
+	//for now, just enable all debugging in developer builds
209
+#ifdef DEVELOPER
210
+	debugFlag = 1;
211
+#endif
212
+
213
+	DEBUG_Notify = DebugNotify();
214
+	DEBUG_statistics = DebugStatistics();
215
+	printf("DEBUG_reset: %08X\n",&DebugStatistics::print); //force a reference to this function
216
+}
217
+
218
+/*static void DEBUG_dumpMemory_fill(EMUFILE *fp, uint32_t size)
219
+{
220
+	static std::vector<uint8_t> buf;
221
+	buf.resize(size);
222
+	memset(&buf[0],0,size);
223
+	fp->fwrite(&buf[0],size);
224
+}*/
225
+
226
+void DEBUG_dumpMemory(EMUFILE* fp)
227
+{
228
+	fp->fseek(0x000000,SEEK_SET); fp->fwrite(MMU.MAIN_MEM,0x800000); //arm9 main mem (8192K)
229
+	fp->fseek(0x900000,SEEK_SET); fp->fwrite(MMU.ARM9_DTCM,0x4000); //arm9 DTCM (16K)
230
+	fp->fseek(0xA00000,SEEK_SET); fp->fwrite(MMU.ARM9_ITCM,0x8000); //arm9 ITCM (32K)
231
+	fp->fseek(0xB00000,SEEK_SET); fp->fwrite(MMU.ARM9_LCD,0xA4000); //LCD mem 656K
232
+	fp->fseek(0xC00000,SEEK_SET); fp->fwrite(MMU.ARM9_VMEM,0x800); //OAM
233
+	fp->fseek(0xD00000,SEEK_SET); fp->fwrite(MMU.ARM7_ERAM,0x10000); //arm7 WRAM (64K)
234
+	fp->fseek(0xE00000,SEEK_SET); fp->fwrite(MMU.ARM7_WIRAM,0x10000); //arm7 wifi RAM ?
235
+	fp->fseek(0xF00000,SEEK_SET); fp->fwrite(MMU.SWIRAM,0x8000); //arm9/arm7 shared WRAM (32KB)
236
+}
237
+
238
+//----------------------------------------------------
239
+
240
+std::vector<Logger *> Logger::channels;
241
+
242
+
243
+static void defaultCallback(const Logger& logger, const char * message) {
244
+	logger.getOutput() << message;
245
+}
246
+
247
+Logger::Logger() {
248
+	out = &std::cout;
249
+	callback = defaultCallback;
250
+	flags = 0;
251
+}
252
+
253
+Logger::~Logger() {
254
+	for(int i=0;i<(int)channels.size();i++)
255
+		delete channels[i];
256
+}
257
+
258
+void Logger::vprintf(const char * format, va_list l, const char * file, unsigned int line) {
259
+	char buffer[1024];
260
+	char * cur = buffer;
261
+
262
+	if (flags & Logger::FILE) cur += sprintf(cur, "%s:", file);
263
+	if (flags & Logger::LINE) cur += sprintf(cur, "%d:", line);
264
+	if (flags) cur += sprintf(cur, " ");
265
+
266
+	::vsnprintf(cur, 1024, format, l);
267
+	callback(*this, buffer);
268
+}
269
+
270
+void Logger::setOutput(std::ostream * o) {
271
+	out = o;
272
+}
273
+
274
+void Logger::setCallback(void (*cback)(const Logger& logger, const char * message)) {
275
+	callback = cback;
276
+}
277
+
278
+void Logger::setFlag(unsigned int flag) {
279
+	this->flags = flag;
280
+}
281
+
282
+void Logger::fixSize(unsigned int channel) {
283
+	while(channel >= channels.size()) {
284
+		channels.push_back(new Logger());
285
+	}
286
+}
287
+
288
+std::ostream& Logger::getOutput() const {
289
+	return *out;
290
+}
291
+
292
+void Logger::log(unsigned int channel, const char * file, unsigned int line, const char * format, ...) {
293
+	fixSize(channel);
294
+
295
+	va_list l;
296
+	va_start(l, format);
297
+	channels[channel]->vprintf(format, l, file, line);
298
+	va_end(l);
299
+}
300
+
301
+void Logger::log(unsigned int channel, const char *, unsigned int, std::ostream& os) {
302
+	fixSize(channel);
303
+
304
+	channels[channel]->setOutput(&os);
305
+}
306
+
307
+void Logger::log(unsigned int channel, const char *, unsigned int, unsigned int flag) {
308
+	fixSize(channel);
309
+
310
+	channels[channel]->setFlag(flag);
311
+}
312
+
313
+void Logger::log(unsigned int channel, const char *, unsigned int, void (*callback)(const Logger& logger, const char * message)) {
314
+	fixSize(channel);
315
+
316
+	channels[channel]->setCallback(callback);
317
+}
318
+
319
+void IdeasLog(armcpu_t* cpu)
320
+{
321
+	uint32_t adr = cpu->R[0];
322
+	for(;;) {
323
+		uint8_t c = _MMU_read08(cpu->proc_ID, MMU_AT_DEBUG, adr);
324
+		adr++;
325
+		if(!c) break;
326
+		printf("%c",c);
327
+	}
328
+	//don't emit a newline. that is a pain in the butt.
329
+}
330
+
331
+void NocashMessage(armcpu_t* cpu)
332
+{
333
+	uint32_t adr = cpu->instruct_adr + 6;
334
+
335
+	std::string todo;
336
+	for(;;) {
337
+		uint8_t c = _MMU_read08(cpu->proc_ID, MMU_AT_DEBUG, adr);
338
+		adr++;
339
+		if(!c) break;
340
+		todo.push_back(c);
341
+	}
342
+
343
+	//r0,r1,r2,...,r15  show register content (displayed as 32bit Hex number)
344
+	//sp,lr,pc          alias for r13,r14,r15
345
+	//scanline          show current scanline number
346
+	//frame             show total number of frames since coldboot
347
+	//totalclks         show total number of clock cycles since coldboot
348
+	//lastclks          show number of cycles since previous lastclks (or zeroclks)
349
+	//zeroclks          resets the 'lastclks' counter
350
+
351
+	//this is very inefficiently coded!
352
+	char tmp[100];
353
+	todo = mass_replace(todo,"%sp%","%r13%");
354
+	todo = mass_replace(todo,"%lr%","%r14%");
355
+	todo = mass_replace(todo,"%pc%","%r15%");
356
+	sprintf(tmp,"%08X",cpu->R[0]); todo = mass_replace(todo,"%r0%",tmp);
357
+	sprintf(tmp,"%08X",cpu->R[1]); todo = mass_replace(todo,"%r1%",tmp);
358
+	sprintf(tmp,"%08X",cpu->R[2]); todo = mass_replace(todo,"%r2%",tmp);
359
+	sprintf(tmp,"%08X",cpu->R[3]); todo = mass_replace(todo,"%r3%",tmp);
360
+	sprintf(tmp,"%08X",cpu->R[4]); todo = mass_replace(todo,"%r4%",tmp);
361
+	sprintf(tmp,"%08X",cpu->R[5]); todo = mass_replace(todo,"%r5%",tmp);
362
+	sprintf(tmp,"%08X",cpu->R[6]); todo = mass_replace(todo,"%r6%",tmp);
363
+	sprintf(tmp,"%08X",cpu->R[7]); todo = mass_replace(todo,"%r7%",tmp);
364
+	sprintf(tmp,"%08X",cpu->R[8]); todo = mass_replace(todo,"%r8%",tmp);
365
+	sprintf(tmp,"%08X",cpu->R[9]); todo = mass_replace(todo,"%r9%",tmp);
366
+	sprintf(tmp,"%08X",cpu->R[10]); todo = mass_replace(todo,"%r10%",tmp);
367
+	sprintf(tmp,"%08X",cpu->R[11]); todo = mass_replace(todo,"%r11%",tmp);
368
+	sprintf(tmp,"%08X",cpu->R[12]); todo = mass_replace(todo,"%r12%",tmp);
369
+	sprintf(tmp,"%08X",cpu->R[13]); todo = mass_replace(todo,"%r13%",tmp);
370
+	sprintf(tmp,"%08X",cpu->R[14]); todo = mass_replace(todo,"%r14%",tmp);
371
+	sprintf(tmp,"%08X",cpu->R[15]); todo = mass_replace(todo,"%r15%",tmp);
372
+	sprintf(tmp,"%d",nds.VCount); todo = mass_replace(todo,"%scanline%",tmp);
373
+	/*sprintf(tmp,"%d",currFrameCounter); */todo = mass_replace(todo,"%frame%",tmp);
374
+	sprintf(tmp,"%lld",nds_timer); todo = mass_replace(todo,"%totalclks%",tmp);
375
+
376
+	printf("%s",todo.c_str());
377
+}
378
+
379
+//-------
380
+DebugNotify DEBUG_Notify;
381
+
382
+//enable bits arent being used right now.
383
+//if you want exhaustive logging, move the print before the early return (or comment the early return)
384
+
385
+//the intent of this system is to provide a compact dialog box showing which debug notifies have been
386
+//triggered in this frame (with a glowing LED!) and which debug notifies have been triggered EVER
387
+//which can be cleared, like a clip indicator in an audio tool.
388
+//obviously all this isnt implemented yet.
389
+
390
+void DebugNotify::NextFrame()
391
+{
392
+#ifdef DEVELOPER
393
+	pingBits.reset();
394
+#endif
395
+}
396
+
397
+void DebugNotify::ReadBeyondEndOfCart(uint32_t addr, uint32_t romsize)
398
+{
399
+#ifdef DEVELOPER
400
+	if(!ping(DEBUG_NOTIFY_READ_BEYOND_END_OF_CART)) return;
401
+	INFO("Reading beyond end of cart! ... %08X >= %08X\n",addr,romsize);
402
+#endif
403
+}
404
+
405
+bool DebugNotify::ping(EDEBUG_NOTIFY which)
406
+{
407
+	bool wasPinged = pingBits[(int)which];
408
+	pingBits[(int)which] = true;
409
+	return !wasPinged;
410
+}