Browse code

update for C++17 compliance, update to latest 2sf, add WINE cross-compile makefiles

Adam Higerd authored on 2021/02/11 15:36:17
Showing 1 changed files
... ...
@@ -38,18 +38,13 @@ GameInfo gameInfo;
38 38
 NDSSystem nds;
39 39
 static std::unique_ptr<CFIRMWARE> firmware;
40 40
 
41
-namespace DLDI
42
-{
43
-	bool tryPatch(void *data, size_t size);
44
-}
45
-
46 41
 int NDS_Init()
47 42
 {
48 43
 	MMU_Init();
49 44
 	nds.VCount = 0;
50 45
 
51 46
 	// got to print this somewhere..
52
-	printf("%s\n", EMU_DESMUME_NAME_AND_VERSION());
47
+	fprintf(stderr, "%s\n", EMU_DESMUME_NAME_AND_VERSION());
53 48
 
54 49
 	armcpu_new(&NDS_ARM7, 1);
55 50
 	armcpu_new(&NDS_ARM9, 0);
... ...
@@ -230,7 +225,7 @@ template<int procnum, int num> struct TSequenceItem_Timer : public TSequenceItem
230 225
 				}
231 226
 #ifndef NDEBUG
232 227
 				if (ctr > 1)
233
-					printf("yikes!!!!! please report!\n");
228
+					fprintf(stderr, "yikes!!!!! please report!\n");
234 229
 #endif
235 230
 			}
236 231
 
... ...
@@ -267,7 +262,7 @@ template<int procnum, int chan> struct TSequenceItem_DMA : public TSequenceItem
267 262
 
268 263
 	void exec()
269 264
 	{
270
-		//printf("exec from TSequenceItem_DMA: %d %d\n",procnum,chan);
265
+		//fprintf(stderr, "exec from TSequenceItem_DMA: %d %d\n",procnum,chan);
271 266
 		this->controller->exec();
272 267
 	}
273 268
 };
... ...
@@ -453,7 +448,7 @@ static void execHardware_hstart_vblankEnd()
453 448
 
454 449
 static void execHardware_hstart_vblankStart()
455 450
 {
456
-	//printf("--------VBLANK!!!--------\n");
451
+	//fprintf(stderr, "--------VBLANK!!!--------\n");
457 452
 
458 453
 	// fire vblank interrupts if necessary
459 454
 	for (int i = 0; i < 2; ++i)
... ...
@@ -794,7 +789,7 @@ template<bool FORCE> void NDS_exec(int32_t)
794 789
 			uint64_t next = sequencer.findNext();
795 790
 			next = std::min(next, nds_timer + kMaxWork); // lets set an upper limit for now
796 791
 
797
-			//printf("%d\n", next - nds_timer);
792
+			//fprintf(stderr, "%d\n", next - nds_timer);
798 793
 
799 794
 			sequencer.reschedule = false;
800 795
 
... ...
@@ -838,7 +833,7 @@ template<int PROCNUM> static void execHardware_interrupts_core()
838 833
 
839 834
 	if (masked && MMU.reg_IME[PROCNUM] && !ARMPROC.CPSR.bits.I)
840 835
 	{
841
-		//printf("Executing IRQ on procnum %d with IF = %08X and IE = %08X\n",PROCNUM,IF,IE);
836
+		//fprintf(stderr, "Executing IRQ on procnum %d with IF = %08X and IE = %08X\n",PROCNUM,IF,IE);
842 837
 		armcpu_irqException(&ARMPROC);
843 838
 	}
844 839
 }
Browse code

* Small Makefile changes.

* Removed a couple files that were not being used.
* Cleanups found with clang's -Weverything (and shutting it up about a
lot of things that were ridiculous, as well as ignoring some of the
warnings still coming up).

Naram Qashat authored on 2014/09/25 12:28:21
Showing 1 changed files
... ...
@@ -36,9 +36,7 @@ TCommonSettings CommonSettings;
36 36
 
37 37
 GameInfo gameInfo;
38 38
 NDSSystem nds;
39
-std::unique_ptr<CFIRMWARE> firmware;
40
-
41
-bool singleStep;
39
+static std::unique_ptr<CFIRMWARE> firmware;
42 40
 
43 41
 namespace DLDI
44 42
 {
... ...
@@ -162,7 +160,7 @@ enum ESI_DISPCNT
162 160
 };
163 161
 
164 162
 uint64_t nds_timer;
165
-uint64_t nds_arm9_timer, nds_arm7_timer;
163
+static uint64_t nds_arm9_timer, nds_arm7_timer;
166 164
 
167 165
 struct TSequenceItem
168 166
 {
... ...
@@ -170,6 +168,8 @@ struct TSequenceItem
170 168
 	uint32_t param;
171 169
 	bool enabled;
172 170
 
171
+	virtual ~TSequenceItem() { }
172
+
173 173
 	virtual bool isTriggered() const
174 174
 	{
175 175
 		return this->enabled && nds_timer >= this->timestamp;
... ...
@@ -330,7 +330,7 @@ struct TSequenceItem_sqrtunit : public TSequenceItem
330 330
 	}
331 331
 };
332 332
 
333
-struct Sequencer
333
+static struct Sequencer
334 334
 {
335 335
 	bool nds_vblankEnded;
336 336
 	bool reschedule;
... ...
@@ -1010,7 +1010,6 @@ static void PrepareBiosARM9()
1010 1010
 
1011 1011
 void NDS_Reset()
1012 1012
 {
1013
-	singleStep = false;
1014 1013
 	bool fw_success = false;
1015 1014
 	auto header = NDS_getROMHeader();
1016 1015
 
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
... ...
@@ -164,8 +164,6 @@ enum ESI_DISPCNT
164 164
 uint64_t nds_timer;
165 165
 uint64_t nds_arm9_timer, nds_arm7_timer;
166 166
 
167
-static const uint64_t kNever = 0xFFFFFFFFFFFFFFFFULL;
168
-
169 167
 struct TSequenceItem
170 168
 {
171 169
 	uint64_t timestamp;
... ...
@@ -910,7 +908,7 @@ static void PrepareBiosARM9()
910 908
 	{
911 909
 		// read arm9 bios from inputfile and flag it if it succeeds
912 910
 		FILE *arm9inf = fopen(CommonSettings.ARM9BIOS, "rb");
913
-		if (fread(MMU.ARM9_BIOS, 1, 4096, arm9inf) == 4096) 
911
+		if (fread(MMU.ARM9_BIOS, 1, 4096, arm9inf) == 4096)
914 912
 			NDS_ARM9.BIOS_loaded = true;
915 913
 		fclose(arm9inf);
916 914
 	}
... ...
@@ -919,7 +917,7 @@ static void PrepareBiosARM9()
919 917
 	if (CommonSettings.SWIFromBIOS && NDS_ARM9.BIOS_loaded)
920 918
 	{
921 919
 		NDS_ARM9.swi_tab = 0;
922
-		
920
+
923 921
 		// if we used routines from bios, apply patches
924 922
 		if (CommonSettings.PatchSWI3)
925 923
 			_MMU_write16<ARMCPU_ARM9>(0xFFFF07CC, 0x4770);
... ...
@@ -927,7 +925,7 @@ static void PrepareBiosARM9()
927 925
 	else
928 926
 		NDS_ARM9.swi_tab = ARM_swi_tab[ARMCPU_ARM9];
929 927
 
930
-	if (!NDS_ARM9.BIOS_loaded) 
928
+	if (!NDS_ARM9.BIOS_loaded)
931 929
 	{
932 930
 		// fake bios content, critical to normal operations, since we dont have a real bios.
933 931
 		// it'd be cool if we could write this in some kind of assembly language, inline or otherwise, without some bulky dependencies
... ...
@@ -1038,7 +1036,7 @@ void NDS_Reset()
1038 1036
 	PrepareBiosARM7();
1039 1037
 	PrepareBiosARM9();
1040 1038
 
1041
-	// according to smea, this is initialized to 3 by the time we get into a user game program. who does this? 
1039
+	// according to smea, this is initialized to 3 by the time we get into a user game program. who does this?
1042 1040
 	// well, the firmware load process is about to write a boot program into SIWRAM for the arm7. so we need it setup by now.
1043 1041
 	// but, this is a bit weird.. I would be expecting the bioses to do that. maybe we have some more detail to emulate.
1044 1042
 	// * is this setting the default, or does the bios do it before loading the firmware programs?
Browse code

Removed a bunch of casts, they seem to be fine without them in most cases.

Naram Qashat authored on 2013/04/18 23:22:54
Showing 1 changed files
... ...
@@ -127,7 +127,7 @@ std::unique_ptr<NDS_header> NDS_getROMHeader()
127 127
 	memcpy(header->logo, MMU.CART_ROM + 192, 156);
128 128
 	header->logoCRC16 = T1ReadWord(MMU.CART_ROM, 348);
129 129
 	header->headerCRC16 = T1ReadWord(MMU.CART_ROM, 350);
130
-	memcpy(header->reserved, MMU.CART_ROM + 352, std::min(160, static_cast<int>(gameInfo.romsize) - 352));
130
+	memcpy(header->reserved, MMU.CART_ROM + 352, std::min<size_t>(160, gameInfo.romsize - 352));
131 131
 
132 132
 	return header;
133 133
 }
... ...
@@ -298,10 +298,10 @@ struct TSequenceItem_divider : public TSequenceItem
298 298
 		T1WriteQuad(MMU.MMU_MEM[ARMCPU_ARM9][0x40], 0x2A0, MMU.divResult);
299 299
 		T1WriteQuad(MMU.MMU_MEM[ARMCPU_ARM9][0x40], 0x2A8, MMU.divMod);
300 300
 #else
301
-		T1WriteLong(MMU.MMU_MEM[ARMCPU_ARM9][0x40], 0x2A0, static_cast<uint32_t>(MMU.divResult));
302
-		T1WriteLong(MMU.MMU_MEM[ARMCPU_ARM9][0x40], 0x2A4, static_cast<uint32_t>(MMU.divResult >> 32));
303
-		T1WriteLong(MMU.MMU_MEM[ARMCPU_ARM9][0x40], 0x2A8, static_cast<uint32_t>(MMU.divMod));
304
-		T1WriteLong(MMU.MMU_MEM[ARMCPU_ARM9][0x40], 0x2AC, static_cast<uint32_t>(MMU.divMod >> 32));
301
+		T1WriteLong(MMU.MMU_MEM[ARMCPU_ARM9][0x40], 0x2A0, MMU.divResult & 0xFFFFFFFF);
302
+		T1WriteLong(MMU.MMU_MEM[ARMCPU_ARM9][0x40], 0x2A4, (MMU.divResult >> 32) & 0xFFFFFFFF);
303
+		T1WriteLong(MMU.MMU_MEM[ARMCPU_ARM9][0x40], 0x2A8, MMU.divMod & 0xFFFFFFFF);
304
+		T1WriteLong(MMU.MMU_MEM[ARMCPU_ARM9][0x40], 0x2AC, (MMU.divMod >> 32) & 0xFFFFFFFF);
305 305
 #endif
306 306
 		MMU.divRunning = false;
307 307
 	}
... ...
@@ -556,10 +556,10 @@ static void execHardware_hstart()
556 556
 	}
557 557
 
558 558
 	// write the new vcount
559
-	T1WriteWord(MMU.ARM9_REG, 6, static_cast<uint16_t>(nds.VCount));
560
-	T1WriteWord(MMU.ARM9_REG, 0x1006, static_cast<uint16_t>(nds.VCount));
561
-	T1WriteWord(MMU.ARM7_REG, 6, static_cast<uint16_t>(nds.VCount));
562
-	T1WriteWord(MMU.ARM7_REG, 0x1006, static_cast<uint16_t>(nds.VCount));
559
+	T1WriteWord(MMU.ARM9_REG, 6, nds.VCount & 0xFFFF);
560
+	T1WriteWord(MMU.ARM9_REG, 0x1006, nds.VCount & 0xFFFF);
561
+	T1WriteWord(MMU.ARM7_REG, 6, nds.VCount & 0xFFFF);
562
+	T1WriteWord(MMU.ARM7_REG, 0x1006, nds.VCount & 0xFFFF);
563 563
 
564 564
 	// turn off hblank status bit
565 565
 	T1WriteWord(MMU.ARM9_REG, 4, T1ReadWord(MMU.ARM9_REG, 4) & 0xFFFD);
... ...
@@ -802,9 +802,9 @@ template<bool FORCE> void NDS_exec(int32_t)
802 802
 
803 803
 			// cast these down to 32bits so that things run faster on 32bit procs
804 804
 			uint64_t nds_timer_base = nds_timer;
805
-			int32_t arm9 = static_cast<int32_t>(nds_arm9_timer - nds_timer);
806
-			int32_t arm7 = static_cast<int32_t>(nds_arm7_timer - nds_timer);
807
-			int32_t s32next = static_cast<int32_t>(next - nds_timer);
805
+			int32_t arm9 = (nds_arm9_timer - nds_timer) & 0xFFFFFFFF;
806
+			int32_t arm7 = (nds_arm7_timer - nds_timer) & 0xFFFFFFFF;
807
+			int32_t s32next = (next - nds_timer) & 0xFFFFFFFF;
808 808
 
809 809
 #ifdef HAVE_JIT
810 810
 			auto arm9arm7 = CommonSettings.use_jit ? armInnerLoop<true, true, true>(nds_timer_base, s32next, arm9, arm7) : armInnerLoop<true, true, false>(nds_timer_base, s32next, arm9, arm7);
Browse code

Updating in_2sf to use a newish version of DeSmuME, 0.9.9 from SVN. Somewhat cleaned up as well, but not everything because it's a pain in the ass.

Naram Qashat authored on 2013/04/18 17:22:55
Showing 1 changed files
... ...
@@ -1,6 +1,6 @@
1 1
 /*
2 2
 	Copyright (C) 2006 yopyop
3
-	Copyright (C) 2008-2012 DeSmuME team
3
+	Copyright (C) 2008-2013 DeSmuME team
4 4
 
5 5
 	This file is free software: you can redistribute it and/or modify
6 6
 	it under the terms of the GNU General Public License as published by
... ...
@@ -21,176 +21,72 @@
21 21
 #include <cstdlib>
22 22
 #include <cmath>
23 23
 #include <zlib.h>
24
-
25
-#include "common.h"
26 24
 #include "NDSSystem.h"
27
-//#include "render3D.h"
28 25
 #include "MMU.h"
29
-//#include "ROMReader.h"
30
-//#include "gfx3d.h"
31
-//#include "utils/decrypt/decrypt.h"
32
-//#include "utils/decrypt/crc.h"
26
+#include "cp15.h"
33 27
 #include "bios.h"
34
-//#include "debug.h"
35
-//#include "cheatSystem.h"
36
-//#include "movie.h"
37
-//#include "Disassembler.h"
38 28
 #include "readwrite.h"
39
-//#include "debug.h"
40 29
 #include "firmware.h"
41 30
 #include "version.h"
42 31
 #include "slot1.h"
43 32
 
44
-#include "path.h"
45
-
46
-//#define LOG_ARM9
47
-//#define LOG_ARM7
48
-//bool dolog = false;
49
-//#define LOG_TO_FILE
50
-//#define LOG_TO_FILE_REGS
51
-
52
-//===============================================================
53
-//FILE *fp_dis7 = NULL;
54
-//FILE *fp_dis9 = NULL;
55
-
56
-PathInfo path;
33
+// ===============================================================
57 34
 
58 35
 TCommonSettings CommonSettings;
59
-//static BaseDriver _stub_driver;
60
-//BaseDriver* driver = &_stub_driver;
61
-//std::string InputDisplayString;
62
-
63
-//static bool LidClosed = false;
64
-//static uint8_t	countLid = 0;
65 36
 
66 37
 GameInfo gameInfo;
67 38
 NDSSystem nds;
68
-CFIRMWARE	*firmware = NULL;
69
-//ADVANsCEne     advsc;
39
+std::unique_ptr<CFIRMWARE> firmware;
70 40
 
71 41
 bool singleStep;
72
-//bool nds_debug_continuing[2];
73
-//int lagframecounter;
74
-//int LagFrameFlag;
75
-//int lastLag;
76
-//int TotalLagFrames;
77
-
78
-//TSCalInfo TSCal;
79 42
 
80 43
 namespace DLDI
81 44
 {
82
-	bool tryPatch(void* data, size_t size);
45
+	bool tryPatch(void *data, size_t size);
83 46
 }
84 47
 
85
-/*void Desmume_InitOnce()
48
+int NDS_Init()
86 49
 {
87
-	static bool initOnce = false;
88
-	if(initOnce) return;
89
-	initOnce = true;*/
90
-
91
-/*#ifdef HAVE_LIBAGG
92
-	extern void Agg_init(); //no need to include just for this
93
-	Agg_init();
94
-#endif*/
95
-//}
96
-
97
-#ifdef GDB_STUB
98
-int NDS_Init( struct armcpu_memory_iface *arm9_mem_if,
99
-struct armcpu_ctrl_iface **arm9_ctrl_iface,
100
-struct armcpu_memory_iface *arm7_mem_if,
101
-struct armcpu_ctrl_iface **arm7_ctrl_iface) {
102
-#else
103
-int NDS_Init() {
104
-#endif
105
-	//nds.idleFrameCounter = 0;
106
-	//memset(nds.runCycleCollector,0,sizeof(nds.runCycleCollector));
107 50
 	MMU_Init();
108 51
 	nds.VCount = 0;
109 52
 
110
-	//got to print this somewhere..
53
+	// got to print this somewhere..
111 54
 	printf("%s\n", EMU_DESMUME_NAME_AND_VERSION());
112 55
 
113
-	/*if (Screen_Init(GFXCORE_DUMMY) != 0)
114
-		return -1;*/
56
+	armcpu_new(&NDS_ARM7, 1);
57
+	armcpu_new(&NDS_ARM9, 0);
115 58
 
116
-	//gfx3d_init();
117
-
118
-#ifdef GDB_STUB
119
-	armcpu_new(&NDS_ARM7,1, arm7_mem_if, arm7_ctrl_iface);
120
-	armcpu_new(&NDS_ARM9,0, arm9_mem_if, arm9_ctrl_iface);
121
-#else
122
-	armcpu_new(&NDS_ARM7,1);
123
-	armcpu_new(&NDS_ARM9,0);
124
-#endif
125
-
126
-	if (SPU_Init(SNDCORE_DUMMY, 740) != 0)
59
+	if (SPU_Init(SNDCORE_DUMMY, 740))
127 60
 		return -1;
128 61
 
129
-	//WIFI_Init() ;
130
-
131
-	// Init calibration info
132
-	//TSCal.adc.x1 = 0x0200;
133
-	//TSCal.adc.y1 = 0x0200;
134
-	//TSCal.scr.x1 = 0x20 + 1; // calibration screen coords are 1-based,
135
-	//TSCal.scr.y1 = 0x20 + 1; // either that or NDS_getADCTouchPosX/Y are wrong.
136
-	//TSCal.adc.x2 = 0x0E00;
137
-	//TSCal.adc.y2 = 0x0800;
138
-	//TSCal.scr.x2 = 0xE0 + 1;
139
-	//TSCal.scr.y2 = 0x80 + 1;
140
-	//TSCal.adc.width = (TSCal.adc.x2 - TSCal.adc.x1);
141
-	//TSCal.adc.height = (TSCal.adc.y2 - TSCal.adc.y1);
142
-	//TSCal.scr.width = (TSCal.scr.x2 - TSCal.scr.x1);
143
-	//TSCal.scr.height = (TSCal.scr.y2 - TSCal.scr.y1);
144
-
145
-	//cheats = new CHEATS();
146
-	//cheatSearch = new CHEATSEARCH();
147
-
148 62
 	return 0;
149 63
 }
150 64
 
151
-void NDS_DeInit() {
152
-	if(MMU.CART_ROM != MMU.UNUSED_RAM)
65
+void NDS_DeInit()
66
+{
67
+	if (MMU.CART_ROM != MMU.UNUSED_RAM)
153 68
 		NDS_FreeROM();
154 69
 
155 70
 	SPU_DeInit();
156
-	//Screen_DeInit();
157 71
 	MMU_DeInit();
158
-	//gpu3D->NDS_3D_Close();
159
-
160
-	//WIFI_DeInit();
161
-	/*if (cheats)
162
-		delete cheats;*/
163
-	/*if (cheatSearch)
164
-		delete cheatSearch;*/
165 72
 
166
-#ifdef LOG_ARM7
167
-	if (fp_dis7 != NULL)
168
-	{
169
-		fclose(fp_dis7);
170
-		fp_dis7 = NULL;
171
-	}
172
-#endif
173
-
174
-#ifdef LOG_ARM9
175
-	if (fp_dis9 != NULL)
176
-	{
177
-		fclose(fp_dis9);
178
-		fp_dis9 = NULL;
179
-	}
73
+#ifdef HAVE_JIT
74
+	arm_jit_close();
180 75
 #endif
181 76
 }
182 77
 
183
-bool NDS_SetROM(uint8_t * rom, uint32_t mask)
78
+bool NDS_SetROM(uint8_t *rom, uint32_t mask)
184 79
 {
185 80
 	MMU_setRom(rom, mask);
186 81
 
187 82
 	return true;
188 83
 }
189 84
 
190
-NDS_header * NDS_getROMHeader()
85
+std::unique_ptr<NDS_header> NDS_getROMHeader()
191 86
 {
192
-	if(MMU.CART_ROM == MMU.UNUSED_RAM) return NULL;
193
-	NDS_header * header = new NDS_header;
87
+	if (MMU.CART_ROM == MMU.UNUSED_RAM)
88
+		return std::unique_ptr<NDS_header>();
89
+	auto header = std::unique_ptr<NDS_header>(new NDS_header);
194 90
 
195 91
 	memcpy(header->gameTile, MMU.CART_ROM, 12);
196 92
 	memcpy(header->gameCode, MMU.CART_ROM + 12, 4);
... ...
@@ -231,800 +127,34 @@ NDS_header * NDS_getROMHeader()
231 127
 	memcpy(header->logo, MMU.CART_ROM + 192, 156);
232 128
 	header->logoCRC16 = T1ReadWord(MMU.CART_ROM, 348);
233 129
 	header->headerCRC16 = T1ReadWord(MMU.CART_ROM, 350);
234
-	memcpy(header->reserved, MMU.CART_ROM + 352, std::min(160, (int)gameInfo.romsize - 352));
130
+	memcpy(header->reserved, MMU.CART_ROM + 352, std::min(160, static_cast<int>(gameInfo.romsize) - 352));
235 131
 
236 132
 	return header;
237 133
 }
238 134
 
239
-
240
-
241
-
242
-/*void debug()
243
-{
244
-	//if(NDS_ARM9.R[15]==0x020520DC) emu_halt();
245
-	//DSLinux
246
-	//if(NDS_ARM9.CPSR.bits.mode == 0) emu_halt();
247
-	//if((NDS_ARM9.R[15]&0xFFFFF000)==0) emu_halt();
248
-	//if((NDS_ARM9.R[15]==0x0201B4F4)&&(NDS_ARM9.R[1]==0x0)) emu_halt();
249
-	//AOE
250
-	//if((NDS_ARM9.R[15]==0x01FFE194)&&(NDS_ARM9.R[0]==0)) emu_halt();
251
-	//if((NDS_ARM9.R[15]==0x01FFE134)&&(NDS_ARM9.R[0]==0)) emu_halt();
252
-
253
-	//BBMAN
254
-	//if(NDS_ARM9.R[15]==0x02098B4C) emu_halt();
255
-	//if(NDS_ARM9.R[15]==0x02004924) emu_halt();
256
-	//if(NDS_ARM9.R[15]==0x02004890) emu_halt();
257
-
258
-	//if(NDS_ARM9.R[15]==0x0202B800) emu_halt();
259
-	//if(NDS_ARM9.R[15]==0x0202B3DC) emu_halt();
260
-	//if((NDS_ARM9.R[1]==0x9AC29AC1)&&(!fait)) {emu_halt();fait = true;}
261
-	//if(NDS_ARM9.R[1]==0x0400004A) {emu_halt();fait = true;}
262
-	if(NDS_ARM9.R[4]==0x2E33373C) emu_halt();
263
-	if(NDS_ARM9.R[15]==0x02036668) //emu_halt();
264
-	{
265
-	nds.logcount++;
266
-	sprintf(logbuf, "%d %08X", nds.logcount, NDS_ARM9.R[13]);
267
-	log::ajouter(logbuf);
268
-	if(nds.logcount==89) execute=false;
269
-	}
270
-	//if(NDS_ARM9.instruction==0) emu_halt();
271
-	//if((NDS_ARM9.R[15]>>28)) emu_halt();
272
-}*/
273
-
274
-//#define DSGBA_LOADER_SIZE 512
275
-/*enum
276
-{
277
-	ROM_NDS = 0,
278
-	ROM_DSGBA
279
-};*/
280
-
281
-#if 0 /* not used */
282
-//http://www.aggregate.org/MAGIC/#Population%20Count%20(Ones%20Count)
283
-static uint32_t ones32(uint32_t x)
284
-{
285
-	/* 32-bit recursive reduction using SWAR...
286
-	but first step is mapping 2-bit values
287
-	into sum of 2 1-bit values in sneaky way
288
-	*/
289
-	x -= ((x >> 1) & 0x55555555);
290
-	x = (((x >> 2) & 0x33333333) + (x & 0x33333333));
291
-	x = (((x >> 4) + x) & 0x0f0f0f0f);
292
-	x += (x >> 8);
293
-	x += (x >> 16);
294
-	return x & 0x0000003f;
295
-}
296
-#endif
297
-
298 135
 RomBanner::RomBanner(bool defaultInit)
299 136
 {
300
-	if(!defaultInit) return;
301
-	version = 1; //Version  (0001h)
302
-	crc16 = 0; //CRC16 across entries 020h..83Fh
303
-	memset(reserved,0,sizeof(reserved));
304
-	memset(bitmap,0,sizeof(bitmap));
305
-	memset(palette,0,sizeof(palette));
306
-	memset(titles,0,sizeof(titles));
307
-	memset(end0xFF,0,sizeof(end0xFF));
308
-}
309
-
310
-/*bool GameInfo::hasRomBanner()
311
-{
312
-	if(header.IconOff + sizeof(RomBanner) > romsize)
313
-		return false;
314
-	else return true;
315
-}*/
316
-
317
-/*const RomBanner& GameInfo::getRomBanner()
318
-{
319
-	//we may not have a valid banner. return a default one
320
-	if(!hasRomBanner())
321
-	{
322
-		static RomBanner defaultBanner(true);
323
-		return defaultBanner;
324
-	}
325
-
326
-	return *(RomBanner*)(romdata+header.IconOff);
327
-}*/
328
-
329
-/*void GameInfo::populate()
330
-{
331
-	const char *regions[] = {	"JPFSEDIRKH",
332
-								"JPN",
333
-								"EUR",
334
-								"FRA",
335
-								"ESP",
336
-								"USA",
337
-								"NOE",
338
-								"ITA",
339
-								"RUS",
340
-								"KOR",
341
-								"HOL",
342
-
343
-	};
344
-
345
-	NDS_header * _header = NDS_getROMHeader();
346
-	header = *_header;
347
-	delete _header;
348
-
349
-	memset(ROMserial, 0, sizeof(ROMserial));
350
-	memset(ROMname, 0, sizeof(ROMname));
351
-
352
-	if (
353
-		//Option 1. - look for this instruction in the game title
354
-		//(did this ever work?)
355
-		//(header->gameTile[0] == 0x2E) &&
356
-		//(header->gameTile[1] == 0x00) &&
357
-		//(header->gameTile[2] == 0x00) &&
358
-		//(header->gameTile[3] == 0xEA)
359
-		//) &&
360
-		//option 2. - look for gamecode #### (default for ndstool)
361
-		//or an invalid gamecode
362
-		(
363
-			((header.gameCode[0] == 0x23) &&
364
-			(header.gameCode[1] == 0x23) &&
365
-			(header.gameCode[2] == 0x23) &&
366
-			(header.gameCode[3] == 0x23)
367
-			) ||
368
-			(header.gameCode[0] == 0x00)
369
-		)
370
-		&&
371
-			header.makerCode == 0x0
372
-		)
373
-	{
374
-		//we can't really make a serial for a homebrew game that hasnt set a game code
375
-		strcpy(ROMserial, "Homebrew");
376
-	}
377
-	else
378
-	{
379
-		strcpy(ROMserial,"NTR-    -");
380
-		memcpy(ROMserial+4, header.gameCode, 4);
381
-
382
-		uint32_t region = (uint32_t)(std::max<int32_t>(strchr(regions[0],header.gameCode[3]) - regions[0] + 1, 0));
383
-		if (region != 0)
384
-			strcat(ROMserial, regions[region]);
385
-		else
386
-			strcat(ROMserial, "Unknown");
387
-	}
388
-
389
-	//rom name is probably set even in homebrew
390
-	memset(ROMname, 0, sizeof(ROMname));
391
-	memcpy(ROMname, header.gameTile, 12);
392
-	trim(ROMname,20);
393
-
394
-		if(header.IconOff < romsize)
395
-		{
396
-			uint8_t num = (T1ReadByte((uint8_t*)romdata, header.IconOff) == 1)?6:7;
397
-			for (int i = 0; i < num; i++)
398
-			{
399
-				wcstombs(ROMfullName[i], (wchar_t *)(romdata+header.IconOff+0x240+(i*0x100)), 0x100);
400
-				trim(ROMfullName[i]);
401
-			}
402
-		}
403
-
404
-	//this may look like a poor heuristic for detecting homebrew, but it is actually pretty good.
405
-	//setting your own game code is stupid, so homebrew should just leave it.
406
-	//however, non-devkitARM-default makefiles may not have set this.
407
-	isHomebrew = !memcmp(header.gameCode,"####",4);
408
-}*/
409
-
410
-/*#ifdef _WINDOWS
411
-
412
-//static std::vector<char> buffer;
413
-//static std::vector<char> v;
414
-
415
-static void loadrom(std::string fname) {
416
-
417
-	FILE* inf = fopen(fname.c_str(),"rb");
418
-	if(!inf) return;
419
-
420
-	fseek(inf,0,SEEK_END);
421
-	int size = ftell(inf);
422
-	fseek(inf,0,SEEK_SET);
423
-
424
-	gameInfo.resize(size);
425
-	fread(gameInfo.romdata,1,size,inf);
426
-	gameInfo.fillGap();
427
-
428
-	fclose(inf);
429
-}
430
-
431
-static int rom_init_path(const char *filename, const char *logicalFilename)
432
-{
433
-	int	type = ROM_NDS;
434
-
435
-	path.init(logicalFilename);
436
-
437
-	if ( path.isdsgba(path.path)) {
438
-		type = ROM_DSGBA;
439
-		loadrom(path.path);
440
-	}
441
-	else if ( !strcasecmp(path.extension().c_str(), "nds")) {
442
-		type = ROM_NDS;
443
-		loadrom(path.path); //n.b. this does nothing if the file can't be found (i.e. if it was an extracted tempfile)...
444
-		//...but since the data was extracted to gameInfo then it is ok
445
-	}
446
-	//ds.gba in archives, it's already been loaded into memory at this point
447
-	else if (path.isdsgba(std::string(logicalFilename))) {
448
-		type = ROM_DSGBA;
449
-	} else {
450
-		//well, try to load it as an nds rom anyway
451
-		type = ROM_NDS;
452
-		loadrom(path.path);
453
-	}
454
-
455
-	if(type == ROM_DSGBA)
456
-	{
457
-		std::vector<char> v(gameInfo.romdata + DSGBA_LOADER_SIZE, gameInfo.romdata + gameInfo.romsize);
458
-		gameInfo.loadData(&v[0],gameInfo.romsize - DSGBA_LOADER_SIZE);
459
-	}
460
-
461
-	//check that size is at least the size of the header
462
-	if (gameInfo.romsize < 352) {
463
-		return -1;
464
-	}
465
-
466
-	return 1;
467
-}
468
-#else
469
-static int rom_init_path(const char *filename, const char *logicalFilename)
470
-{
471
-	int			ret;
472
-	int			type;
473
-	ROMReader_struct	*reader;
474
-	void			*file;
475
-	uint32_t			size;
476
-	char			*noext;
477
-
478
-	noext = strdup(filename);
479
-	reader = ROMReaderInit(&noext);
480
-	free(noext);
481
-
482
-	if (logicalFilename)
483
-		path.init(logicalFilename);
484
-	else
485
-		path.init(filename);
486
-
487
-	if (!strcasecmp(path.extension().c_str(), "zip"))
488
-		type = ROM_NDS;
489
-	else if (!strcasecmp(path.extension().c_str(), "nds"))
490
-		type = ROM_NDS;
491
-	else if (path.isdsgba(path.path))
492
-		type = ROM_DSGBA;
493
-	else
494
-		type = ROM_NDS;
495
-
496
-	file = reader->Init(filename);
497
-	if (!file)
498
-	{
499
-		reader->DeInit(file);
500
-		return -1;
501
-	}
502
-
503
-	size = reader->Size(file);
504
-
505
-	if(type == ROM_DSGBA)
506
-	{
507
-		reader->Seek(file, DSGBA_LOADER_SIZE, SEEK_SET);
508
-		size -= DSGBA_LOADER_SIZE;
509
-	}
510
-
511
-	//check that size is at least the size of the header
512
-	if (size < 352) {
513
-		reader->DeInit(file);
514
-		return -1;
515
-	}
516
-
517
-	// Make sure old ROM is freed first(at least this way we won't be eating
518
-	// up a ton of ram before the old ROM is freed)
519
-	if(MMU.CART_ROM != MMU.UNUSED_RAM)
520
-		NDS_FreeROM();
521
-
522
-	gameInfo.resize(size);
523
-	ret = reader->Read(file, gameInfo.romdata, size);
524
-	gameInfo.fillGap();
525
-	reader->DeInit(file);
526
-
527
-	return ret;
137
+	if (!defaultInit)
138
+		return;
139
+	this->version = 1; //Version  (0001h)
140
+	this->crc16 = 0; //CRC16 across entries 020h..83Fh
141
+	memset(this->reserved, 0, sizeof(this->reserved));
142
+	memset(this->bitmap, 0, sizeof(this->bitmap));
143
+	memset(this->palette, 0, sizeof(this->palette));
144
+	memset(this->titles, 0, sizeof(this->titles));
145
+	memset(this->end0xFF, 0, sizeof(this->end0xFF));
528 146
 }
529
-#endif*/
530
-
531
-/*int NDS_LoadROM(const char *filename, const char *logicalFilename)
532
-{
533
-	int	ret;
534
-	char	buf[MAX_PATH];
535
-
536
-	if (filename == NULL)
537
-		return -1;
538
-
539
-	ret = rom_init_path(filename, logicalFilename);
540
-	if (ret < 1)
541
-		return ret;
542
-
543
-	//decrypt if necessary..
544
-	//but this is untested and suspected to fail on big endian, so lets not support this on big endian
545
-#ifndef WORDS_BIGENDIAN
546
-	bool okRom = DecryptSecureArea((uint8_t*)gameInfo.romdata,gameInfo.romsize);
547
-
548
-	if(!okRom) {
549
-		printf("Specified file is not a valid rom\n");
550
-		return -1;
551
-	}
552
-#endif
553
-
554
-	if (cheatSearch)
555
-		cheatSearch->close();
556
-	FCEUI_StopMovie();
557
-
558
-	MMU_unsetRom();
559
-	NDS_SetROM((uint8_t*)gameInfo.romdata, gameInfo.mask);
560
-
561
-	gameInfo.populate();
562
-	gameInfo.crc = crc32(0,(uint8_t*)gameInfo.romdata,gameInfo.romsize);
563
-	//INFO("\nROM game code: %c%c%c%c\n", gameInfo.header.gameCode[0], gameInfo.header.gameCode[1], gameInfo.header.gameCode[2], gameInfo.header.gameCode[3]);
564
-	//INFO("ROM crc: %08X\n", gameInfo.crc);
565
-	//INFO("ROM serial: %s\n", gameInfo.ROMserial);
566
-	//INFO("ROM internal name: %s\n", gameInfo.ROMname);
567
-
568
-	memset(buf, 0, MAX_PATH);
569
-	strcpy(buf, path.pathToModule);
570
-	strcat(buf, "desmume.ddb");							// DeSmuME database	:)
571
-	advsc.setDatabase(buf);
572
-	buf[0] = gameInfo.header.gameCode[0];
573
-	buf[1] = gameInfo.header.gameCode[1];
574
-	buf[2] = gameInfo.header.gameCode[2];
575
-	buf[3] = gameInfo.header.gameCode[3];
576
-	buf[4] = 0;
577
-	if (advsc.checkDB(buf))
578
-	{
579
-		u8 sv = advsc.getSaveType();
580
-		printf("ADVANsCEne database:\n");
581
-		printf("\t* ROM save type: ");
582
-		if (sv == 0xFF)
583
-			printf("Unknown");
584
-		else
585
-			if (sv == 0xFE)
586
-				printf("None");
587
-			else
588
-			{
589
-				printf("%s", save_names[sv]);
590
-				if (CommonSettings.autodetectBackupMethod == 1)
591
-					backup_setManualBackupType(sv+1);
592
-			}
593
-		printf("\n\t* ROM crc: %08X\n", advsc.getCRC32());
594
-	}
595
-	printf("\n");
596
-
597
-	//for homebrew, try auto-patching DLDI. should be benign if there is no DLDI or if it fails
598
-	if(gameInfo.isHomebrew)
599
-		DLDI::tryPatch((void*)gameInfo.romdata, gameInfo.romsize);
600
-
601
-	memset(buf, 0, MAX_PATH);
602
-	path.getpathnoext(path.BATTERY, buf);
603
-	strcat(buf, ".dsv");							// DeSmuME memory card	:)
604
-	MMU_new.backupDevice.load_rom(buf);
605
-
606
-	memset(buf, 0, MAX_PATH);
607
-	path.getpathnoext(path.CHEATS, buf);
608
-	strcat(buf, ".dct");							// DeSmuME cheat		:)
609
-	cheats->init(buf);
610
-
611
-	NDS_Reset();
612
-
613
-	return ret;
614
-}*/
615 147
 
616 148
 void NDS_FreeROM()
617 149
 {
618
-	//FCEUI_StopMovie();
619
-	if ((uint8_t*)MMU.CART_ROM == (uint8_t*)gameInfo.romdata)
620
-		gameInfo.romdata = NULL;
150
+	if (MMU.CART_ROM == reinterpret_cast<uint8_t *>(&gameInfo.romdata[0]))
151
+		gameInfo.romdata.reset();
621 152
 	if (MMU.CART_ROM != MMU.UNUSED_RAM)
622 153
 		delete [] MMU.CART_ROM;
623 154
 	MMU_unsetRom();
624 155
 }
625 156
 
626
-
627
-
628
-/*int NDS_ImportSave(const char *filename)
629
-{
630
-	if (strlen(filename) < 4)
631
-		return 0;
632
-
633
-	if (memcmp(filename+strlen(filename)-4, ".duc", 4) == 0)
634
-		return MMU_new.backupDevice.load_duc(filename);
635
-	else
636
-		if (MMU_new.backupDevice.load_no_gba(filename))
637
-			return 1;
638
-		else
639
-			return MMU_new.backupDevice.load_raw(filename);
640
-
641
-	//return 0;
642
-}*/
643
-
644
-/*bool NDS_ExportSave(const char *filename)
645
-{
646
-	if (strlen(filename) < 4)
647
-		return false;
648
-
649
-	if (memcmp(filename+strlen(filename)-5, ".sav*", 5) == 0)
650
-	{
651
-		char tmp[MAX_PATH];
652
-		memset(tmp, 0, MAX_PATH);
653
-		strcpy(tmp, filename);
654
-		tmp[strlen(tmp)-1] = 0;
655
-		return MMU_new.backupDevice.save_no_gba(tmp);
656
-	}
657
-
658
-	if (memcmp(filename+strlen(filename)-4, ".sav", 4) == 0)
659
-		return MMU_new.backupDevice.save_raw(filename);
660
-
661
-	return false;
662
-}*/
663
-
664
-/*static int WritePNGChunk(FILE *fp, uint32 size, const char *type, const uint8 *data)
665
-{
666
-	uint32 crc;
667
-
668
-	uint8 tempo[4];
669
-
670
-	tempo[0]=size>>24;
671
-	tempo[1]=size>>16;
672
-	tempo[2]=size>>8;
673
-	tempo[3]=size;
674
-
675
-	if(fwrite(tempo,4,1,fp)!=1)
676
-		return 0;
677
-	if(fwrite(type,4,1,fp)!=1)
678
-		return 0;
679
-
680
-	if(size)
681
-		if(fwrite(data,1,size,fp)!=size)
682
-			return 0;
683
-
684
-	crc = crc32(0,(uint8 *)type,4);
685
-	if(size)
686
-		crc = crc32(crc,data,size);
687
-
688
-	tempo[0]=crc>>24;
689
-	tempo[1]=crc>>16;
690
-	tempo[2]=crc>>8;
691
-	tempo[3]=crc;
692
-
693
-	if(fwrite(tempo,4,1,fp)!=1)
694
-		return 0;
695
-	return 1;
696
-}*/
697
-/*int NDS_WritePNG(const char *fname)
698
-{
699
-	int x, y;
700
-	int width=256;
701
-	int height=192*2;
702
-	uint16_t * bmp = (uint16_t *)GPU_screen;
703
-	FILE *pp=NULL;
704
-	uint8 *compmem = NULL;
705
-	uLongf compmemsize = (uLongf)( (height * (width + 1) * 3 * 1.001 + 1) + 12 );
706
-
707
-	if(!(compmem=(uint8 *)malloc(compmemsize)))
708
-		return 0;
709
-
710
-	if(!(pp=fopen(fname, "wb")))
711
-	{
712
-		goto PNGerr;
713
-	}
714
-	{
715
-		const uint8 header[8]={137,80,78,71,13,10,26,10};
716
-		if(fwrite(header,8,1,pp)!=1)
717
-			goto PNGerr;
718
-	}
719
-
720
-	{
721
-		uint8 chunko[13];
722
-
723
-		chunko[0] = width >> 24;		// Width
724
-		chunko[1] = width >> 16;
725
-		chunko[2] = width >> 8;
726
-		chunko[3] = width;
727
-
728
-		chunko[4] = height >> 24;		// Height
729
-		chunko[5] = height >> 16;
730
-		chunko[6] = height >> 8;
731
-		chunko[7] = height;
732
-
733
-		chunko[8]=8;				// 8 bits per sample(24 bits per pixel)
734
-		chunko[9]=2;				// Color type; RGB triplet
735
-		chunko[10]=0;				// compression: deflate
736
-		chunko[11]=0;				// Basic adapative filter set(though none are used).
737
-		chunko[12]=0;				// No interlace.
738
-
739
-		if(!WritePNGChunk(pp,13,"IHDR",chunko))
740
-			goto PNGerr;
741
-	}
742
-
743
-	{
744
-		uint8 *tmp_buffer;
745
-		uint8 *tmp_inc;
746
-		tmp_inc = tmp_buffer = (uint8 *)malloc((width * 3 + 1) * height);
747
-
748
-		for(y=0;y<height;y++)
749
-		{
750
-			*tmp_inc = 0;
751
-			tmp_inc++;
752
-			for(x=0;x<width;x++)
753
-			{
754
-				int r,g,b;
755
-				uint16_t pixel = bmp[y*256+x];
756
-				r = pixel>>10;
757
-				pixel-=r<<10;
758
-				g = pixel>>5;
759
-				pixel-=g<<5;
760
-				b = pixel;
761
-				r*=255/31;
762
-				g*=255/31;
763
-				b*=255/31;
764
-				tmp_inc[0] = b;
765
-				tmp_inc[1] = g;
766
-				tmp_inc[2] = r;
767
-				tmp_inc += 3;
768
-			}
769
-		}
770
-
771
-		if(compress(compmem, &compmemsize, tmp_buffer, height * (width * 3 + 1))!=Z_OK)
772
-		{
773
-			if(tmp_buffer) free(tmp_buffer);
774
-			goto PNGerr;
775
-		}
776
-		if(tmp_buffer) free(tmp_buffer);
777
-		if(!WritePNGChunk(pp,compmemsize,"IDAT",compmem))
778
-			goto PNGerr;
779
-	}
780
-	if(!WritePNGChunk(pp,0,"IEND",0))
781
-		goto PNGerr;
782
-
783
-	free(compmem);
784
-	fclose(pp);
785
-
786
-	return 1;
787
-
788
-PNGerr:
789
-	if(compmem)
790
-		free(compmem);
791
-	if(pp)
792
-		fclose(pp);
793
-	return 0;
794
-}*/
795
-
796
-/*typedef struct
797
-{
798
-	uint32_t size;
799
-	int32_t width;
800
-	int32_t height;
801
-	uint16_t planes;
802
-	uint16_t bpp;
803
-	uint32_t cmptype;
804
-	uint32_t imgsize;
805
-	int32_t hppm;
806
-	int32_t vppm;
807
-	uint32_t numcol;
808
-	uint32_t numimpcol;
809
-} bmpimgheader_struct;
810
-
811
-#include "PACKED.h"
812
-typedef struct
813
-{
814
-	uint16_t id __PACKED;
815
-	uint32_t size __PACKED;
816
-	uint16_t reserved1 __PACKED;
817
-	uint16_t reserved2 __PACKED;
818
-	uint32_t imgoffset __PACKED;
819
-} bmpfileheader_struct;
820
-#include "PACKED_END.h"*/
821
-
822
-/*int NDS_WriteBMP(const char *filename)
823
-{
824
-	bmpfileheader_struct fileheader;
825
-	bmpimgheader_struct imageheader;
826
-	FILE *file;
827
-	int i,j;
828
-	uint16_t * bmp = (uint16_t *)GPU_screen;
829
-	size_t elems_written = 0;
830
-
831
-	memset(&fileheader, 0, sizeof(fileheader));
832
-	fileheader.size = sizeof(fileheader);
833
-	fileheader.id = 'B' | ('M' << 8);
834
-	fileheader.imgoffset = sizeof(fileheader)+sizeof(imageheader);
835
-
836
-	memset(&imageheader, 0, sizeof(imageheader));
837
-	imageheader.size = sizeof(imageheader);
838
-	imageheader.width = 256;
839
-	imageheader.height = 192*2;
840
-	imageheader.planes = 1;
841
-	imageheader.bpp = 24;
842
-	imageheader.cmptype = 0; // None
843
-	imageheader.imgsize = imageheader.width * imageheader.height * 3;
844
-
845
-	if ((file = fopen(filename,"wb")) == NULL)
846
-		return 0;
847
-
848
-	elems_written += fwrite(&fileheader, 1, sizeof(fileheader), file);
849
-	elems_written += fwrite(&imageheader, 1, sizeof(imageheader), file);
850
-
851
-	for(j=0;j<192*2;j++)
852
-	{
853
-		for(i=0;i<256;i++)
854
-		{
855
-			uint8_t r,g,b;
856
-			uint16_t pixel = bmp[(192*2-j-1)*256+i];
857
-			r = pixel>>10;
858
-			pixel-=r<<10;
859
-			g = pixel>>5;
860
-			pixel-=g<<5;
861
-			b = (uint8_t)pixel;
862
-			r*=255/31;
863
-			g*=255/31;
864
-			b*=255/31;
865
-			elems_written += fwrite(&r, 1, sizeof(uint8_t), file);
866
-			elems_written += fwrite(&g, 1, sizeof(uint8_t), file);
867
-			elems_written += fwrite(&b, 1, sizeof(uint8_t), file);
868
-		}
869
-	}
870
-	fclose(file);
871
-
872
-	return 1;
873
-}*/
874
-
875
-/*int NDS_WriteBMP_32bppBuffer(int width, int height, const void* buf, const char *filename)
876
-{
877
-	bmpfileheader_struct fileheader;
878
-	bmpimgheader_struct imageheader;
879
-	FILE *file;
880
-	size_t elems_written = 0;
881
-	memset(&fileheader, 0, sizeof(fileheader));
882
-	fileheader.size = sizeof(fileheader);
883
-	fileheader.id = 'B' | ('M' << 8);
884
-	fileheader.imgoffset = sizeof(fileheader)+sizeof(imageheader);
885
-
886
-	memset(&imageheader, 0, sizeof(imageheader));
887
-	imageheader.size = sizeof(imageheader);
888
-	imageheader.width = width;
889
-	imageheader.height = height;
890
-	imageheader.planes = 1;
891
-	imageheader.bpp = 32;
892
-	imageheader.cmptype = 0; // None
893
-	imageheader.imgsize = imageheader.width * imageheader.height * 4;
894
-
895
-	if ((file = fopen(filename,"wb")) == NULL)
896
-		return 0;
897
-
898
-	elems_written += fwrite(&fileheader, 1, sizeof(fileheader), file);
899
-	elems_written += fwrite(&imageheader, 1, sizeof(imageheader), file);
900
-
901
-	for(int i=0;i<height;i++)
902
-		for(int x=0;x<width;x++)
903
-		{
904
-			uint8_t* pixel = (uint8_t*)buf + (height-i-1)*width*4;
905
-			pixel += (x*4);
906
-			elems_written += fwrite(pixel+2,1,1,file);
907
-			elems_written += fwrite(pixel+1,1,1,file);
908
-			elems_written += fwrite(pixel+0,1,1,file);
909
-			elems_written += fwrite(pixel+3,1,1,file);
910
-		}
911
-	fclose(file);
912
-
913
-	return 1;
914
-}*/
915
-
916 157
 void NDS_Sleep() { nds.sleeping = true; }
917
-/*void NDS_ToggleCardEject()
918
-{
919
-	if(!nds.cardEjected)
920
-	{
921
-		//staff of kings will test this (it also uses the arm9 0xB8 poll)
922
-		NDS_makeIrq(ARMCPU_ARM7, IRQ_BIT_GC_IREQ_MC);
923
-	}
924
-	nds.cardEjected ^= true;
925
-}*/
926
-
927
-
928
-/*class FrameSkipper
929
-{
930
-public:
931
-	void RequestSkip()
932
-	{
933
-		nextSkip = true;
934
-	}
935
-	void OmitSkip(bool force, bool forceEvenIfCapturing=false)
936
-	{
937
-		nextSkip = false;
938
-		if((force && consecutiveNonCaptures > 30) || forceEvenIfCapturing)
939
-		{
940
-			SkipCur2DFrame = false;
941
-			SkipCur3DFrame = false;
942
-			SkipNext2DFrame = false;
943
-			if(forceEvenIfCapturing)
944
-				consecutiveNonCaptures = 0;
945
-		}
946
-	}
947
-	void Advance()
948
-	{
949
-		bool capturing = false*//*(MainScreen.gpu->dispCapCnt.enabled || (MainScreen.gpu->dispCapCnt.val & 0x80000000))*//*;
950
-
951
-		if(capturing && consecutiveNonCaptures > 30)
952
-		{
953
-			// the worst-looking graphics corruption problems from frameskip
954
-			// are the result of skipping the capture on first frame it turns on.
955
-			// so we do this to handle the capture immediately,
956
-			// despite the risk of 1 frame of 2d/3d mismatch or wrong screen display.
957
-			SkipNext2DFrame = false;
958
-			nextSkip = false;
959
-		}
960
-		else if(*//*lastOffset != MainScreen.offset && *//*lastSkip && !skipped)
961
-		{
962
-			// if we're switching from not skipping to skipping
963
-			// and the screens are also switching around this frame,
964
-			// go for 1 extra frame without skipping.
965
-			// this avoids the scenario where we only draw one of the two screens
966
-			// when a game is switching screens every frame.
967
-			nextSkip = false;
968
-		}
969
-
970
-		if(capturing)
971
-			consecutiveNonCaptures = 0;
972
-		else if(!(consecutiveNonCaptures > 9000)) // arbitrary cap to avoid eventual wrap
973
-			consecutiveNonCaptures++;
974
-		lastLastOffset = lastOffset;
975
-		//lastOffset = MainScreen.offset;
976
-		lastSkip = skipped;
977
-		skipped = nextSkip;
978
-		nextSkip = false;
979
-
980
-		SkipCur2DFrame = SkipNext2DFrame;
981
-		SkipCur3DFrame = skipped;
982
-		SkipNext2DFrame = skipped;
983
-	}
984
-	inline bool ShouldSkip2D()
985
-	{
986
-		return SkipCur2DFrame;
987
-	}
988
-	inline bool ShouldSkip3D()
989
-	{
990
-		return SkipCur3DFrame;
991
-	}
992
-	FrameSkipper()
993
-	{
994
-		nextSkip = false;
995
-		skipped = false;
996
-		lastSkip = false;
997
-		lastOffset = 0;
998
-		SkipCur2DFrame = false;
999
-		SkipCur3DFrame = false;
1000
-		SkipNext2DFrame = false;
1001
-		consecutiveNonCaptures = 0;
1002
-	}
1003
-private:
1004
-	bool nextSkip;
1005
-	bool skipped;
1006
-	bool lastSkip;
1007
-	int lastOffset;
1008
-	int lastLastOffset;
1009
-	int consecutiveNonCaptures;
1010
-	bool SkipCur2DFrame;
1011
-	bool SkipCur3DFrame;
1012
-	bool SkipNext2DFrame;
1013
-};*/
1014
-//static FrameSkipper frameSkipper;
1015
-
1016
-
1017
-/*void NDS_SkipNextFrame() {
1018
-	//if (!driver->AVI_IsRecording()) {
1019
-		//frameSkipper.RequestSkip();
1020
-	//}
1021
-}*/
1022
-/*void NDS_OmitFrameSkip(int force) {
1023
-	//frameSkipper.OmitSkip(force > 0, force > 1);
1024
-}*/
1025
-
1026
-//#define INDEX(i) ((((i)>>16)&0xFF0)|(((i)>>4)&0xF))
1027
-
1028 158
 
1029 159
 enum ESI_DISPCNT
1030 160
 {
... ...
@@ -1042,235 +172,164 @@ struct TSequenceItem
1042 172
 	uint32_t param;
1043 173
 	bool enabled;
1044 174
 
1045
-	/*virtual void save(EMUFILE* os)
1046
-	{
1047
-		write64le(timestamp,os);
1048
-		write32le(param,os);
1049
-		writebool(enabled,os);
1050
-	}*/
1051
-
1052
-	virtual bool load(EMUFILE* is)
175
+	virtual bool isTriggered() const
1053 176
 	{
1054
-		if(read64le(&timestamp,is) != 1) return false;
1055
-		if(read32le(&param,is) != 1) return false;
1056
-		if(readbool(&enabled,is) != 1) return false;
1057
-		return true;
177
+		return this->enabled && nds_timer >= this->timestamp;
1058 178
 	}
1059 179
 
1060
-	inline bool isTriggered()
180
+	virtual uint64_t next() const
1061 181
 	{
1062
-		return enabled && nds_timer >= timestamp;
1063
-	}
1064
-
1065
-	inline uint64_t next()
1066
-	{
1067
-		return timestamp;
182
+		return this->timestamp;
1068 183
 	}
1069 184
 };
1070 185
 
1071
-/*struct TSequenceItem_GXFIFO : public TSequenceItem
1072
-{
1073
-	inline bool isTriggered()
1074
-	{
1075
-		return enabled && nds_timer >= MMU.gfx3dCycles;
1076
-	}
1077
-
1078
-	inline void exec()
1079
-	{
1080
-		IF_DEVELOPER(DEBUG_statistics.sequencerExecutionCounters[4]++);
1081
-		while(isTriggered()) {
1082
-			enabled = false;
1083
-			//gfx3d_execute3D();
1084
-		}
1085
-	}
1086
-
1087
-	inline uint64_t next()
1088
-	{
1089
-		if(enabled) return MMU.gfx3dCycles;
1090
-		else return kNever;
1091
-	}
1092
-};*/
1093
-
1094 186
 template<int procnum, int num> struct TSequenceItem_Timer : public TSequenceItem
1095 187
 {
1096
-	inline bool isTriggered()
188
+	bool isTriggered() const
1097 189
 	{
1098
-		return enabled && nds_timer >= nds.timerCycle[procnum][num];
190
+		return this->enabled && nds_timer >= nds.timerCycle[procnum][num];
1099 191
 	}
1100 192
 
1101
-	inline void schedule()
193
+	void schedule()
1102 194
 	{
1103
-		enabled = MMU.timerON[procnum][num] && MMU.timerMODE[procnum][num] != 0xFFFF;
195
+		this->enabled = MMU.timerON[procnum][num] && MMU.timerMODE[procnum][num] != 0xFFFF;
1104 196
 	}
1105 197
 
1106
-	inline uint64_t next()
198
+	uint64_t next() const
1107 199
 	{
1108 200
 		return nds.timerCycle[procnum][num];
1109 201
 	}
1110 202
 
1111
-	inline void exec()
203
+	void exec()
1112 204
 	{
1113
-		IF_DEVELOPER(DEBUG_statistics.sequencerExecutionCounters[13+procnum*4+num]++);
1114
-		uint8_t* regs = procnum==0?MMU.ARM9_REG:MMU.ARM7_REG;
205
+		uint8_t *regs = !procnum ? MMU.ARM9_REG : MMU.ARM7_REG;
1115 206
 		bool first = true, over;
1116
-		//we'll need to check chained timers..
1117
-		for(int i=num;i<4;i++)
207
+		// we'll need to check chained timers..
208
+		for (int i = num; i < 4; ++i)
1118 209
 		{
1119
-			//maybe too many checks if this is here, but we need it here for now
1120
-			if(!MMU.timerON[procnum][i]) return;
210
+			// maybe too many checks if this is here, but we need it here for now
211
+			if (!MMU.timerON[procnum][i])
212
+				return;
1121 213
 
1122
-			if(MMU.timerMODE[procnum][i] == 0xFFFF)
214
+			if (MMU.timerMODE[procnum][i] == 0xFFFF)
1123 215
 			{
1124
-				++(MMU.timer[procnum][i]);
216
+				++MMU.timer[procnum][i];
1125 217
 				over = !MMU.timer[procnum][i];
1126 218
 			}
1127 219
 			else
1128 220
 			{
1129
-				if(!first) break; //this timer isn't chained. break the chain
221
+				if (!first)
222
+					break; // this timer isn't chained. break the chain
1130 223
 				first = false;
1131 224
 
1132 225
 				over = true;
1133 226
 				int remain = 65536 - MMU.timerReload[procnum][i];
1134
-				int ctr=0;
1135
-				while(nds.timerCycle[procnum][i] <= nds_timer) {
1136
-					nds.timerCycle[procnum][i] += (remain << MMU.timerMODE[procnum][i]);
1137
-					ctr++;
227
+				int ctr = 0;
228
+				while (nds.timerCycle[procnum][i] <= nds_timer)
229
+				{
230
+					nds.timerCycle[procnum][i] += remain << MMU.timerMODE[procnum][i];
231
+					++ctr;
1138 232
 				}
1139 233
 #ifndef NDEBUG
1140
-				if(ctr>1) {
234
+				if (ctr > 1)
1141 235
 					printf("yikes!!!!! please report!\n");
1142
-				}
1143 236
 #endif
1144 237
 			}
1145 238
 
1146
-			if(over)
239
+			if (over)
1147 240
 			{
1148 241
 				MMU.timer[procnum][i] = MMU.timerReload[procnum][i];
1149
-				if(T1ReadWord(regs, 0x102 + i*4) & 0x40)
1150
-				{
242
+				if (T1ReadWord(regs, 0x102 + i * 4) & 0x40)
1151 243
 					NDS_makeIrq(procnum, IRQ_BIT_TIMER_0 + i);
1152
-				}
1153 244
 			}
1154 245
 			else
1155
-				break; //no more chained timers to trigger. we're done here
246
+				break; // no more chained timers to trigger. we're done here
1156 247
 		}
1157 248
 	}
1158 249
 };
1159 250
 
1160 251
 template<int procnum, int chan> struct TSequenceItem_DMA : public TSequenceItem
1161 252
 {
1162
-	DmaController* controller;
253
+	DmaController *controller;
1163 254
 
1164
-	inline bool isTriggered()
255
+	bool isTriggered() const
1165 256
 	{
1166
-		return controller->dmaCheck && nds_timer>= controller->nextEvent;
257
+		return this->controller->dmaCheck && nds_timer>= this->controller->nextEvent;
1167 258
 	}
1168 259
 
1169
-	inline bool isEnabled() {
1170
-		return controller->dmaCheck?true:false;
260
+	bool isEnabled() const
261
+	{
262
+		return this->controller->dmaCheck;
1171 263
 	}
1172 264
 
1173
-	inline uint64_t next()
265
+	uint64_t next() const
1174 266
 	{
1175
-		return controller->nextEvent;
267
+		return this->controller->nextEvent;
1176 268
 	}
1177 269
 
1178
-	inline void exec()
270
+	void exec()
1179 271
 	{
1180
-		IF_DEVELOPER(DEBUG_statistics.sequencerExecutionCounters[5+procnum*4+chan]++);
1181
-
1182
-		//if (nds.freezeBus) return;
1183
-
1184 272
 		//printf("exec from TSequenceItem_DMA: %d %d\n",procnum,chan);
1185
-		controller->exec();
1186
-//		//give gxfifo dmas a chance to re-trigger
1187
-//		if(MMU.DMAStartTime[procnum][chan] == EDMAMode_GXFifo) {
1188
-//			MMU.DMAing[procnum][chan] = false;
1189
-//			if (gxFIFO.size <= 127)
1190
-//			{
1191
-//				execHardware_doDma(procnum,chan,EDMAMode_GXFifo);
1192
-//				if (MMU.DMACompleted[procnum][chan])
1193
-//					goto docomplete;
1194
-//				else return;
1195
-//			}
1196
-//		}
1197
-//
1198
-//docomplete:
1199
-//		if (MMU.DMACompleted[procnum][chan])
1200
-//		{
1201
-//			uint8_t* regs = procnum==0?MMU.ARM9_REG:MMU.ARM7_REG;
1202
-//
1203
-//			//disable the channel
1204
-//			if(MMU.DMAStartTime[procnum][chan] != EDMAMode_GXFifo) {
1205
-//				T1WriteLong(regs, 0xB8 + (0xC*chan), T1ReadLong(regs, 0xB8 + (0xC*chan)) & 0x7FFFFFFF);
1206
-//				MMU.DMACrt[procnum][chan] &= 0x7FFFFFFF; //blehhh i hate this shit being mirrored in memory
1207
-//			}
1208
-//
1209
-//			if((MMU.DMACrt[procnum][chan])&(1<<30)) {
1210
-//				if(procnum==0) NDS_makeARM9Int(8+chan);
1211
-//				else NDS_makeARM7Int(8+chan);
1212
-//			}
1213
-//
1214
-//			MMU.DMAing[procnum][chan] = false;
1215
-//		}
1216
-
273
+		this->controller->exec();
1217 274
 	}
1218 275
 };
1219 276
 
1220 277
 struct TSequenceItem_divider : public TSequenceItem
1221 278
 {
1222
-	inline bool isTriggered()
279
+	bool isTriggered() const
1223 280
 	{
1224 281
 		return MMU.divRunning && nds_timer >= MMU.divCycles;
1225 282
 	}
1226 283
 
1227
-	bool isEnabled() { return MMU.divRunning!=0; }
284
+	bool isEnabled()
285
+	{
286
+		return MMU.divRunning;
287
+	}
1228 288
 
1229
-	inline uint64_t next()
289
+	uint64_t next() const
1230 290
 	{
1231 291
 		return MMU.divCycles;
1232 292
 	}
1233 293
 
1234 294
 	void exec()
1235 295
 	{
1236
-		IF_DEVELOPER(DEBUG_statistics.sequencerExecutionCounters[2]++);
1237 296
 		MMU_new.div.busy = 0;
1238 297
 #ifdef _WIN64
1239 298
 		T1WriteQuad(MMU.MMU_MEM[ARMCPU_ARM9][0x40], 0x2A0, MMU.divResult);
1240 299
 		T1WriteQuad(MMU.MMU_MEM[ARMCPU_ARM9][0x40], 0x2A8, MMU.divMod);
1241 300
 #else
1242
-		T1WriteLong(MMU.MMU_MEM[ARMCPU_ARM9][0x40], 0x2A0, (uint32_t)MMU.divResult);
1243
-		T1WriteLong(MMU.MMU_MEM[ARMCPU_ARM9][0x40], 0x2A4, (uint32_t)(MMU.divResult >> 32));
1244
-		T1WriteLong(MMU.MMU_MEM[ARMCPU_ARM9][0x40], 0x2A8, (uint32_t)MMU.divMod);
1245
-		T1WriteLong(MMU.MMU_MEM[ARMCPU_ARM9][0x40], 0x2AC, (uint32_t)(MMU.divMod >> 32));
301
+		T1WriteLong(MMU.MMU_MEM[ARMCPU_ARM9][0x40], 0x2A0, static_cast<uint32_t>(MMU.divResult));
302
+		T1WriteLong(MMU.MMU_MEM[ARMCPU_ARM9][0x40], 0x2A4, static_cast<uint32_t>(MMU.divResult >> 32));
303
+		T1WriteLong(MMU.MMU_MEM[ARMCPU_ARM9][0x40], 0x2A8, static_cast<uint32_t>(MMU.divMod));
304
+		T1WriteLong(MMU.MMU_MEM[ARMCPU_ARM9][0x40], 0x2AC, static_cast<uint32_t>(MMU.divMod >> 32));
1246 305
 #endif
1247 306
 		MMU.divRunning = false;
1248 307
 	}
1249
-
1250 308
 };
1251 309
 
1252 310
 struct TSequenceItem_sqrtunit : public TSequenceItem
1253 311
 {
1254
-	inline bool isTriggered()
312
+	bool isTriggered() const
1255 313
 	{
1256 314
 		return MMU.sqrtRunning && nds_timer >= MMU.sqrtCycles;
1257 315
 	}
1258 316
 
1259
-	bool isEnabled() { return MMU.sqrtRunning!=0; }
317
+	bool isEnabled()
318
+	{
319
+		return MMU.sqrtRunning;
320
+	}
1260 321
 
1261
-	inline uint64_t next()
322
+	uint64_t next() const
1262 323
 	{
1263 324
 		return MMU.sqrtCycles;
1264 325
 	}
1265 326
 
1266
-	inline void exec()
327
+	void exec()
1267 328
 	{
1268
-		IF_DEVELOPER(DEBUG_statistics.sequencerExecutionCounters[3]++);
1269 329
 		MMU_new.sqrt.busy = 0;
1270 330
 		T1WriteLong(MMU.MMU_MEM[ARMCPU_ARM9][0x40], 0x2B4, MMU.sqrtResult);
1271 331
 		MMU.sqrtRunning = false;
1272 332
 	}
1273
-
1274 333
 };
1275 334
 
1276 335
 struct Sequencer
... ...
@@ -1282,75 +341,26 @@ struct Sequencer
1282 341
 	TSequenceItem_divider divider;
1283 342
 	TSequenceItem_sqrtunit sqrtunit;
1284 343
 	TSequenceItem/*_GXFIFO*/ gxfifo;
1285
-	TSequenceItem_DMA<0,0> dma_0_0; TSequenceItem_DMA<0,1> dma_0_1;
1286
-	TSequenceItem_DMA<0,2> dma_0_2; TSequenceItem_DMA<0,3> dma_0_3;
1287
-	TSequenceItem_DMA<1,0> dma_1_0; TSequenceItem_DMA<1,1> dma_1_1;
1288
-	TSequenceItem_DMA<1,2> dma_1_2; TSequenceItem_DMA<1,3> dma_1_3;
1289
-	TSequenceItem_Timer<0,0> timer_0_0; TSequenceItem_Timer<0,1> timer_0_1;
1290
-	TSequenceItem_Timer<0,2> timer_0_2; TSequenceItem_Timer<0,3> timer_0_3;
1291
-	TSequenceItem_Timer<1,0> timer_1_0; TSequenceItem_Timer<1,1> timer_1_1;
1292
-	TSequenceItem_Timer<1,2> timer_1_2; TSequenceItem_Timer<1,3> timer_1_3;
344
+	TSequenceItem_DMA<0, 0> dma_0_0; TSequenceItem_DMA<0, 1> dma_0_1;
345
+	TSequenceItem_DMA<0, 2> dma_0_2; TSequenceItem_DMA<0, 3> dma_0_3;
346
+	TSequenceItem_DMA<1, 0> dma_1_0; TSequenceItem_DMA<1, 1> dma_1_1;
347
+	TSequenceItem_DMA<1, 2> dma_1_2; TSequenceItem_DMA<1, 3> dma_1_3;
348
+	TSequenceItem_Timer<0, 0> timer_0_0; TSequenceItem_Timer<0, 1> timer_0_1;
349
+	TSequenceItem_Timer<0, 2> timer_0_2; TSequenceItem_Timer<0, 3> timer_0_3;
350
+	TSequenceItem_Timer<1, 0> timer_1_0; TSequenceItem_Timer<1, 1> timer_1_1;
351
+	TSequenceItem_Timer<1, 2> timer_1_2; TSequenceItem_Timer<1, 3> timer_1_3;
1293 352
 
1294 353
 	void init();
1295 354
 
1296 355
 	void execHardware();
1297 356
 	uint64_t findNext();
1298
-
1299
-	/*void save(EMUFILE* os)
1300
-	{
1301
-		write64le(nds_timer,os);
1302
-		write64le(nds_arm9_timer,os);
1303
-		write64le(nds_arm7_timer,os);
1304
-		dispcnt.save(os);
1305
-		divider.save(os);
1306
-		sqrtunit.save(os);
1307
-		gxfifo.save(os);
1308
-		wifi.save(os);
1309
-#define SAVE(I,X,Y) I##_##X##_##Y .save(os);
1310
-		SAVE(timer,0,0); SAVE(timer,0,1); SAVE(timer,0,2); SAVE(timer,0,3);
1311
-		SAVE(timer,1,0); SAVE(timer,1,1); SAVE(timer,1,2); SAVE(timer,1,3);
1312
-		SAVE(dma,0,0); SAVE(dma,0,1); SAVE(dma,0,2); SAVE(dma,0,3);
1313
-		SAVE(dma,1,0); SAVE(dma,1,1); SAVE(dma,1,2); SAVE(dma,1,3);
1314
-#undef SAVE
1315
-	}*/
1316
-
1317
-	bool load(EMUFILE* is, int version)
1318
-	{
1319
-		if(read64le(&nds_timer,is) != 1) return false;
1320
-		if(read64le(&nds_arm9_timer,is) != 1) return false;
1321
-		if(read64le(&nds_arm7_timer,is) != 1) return false;
1322
-		if(!dispcnt.load(is)) return false;
1323
-		if(!divider.load(is)) return false;
1324
-		if(!sqrtunit.load(is)) return false;
1325
-		if(!gxfifo.load(is)) return false;
1326
-		if(version >= 1) if(!wifi.load(is)) return false;
1327
-#define LOAD(I,X,Y) if(!I##_##X##_##Y .load(is)) return false;
1328
-		LOAD(timer,0,0); LOAD(timer,0,1); LOAD(timer,0,2); LOAD(timer,0,3);
1329
-		LOAD(timer,1,0); LOAD(timer,1,1); LOAD(timer,1,2); LOAD(timer,1,3);
1330
-		LOAD(dma,0,0); LOAD(dma,0,1); LOAD(dma,0,2); LOAD(dma,0,3);
1331
-		LOAD(dma,1,0); LOAD(dma,1,1); LOAD(dma,1,2); LOAD(dma,1,3);
1332
-#undef LOAD
1333
-
1334
-		return true;
1335
-	}
1336
-
1337 357
 } sequencer;
1338 358
 
1339
-/*void NDS_RescheduleGXFIFO(uint32_t cost)
1340
-{
1341
-	//if(!sequencer.gxfifo.enabled) {
1342
-		//MMU.gfx3dCycles = nds_timer;
1343
-		//sequencer.gxfifo.enabled = true;
1344
-	//}
1345
-	//MMU.gfx3dCycles += cost;
1346
-	NDS_Reschedule();
1347
-}*/
1348
-
1349 359
 void NDS_RescheduleTimers()
1350 360
 {
1351
-#define check(X,Y) sequencer.timer_##X##_##Y .schedule();
1352
-	check(0,0); check(0,1); check(0,2); check(0,3);
1353
-	check(1,0); check(1,1); check(1,2); check(1,3);
361
+#define check(X, Y) sequencer.timer_##X##_##Y .schedule();
362
+	check(0, 0); check(0, 1); check(0, 2); check(0, 3);
363
+	check(1, 0); check(1, 1); check(1, 2); check(1, 3);
1354 364
 #undef check
1355 365
 
1356 366
 	NDS_Reschedule();
... ...
@@ -1360,21 +370,19 @@ void NDS_RescheduleDMA()
1360 370
 {
1361 371
 	//TBD
1362 372
 	NDS_Reschedule();
1363
-
1364 373
 }
1365 374
 
1366 375
 static void initSchedule()
1367 376
 {
1368 377
 	sequencer.init();
1369 378
 
1370
-	//begin at the very end of the last scanline
1371
-	//so that at t=0 we can increment to scanline=0
379
+	// begin at the very end of the last scanline
380
+	// so that at t=0 we can increment to scanline=0
1372 381
 	nds.VCount = 262;
1373 382
 
1374 383
 	sequencer.nds_vblankEnded = false;
1375 384
 }
1376 385
 
1377
-
1378 386
 // 2196372 ~= (ARM7_CLOCK << 16) / 1000000
1379 387
 // This value makes more sense to me, because:
1380 388
 // ARM7_CLOCK   = 33.51 mhz
... ...
@@ -1388,93 +396,51 @@ void Sequencer::init()
1388 396
 	NDS_RescheduleTimers();
1389 397
 	NDS_RescheduleDMA();
1390 398
 
1391
-	reschedule = false;
399
+	this->reschedule = false;
1392 400
 	nds_timer = 0;
1393 401
 	nds_arm9_timer = 0;
1394 402
 	nds_arm7_timer = 0;
1395 403
 
1396
-	dispcnt.enabled = true;
1397
-	dispcnt.param = ESI_DISPCNT_HStart;
1398
-	dispcnt.timestamp = 0;
1399
-
1400
-	//gxfifo.enabled = false;
1401
-
1402
-	dma_0_0.controller = &MMU_new.dma[0][0];
1403
-	dma_0_1.controller = &MMU_new.dma[0][1];
1404
-	dma_0_2.controller = &MMU_new.dma[0][2];
1405
-	dma_0_3.controller = &MMU_new.dma[0][3];
1406
-	dma_1_0.controller = &MMU_new.dma[1][0];
1407
-	dma_1_1.controller = &MMU_new.dma[1][1];
1408
-	dma_1_2.controller = &MMU_new.dma[1][2];
1409
-	dma_1_3.controller = &MMU_new.dma[1][3];
1410
-
1411
-
1412
-	/*#ifdef EXPERIMENTAL_WIFI_COMM
1413
-	wifi.enabled = true;
1414
-	wifi.timestamp = kWifiCycles;
1415
-	#else
1416
-	wifi.enabled = false;
1417
-	#endif*/
404
+	this->dispcnt.enabled = true;
405
+	this->dispcnt.param = ESI_DISPCNT_HStart;
406
+	this->dispcnt.timestamp = 0;
407
+
408
+	this->dma_0_0.controller = &MMU_new.dma[0][0];
409
+	this->dma_0_1.controller = &MMU_new.dma[0][1];
410
+	this->dma_0_2.controller = &MMU_new.dma[0][2];
411
+	this->dma_0_3.controller = &MMU_new.dma[0][3];
412
+	this->dma_1_0.controller = &MMU_new.dma[1][0];
413
+	this->dma_1_1.controller = &MMU_new.dma[1][1];
414
+	this->dma_1_2.controller = &MMU_new.dma[1][2];
415
+	this->dma_1_3.controller = &MMU_new.dma[1][3];
1418 416
 }
1419 417
 
1420
-//this isnt helping much right now. work on it later
1421
-//#include "utils/task.h"
1422
-//Task taskSubGpu(true);
1423
-//void* renderSubScreen(void*)
1424
-//{
1425
-//	GPU_RenderLine(&SubScreen, nds.VCount, SkipCur2DFrame);
1426
-//	return NULL;
1427
-//}
1428
-
1429 418
 static void execHardware_hblank()
1430 419
 {
1431
-	//this logic keeps moving around.
1432
-	//now, we try and give the game as much time as possible to finish doing its work for the scanline,
1433
-	//by drawing scanline N at the end of drawing time (but before subsequent interrupt or hdma-driven events happen)
1434
-	//don't try to do this at the end of the scanline, because some games (sonic classics) may use hblank IRQ to set
1435
-	//scroll regs for the next scanline
1436
-	if(nds.VCount<192)
1437
-	{
1438
-		//taskSubGpu.execute(renderSubScreen,NULL);
1439
-		//GPU_RenderLine(&MainScreen, nds.VCount, frameSkipper.ShouldSkip2D());
1440
-		//GPU_RenderLine(&SubScreen, nds.VCount, frameSkipper.ShouldSkip2D());
1441
-		//taskSubGpu.finish();
1442
-
1443
-		//trigger hblank dmas
1444
-		//but notice, we do that just after we finished drawing the line
1445
-		//(values copied by this hdma should not be used until the next scanline)
420
+	// this logic keeps moving around.
421
+	// now, we try and give the game as much time as possible to finish doing its work for the scanline,
422
+	// by drawing scanline N at the end of drawing time (but before subsequent interrupt or hdma-driven events happen)
423
+	// don't try to do this at the end of the scanline, because some games (sonic classics) may use hblank IRQ to set
424
+	// scroll regs for the next scanline
425
+	if (nds.VCount < 192)
426
+		// trigger hblank dmas
427
+		// but notice, we do that just after we finished drawing the line
428
+		// (values copied by this hdma should not be used until the next scanline)
1446 429
 		triggerDma(EDMAMode_HBlank);
1447
-	}
1448 430
 
1449
-	if(nds.VCount==262)
1450
-	{
1451
-		//we need to trigger one last hblank dma since
1452
-		//a. we're sort of lagged behind by one scanline
1453
-		//b. i think that 193 hblanks actually fire (one for the hblank in scanline 262)
1454
-		//this is demonstrated by NSMB splot-parallaxing clouds
1455
-		//for some reason the game will setup two hdma scroll register buffers
1456
-		//to be run consecutively, and unless we do this, the second buffer will be offset by one scanline
1457
-		//causing a glitch in the 0th scanline
1458
-		//triggerDma(EDMAMode_HBlank);
1459
-
1460
-		//BUT! this was removed in order to make glitches in megaman zero collection (mmz 4 1st level) work.
1461
-		//and, it seems that it is no longer necessary in nsmb. perhaps something else fixed it
1462
-	}
1463
-
1464
-
1465
-	//turn on hblank status bit
431
+	// turn on hblank status bit
1466 432
 	T1WriteWord(MMU.ARM9_REG, 4, T1ReadWord(MMU.ARM9_REG, 4) | 2);
1467 433
 	T1WriteWord(MMU.ARM7_REG, 4, T1ReadWord(MMU.ARM7_REG, 4) | 2);
1468 434
 
1469
-	//fire hblank interrupts if necessary
1470
-	if(T1ReadWord(MMU.ARM9_REG, 4) & 0x10) NDS_makeIrq(ARMCPU_ARM9,IRQ_BIT_LCD_HBLANK);
1471
-	if(T1ReadWord(MMU.ARM7_REG, 4) & 0x10) NDS_makeIrq(ARMCPU_ARM7,IRQ_BIT_LCD_HBLANK);
435
+	// fire hblank interrupts if necessary
436
+	if (T1ReadWord(MMU.ARM9_REG, 4) & 0x10)
437
+		NDS_makeIrq(ARMCPU_ARM9, IRQ_BIT_LCD_HBLANK);
438
+	if (T1ReadWord(MMU.ARM7_REG, 4) & 0x10)
439
+		NDS_makeIrq(ARMCPU_ARM7, IRQ_BIT_LCD_HBLANK);
1472 440
 
1473
-	//emulation housekeeping. for some reason we always do this at hblank,
1474
-	//even though it sounds more reasonable to do it at hstart
441
+	// emulation housekeeping. for some reason we always do this at hblank,
442
+	// even though it sounds more reasonable to do it at hstart
1475 443
 	SPU_Emulate_core();
1476
-	//driver->AVI_SoundUpdate(SPU_core->outbuf,spu_core_samples);
1477
-	//WAV_WavSoundUpdate(SPU_core->outbuf,spu_core_samples);
1478 444
 }
1479 445
 
1480 446
 static void execHardware_hstart_vblankEnd()
... ...
@@ -1482,201 +448,156 @@ static void execHardware_hstart_vblankEnd()
1482 448
 	sequencer.nds_vblankEnded = true;
1483 449
 	sequencer.reschedule = true;
1484 450
 
1485
-	//turn off vblank status bit
451
+	// turn off vblank status bit
1486 452
 	T1WriteWord(MMU.ARM9_REG, 4, T1ReadWord(MMU.ARM9_REG, 4) & ~1);
1487 453
 	T1WriteWord(MMU.ARM7_REG, 4, T1ReadWord(MMU.ARM7_REG, 4) & ~1);
1488
-
1489
-	//some emulation housekeeping
1490
-	//frameSkipper.Advance();
1491 454
 }
1492 455
 
1493 456
 static void execHardware_hstart_vblankStart()
1494 457
 {
1495 458
 	//printf("--------VBLANK!!!--------\n");
1496 459
 
1497
-	//fire vblank interrupts if necessary
1498
-	for(int i=0;i<2;i++)
1499
-		if(MMU.reg_IF_pending[i] & (1<<IRQ_BIT_LCD_VBLANK))
460
+	// fire vblank interrupts if necessary
461
+	for (int i = 0; i < 2; ++i)
462
+		if (MMU.reg_IF_pending[i] & (1 << IRQ_BIT_LCD_VBLANK))
1500 463
 		{
1501
-			MMU.reg_IF_pending[i] &= ~(1<<IRQ_BIT_LCD_VBLANK);
1502
-			NDS_makeIrq(i,IRQ_BIT_LCD_VBLANK);
464
+			MMU.reg_IF_pending[i] &= ~(1 << IRQ_BIT_LCD_VBLANK);
465
+			NDS_makeIrq(i, IRQ_BIT_LCD_VBLANK);
1503 466
 		}
1504 467
 
1505
-	//trigger vblank dmas
468
+	// trigger vblank dmas
1506 469
 	triggerDma(EDMAMode_VBlank);
1507
-
1508
-	//tracking for arm9 load average
1509
-	//nds.runCycleCollector[0][nds.idleFrameCounter] = 1120380-nds.idleCycles[0];
1510
-	//nds.runCycleCollector[1][nds.idleFrameCounter] = 1120380-nds.idleCycles[1];
1511
-	//nds.idleFrameCounter++;
1512
-	//nds.idleFrameCounter &= 15;
1513
-	//nds.idleCycles[0] = 0;
1514
-	//nds.idleCycles[1] = 0;
1515 470
 }
1516 471
 
1517 472
 static uint16_t execHardware_gen_vmatch_goal()
1518 473
 {
1519 474
 	uint16_t vmatch = T1ReadWord(MMU.ARM9_REG, 4);
1520
-	vmatch = ((vmatch>>8)|((vmatch<<1)&(1<<8)));
475
+	vmatch = (vmatch >> 8) | ((vmatch << 1) & (1 << 8));
1521 476
 	return vmatch;
1522 477
 }
1523 478
 
1524 479
 static void execHardware_hstart_vcount_irq()
1525 480
 {
1526
-	//trigger pending VMATCH irqs
1527
-	if(MMU.reg_IF_pending[ARMCPU_ARM9] & (1<<IRQ_BIT_LCD_VMATCH))
481
+	// trigger pending VMATCH irqs
482
+	if (MMU.reg_IF_pending[ARMCPU_ARM9] & (1 << IRQ_BIT_LCD_VMATCH))
1528 483
 	{
1529
-		MMU.reg_IF_pending[ARMCPU_ARM9] &= ~(1<<IRQ_BIT_LCD_VMATCH);
1530
-		NDS_makeIrq(ARMCPU_ARM9,IRQ_BIT_LCD_VMATCH);
484
+		MMU.reg_IF_pending[ARMCPU_ARM9] &= ~(1 << IRQ_BIT_LCD_VMATCH);
485
+		NDS_makeIrq(ARMCPU_ARM9, IRQ_BIT_LCD_VMATCH);
1531 486
 	}
1532
-	if(MMU.reg_IF_pending[ARMCPU_ARM7] & (1<<IRQ_BIT_LCD_VMATCH))
487
+	if(MMU.reg_IF_pending[ARMCPU_ARM7] & (1 << IRQ_BIT_LCD_VMATCH))
1533 488
 	{
1534
-		MMU.reg_IF_pending[ARMCPU_ARM7] &= ~(1<<IRQ_BIT_LCD_VMATCH);
1535
-		NDS_makeIrq(ARMCPU_ARM7,IRQ_BIT_LCD_VMATCH);
489
+		MMU.reg_IF_pending[ARMCPU_ARM7] &= ~(1 << IRQ_BIT_LCD_VMATCH);
490
+		NDS_makeIrq(ARMCPU_ARM7, IRQ_BIT_LCD_VMATCH);
1536 491
 	}
1537 492
 }
1538 493
 
1539 494
 static void execHardware_hstart_vcount()
1540 495
 {
1541 496
 	uint16_t vmatch = execHardware_gen_vmatch_goal();
1542
-	if(nds.VCount==vmatch)
497
+	if (nds.VCount == vmatch)
1543 498
 	{
1544
-		//arm9 vmatch
499
+		// arm9 vmatch
1545 500
 		T1WriteWord(MMU.ARM9_REG, 4, T1ReadWord(MMU.ARM9_REG, 4) | 4);
1546
-		if(T1ReadWord(MMU.ARM9_REG, 4) & 32) {
1547
-			MMU.reg_IF_pending[ARMCPU_ARM9] |= (1<<IRQ_BIT_LCD_VMATCH);
1548
-		}
501
+		if (T1ReadWord(MMU.ARM9_REG, 4) & 32)
502
+			MMU.reg_IF_pending[ARMCPU_ARM9] |= 1 << IRQ_BIT_LCD_VMATCH;
1549 503
 	}
1550 504
 	else
1551 505
 		T1WriteWord(MMU.ARM9_REG, 4, T1ReadWord(MMU.ARM9_REG, 4) & 0xFFFB);
1552 506
 
1553 507
 	vmatch = T1ReadWord(MMU.ARM7_REG, 4);
1554
-	vmatch = ((vmatch>>8)|((vmatch<<1)&(1<<8)));
1555
-	if(nds.VCount==vmatch)
508
+	vmatch = (vmatch >> 8) | ((vmatch << 1) & (1 << 8));
509
+	if (nds.VCount == vmatch)
1556 510
 	{
1557
-		//arm7 vmatch
511
+		// arm7 vmatch
1558 512
 		T1WriteWord(MMU.ARM7_REG, 4, T1ReadWord(MMU.ARM7_REG, 4) | 4);
1559
-		if(T1ReadWord(MMU.ARM7_REG, 4) & 32)
1560
-			MMU.reg_IF_pending[ARMCPU_ARM7] |= (1<<IRQ_BIT_LCD_VMATCH);
513
+		if (T1ReadWord(MMU.ARM7_REG, 4) & 32)
514
+			MMU.reg_IF_pending[ARMCPU_ARM7] |= 1 << IRQ_BIT_LCD_VMATCH;
1561 515
 	}
1562 516
 	else
1563 517
 		T1WriteWord(MMU.ARM7_REG, 4, T1ReadWord(MMU.ARM7_REG, 4) & 0xFFFB);
1564 518
 }
1565 519
 
1566
-static void execHardware_hdraw()
1567
-{
1568
-	//due to hacks in our selection of rendering time, we do not actually render here as intended.
1569
-	//consider changing this if there is some problem with raster fx timing but check the documentation near the gpu rendering calls
1570
-	//to make sure you check for regressions (nsmb, sonic classics, et al)
1571
-}
1572
-
1573 520
 static void execHardware_hstart_irq()
1574 521
 {
1575
-	//this function very soon after the registers get updated to trigger IRQs
1576
-	//this is necessary to fix "egokoro kyoushitsu" which idles waiting for vcount=192, which never happens due to a long vblank irq
1577
-	//100% accurate emulation would require the read of VCOUNT to be in the pipeline already with the irq coming in behind it, thus
1578
-	//allowing the vcount to register as 192 occasionally (maybe about 1 out of 28 frames)
1579
-	//the actual length of the delay is in execHardware() where the events are scheduled
522
+	// this function very soon after the registers get updated to trigger IRQs
523
+	// this is necessary to fix "egokoro kyoushitsu" which idles waiting for vcount=192, which never happens due to a long vblank irq
524
+	// 100% accurate emulation would require the read of VCOUNT to be in the pipeline already with the irq coming in behind it, thus
525
+	// allowing the vcount to register as 192 occasionally (maybe about 1 out of 28 frames)
526
+	// the actual length of the delay is in execHardware() where the events are scheduled
1580 527
 	sequencer.reschedule = true;
1581
-	if(nds.VCount==192)
1582
-	{
1583
-		//when the vcount hits 192, vblank begins
528
+	if (nds.VCount == 192)
529
+		// when the vcount hits 192, vblank begins
1584 530
 		execHardware_hstart_vblankStart();
1585
-	}
1586 531
 
1587 532
 	execHardware_hstart_vcount_irq();
1588 533
 }
1589 534
 
1590 535
 static void execHardware_hstart()
1591 536
 {
1592
-	nds.VCount++;
1593
-
1594
-	//end of 3d vblank
1595
-	//this should be 214, but we are going to be generous for games with tight timing
1596
-	//they shouldnt be changing any textures at 262 but they might accidentally still be at 214
1597
-	//so..
1598
-	/*if((CommonSettings.rigorous_timing && nds.VCount==214) || (!CommonSettings.rigorous_timing && nds.VCount==262))
1599
-	{
1600
-		gfx3d_VBlankEndSignal(frameSkipper.ShouldSkip3D());
1601
-	}*/
537
+	++nds.VCount;
1602 538
 
1603
-	if(nds.VCount==263)
1604
-	{
1605
-		//when the vcount hits 263 it rolls over to 0
1606
-		nds.VCount=0;
1607
-	}
1608
-	if(nds.VCount==262)
1609
-	{
1610
-		//when the vcount hits 262, vblank ends (oam pre-renders by one scanline)
539
+	if (nds.VCount == 263)
540
+		// when the vcount hits 263 it rolls over to 0
541
+		nds.VCount = 0;
542
+	if (nds.VCount == 262)
543
+		// when the vcount hits 262, vblank ends (oam pre-renders by one scanline)
1611 544
 		execHardware_hstart_vblankEnd();
1612
-	}
1613
-	/*else if(nds.VCount==191)
1614
-	{
1615
-		//when the vcount hits 191, the 3d vblank occurs (maybe because OAM doesnt need to run anymore, so we can power it down, and give the 3d as much time as possible?)
1616
-		gfx3d_VBlankSignal();
1617
-	}*/
1618
-	else if(nds.VCount==192)
545
+	else if (nds.VCount == 192)
1619 546
 	{
1620
-		//turn on vblank status bit
547
+		// turn on vblank status bit
1621 548
 		T1WriteWord(MMU.ARM9_REG, 4, T1ReadWord(MMU.ARM9_REG, 4) | 1);
1622 549
 		T1WriteWord(MMU.ARM7_REG, 4, T1ReadWord(MMU.ARM7_REG, 4) | 1);
1623 550
 
1624
-		//check whether we'll need to fire vblank irqs
1625
-		if(T1ReadWord(MMU.ARM9_REG, 4) & 0x8) MMU.reg_IF_pending[ARMCPU_ARM9] |= (1<<IRQ_BIT_LCD_VBLANK);
1626
-		if(T1ReadWord(MMU.ARM7_REG, 4) & 0x8) MMU.reg_IF_pending[ARMCPU_ARM7] |= (1<<IRQ_BIT_LCD_VBLANK);
551
+		// check whether we'll need to fire vblank irqs
552
+		if (T1ReadWord(MMU.ARM9_REG, 4) & 0x8)
553
+			MMU.reg_IF_pending[ARMCPU_ARM9] |= 1 << IRQ_BIT_LCD_VBLANK;
554
+		if (T1ReadWord(MMU.ARM7_REG, 4) & 0x8)
555
+			MMU.reg_IF_pending[ARMCPU_ARM7] |= 1 << IRQ_BIT_LCD_VBLANK;
1627 556
 	}
1628 557
 
1629
-	//write the new vcount
558
+	// write the new vcount
1630 559
 	T1WriteWord(MMU.ARM9_REG, 6, static_cast<uint16_t>(nds.VCount));
1631 560
 	T1WriteWord(MMU.ARM9_REG, 0x1006, static_cast<uint16_t>(nds.VCount));
1632 561
 	T1WriteWord(MMU.ARM7_REG, 6, static_cast<uint16_t>(nds.VCount));
1633 562
 	T1WriteWord(MMU.ARM7_REG, 0x1006, static_cast<uint16_t>(nds.VCount));
1634 563
 
1635
-	//turn off hblank status bit
564
+	// turn off hblank status bit
1636 565
 	T1WriteWord(MMU.ARM9_REG, 4, T1ReadWord(MMU.ARM9_REG, 4) & 0xFFFD);
1637 566
 	T1WriteWord(MMU.ARM7_REG, 4, T1ReadWord(MMU.ARM7_REG, 4) & 0xFFFD);
1638 567
 
1639
-	//handle vcount status
568
+	// handle vcount status
1640 569
 	execHardware_hstart_vcount();
1641 570
 
1642
-	//trigger hstart dmas
571
+	// trigger hstart dmas
1643 572
 	triggerDma(EDMAMode_HStart);
1644 573
 
1645
-	if(nds.VCount<192)
1646
-	{
1647
-		//this is hacky.
1648
-		//there is a corresponding hack in doDMA.
1649
-		//it should be driven by a fifo (and generate just in time as the scanline is displayed)
1650
-		//but that isnt even possible until we have some sort of sub-scanline timing.
1651
-		//it may not be necessary.
574
+	if (nds.VCount < 192)
575
+		// this is hacky.
576
+		// there is a corresponding hack in doDMA.
577
+		// it should be driven by a fifo (and generate just in time as the scanline is displayed)
578
+		// but that isnt even possible until we have some sort of sub-scanline timing.
579
+		// it may not be necessary.
1652 580
 		triggerDma(EDMAMode_MemDisplay);
1653
-	}
1654 581
 }
1655 582
 
1656 583
 void NDS_Reschedule()
1657 584
 {
1658
-	IF_DEVELOPER(if(!sequencer.reschedule) DEBUG_statistics.sequencerExecutionCounters[0]++;);
1659 585
 	sequencer.reschedule = true;
1660 586
 }
1661 587
 
1662
-/*inline uint32_t _fast_min32(uint32_t a, uint32_t b, uint32_t c, uint32_t d)
588
+static inline uint64_t _fast_min(uint64_t a, uint64_t b)
1663 589
 {
1664
-	return (( ((int32_t)(a-b)) >> (32-1)) & (c^d)) ^ d;
1665
-}*/
1666
-
1667
-inline uint64_t _fast_min(uint64_t a, uint64_t b)
1668
-{
1669
-	//you might find that this is faster on a 64bit system; someone should try it
1670
-	//http://aggregate.org/MAGIC/#Integer%20Selection
590
+	// you might find that this is faster on a 64bit system; someone should try it
591
+	// http://aggregate.org/MAGIC/#Integer%20Selection
1671 592
 	//uint64_t ret = (((((s64)(a-b)) >> (64-1)) & (a^b)) ^ b);
1672 593
 	//assert(ret==min(a,b));
1673 594
 	//return ret;
1674 595
 
1675
-	//but this ends up being the fastest on 32bits
596
+	// but this ends up being the fastest on 32bits
1676 597
 	return a<b?a:b;
1677 598
 
1678
-	//just for the record, I tried to do the 64bit math on a 32bit proc
1679
-	//using sse2 and it was really slow
599
+	// just for the record, I tried to do the 64bit math on a 32bit proc
600
+	// using sse2 and it was really slow
1680 601
 	//__m128i __a; __a.m128i_u64[0] = a;
1681 602
 	//__m128i __b; __b.m128i_u64[0] = b;
1682 603
 	//__m128i xorval = _mm_xor_si128(__a,__b);
... ...
@@ -1687,28 +608,27 @@ inline uint64_t _fast_min(uint64_t a, uint64_t b)
1687 608
 	//return temp.m128i_u64[0];
1688 609
 }
1689 610
 
1690
-
1691
-
1692 611
 uint64_t Sequencer::findNext()
1693 612
 {
1694
-	//this one is always enabled so dont bother to check it
1695
-	uint64_t next = dispcnt.next();
1696
-
1697
-	if(divider.isEnabled()) next = _fast_min(next,divider.next());
1698
-	if(sqrtunit.isEnabled()) next = _fast_min(next,sqrtunit.next());
1699
-	//if(gxfifo.enabled) next = _fast_min(next,gxfifo.next());
613
+	// this one is always enabled so dont bother to check it
614
+	uint64_t next = this->dispcnt.next();
1700 615
 
1701
-#ifdef EXPERIMENTAL_WIFI_COMM
1702
-	next = _fast_min(next,wifi.next());
1703
-#endif
616
+	if (this->divider.isEnabled())
617
+		next = _fast_min(next, this->divider.next());
618
+	if (this->sqrtunit.isEnabled())
619
+		next = _fast_min(next, this->sqrtunit.next());
1704 620
 
1705
-#define test(X,Y) if(dma_##X##_##Y .isEnabled()) next = _fast_min(next,dma_##X##_##Y .next());
1706
-	test(0,0); test(0,1); test(0,2); test(0,3);
1707
-	test(1,0); test(1,1); test(1,2); test(1,3);
621
+#define test(X, Y) \
622
+	if (this->dma_##X##_##Y .isEnabled()) \
623
+		next = _fast_min(next, this->dma_##X##_##Y .next());
624
+	test(0, 0); test(0, 1); test(0, 2); test(0, 3);
625
+	test(1, 0); test(1, 1); test(1, 2); test(1, 3);
1708 626
 #undef test
1709
-#define test(X,Y) if(timer_##X##_##Y .enabled) next = _fast_min(next,timer_##X##_##Y .next());
1710
-	test(0,0); test(0,1); test(0,2); test(0,3);
1711
-	test(1,0); test(1,1); test(1,2); test(1,3);
627
+#define test(X, Y) \
628
+	if (this->timer_##X##_##Y .enabled) \
629
+		next = _fast_min(next, this->timer_##X##_##Y .next());
630
+	test(0, 0); test(0, 1); test(0, 2); test(0, 3);
631
+	test(1, 0); test(1, 1); test(1, 2); test(1, 3);
1712 632
 #undef test
1713 633
 
1714 634
 	return next;
... ...
@@ -1716,197 +636,70 @@ uint64_t Sequencer::findNext()
1716 636
 
1717 637
 void Sequencer::execHardware()
1718 638
 {
1719
-	if(dispcnt.isTriggered())
639
+	if (this->dispcnt.isTriggered())
1720 640
 	{
1721
-
1722
-		IF_DEVELOPER(DEBUG_statistics.sequencerExecutionCounters[1]++);
1723
-
1724
-		switch(dispcnt.param)
641
+		switch (this->dispcnt.param)
1725 642
 		{
1726
-		case ESI_DISPCNT_HStart:
1727
-			execHardware_hstart();
1728
-			//(used to be 3168)
1729
-			//hstart is actually 8 dots before the visible drawing begins
1730
-			//we're going to run 1 here and then run 7 in the next case
1731
-			dispcnt.timestamp += 1*6*2;
1732
-			dispcnt.param = ESI_DISPCNT_HStartIRQ;
1733
-			break;
1734
-		case ESI_DISPCNT_HStartIRQ:
1735
-			execHardware_hstart_irq();
1736
-			dispcnt.timestamp += 7*6*2;
1737
-			dispcnt.param = ESI_DISPCNT_HDraw;
1738
-			break;
1739
-
1740
-		case ESI_DISPCNT_HDraw:
1741
-			execHardware_hdraw();
1742
-			//duration of non-blanking period is ~1606 clocks (gbatek agrees) [but says its different on arm7]
1743
-			//im gonna call this 267 dots = 267*6=1602
1744
-			//so, this event lasts 267 dots minus the 8 dot preroll
1745
-			dispcnt.timestamp += (267-8)*6*2;
1746
-			dispcnt.param = ESI_DISPCNT_HBlank;
1747
-			break;
1748
-
1749
-		case ESI_DISPCNT_HBlank:
1750
-			execHardware_hblank();
1751
-			//(once this was 1092 or 1092/12=91 dots.)
1752
-			//there are surely 355 dots per scanline, less 267 for non-blanking period. the rest is hblank and then after that is hstart
1753
-			dispcnt.timestamp += (355-267)*6*2;
1754
-			dispcnt.param = ESI_DISPCNT_HStart;
1755
-			break;
643
+			case ESI_DISPCNT_HStart:
644
+				execHardware_hstart();
645
+				// (used to be 3168)
646
+				// hstart is actually 8 dots before the visible drawing begins
647
+				// we're going to run 1 here and then run 7 in the next case
648
+				this->dispcnt.timestamp += 12;
649
+				this->dispcnt.param = ESI_DISPCNT_HStartIRQ;
650
+				break;
651
+			case ESI_DISPCNT_HStartIRQ:
652
+				execHardware_hstart_irq();
653
+				this->dispcnt.timestamp += 84;
654
+				this->dispcnt.param = ESI_DISPCNT_HDraw;
655
+				break;
656
+			case ESI_DISPCNT_HDraw:
657
+				// duration of non-blanking period is ~1606 clocks (gbatek agrees) [but says its different on arm7]
658
+				// im gonna call this 267 dots = 267*6=1602
659
+				// so, this event lasts 267 dots minus the 8 dot preroll
660
+				this->dispcnt.timestamp += 3108;
661
+				this->dispcnt.param = ESI_DISPCNT_HBlank;
662
+				break;
663
+			case ESI_DISPCNT_HBlank:
664
+				execHardware_hblank();
665
+				// (once this was 1092 or 1092/12=91 dots.)
666
+				// there are surely 355 dots per scanline, less 267 for non-blanking period. the rest is hblank and then after that is hstart
667
+				this->dispcnt.timestamp += 1056;
668
+				this->dispcnt.param = ESI_DISPCNT_HStart;
1756 669
 		}
1757 670
 	}
1758 671
 
1759
-#ifdef EXPERIMENTAL_WIFI_COMM
1760
-	if(wifi.isTriggered())
1761
-	{
1762
-		WIFI_usTrigger();
1763
-		wifi.timestamp += kWifiCycles;
1764
-	}
1765
-#endif
1766
-
1767
-	if(divider.isTriggered()) divider.exec();
1768
-	if(sqrtunit.isTriggered()) sqrtunit.exec();
1769
-	//if(gxfifo.isTriggered()) gxfifo.exec();
1770
-
672
+	if (this->divider.isTriggered())
673
+		this->divider.exec();
674
+	if (this->sqrtunit.isTriggered())
675
+		this->sqrtunit.exec();
1771 676
 
1772
-#define test(X,Y) if(dma_##X##_##Y .isTriggered()) dma_##X##_##Y .exec();
1773
-	test(0,0); test(0,1); test(0,2); test(0,3);
1774
-	test(1,0); test(1,1); test(1,2); test(1,3);
677
+#define test(X, Y) \
678
+	if (this->dma_##X##_##Y .isTriggered()) \
679
+		this->dma_##X##_##Y .exec();
680
+	test(0, 0); test(0, 1); test(0, 2); test(0, 3);
681
+	test(1, 0); test(1, 1); test(1, 2); test(1, 3);
1775 682
 #undef test
1776
-#define test(X,Y) if(timer_##X##_##Y .enabled) if(timer_##X##_##Y .isTriggered()) timer_##X##_##Y .exec();
1777
-	test(0,0); test(0,1); test(0,2); test(0,3);
1778
-	test(1,0); test(1,1); test(1,2); test(1,3);
683
+#define test(X, Y) \
684
+	if (this->timer_##X##_##Y .enabled && this->timer_##X##_##Y .isTriggered()) \
685
+		this->timer_##X##_##Y .exec();
686
+	test(0, 0); test(0, 1); test(0, 2); test(0, 3);
687
+	test(1, 0); test(1, 1); test(1, 2); test(1, 3);
1779 688
 #undef test
1780 689
 }
1781 690
 
1782 691
 void execHardware_interrupts();
1783 692
 
1784
-//static void saveUserInput(EMUFILE* os);
1785
-static bool loadUserInput(EMUFILE* is, int version);
1786
-
1787
-/*void nds_savestate(EMUFILE* os)
1788
-{
1789
-	//version
1790
-	write32le(3,os);
1791
-
1792
-	//sequencer.save(os);
1793
-
1794
-	saveUserInput(os);
1795
-
1796
-	write32le(LidClosed,os);
1797
-	write8le(countLid,os);
1798
-}*/
1799
-
1800
-bool nds_loadstate(EMUFILE* is, int)
1801
-{
1802
-	// this isn't part of the savestate loading logic, but
1803
-	// don't skip the next frame after loading a savestate
1804
-	//frameSkipper.OmitSkip(true, true);
1805
-
1806
-	//read version
1807
-	uint32_t version;
1808
-	if(read32le(&version,is) != 1) return false;
1809
-
1810
-	if(version > 3) return false;
1811
-
1812
-	bool temp = true;
1813
-	temp &= sequencer.load(is, version);
1814
-	if(version <= 1 || !temp) return temp;
1815
-	temp &= loadUserInput(is, version);
1816
-
1817
-	if(version < 3) return temp;
1818
-
1819
-	uint32_t tmpu32;
1820
-	read32le(&tmpu32,is);
1821
-	uint8_t tmpu8;
1822
-	read8le(&tmpu8,is);
1823
-
1824
-	return temp;
1825
-}
1826
-
1827
-/*inline void arm9log()
1828
-{
1829
-#ifdef LOG_ARM9
1830
-	if(dolog)
1831
-	{
1832
-		char dasmbuf[4096];
1833
-		if(NDS_ARM9.CPSR.bits.T)
1834
-			des_thumb_instructions_set[((NDS_ARM9.instruction)>>6)&1023](NDS_ARM9.instruct_adr, NDS_ARM9.instruction, dasmbuf);
1835
-		else
1836
-			des_arm_instructions_set[INDEX(NDS_ARM9.instruction)](NDS_ARM9.instruct_adr, NDS_ARM9.instruction, dasmbuf);
1837
-
1838
-#ifdef LOG_TO_FILE
1839
-		if (!fp_dis9) return;
1840
-#ifdef LOG_TO_FILE_REGS
1841
-		fprintf(fp_dis9, "\t\t;R0:%08X R1:%08X R2:%08X R3:%08X R4:%08X R5:%08X R6:%08X R7:%08X R8:%08X R9:%08X\n\t\t;R10:%08X R11:%08X R12:%08X R13:%08X R14:%08X R15:%08X| next %08X, N:%i Z:%i C:%i V:%i\n",
1842
-			NDS_ARM9.R[0],  NDS_ARM9.R[1],  NDS_ARM9.R[2],  NDS_ARM9.R[3],  NDS_ARM9.R[4],  NDS_ARM9.R[5],  NDS_ARM9.R[6],  NDS_ARM9.R[7],
1843
-			NDS_ARM9.R[8],  NDS_ARM9.R[9],  NDS_ARM9.R[10],  NDS_ARM9.R[11],  NDS_ARM9.R[12],  NDS_ARM9.R[13],  NDS_ARM9.R[14],  NDS_ARM9.R[15],
1844
-			NDS_ARM9.next_instruction, NDS_ARM9.CPSR.bits.N, NDS_ARM9.CPSR.bits.Z, NDS_ARM9.CPSR.bits.C, NDS_ARM9.CPSR.bits.V);
1845
-#endif
1846
-		fprintf(fp_dis9, "%s %08X\t%08X \t%s\n", NDS_ARM9.CPSR.bits.T?"THUMB":"ARM", NDS_ARM9.instruct_adr, NDS_ARM9.instruction, dasmbuf);*/
1847
-		/*if (NDS_ARM9.instruction == 0)
1848
-		{
1849
-			dolog = false;
1850
-			INFO("Disassembler is stopped\n");
1851
-		}*/
1852
-/*#else
1853
-		printf("%05d:%03d %12lld 9:%08X %08X %-30s R00:%08X R01:%08X R02:%08X R03:%08X R04:%08X R05:%08X R06:%08X R07:%08X R08:%08X R09:%08X R10:%08X R11:%08X R12:%08X R13:%08X R14:%08X R15:%08X\n",
1854
-			currFrameCounter, nds.VCount, nds_timer,
1855
-			NDS_ARM9.instruct_adr,NDS_ARM9.instruction, dasmbuf,
1856
-			NDS_ARM9.R[0],  NDS_ARM9.R[1],  NDS_ARM9.R[2],  NDS_ARM9.R[3],  NDS_ARM9.R[4],  NDS_ARM9.R[5],  NDS_ARM9.R[6],  NDS_ARM9.R[7],
1857
-			NDS_ARM9.R[8],  NDS_ARM9.R[9],  NDS_ARM9.R[10],  NDS_ARM9.R[11],  NDS_ARM9.R[12],  NDS_ARM9.R[13],  NDS_ARM9.R[14],  NDS_ARM9.R[15]);
1858
-#endif
1859
-	}
1860
-#endif
1861
-}*/
1862
-
1863
-/*inline void arm7log()
1864
-{
1865
-#ifdef LOG_ARM7
1866
-	if(dolog)
1867
-	{
1868
-		char dasmbuf[4096];
1869
-		if(NDS_ARM7.CPSR.bits.T)
1870
-			des_thumb_instructions_set[((NDS_ARM7.instruction)>>6)&1023](NDS_ARM7.instruct_adr, NDS_ARM7.instruction, dasmbuf);
1871
-		else
1872
-			des_arm_instructions_set[INDEX(NDS_ARM7.instruction)](NDS_ARM7.instruct_adr, NDS_ARM7.instruction, dasmbuf);
1873
-#ifdef LOG_TO_FILE
1874
-		if (!fp_dis7) return;
1875
-#ifdef LOG_TO_FILE_REGS
1876
-		fprintf(fp_dis7, "\t\t;R0:%08X R1:%08X R2:%08X R3:%08X R4:%08X R5:%08X R6:%08X R7:%08X R8:%08X R9:%08X\n\t\t;R10:%08X R11:%08X R12:%08X R13:%08X R14:%08X R15:%08X| next %08X, N:%i Z:%i C:%i V:%i\n",
1877
-			NDS_ARM7.R[0],  NDS_ARM7.R[1],  NDS_ARM7.R[2],  NDS_ARM7.R[3],  NDS_ARM7.R[4],  NDS_ARM7.R[5],  NDS_ARM7.R[6],  NDS_ARM7.R[7],
1878
-			NDS_ARM7.R[8],  NDS_ARM7.R[9],  NDS_ARM7.R[10],  NDS_ARM7.R[11],  NDS_ARM7.R[12],  NDS_ARM7.R[13],  NDS_ARM7.R[14],  NDS_ARM7.R[15],
1879
-			NDS_ARM7.next_instruction, NDS_ARM7.CPSR.bits.N, NDS_ARM7.CPSR.bits.Z, NDS_ARM7.CPSR.bits.C, NDS_ARM7.CPSR.bits.V);
1880
-#endif
1881
-		fprintf(fp_dis7, "%s %08X\t%08X \t%s\n", NDS_ARM7.CPSR.bits.T?"THUMB":"ARM", NDS_ARM7.instruct_adr, NDS_ARM7.instruction, dasmbuf);*/
1882
-		/*if (NDS_ARM7.instruction == 0)
1883
-		{
1884
-			dolog = false;
1885
-			INFO("Disassembler is stopped\n");
1886
-		}*/
1887
-/*#else
1888
-		printf("%05d:%03d %12lld 7:%08X %08X %-30s R00:%08X R01:%08X R02:%08X R03:%08X R04:%08X R05:%08X R06:%08X R07:%08X R08:%08X R09:%08X R10:%08X R11:%08X R12:%08X R13:%08X R14:%08X R15:%08X\n",
1889
-			currFrameCounter, nds.VCount, nds_timer,
1890
-			NDS_ARM7.instruct_adr,NDS_ARM7.instruction, dasmbuf,
1891
-			NDS_ARM7.R[0],  NDS_ARM7.R[1],  NDS_ARM7.R[2],  NDS_ARM7.R[3],  NDS_ARM7.R[4],  NDS_ARM7.R[5],  NDS_ARM7.R[6],  NDS_ARM7.R[7],
1892
-			NDS_ARM7.R[8],  NDS_ARM7.R[9],  NDS_ARM7.R[10],  NDS_ARM7.R[11],  NDS_ARM7.R[12],  NDS_ARM7.R[13],  NDS_ARM7.R[14],  NDS_ARM7.R[15]);
1893
-#endif
1894
-	}
1895
-#endif
1896
-}*/
1897
-
1898
-//these have not been tuned very well yet.
693
+// these have not been tuned very well yet.
1899 694
 static const int kMaxWork = 4000;
1900 695
 static const int kIrqWait = 4000;
1901 696
 
1902
-
1903
-template<bool doarm9, bool doarm7>
1904
-static inline int32_t minarmtime(int32_t arm9, int32_t arm7)
697
+template<bool doarm9, bool doarm7> static inline int32_t minarmtime(int32_t arm9, int32_t arm7)
1905 698
 {
1906
-	if(doarm9)
699
+	if (doarm9)
1907 700
 	{
1908
-		if(doarm7)
1909
-			return std::min(arm9,arm7);
701
+		if (doarm7)
702
+			return std::min(arm9, arm7);
1910 703
 		else
1911 704
 			return arm9;
1912 705
 	}
... ...
@@ -1914,206 +707,124 @@ static inline int32_t minarmtime(int32_t arm9, int32_t arm7)
1914 707
 		return arm7;
1915 708
 }
1916 709
 
710
+#ifdef HAVE_JIT
711
+template<bool doarm9, bool doarm7, bool jit>
712
+#else
1917 713
 template<bool doarm9, bool doarm7>
1918
-static /*donotinline*/ std::pair<int32_t,int32_t> armInnerLoop(
1919
-	const uint64_t nds_timer_base, const int32_t s32next, int32_t arm9, int32_t arm7)
714
+#endif
715
+static std::pair<int32_t, int32_t> armInnerLoop(uint64_t nds_timer_base, int32_t s32next, int32_t arm9, int32_t arm7)
1920 716
 {
1921
-	int32_t timer = minarmtime<doarm9,doarm7>(arm9,arm7);
1922
-	while(timer < s32next && !sequencer.reschedule && execute)
717
+	int32_t timer = minarmtime<doarm9, doarm7>(arm9, arm7);
718
+	while (timer < s32next && !sequencer.reschedule && execute)
1923 719
 	{
1924
-		if(doarm9 && (!doarm7 || arm9 <= timer))
720
+		if (doarm9 && (!doarm7 || arm9 <= timer))
1925 721
 		{
1926
-			if(!NDS_ARM9.waitIRQ&&!nds.freezeBus)
722
+			if (!NDS_ARM9.waitIRQ && !nds.freezeBus)
1927 723
 			{
1928
-				//arm9log();
724
+#ifdef HAVE_JIT
725
+				arm9 += armcpu_exec<ARMCPU_ARM9, jit>();
726
+#else
1929 727
 				arm9 += armcpu_exec<ARMCPU_ARM9>();
1930
-				#ifdef DEVELOPER
1931
-					nds_debug_continuing[0] = false;
1932
-				#endif
728
+#endif
1933 729
 			}
1934 730
 			else
1935
-			{
1936
-				//int32_t temp = arm9;
1937 731
 				arm9 = std::min(s32next, arm9 + kIrqWait);
1938
-				//nds.idleCycles[0] += arm9-temp;
1939
-				//if (gxFIFO.size < 255) nds.freezeBus = false;
1940
-			}
1941 732
 		}
1942
-		if(doarm7 && (!doarm9 || arm7 <= timer))
733
+		if (doarm7 && (!doarm9 || arm7 <= timer))
1943 734
 		{
1944
-			if(!NDS_ARM7.waitIRQ&&!nds.freezeBus)
735
+			if (!NDS_ARM7.waitIRQ && !nds.freezeBus)
1945 736
 			{
1946
-				//arm7log();
1947
-				arm7 += (armcpu_exec<ARMCPU_ARM7>()<<1);
1948
-				#ifdef DEVELOPER
1949
-					nds_debug_continuing[1] = false;
1950
-				#endif
737
+#ifdef HAVE_JIT
738
+				arm7 += armcpu_exec<ARMCPU_ARM7, jit>() << 1;
739
+#else
740
+				arm7 += armcpu_exec<ARMCPU_ARM7>() << 1;
741
+#endif
1951 742
 			}
1952 743
 			else
1953 744
 			{
1954
-				//int32_t temp = arm7;
1955 745
 				arm7 = std::min(s32next, arm7 + kIrqWait);
1956
-				//nds.idleCycles[1] += arm7-temp;
1957
-				if(arm7 == s32next)
746
+				if (arm7 == s32next)
1958 747
 				{
1959
-					nds_timer = nds_timer_base + minarmtime<doarm9,false>(arm9,arm7);
1960
-					return armInnerLoop<doarm9,false>(nds_timer_base, s32next, arm9, arm7);
748
+					nds_timer = nds_timer_base + minarmtime<doarm9, false>(arm9, arm7);
749
+#ifdef HAVE_JIT
750
+					return armInnerLoop<doarm9, false, jit>(nds_timer_base, s32next, arm9, arm7);
751
+#else
752
+					return armInnerLoop<doarm9, false>(nds_timer_base, s32next, arm9, arm7);
753
+#endif
1961 754
 				}
1962 755
 			}
1963 756
 		}
1964 757
 
1965
-		timer = minarmtime<doarm9,doarm7>(arm9,arm7);
758
+		timer = minarmtime<doarm9, doarm7>(arm9, arm7);
1966 759
 		nds_timer = nds_timer_base + timer;
1967 760
 	}
1968 761
 
1969 762
 	return std::make_pair(arm9, arm7);
1970 763
 }
1971 764
 
1972
-/*void NDS_debug_break()
1973
-{
1974
-	NDS_ARM9.stalled = NDS_ARM7.stalled = 1;
1975
-
1976
-	//triggers an immediate exit from the cpu loop
1977
-	NDS_Reschedule();
1978
-}*/
1979
-
1980
-/*void NDS_debug_continue()
1981
-{
1982
-	NDS_ARM9.stalled = NDS_ARM7.stalled = 0;
1983
-}*/
1984
-
1985
-/*void NDS_debug_step()
765
+template<bool FORCE> void NDS_exec(int32_t)
1986 766
 {
1987
-	NDS_debug_continue();
1988
-	singleStep = true;
1989
-}*/
1990
-
1991
-template<bool FORCE>
1992
-void NDS_exec(int32_t)
1993
-{
1994
-	//LagFrameFlag=1;
1995
-
1996
-	/*if((currFrameCounter&63) == 0)
1997
-		MMU_new.backupDevice.lazy_flush();*/
1998
-
1999 767
 	sequencer.nds_vblankEnded = false;
2000 768
 
2001
-	//nds.cpuloopIterationCount = 0;
2002
-
2003
-	IF_DEVELOPER(for(int i=0;i<32;i++) DEBUG_statistics.sequencerExecutionCounters[i] = 0);
2004
-
2005
-	if(nds.sleeping)
769
+	if (nds.sleeping)
2006 770
 	{
2007
-		//speculative code: if ANY irq happens, wake up the arm7.
2008
-		//I think the arm7 program analyzes the system and may decide not to wake up
2009
-		//if it is dissatisfied with the conditions
2010
-		if((MMU.reg_IE[1] & MMU.gen_IF<1>()))
2011
-		{
771
+		// speculative code: if ANY irq happens, wake up the arm7.
772
+		// I think the arm7 program analyzes the system and may decide not to wake up
773
+		// if it is dissatisfied with the conditions
774
+		if (MMU.reg_IE[1] & MMU.gen_IF<1>())
2012 775
 			nds.sleeping = false;
2013
-		}
2014 776
 	}
2015 777
 	else
2016 778
 	{
2017
-		for(;;)
779
+		for (;;)
2018 780
 		{
2019
-			//trap the debug-stalled condition
2020
-			#ifdef DEVELOPER
2021
-				singleStep = false;
2022
-				//(gdb stub doesnt yet know how to trigger these immediately by calling reschedule)
2023
-				while((NDS_ARM9.stalled || NDS_ARM7.stalled) && execute)
2024
-				{
2025
-					driver->EMU_DebugIdleUpdate();
2026
-					nds_debug_continuing[0] = nds_debug_continuing[1] = true;
2027
-				}
2028
-			#endif
2029
-
2030
-			//nds.cpuloopIterationCount++;
2031 781
 			sequencer.execHardware();
2032 782
 
2033
-			//break out once per frame
2034
-			if(sequencer.nds_vblankEnded) break;
2035
-			//it should be benign to execute execHardware in the next frame,
2036
-			//since there won't be anything for it to do (everything should be scheduled in the future)
783
+			// break out once per frame
784
+			if (sequencer.nds_vblankEnded)
785
+				break;
786
+			// it should be benign to execute execHardware in the next frame,
787
+			// since there won't be anything for it to do (everything should be scheduled in the future)
2037 788
 
2038
-			//bail in case the system halted
2039
-			if(!execute) break;
789
+			// bail in case the system halted
790
+			if (!execute)
791
+				break;
2040 792
 
2041 793
 			execHardware_interrupts();
2042 794
 
2043
-			//find next work unit:
795
+			// find next work unit:
2044 796
 			uint64_t next = sequencer.findNext();
2045
-			next = std::min(next,nds_timer+kMaxWork); //lets set an upper limit for now
797
+			next = std::min(next, nds_timer + kMaxWork); // lets set an upper limit for now
2046 798
 
2047
-			//printf("%d\n",(next-nds_timer));
799
+			//printf("%d\n", next - nds_timer);
2048 800
 
2049 801
 			sequencer.reschedule = false;
2050 802
 
2051
-			//cast these down to 32bits so that things run faster on 32bit procs
803
+			// cast these down to 32bits so that things run faster on 32bit procs
2052 804
 			uint64_t nds_timer_base = nds_timer;
2053
-			int32_t arm9 = (int32_t)(nds_arm9_timer-nds_timer);
2054
-			int32_t arm7 = (int32_t)(nds_arm7_timer-nds_timer);
2055
-			int32_t s32next = (int32_t)(next-nds_timer);
2056
-
2057
-			#ifdef DEVELOPER
2058
-				if(singleStep)
2059
-				{
2060
-					s32next = 1;
2061
-				}
2062
-			#endif
2063
-
2064
-			std::pair<int32_t,int32_t> arm9arm7 = armInnerLoop<true,true>(nds_timer_base,s32next,arm9,arm7);
805
+			int32_t arm9 = static_cast<int32_t>(nds_arm9_timer - nds_timer);
806
+			int32_t arm7 = static_cast<int32_t>(nds_arm7_timer - nds_timer);
807
+			int32_t s32next = static_cast<int32_t>(next - nds_timer);
2065 808
 
2066
-			#ifdef DEVELOPER
2067
-				if(singleStep)
2068
-				{
2069
-					NDS_ARM9.stalled = NDS_ARM7.stalled = 1;
2070
-				}
2071
-			#endif
809
+#ifdef HAVE_JIT
810
+			auto arm9arm7 = CommonSettings.use_jit ? armInnerLoop<true, true, true>(nds_timer_base, s32next, arm9, arm7) : armInnerLoop<true, true, false>(nds_timer_base, s32next, arm9, arm7);
811
+#else
812
+			auto arm9arm7 = armInnerLoop<true, true>(nds_timer_base, s32next, arm9, arm7);
813
+#endif
2072 814
 
2073 815
 			arm9 = arm9arm7.first;
2074 816
 			arm7 = arm9arm7.second;
2075
-			nds_arm7_timer = nds_timer_base+arm7;
2076
-			nds_arm9_timer = nds_timer_base+arm9;
817
+			nds_arm7_timer = nds_timer_base + arm7;
818
+			nds_arm9_timer = nds_timer_base + arm9;
2077 819
 
2078
-#ifndef NDEBUG
2079
-			//what we find here is dependent on the timing constants above
2080
-			//if(nds_timer>next && (nds_timer-next)>22)
2081
-			//	printf("curious. please report: over by %d\n",(int)(nds_timer-next));
2082
-#endif
2083
-
2084
-			//if we were waiting for an irq, don't wait too long:
2085
-			//let's re-analyze it after this hardware event (this rolls back a big burst of irq waiting which may have been interrupted by a resynch)
2086
-			if(NDS_ARM9.waitIRQ)
2087
-			{
2088
-				//nds.idleCycles[0] -= (int32_t)(nds_arm9_timer-nds_timer);
820
+			// if we were waiting for an irq, don't wait too long:
821
+			// let's re-analyze it after this hardware event (this rolls back a big burst of irq waiting which may have been interrupted by a resynch)
822
+			if (NDS_ARM9.waitIRQ)
2089 823
 				nds_arm9_timer = nds_timer;
2090
-			}
2091
-			if(NDS_ARM7.waitIRQ)
2092
-			{
2093
-				//nds.idleCycles[1] -= (int32_t)(nds_arm7_timer-nds_timer);
824
+			if (NDS_ARM7.waitIRQ)
2094 825
 				nds_arm7_timer = nds_timer;
2095
-			}
2096 826
 		}
2097 827
 	}
2098
-
2099
-	//DEBUG_statistics.printSequencerExecutionCounters();
2100
-	//DEBUG_statistics.print();
2101
-
2102
-	//end of frame emulation housekeeping
2103
-	/*if(LagFrameFlag)
2104
-	{
2105
-		lagframecounter++;
2106
-		TotalLagFrames++;
2107
-	}
2108
-	else
2109
-	{
2110
-		lastLag = lagframecounter;
2111
-		lagframecounter = 0;
2112
-	}*/
2113
-	//currFrameCounter++;
2114
-	//DEBUG_Notify.NextFrame();
2115
-	/*if (cheats)
2116
-		cheats->process();*/
2117 828
 }
2118 829
 
2119 830
 template<int PROCNUM> static void execHardware_interrupts_core()
... ...
@@ -2121,13 +832,13 @@ template<int PROCNUM> static void execHardware_interrupts_core()
2121 832
 	uint32_t IF = MMU.gen_IF<PROCNUM>();
2122 833
 	uint32_t IE = MMU.reg_IE[PROCNUM];
2123 834
 	uint32_t masked = IF & IE;
2124
-	if(ARMPROC.halt_IE_and_IF && masked)
835
+	if (ARMPROC.halt_IE_and_IF && masked)
2125 836
 	{
2126 837
 		ARMPROC.halt_IE_and_IF = false;
2127 838
 		ARMPROC.waitIRQ = false;
2128 839
 	}
2129 840
 
2130
-	if(masked && MMU.reg_IME[PROCNUM] && !ARMPROC.CPSR.bits.I)
841
+	if (masked && MMU.reg_IME[PROCNUM] && !ARMPROC.CPSR.bits.I)
2131 842
 	{
2132 843
 		//printf("Executing IRQ on procnum %d with IF = %08X and IE = %08X\n",PROCNUM,IF,IE);
2133 844
 		armcpu_irqException(&ARMPROC);
... ...
@@ -2140,115 +851,45 @@ void execHardware_interrupts()
2140 851
 	execHardware_interrupts_core<ARMCPU_ARM7>();
2141 852
 }
2142 853
 
2143
-//static void resetUserInput();
2144
-
2145
-//bool _HACK_DONT_STOPMOVIE = false;
2146
-void NDS_Reset()
854
+static void PrepareBiosARM7()
2147 855
 {
2148
-	singleStep = false;
2149
-	//nds_debug_continuing[0] = nds_debug_continuing[1] = false;
2150
-	uint32_t src = 0;
2151
-	uint32_t dst = 0;
2152
-	bool fw_success = false;
2153
-	FILE* inf = NULL;
2154
-	NDS_header * header = NDS_getROMHeader();
2155
-
2156
-	//DEBUG_reset();
2157
-
2158
-	if (!header) return ;
2159
-
2160
-	nds.sleeping = false;
2161
-	nds.cardEjected = false;
2162
-	nds.freezeBus = 0;
2163
-	//nds.power1.lcd = nds.power1.gpuMain = nds.power1.gfx3d_render = nds.power1.gfx3d_geometry = nds.power1.gpuSub = nds.power1.dispswap = 1;
2164
-	//nds.power2.speakers = 1;
2165
-	//nds.power2.wifi = 0;
2166
-
2167
-	nds_timer = 0;
2168
-	nds_arm9_timer = 0;
2169
-	nds_arm7_timer = 0;
2170
-
2171
-	/*if(movieMode != MOVIEMODE_INACTIVE && !_HACK_DONT_STOPMOVIE)
2172
-		movie_reset_command = true;*/
2173
-
2174
-	/*if(movieMode == MOVIEMODE_INACTIVE) {
2175
-		//currFrameCounter = 0;
2176
-		lagframecounter = 0;
2177
-		LagFrameFlag = 0;
2178
-		lastLag = 0;
2179
-		TotalLagFrames = 0;
2180
-	}*/
2181
-
2182
-	SPU_DeInit();
2183
-
2184
-	MMU_Reset();
2185
-
2186
-	//put random garbage in vram for homebrew games, to help mimic the situation where libnds does not clear out junk
2187
-	//which the card's launcher may or may not have left behind
2188
-  //1. retail games dont clear TCM, so why should we jumble it and expect homebrew to clear it?
2189
-  //2. some retail games _dont boot_ if main memory is jumbled. wha...?
2190
-  //3. clearing this is not as useful as tracking uninitialized reads in dev+ builds
2191
-  //4. the vram clearing causes lots of graphical corruptions in badly coded homebrews. this reduces compatibility substantially
2192
-  //conclusion: disable it for now and bring it back as an option
2193
-	//if(gameInfo.isHomebrew)
2194
-	//{
2195
-	//	uint32_t w=100000,x=99,y=117,z=19382173;
2196
-	//	CTASSERT(sizeof(MMU.ARM9_LCD) < sizeof(MMU.MAIN_MEM));
2197
-	//	CTASSERT(sizeof(MMU.ARM9_VMEM) < sizeof(MMU.MAIN_MEM));
2198
-	//	CTASSERT(sizeof(MMU.ARM9_ITCM) < sizeof(MMU.MAIN_MEM));
2199
-	//	CTASSERT(sizeof(MMU.ARM9_DTCM) < sizeof(MMU.MAIN_MEM));
2200
-	//	for(int i=0;i<sizeof(MMU.MAIN_MEM);i++)
2201
-	//	{
2202
-	//		uint32_t t= (x^(x<<11));
2203
-	//		x=y;
2204
-	//		y=z;
2205
-	//		z=w;
2206
-	//		t = (w= (w^(w>>19))^(t^(t>>8)));
2207
-	//		//MMU.MAIN_MEM[i] = t;
2208
-	//		if (i<sizeof(MMU.ARM9_LCD)) MMU.ARM9_LCD[i] = t;
2209
-	//		if (i<sizeof(MMU.ARM9_VMEM)) MMU.ARM9_VMEM[i] = t;
2210
-	//		//if (i<sizeof(MMU.ARM9_ITCM)) MMU.ARM9_ITCM[i] = t;
2211
-	//		//if (i<sizeof(MMU.ARM9_DTCM)) MMU.ARM9_DTCM[i] = t;
2212
-	//	}
2213
-	//}
2214
-
2215 856
 	NDS_ARM7.BIOS_loaded = false;
2216
-	NDS_ARM9.BIOS_loaded = false;
2217 857
 	memset(MMU.ARM7_BIOS, 0, sizeof(MMU.ARM7_BIOS));
2218
-	memset(MMU.ARM9_BIOS, 0, sizeof(MMU.ARM9_BIOS));
2219
-
2220
-	//ARM7 BIOS IRQ HANDLER
2221
-	if(CommonSettings.UseExtBIOS == true)
2222
-		inf = fopen(CommonSettings.ARM7BIOS,"rb");
2223
-	else
2224
-		inf = NULL;
2225
-
2226
-	if(inf)
858
+	if (CommonSettings.UseExtBIOS)
2227 859
 	{
2228
-		if (fread(MMU.ARM7_BIOS,1,16384,inf) == 16384) NDS_ARM7.BIOS_loaded = true;
2229
-		fclose(inf);
860
+		// read arm7 bios from inputfile and flag it if it succeeds
861
+		FILE *arm7inf = fopen(CommonSettings.ARM7BIOS, "rb");
862
+		if (fread(MMU.ARM7_BIOS, 1, 16384, arm7inf) == 16384)
863
+			NDS_ARM7.BIOS_loaded = true;
864
+		fclose(arm7inf);
865
+	}
2230 866
 
2231
-		if((CommonSettings.SWIFromBIOS) && (NDS_ARM7.BIOS_loaded)) NDS_ARM7.swi_tab = 0;
2232
-		else NDS_ARM7.swi_tab = ARM7_swi_tab;
867
+	// choose to use SWI emulation or routines from bios
868
+	if (CommonSettings.SWIFromBIOS && NDS_ARM7.BIOS_loaded)
869
+	{
870
+		NDS_ARM7.swi_tab = 0;
2233 871
 
872
+		// if we used routines from bios, apply patches
2234 873
 		if (CommonSettings.PatchSWI3)
2235 874
 			_MMU_write16<ARMCPU_ARM7>(0x00002F08, 0x4770);
2236
-
2237
-		//INFO("ARM7 BIOS is %s.\n", NDS_ARM7.BIOS_loaded?"loaded":"failed");
2238 875
 	}
2239 876
 	else
877
+		NDS_ARM7.swi_tab = ARM_swi_tab[ARMCPU_ARM7];
878
+
879
+	if (!NDS_ARM7.BIOS_loaded)
2240 880
 	{
2241
-		NDS_ARM7.swi_tab = ARM7_swi_tab;
881
+		// fake bios content, critical to normal operations, since we dont have a real bios.
2242 882
 
2243 883
 #if 0
884
+		// someone please document what is in progress here
2244 885
 		// TODO
2245
-		T1WriteLong(MMU.ARM7_BIOS, 0x0000, 0xEAFFFFFE);		// loop for Reset !!!
2246
-		T1WriteLong(MMU.ARM7_BIOS, 0x0004, 0xEAFFFFFE);		// loop for Undef instr expection
2247
-		T1WriteLong(MMU.ARM7_BIOS, 0x0008, 0xEA00009C);		// SWI
2248
-		T1WriteLong(MMU.ARM7_BIOS, 0x000C, 0xEAFFFFFE);		// loop for Prefetch Abort
2249
-		T1WriteLong(MMU.ARM7_BIOS, 0x0010, 0xEAFFFFFE);		// loop for Data Abort
2250
-		T1WriteLong(MMU.ARM7_BIOS, 0x0014, 0x00000000);		// Reserved
2251
-		T1WriteLong(MMU.ARM7_BIOS, 0x001C, 0x00000000);		// Fast IRQ
886
+		T1WriteLong(MMU.ARM7_BIOS, 0x0000, 0xEAFFFFFE); // loop for Reset !!!
887
+		T1WriteLong(MMU.ARM7_BIOS, 0x0004, 0xEAFFFFFE); // loop for Undef instr expection
888
+		T1WriteLong(MMU.ARM7_BIOS, 0x0008, 0xEA00009C); // SWI
889
+		T1WriteLong(MMU.ARM7_BIOS, 0x000C, 0xEAFFFFFE); // loop for Prefetch Abort
890
+		T1WriteLong(MMU.ARM7_BIOS, 0x0010, 0xEAFFFFFE); // loop for Data Abort
891
+		T1WriteLong(MMU.ARM7_BIOS, 0x0014, 0x00000000); // Reserved
892
+		T1WriteLong(MMU.ARM7_BIOS, 0x001C, 0x00000000); // Fast IRQ
2252 893
 #endif
2253 894
 		T1WriteLong(MMU.ARM7_BIOS, 0x0000, 0xE25EF002);
2254 895
 		T1WriteLong(MMU.ARM7_BIOS, 0x0018, 0xEA000000);
... ...
@@ -2259,52 +900,75 @@ void NDS_Reset()
2259 900
 		T1WriteLong(MMU.ARM7_BIOS, 0x0030, 0xE8BD500F);
2260 901
 		T1WriteLong(MMU.ARM7_BIOS, 0x0034, 0xE25EF004);
2261 902
 	}
903
+}
2262 904
 
2263
-	//ARM9 BIOS IRQ HANDLER
2264
-	if(CommonSettings.UseExtBIOS == true)
2265
-		inf = fopen(CommonSettings.ARM9BIOS,"rb");
2266
-	else
2267
-		inf = NULL;
2268
-
2269
-	if(inf)
905
+static void PrepareBiosARM9()
906
+{
907
+	memset(MMU.ARM9_BIOS, 0, sizeof(MMU.ARM9_BIOS));
908
+	NDS_ARM9.BIOS_loaded = false;
909
+	if (CommonSettings.UseExtBIOS)
2270 910
 	{
2271
-		if (fread(MMU.ARM9_BIOS,1,4096,inf) == 4096) NDS_ARM9.BIOS_loaded = true;
2272
-		fclose(inf);
2273
-
2274
-		if((CommonSettings.SWIFromBIOS) && (NDS_ARM9.BIOS_loaded)) NDS_ARM9.swi_tab = 0;
2275
-		else NDS_ARM9.swi_tab = ARM9_swi_tab;
911
+		// read arm9 bios from inputfile and flag it if it succeeds
912
+		FILE *arm9inf = fopen(CommonSettings.ARM9BIOS, "rb");
913
+		if (fread(MMU.ARM9_BIOS, 1, 4096, arm9inf) == 4096) 
914
+			NDS_ARM9.BIOS_loaded = true;
915
+		fclose(arm9inf);
916
+	}
2276 917
 
918
+	// choose to use SWI emulation or routines from bios
919
+	if (CommonSettings.SWIFromBIOS && NDS_ARM9.BIOS_loaded)
920
+	{
921
+		NDS_ARM9.swi_tab = 0;
922
+		
923
+		// if we used routines from bios, apply patches
2277 924
 		if (CommonSettings.PatchSWI3)
2278 925
 			_MMU_write16<ARMCPU_ARM9>(0xFFFF07CC, 0x4770);
2279
-
2280
-		//INFO("ARM9 BIOS is %s.\n", NDS_ARM9.BIOS_loaded?"loaded":"failed");
2281 926
 	}
2282 927
 	else
928
+		NDS_ARM9.swi_tab = ARM_swi_tab[ARMCPU_ARM9];
929
+
930
+	if (!NDS_ARM9.BIOS_loaded) 
2283 931
 	{
2284
-		NDS_ARM9.swi_tab = ARM9_swi_tab;
932
+		// fake bios content, critical to normal operations, since we dont have a real bios.
933
+		// it'd be cool if we could write this in some kind of assembly language, inline or otherwise, without some bulky dependencies
934
+		// perhaps we could build it with devkitarm? but thats bulky (offline) dependencies, to be sure..
2285 935
 
2286
-		//bios chains data abort to fast irq
936
+		// reminder: bios chains data abort to fast irq
2287 937
 
2288
-		//exception vectors:
2289
-		T1WriteLong(MMU.ARM9_BIOS, 0x0000, 0xEAFFFFFE);		// (infinite loop for) Reset !!!
2290
-		//T1WriteLong(MMU.ARM9_BIOS, 0x0004, 0xEAFFFFFE);		// (infinite loop for) Undefined instruction
2291
-		T1WriteLong(MMU.ARM9_BIOS, 0x0004, 0xEA000004);		// Undefined instruction -> Fast IRQ (just guessing)
2292
-		T1WriteLong(MMU.ARM9_BIOS, 0x0008, 0xEA00009C);		// SWI -> ?????
2293
-		T1WriteLong(MMU.ARM9_BIOS, 0x000C, 0xEAFFFFFE);		// (infinite loop for) Prefetch Abort
2294
-		T1WriteLong(MMU.ARM9_BIOS, 0x0010, 0xEA000001);		// Data Abort -> Fast IRQ
2295
-		T1WriteLong(MMU.ARM9_BIOS, 0x0014, 0x00000000);		// Reserved
2296
-		T1WriteLong(MMU.ARM9_BIOS, 0x0018, 0xEA000095);		// Normal IRQ -> 0x0274
2297
-		T1WriteLong(MMU.ARM9_BIOS, 0x001C, 0xEA00009D);		// Fast IRQ -> 0x0298
938
+		// exception vectors:
939
+		T1WriteLong(MMU.ARM9_BIOS, 0x0000, 0xEAFFFFFE); // (infinite loop for) Reset !!!
940
+		//T1WriteLong(MMU.ARM9_BIOS, 0x0004, 0xEAFFFFFE); // (infinite loop for) Undefined instruction
941
+		T1WriteLong(MMU.ARM9_BIOS, 0x0004, 0xEA000004); // Undefined instruction -> Fast IRQ (just guessing)
942
+		T1WriteLong(MMU.ARM9_BIOS, 0x0008, 0xEA00009C); // SWI -> ?????
943
+		T1WriteLong(MMU.ARM9_BIOS, 0x000C, 0xEAFFFFFE); // (infinite loop for) Prefetch Abort
944
+		T1WriteLong(MMU.ARM9_BIOS, 0x0010, 0xEA000001); // Data Abort -> Fast IRQ
945
+		T1WriteLong(MMU.ARM9_BIOS, 0x0014, 0x00000000); // Reserved
946
+		T1WriteLong(MMU.ARM9_BIOS, 0x0018, 0xEA000095); // Normal IRQ -> 0x0274
947
+		T1WriteLong(MMU.ARM9_BIOS, 0x001C, 0xEA00009D); // Fast IRQ -> 0x0298
948
+
949
+		static const uint8_t logo_data[] =
950
+		{
951
+			0x24, 0xFF, 0xAE, 0x51, 0x69, 0x9A, 0xA2, 0x21, 0x3D, 0x84, 0x82, 0x0A, 0x84, 0xE4, 0x09, 0xAD,
952
+			0x11, 0x24, 0x8B, 0x98, 0xC0, 0x81, 0x7F, 0x21, 0xA3, 0x52, 0xBE, 0x19, 0x93, 0x09, 0xCE, 0x20,
953
+			0x10, 0x46, 0x4A, 0x4A, 0xF8, 0x27, 0x31, 0xEC, 0x58, 0xC7, 0xE8, 0x33, 0x82, 0xE3, 0xCE, 0xBF,
954
+			0x85, 0xF4, 0xDF, 0x94, 0xCE, 0x4B, 0x09, 0xC1, 0x94, 0x56, 0x8A, 0xC0, 0x13, 0x72, 0xA7, 0xFC,
955
+			0x9F, 0x84, 0x4D, 0x73, 0xA3, 0xCA, 0x9A, 0x61, 0x58, 0x97, 0xA3, 0x27, 0xFC, 0x03, 0x98, 0x76,
956
+			0x23, 0x1D, 0xC7, 0x61, 0x03, 0x04, 0xAE, 0x56, 0xBF, 0x38, 0x84, 0x00, 0x40, 0xA7, 0x0E, 0xFD,
957
+			0xFF, 0x52, 0xFE, 0x03, 0x6F, 0x95, 0x30, 0xF1, 0x97, 0xFB, 0xC0, 0x85, 0x60, 0xD6, 0x80, 0x25,
958
+			0xA9, 0x63, 0xBE, 0x03, 0x01, 0x4E, 0x38, 0xE2, 0xF9, 0xA2, 0x34, 0xFF, 0xBB, 0x3E, 0x03, 0x44,
959
+			0x78, 0x00, 0x90, 0xCB, 0x88, 0x11, 0x3A, 0x94, 0x65, 0xC0, 0x7C, 0x63, 0x87, 0xF0, 0x3C, 0xAF,
960
+			0xD6, 0x25, 0xE4, 0x8B, 0x38, 0x0A, 0xAC, 0x72, 0x21, 0xD4, 0xF8, 0x07
961
+		};
2298 962
 
2299 963
 		// logo (do some games fail to boot without this? example?)
2300
-		for (int t = 0; t < 0x9C; t++)
964
+		for (int t = 0; t < 0x9C; ++t)
2301 965
 			MMU.ARM9_BIOS[t + 0x20] = logo_data[t];
2302 966
 
2303 967
 		//...0xBC:
2304 968
 
2305
-		//(now what goes in this gap??)
969
+		// (now what goes in this gap??)
2306 970
 
2307
-		//IRQ handler: get dtcm address and jump to a vector in it
971
+		// IRQ handler: get dtcm address and jump to a vector in it
2308 972
 		T1WriteLong(MMU.ARM9_BIOS, 0x0274, 0xE92D500F); //STMDB SP!, {R0-R3,R12,LR}
2309 973
 		T1WriteLong(MMU.ARM9_BIOS, 0x0278, 0xEE190F11); //MRC CP15, 0, R0, CR9, CR1, 0
2310 974
 		T1WriteLong(MMU.ARM9_BIOS, 0x027C, 0xE1A00620); //MOV R0, R0, LSR #C
... ...
@@ -2313,81 +977,100 @@ void NDS_Reset()
2313 977
 		T1WriteLong(MMU.ARM9_BIOS, 0x0288, 0xE28FE000); //ADD LR, PC, #0
2314 978
 		T1WriteLong(MMU.ARM9_BIOS, 0x028C, 0xE510F004); //LDR PC, [R0, -#4]
2315 979
 
2316
-		//????
2317
-		T1WriteLong(MMU.ARM9_BIOS, 0x0290, 0xE8BD500F); //LDMIA SP!, {R0-R3,R12,LR}
2318
-		T1WriteLong(MMU.ARM9_BIOS, 0x0294, 0xE25EF004); //SUBS PC, LR, #4
2319
-
2320
-		//-------
2321
-		//FIQ and abort exception handler
2322
-		//TODO - this code is copied from the bios. refactor it
2323
-		//friendly reminder: to calculate an immediate offset: encoded = (desired_address-cur_address-8)
980
+		// ????
981
+		T1WriteLong(MMU.ARM9_BIOS, 0x0290, 0xE8BD500F); // LDMIA SP!, {R0-R3,R12,LR}
982
+		T1WriteLong(MMU.ARM9_BIOS, 0x0294, 0xE25EF004); // SUBS PC, LR, #4
2324 983
 
2325
-		T1WriteLong(MMU.ARM9_BIOS, 0x0298, 0xE10FD000); //MRS SP, CPSR
2326
-		T1WriteLong(MMU.ARM9_BIOS, 0x029C, 0xE38DD0C0); //ORR SP, SP, #C0
984
+		// -------
985
+		// FIQ and abort exception handler
986
+		// TODO - this code is copied from the bios. refactor it
987
+		// friendly reminder: to calculate an immediate offset: encoded = (desired_address-cur_address-8)
2327 988
 
2328
-		T1WriteLong(MMU.ARM9_BIOS, 0x02A0, 0xE12FF00D); //MSR CPSR_fsxc, SP
2329
-		T1WriteLong(MMU.ARM9_BIOS, 0x02A4, 0xE59FD000 | (0x2D4-0x2A4-8)); //LDR SP, [FFFF02D4]
2330
-		T1WriteLong(MMU.ARM9_BIOS, 0x02A8, 0xE28DD001); //ADD SP, SP, #1
2331
-		T1WriteLong(MMU.ARM9_BIOS, 0x02AC, 0xE92D5000); //STMDB SP!, {R12,LR}
989
+		T1WriteLong(MMU.ARM9_BIOS, 0x0298, 0xE10FD000); // MRS SP, CPSR
990
+		T1WriteLong(MMU.ARM9_BIOS, 0x029C, 0xE38DD0C0); // ORR SP, SP, #C0
2332 991
 
2333
-		T1WriteLong(MMU.ARM9_BIOS, 0x02B0, 0xE14FE000); //MRS LR, SPSR
2334
-		T1WriteLong(MMU.ARM9_BIOS, 0x02B4, 0xEE11CF10); //MRC CP15, 0, R12, CR1, CR0, 0
2335
-		T1WriteLong(MMU.ARM9_BIOS, 0x02B8, 0xE92D5000); //STMDB SP!, {R12,LR}
2336
-		T1WriteLong(MMU.ARM9_BIOS, 0x02BC, 0xE3CCC001); //BIC R12, R12, #1
992
+		T1WriteLong(MMU.ARM9_BIOS, 0x02A0, 0xE12FF00D); // MSR CPSR_fsxc, SP
993
+		T1WriteLong(MMU.ARM9_BIOS, 0x02A4, 0xE59FD028); // LDR SP, [FFFF02D4]
994
+		T1WriteLong(MMU.ARM9_BIOS, 0x02A8, 0xE28DD001); // ADD SP, SP, #1
995
+		T1WriteLong(MMU.ARM9_BIOS, 0x02AC, 0xE92D5000); // STMDB SP!, {R12,LR}
2337 996
 
2338
-		T1WriteLong(MMU.ARM9_BIOS, 0x02C0, 0xEE01CF10); //MCR CP15, 0, R12, CR1, CR0, 0
2339
-		T1WriteLong(MMU.ARM9_BIOS, 0x02C4, 0xE3CDC001); //BIC R12, SP, #1
2340
-		T1WriteLong(MMU.ARM9_BIOS, 0x02C8, 0xE59CC010); //LDR R12, [R12, #10]
2341
-		T1WriteLong(MMU.ARM9_BIOS, 0x02CC, 0xE35C0000); //CMP R12, #0
997
+		T1WriteLong(MMU.ARM9_BIOS, 0x02B0, 0xE14FE000); // MRS LR, SPSR
998
+		T1WriteLong(MMU.ARM9_BIOS, 0x02B4, 0xEE11CF10); // MRC CP15, 0, R12, CR1, CR0, 0
999
+		T1WriteLong(MMU.ARM9_BIOS, 0x02B8, 0xE92D5000); // STMDB SP!, {R12,LR}
1000
+		T1WriteLong(MMU.ARM9_BIOS, 0x02BC, 0xE3CCC001); // BIC R12, R12, #1
2342 1001
 
2343
-		T1WriteLong(MMU.ARM9_BIOS, 0x02D0, 0x112FFF3C); //BLXNE R12
2344
-		T1WriteLong(MMU.ARM9_BIOS, 0x02D4, 0x027FFD9C); //0x027FFD9C
2345
-		//---------
1002
+		T1WriteLong(MMU.ARM9_BIOS, 0x02C0, 0xEE01CF10); // MCR CP15, 0, R12, CR1, CR0, 0
1003
+		T1WriteLong(MMU.ARM9_BIOS, 0x02C4, 0xE3CDC001); // BIC R12, SP, #1
1004
+		T1WriteLong(MMU.ARM9_BIOS, 0x02C8, 0xE59CC010); // LDR R12, [R12, #10]
1005
+		T1WriteLong(MMU.ARM9_BIOS, 0x02CC, 0xE35C0000); // CMP R12, #0
2346 1006
 
1007
+		T1WriteLong(MMU.ARM9_BIOS, 0x02D0, 0x112FFF3C); // BLXNE R12
1008
+		T1WriteLong(MMU.ARM9_BIOS, 0x02D4, 0x027FFD9C); // 0x027FFD9C
1009
+		// ---------
2347 1010
 	}
1011
+}
2348 1012
 
2349
-#ifdef LOG_ARM7
2350
-	if (fp_dis7 != NULL)
2351
-	{
2352
-		fclose(fp_dis7);
2353
-		fp_dis7 = NULL;
2354
-	}
2355
-	fp_dis7 = fopen("D:\\desmume_dis7.asm", "w");
2356
-#endif
1013
+void NDS_Reset()
1014
+{
1015
+	singleStep = false;
1016
+	bool fw_success = false;
1017
+	auto header = NDS_getROMHeader();
2357 1018
 
2358
-#ifdef LOG_ARM9
2359
-	if (fp_dis9 != NULL)
2360
-	{
2361
-		fclose(fp_dis9);
2362
-		fp_dis9 = NULL;
2363
-	}
2364
-	fp_dis9 = fopen("D:\\desmume_dis9.asm", "w");
1019
+	if (!header)
1020
+		return;
1021
+
1022
+	nds.sleeping = false;
1023
+	nds.cardEjected = false;
1024
+	nds.freezeBus = 0;
1025
+
1026
+	nds_timer = 0;
1027
+	nds_arm9_timer = 0;
1028
+	nds_arm7_timer = 0;
1029
+
1030
+	SPU_DeInit();
1031
+
1032
+	MMU_Reset();
1033
+
1034
+#ifdef HAVE_JIT
1035
+	arm_jit_reset(CommonSettings.use_jit);
2365 1036
 #endif
2366 1037
 
2367
-	if (firmware)
2368
-	{
2369
-		delete firmware;
2370
-		firmware = NULL;
2371
-	}
2372
-	firmware = new CFIRMWARE();
1038
+	PrepareBiosARM7();
1039
+	PrepareBiosARM9();
1040
+
1041
+	// according to smea, this is initialized to 3 by the time we get into a user game program. who does this? 
1042
+	// well, the firmware load process is about to write a boot program into SIWRAM for the arm7. so we need it setup by now.
1043
+	// but, this is a bit weird.. I would be expecting the bioses to do that. maybe we have some more detail to emulate.
1044
+	// * is this setting the default, or does the bios do it before loading the firmware programs?
1045
+	// at any, it's important that this be done long before the user code ever runs
1046
+	_MMU_write08<ARMCPU_ARM9>(REG_WRAMCNT, 3);
1047
+
1048
+	firmware.reset(new CFIRMWARE());
2373 1049
 	fw_success = firmware->load();
1050
+
2374 1051
 	if (NDS_ARM7.BIOS_loaded && NDS_ARM9.BIOS_loaded && CommonSettings.BootFromFirmware && fw_success)
2375 1052
 	{
2376
-		// Copy secure area to memory if needed
2377
-		if ((header->ARM9src >= 0x4000) && (header->ARM9src < 0x8000))
1053
+		// Copy secure area to memory if needed.
1054
+		// could we get a comment about what's going on here?
1055
+		// how does this stuff get copied before anything ever even runs?
1056
+		// does it get mapped straight to the rom somehow?
1057
+		// This code could be made more clear too.
1058
+		if (header->ARM9src >= 0x4000 && header->ARM9src < 0x8000)
2378 1059
 		{
2379
-			src = header->ARM9src;
2380
-			dst = header->ARM9cpy;
1060
+			uint32_t src = header->ARM9src;
1061
+			uint32_t dst = header->ARM9cpy;
2381 1062
 
2382 1063
 			uint32_t size = (0x8000 - src) >> 2;
2383
-			//INFO("Copy secure area from 0x%08X to 0x%08X (size %i/0x%08X)\n", src, dst, size, size);
2384
-			for (uint32_t i = 0; i < size; i++)
1064
+
1065
+			for (uint32_t i = 0; i < size; ++i)
2385 1066
 			{
2386 1067
 				_MMU_write32<ARMCPU_ARM9>(dst, T1ReadLong(MMU.CART_ROM, src));
2387
-				src += 4; dst += 4;
1068
+				src += 4;
1069
+				dst += 4;
2388 1070
 			}
2389 1071
 		}
2390 1072
 
1073
+		// TODO someone describe why here
2391 1074
 		if (firmware->patched)
2392 1075
 		{
2393 1076
 			armcpu_init(&NDS_ARM7, 0x00000008);
... ...
@@ -2395,138 +1078,107 @@ void NDS_Reset()
2395 1078
 		}
2396 1079
 		else
2397 1080
 		{
2398
-			//INFO("Booting at ARM9: 0x%08X, ARM7: 0x%08X\n", firmware->ARM9bootAddr, firmware->ARM7bootAddr);
2399
-			// need for firmware
2400
-			//armcpu_init(&NDS_ARM7, 0x00000008);
2401
-			//armcpu_init(&NDS_ARM9, 0xFFFF0008);
1081
+			// set the cpus to an initial state with their respective firmware program entrypoints
2402 1082
 			armcpu_init(&NDS_ARM7, firmware->ARM7bootAddr);
2403 1083
 			armcpu_init(&NDS_ARM9, firmware->ARM9bootAddr);
2404 1084
 		}
2405 1085
 
2406
-			_MMU_write08<ARMCPU_ARM9>(0x04000300, 0);
2407
-			_MMU_write08<ARMCPU_ARM7>(0x04000300, 0);
1086
+		// set REG_POSTFLG to the value indicating pre-firmware status
1087
+		MMU.ARM9_REG[0x300] = 0;
1088
+		MMU.ARM7_REG[0x300] = 0;
2408 1089
 	}
2409 1090
 	else
2410 1091
 	{
2411
-		src = header->ARM9src;
2412
-		dst = header->ARM9cpy;
1092
+		// fake firmware boot-up process
2413 1093
 
2414
-		for(uint32_t i = 0; i < (header->ARM9binSize>>2); ++i)
1094
+		// copy the arm9 program to the address specified by rom header
1095
+		uint32_t src = header->ARM9src;
1096
+		uint32_t dst = header->ARM9cpy;
1097
+		for (uint32_t i = 0; i < (header->ARM9binSize >> 2); ++i)
2415 1098
 		{
2416 1099
 			_MMU_write32<ARMCPU_ARM9>(dst, T1ReadLong(MMU.CART_ROM, src));
2417 1100
 			dst += 4;
2418 1101
 			src += 4;
2419 1102
 		}
2420 1103
 
1104
+		// copy the arm7 program to the address specified by rom header
2421 1105
 		src = header->ARM7src;
2422 1106
 		dst = header->ARM7cpy;
2423 1107
 
2424
-		for(uint32_t i = 0; i < (header->ARM7binSize>>2); ++i)
1108
+		for (uint32_t i = 0; i < (header->ARM7binSize >> 2); ++i)
2425 1109
 		{
2426 1110
 			_MMU_write32<ARMCPU_ARM7>(dst, T1ReadLong(MMU.CART_ROM, src));
2427 1111
 			dst += 4;
2428 1112
 			src += 4;
2429 1113
 		}
2430 1114
 
1115
+		// set the cpus to an initial state with their respective programs entrypoints
2431 1116
 		armcpu_init(&NDS_ARM7, header->ARM7exe);
2432 1117
 		armcpu_init(&NDS_ARM9, header->ARM9exe);
2433 1118
 
2434
-		_MMU_write08<ARMCPU_ARM9>(REG_POSTFLG, 1);
2435
-		_MMU_write08<ARMCPU_ARM7>(REG_POSTFLG, 1);
1119
+		// set REG_POSTFLG to the value indicating post-firmware status
1120
+		MMU.ARM9_REG[0x300] = 1;
1121
+		MMU.ARM7_REG[0x300] = 1;
2436 1122
 	}
2437
-	//bitbox 4k demo is so stripped down it relies on default stack values
2438
-	//otherwise the arm7 will crash before making a sound
2439
-	//(these according to gbatek softreset bios docs)
1123
+
1124
+	// only ARM9 have co-processor
1125
+	reconstruct(&cp15);
1126
+	cp15.reset(&NDS_ARM9);
1127
+
1128
+	// bitbox 4k demo is so stripped down it relies on default stack values
1129
+	// otherwise the arm7 will crash before making a sound
1130
+	// (these according to gbatek softreset bios docs)
2440 1131
 	NDS_ARM7.R13_svc = 0x0380FFDC;
2441 1132
 	NDS_ARM7.R13_irq = 0x0380FFB0;
2442 1133
 	NDS_ARM7.R13_usr = 0x0380FF00;
2443 1134
 	NDS_ARM7.R[13] = NDS_ARM7.R13_usr;
2444
-	//and let's set these for the arm9 while we're at it, though we have no proof
1135
+	// and let's set these for the arm9 while we're at it, though we have no proof
2445 1136
 	NDS_ARM9.R13_svc = 0x00803FC0;
2446 1137
 	NDS_ARM9.R13_irq = 0x00803FA0;
2447 1138
 	NDS_ARM9.R13_usr = 0x00803EC0;
2448
-	NDS_ARM9.R13_abt = NDS_ARM9.R13_usr; //?????
2449
-	//I think it is wrong to take gbatek's "SYS" and put it in USR--maybe USR doesnt matter.
2450
-	//i think SYS is all the misc modes. please verify by setting nonsensical stack values for USR here
1139
+	NDS_ARM9.R13_abt = NDS_ARM9.R13_usr; // ?????
1140
+	// I think it is wrong to take gbatek's "SYS" and put it in USR--maybe USR doesnt matter.
1141
+	// i think SYS is all the misc modes. please verify by setting nonsensical stack values for USR here
2451 1142
 	NDS_ARM9.R[13] = NDS_ARM9.R13_usr;
2452
-	//n.b.: im not sure about all these, I dont know enough about arm9 svc/irq/etc modes
2453
-	//and how theyre named in desmume to match them up correctly. i just guessed.
1143
+	// n.b.: im not sure about all these, I dont know enough about arm9 svc/irq/etc modes
1144
+	// and how theyre named in desmume to match them up correctly. i just guessed.
2454 1145
 
2455
-	//nds.wifiCycle = 0;
2456
-	memset(nds.timerCycle, 0, sizeof(uint64_t) * 2 * 4);
1146
+	memset(nds.timerCycle, 0, sizeof(uint64_t) * 8);
2457 1147
 	nds.old = 0;
2458
-	//nds.touchX = nds.touchY = 0;
2459
-	//nds.isTouch = 0;
2460
-	//nds.debugConsole = CommonSettings.DebugConsole;
2461
-	//nds.ensataEmulation = CommonSettings.EnsataEmulation;
2462
-	//nds.ensataHandshake = ENSATA_HANDSHAKE_none;
2463
-	//nds.ensataIpcSyncCounter = 0;
2464
-	SetupMMU(/*nds.Is_DebugConsole()*/false,nds.Is_DSI());
1148
+	SetupMMU(false, nds.Is_DSI());
2465 1149
 
2466 1150
 	_MMU_write16<ARMCPU_ARM9>(REG_KEYINPUT, 0x3FF);
2467 1151
 	_MMU_write16<ARMCPU_ARM7>(REG_KEYINPUT, 0x3FF);
2468 1152
 	_MMU_write08<ARMCPU_ARM7>(REG_EXTKEYIN, 0x43);
2469 1153
 
2470
-	//LidClosed = false;
2471
-	//countLid = 0;
2472
-
2473
-	//resetUserInput();
2474
-
2475
-	//Setup a copy of the firmware user settings in memory.
2476
-	//(this is what the DS firmware would do).
1154
+	// Setup a copy of the firmware user settings in memory.
1155
+	// (this is what the DS firmware would do).
2477 1156
 	{
2478 1157
 		uint8_t temp_buffer[NDS_FW_USER_SETTINGS_MEM_BYTE_COUNT];
2479
-		int fw_index;
2480 1158
 
2481
-		if ( copy_firmware_user_data( temp_buffer, &MMU.fw.data[0])) {
2482
-			for ( fw_index = 0; fw_index < NDS_FW_USER_SETTINGS_MEM_BYTE_COUNT; fw_index++)
1159
+		if (copy_firmware_user_data(temp_buffer, &MMU.fw.data[0]))
1160
+			for (int fw_index = 0; fw_index < NDS_FW_USER_SETTINGS_MEM_BYTE_COUNT; ++fw_index)
2483 1161
 				_MMU_write08<ARMCPU_ARM9>(0x027FFC80 + fw_index, temp_buffer[fw_index]);
2484
-		}
2485 1162
 	}
2486 1163
 
2487 1164
 	// Copy the whole header to Main RAM 0x27FFE00 on startup. (http://nocash.emubase.de/gbatek.htm#dscartridgeheader)
2488
-	//once upon a time this copied 0x90 more. this was thought to be wrong, and changed.
2489
-	if(nds.Is_DSI())
1165
+	// once upon a time this copied 0x90 more. this was thought to be wrong, and changed.
1166
+	if (nds.Is_DSI())
2490 1167
 	{
2491
-		//dsi needs this copied later in memory. there are probably a number of things that  get copied to a later location in memory.. thats where the NDS consoles tend to stash stuff.
2492
-		for (int i = 0; i < ((0x170)/4); i++)
2493
-			_MMU_write32<ARMCPU_ARM9>(0x02FFFE00+i*4, LE_TO_LOCAL_32(((uint32_t*)MMU.CART_ROM)[i]));
1168
+		// dsi needs this copied later in memory. there are probably a number of things that  get copied to a later location in memory.. thats where the NDS consoles tend to stash stuff.
1169
+		for (int i = 0; i < 92; ++i)
1170
+			_MMU_write32<ARMCPU_ARM9>(0x02FFFE00 + i * 4, LE_TO_LOCAL_32(reinterpret_cast<uint32_t *>(MMU.CART_ROM)[i]));
2494 1171
 	}
2495 1172
 	else
2496 1173
 	{
2497
-		for (int i = 0; i < ((0x170)/4); i++)
2498
-			_MMU_write32<ARMCPU_ARM9>(0x027FFE00+i*4, LE_TO_LOCAL_32(((uint32_t*)MMU.CART_ROM)[i]));
1174
+		for (int i = 0; i < 92; ++i)
1175
+			_MMU_write32<ARMCPU_ARM9>(0x027FFE00 + i * 4, LE_TO_LOCAL_32(reinterpret_cast<uint32_t *>(MMU.CART_ROM)[i]));
2499 1176
 	}
2500 1177
 
2501 1178
 	// Write the header checksum to memory (the firmware needs it to see the cart)
2502 1179
 	_MMU_write16<ARMCPU_ARM9>(0x027FF808, T1ReadWord(MMU.CART_ROM, 0x15E));
2503 1180
 
2504
-	//--------------------------------
2505
-	//setup the homebrew argv
2506
-	//this is useful for nitrofs apps which are emulating themselves via cflash
2507
-	//struct __argv {
2508
-	//	int argvMagic;		//!< argv magic number, set to 0x5f617267 ('_arg') if valid
2509
-	//	char *commandLine;	//!< base address of command line, set of null terminated strings
2510
-	//	int length;			//!< total length of command line
2511
-	//	int argc;			//!< internal use, number of arguments
2512
-	//	char **argv;		//!< internal use, argv pointer
2513
-	//};
2514
-	std::string rompath = "fat:/" + path.RomName;
2515
-	const uint32_t kCommandline = 0x027E0000;
2516
-	//const uint32_t kCommandline = 0x027FFF84;
2517
-
2518
-	//
2519
-	_MMU_write32<ARMCPU_ARM9>(0x02FFFE70, 0x5f617267);
2520
-	_MMU_write32<ARMCPU_ARM9>(0x02FFFE74, kCommandline); //(commandline starts here)
2521
-	_MMU_write32<ARMCPU_ARM9>(0x02FFFE78, rompath.size()+1);
2522
-	//0x027FFF7C (argc)
2523
-	//0x027FFF80 (argv)
2524
-	for(size_t i=0;i<rompath.size();i++)
2525
-		_MMU_write08<ARMCPU_ARM9>(kCommandline+i, rompath[i]);
2526
-	_MMU_write08<ARMCPU_ARM9>(kCommandline+rompath.size(), 0);
2527
-	//--------------------------------
2528
-
2529
-	if ((firmware->patched) && (CommonSettings.UseExtBIOS == true) && (CommonSettings.BootFromFirmware == true) && (fw_success == true))
1181
+	if (firmware->patched && CommonSettings.UseExtBIOS && CommonSettings.BootFromFirmware && fw_success)
2530 1182
 	{
2531 1183
 		// HACK! for flashme
2532 1184
 		_MMU_write32<ARMCPU_ARM9>(0x27FFE24, firmware->ARM9bootAddr);
... ...
@@ -2534,473 +1186,14 @@ void NDS_Reset()
2534 1186
 	}
2535 1187
 
2536 1188
 	// make system think it's booted from card -- EXTREMELY IMPORTANT!!! Thanks to cReDiAr
2537
-	_MMU_write08<ARMCPU_ARM9>(0x02FFFC40,0x1);
2538
-	_MMU_write08<ARMCPU_ARM7>(0x02FFFC40,0x1);
2539
-
2540
-	// Save touchscreen calibration info in a structure
2541
-	// so we can easily access it at any time
2542
-	//TSCal.adc.x1 = _MMU_read16<ARMCPU_ARM7>(0x027FFC80 + 0x58);
2543
-	//TSCal.adc.y1 = _MMU_read16<ARMCPU_ARM7>(0x027FFC80 + 0x5A);
2544
-	//TSCal.scr.x1 = _MMU_read08<ARMCPU_ARM7>(0x027FFC80 + 0x5C);
2545
-	//TSCal.scr.y1 = _MMU_read08<ARMCPU_ARM7>(0x027FFC80 + 0x5D);
2546
-	//TSCal.adc.x2 = _MMU_read16<ARMCPU_ARM7>(0x027FFC80 + 0x5E);
2547
-	//TSCal.adc.y2 = _MMU_read16<ARMCPU_ARM7>(0x027FFC80 + 0x60);
2548
-	//TSCal.scr.x2 = _MMU_read08<ARMCPU_ARM7>(0x027FFC80 + 0x62);
2549
-	//TSCal.scr.y2 = _MMU_read08<ARMCPU_ARM7>(0x027FFC80 + 0x63);
2550
-
2551
-	//TSCal.adc.width = (TSCal.adc.x2 - TSCal.adc.x1);
2552
-	//TSCal.adc.height = (TSCal.adc.y2 - TSCal.adc.y1);
2553
-	//TSCal.scr.width = (TSCal.scr.x2 - TSCal.scr.x1);
2554
-	//TSCal.scr.height = (TSCal.scr.y2 - TSCal.scr.y1);
2555
-
2556
-	//MainScreen.offset = 0;
2557
-	//SubScreen.offset = 192;
2558
-
2559
-	//_MMU_write32[ARMCPU_ARM9](0x02007FFC, 0xE92D4030);
2560
-
2561
-	delete header;
2562
-
2563
-	//Screen_Reset();
2564
-	//gfx3d_reset();
2565
-	//gpu3D->NDS_3D_Reset();
2566
-	//slot1Reset();
2567
-
2568
-	//WIFI_Reset();
2569
-
2570
-	//memcpy(FW_Mac, (MMU.fw.data + 0x36), 6);
1189
+	_MMU_write08<ARMCPU_ARM9>(0x02FFFC40, 0x1);
1190
+	_MMU_write08<ARMCPU_ARM7>(0x02FFFC40, 0x1);
2571 1191
 
2572 1192
 	initSchedule();
2573 1193
 
2574 1194
 	SPU_ReInit();
2575 1195
 }
2576 1196
 
2577
-/*static std::string MakeInputDisplayString(uint16_t pad, const std::string* Buttons, int count) {
2578
-    std::string s;
2579
-    for (int x = 0; x < count; x++) {
2580
-        if (pad & (1 << x))
2581
-            s.append(Buttons[x].size(), ' ');
2582
-        else
2583
-            s += Buttons[x];
2584
-    }
2585
-    return s;
2586
-}*/
2587
-
2588
-/*static std::string MakeInputDisplayString(uint16_t pad, uint16_t padExt) {
2589
-    const std::string Buttons[] = {"A", "B", "Sl", "St", "R", "L", "U", "D", "Rs", "Ls"};
2590
-    const std::string Ext[] = {"X", "Y"};
2591
-
2592
-    std::string s = MakeInputDisplayString(pad, Ext, ARRAY_SIZE(Ext));
2593
-    s += MakeInputDisplayString(padExt, Buttons, ARRAY_SIZE(Buttons));
2594
-
2595
-    return s;
2596
-}*/
2597
-
2598
-
2599
-//buttonstruct<bool> Turbo;
2600
-buttonstruct<int> TurboTime;
2601
-//buttonstruct<bool> AutoHold;
2602
-
2603
-/*void ClearAutoHold() {
2604
-
2605
-	for (uint32_t i=0; i < ARRAY_SIZE(AutoHold.array); i++) {
2606
-		AutoHold.array[i]=false;
2607
-	}
2608
-}*/
2609
-
2610
-
2611
-/*inline uint16_t NDS_getADCTouchPosX(uint16_t scrX)
2612
-{
2613
-	// this is a little iffy,
2614
-	// we're basically adjusting the ADC results to
2615
-	// compensate for how they will be interpreted.
2616
-	// the actual system doesn't do this transformation.
2617
-	int rv = (scrX - TSCal.scr.x1 + 1) * TSCal.adc.width / TSCal.scr.width + TSCal.adc.x1;
2618
-	rv = min(0xFFF, max(0, rv));
2619
-	return (uint16_t)rv;
2620
-}*/
2621
-/*inline uint16_t NDS_getADCTouchPosY(uint16_t scrY)
2622
-{
2623
-	int rv = (scrY - TSCal.scr.y1 + 1) * TSCal.adc.height / TSCal.scr.height + TSCal.adc.y1;
2624
-	rv = min(0xFFF, max(0, rv));
2625
-	return (uint16_t)rv;
2626
-}*/
2627
-
2628
-//static UserInput rawUserInput = {}; // requested input, generally what the user is physically pressing
2629
-static UserInput intermediateUserInput; // intermediate buffer for modifications (seperated from finalUserInput for safety reasons)
2630
-static UserInput finalUserInput; // what gets sent to the game and possibly recorded
2631
-bool validToProcessInput = false;
2632
-
2633
-/*const UserInput& NDS_getRawUserInput()
2634
-{
2635
-	return rawUserInput;
2636
-}*/
2637
-/*UserInput& NDS_getProcessingUserInput()
2638
-{
2639
-	assert(validToProcessInput);
2640
-	return intermediateUserInput;
2641
-}*/
2642
-/*bool NDS_isProcessingUserInput()
2643
-{
2644
-	return validToProcessInput;
2645
-}*/
2646
-/*const UserInput& NDS_getFinalUserInput()
2647
-{
2648
-	return finalUserInput;
2649
-}*/
2650
-
2651
-
2652
-/*static void saveUserInput(EMUFILE* os, UserInput& input)
2653
-{
2654
-	os->fwrite((const char*)input.buttons.array, 14);
2655
-	writebool(input.touch.isTouch, os);
2656
-	write16le(input.touch.touchX, os);
2657
-	write16le(input.touch.touchY, os);
2658
-	write32le(input.mic.micButtonPressed, os);
2659
-}*/
2660
-static bool loadUserInput(EMUFILE* is, UserInput& input, int)
2661
-{
2662
-	is->fread((char*)input.buttons.array, 14);
2663
-	readbool(&input.touch.isTouch, is);
2664
-	read16le(&input.touch.touchX, is);
2665
-	read16le(&input.touch.touchY, is);
2666
-	read32le(&input.mic.micButtonPressed, is);
2667
-	return true;
2668
-}
2669
-/*static void resetUserInput(UserInput& input)
2670
-{
2671
-	memset(&input, 0, sizeof(UserInput));
2672
-}*/
2673
-// (userinput is kind of a misnomer, e.g. finalUserInput has to mirror nds.pad, nds.touchX, etc.)
2674
-/*static void saveUserInput(EMUFILE* os)
2675
-{
2676
-	saveUserInput(os, finalUserInput);
2677
-	saveUserInput(os, intermediateUserInput); // saved in case a savestate is made during input processing (which Lua could do if nothing else)
2678
-	writebool(validToProcessInput, os);
2679
-	for(int i = 0; i < 14; i++)
2680
-		write32le(TurboTime.array[i], os); // saved to make autofire more tolerable to use with re-recording
2681
-}*/
2682
-static bool loadUserInput(EMUFILE* is, int version)
2683
-{
2684
-	bool rv = true;
2685
-	rv &= loadUserInput(is, finalUserInput, version);
2686
-	rv &= loadUserInput(is, intermediateUserInput, version);
2687
-	readbool(&validToProcessInput, is);
2688
-	for(int i = 0; i < 14; i++)
2689
-		read32le((uint32_t*)&TurboTime.array[i], is);
2690
-	return rv;
2691
-}
2692
-/*static void resetUserInput()
2693
-{
2694
-	resetUserInput(finalUserInput);
2695
-	resetUserInput(intermediateUserInput);
2696
-}*/
2697
-
2698
-/*static inline void gotInputRequest()
2699
-{
2700
-	// nobody should set the raw input while we're processing the input.
2701
-	// it might not screw anything up but it would be completely useless.
2702
-	assert(!validToProcessInput);
2703
-}*/
2704
-
2705
-/*void NDS_setPad(bool R,bool L,bool D,bool U,bool T,bool S,bool B,bool A,bool Y,bool X,bool W,bool E,bool G, bool F)
2706
-{
2707
-	gotInputRequest();
2708
-	UserButtons& rawButtons = rawUserInput.buttons;
2709
-	rawButtons.R = R;
2710
-	rawButtons.L = L;
2711
-	rawButtons.D = D;
2712
-	rawButtons.U = U;
2713
-	rawButtons.T = T;
2714
-	rawButtons.S = S;
2715
-	rawButtons.B = B;
2716
-	rawButtons.A = A;
2717
-	rawButtons.Y = Y;
2718
-	rawButtons.X = X;
2719
-	rawButtons.W = W;
2720
-	rawButtons.E = E;
2721
-	rawButtons.G = G;
2722
-	rawButtons.F = F;
2723
-}*/
2724
-/*void NDS_setTouchPos(uint16_t x, uint16_t y)
2725
-{
2726
-	gotInputRequest();
2727
-	rawUserInput.touch.touchX = NDS_getADCTouchPosX(x);
2728
-	rawUserInput.touch.touchY = NDS_getADCTouchPosY(y);
2729
-	rawUserInput.touch.isTouch = true;*/
2730
-
2731
-	/*if(movieMode != MOVIEMODE_INACTIVE && movieMode != MOVIEMODE_FINISHED)
2732
-	{
2733
-		// just in case, since the movie only stores 8 bits per touch coord
2734
-		rawUserInput.touch.touchX &= 0x0FF0;
2735
-		rawUserInput.touch.touchY &= 0x0FF0;
2736
-	}*/
2737
-/*
2738
-#ifndef WIN32
2739
-	// FIXME: this code should be deleted from here,
2740
-	// other platforms should call NDS_beginProcessingInput,NDS_endProcessingInput once per frame instead
2741
-	// (see the function called "StepRunLoop_Core" in src/windows/main.cpp),
2742
-	// but I'm leaving this here for now since I can't test those other platforms myself.
2743
-	nds.touchX = rawUserInput.touch.touchX;
2744
-	nds.touchY = rawUserInput.touch.touchY;
2745
-	nds.isTouch = 1;
2746
-	MMU.ARM7_REG[0x136] &= 0xBF;
2747
-#endif
2748
-}*/
2749
-/*void NDS_releaseTouch()
2750
-{
2751
-	gotInputRequest();
2752
-	rawUserInput.touch.touchX = 0;
2753
-	rawUserInput.touch.touchY = 0;
2754
-	rawUserInput.touch.isTouch = false;
2755
-
2756
-#ifndef WIN32
2757
-	// FIXME: this code should be deleted from here,
2758
-	// other platforms should call NDS_beginProcessingInput,NDS_endProcessingInput once per frame instead
2759
-	// (see the function called "StepRunLoop_Core" in src/windows/main.cpp),
2760
-	// but I'm leaving this here for now since I can't test those other platforms myself.
2761
-	nds.touchX = 0;
2762
-	nds.touchY = 0;
2763
-	nds.isTouch = 0;
2764
-	MMU.ARM7_REG[0x136] |= 0x40;
2765
-#endif
2766
-}*/
2767
-/*void NDS_setMic(bool pressed)
2768
-{
2769
-	gotInputRequest();
2770
-	rawUserInput.mic.micButtonPressed = (pressed ? true : false);
2771
-}*/
2772
-
2773
-
2774
-//static void NDS_applyFinalInput();
2775
-
2776
-
2777
-/*void NDS_beginProcessingInput()
2778
-{
2779
-	// start off from the raw input
2780
-	intermediateUserInput = rawUserInput;
2781
-
2782
-	// processing is valid now
2783
-	validToProcessInput = true;
2784
-}*/
2785
-
2786
-/*void NDS_endProcessingInput()
2787
-{
2788
-	// transfer the processed input
2789
-	finalUserInput = intermediateUserInput;
2790
-
2791
-	// processing is invalid now
2792
-	validToProcessInput = false;
2793
-
2794
-	// use the final input for a few things right away
2795
-	NDS_applyFinalInput();
2796
-}*/
2797
-
2798
-
2799
-
2800
-
2801
-
2802
-
2803
-
2804
-
2805
-/*static void NDS_applyFinalInput()
2806
-{
2807
-	const UserInput& input = NDS_getFinalUserInput();
2808
-
2809
-	uint16_t	pad	= (0 |
2810
-		((input.buttons.A ? 0 : 0x80) >> 7) |
2811
-		((input.buttons.B ? 0 : 0x80) >> 6) |
2812
-		((input.buttons.T ? 0 : 0x80) >> 5) |
2813
-		((input.buttons.S ? 0 : 0x80) >> 4) |
2814
-		((input.buttons.R ? 0 : 0x80) >> 3) |
2815
-		((input.buttons.L ? 0 : 0x80) >> 2) |
2816
-		((input.buttons.U ? 0 : 0x80) >> 1) |
2817
-		((input.buttons.D ? 0 : 0x80)     ) |
2818
-		((input.buttons.E ? 0 : 0x80) << 1) |
2819
-		((input.buttons.W ? 0 : 0x80) << 2)) ;
2820
-
2821
-	((uint16_t *)MMU.ARM9_REG)[0x130>>1] = (uint16_t)pad;
2822
-	((uint16_t *)MMU.ARM7_REG)[0x130>>1] = (uint16_t)pad;
2823
-
2824
-	uint16_t k_cnt = ((uint16_t *)MMU.ARM9_REG)[0x132>>1];
2825
-	if ( k_cnt & (1<<14))
2826
-	{
2827
-		//INFO("ARM9: KeyPad IRQ (pad 0x%04X, cnt 0x%04X (condition %s))\n", pad, k_cnt, k_cnt&(1<<15)?"AND":"OR");
2828
-		uint16_t k_cnt_selected = (k_cnt & 0x3F);
2829
-		if (k_cnt&(1<<15))	// AND
2830
-		{
2831
-			if ((~pad & k_cnt_selected) == k_cnt_selected) NDS_makeIrq(ARMCPU_ARM9,IRQ_BIT_KEYPAD);
2832
-		}
2833
-		else				// OR
2834
-		{
2835
-			if (~pad & k_cnt_selected) NDS_makeIrq(ARMCPU_ARM9,IRQ_BIT_KEYPAD);
2836
-		}
2837
-	}
2838
-
2839
-	k_cnt = ((uint16_t *)MMU.ARM7_REG)[0x132>>1];
2840
-	if ( k_cnt & (1<<14))
2841
-	{
2842
-		//INFO("ARM7: KeyPad IRQ (pad 0x%04X, cnt 0x%04X (condition %s))\n", pad, k_cnt, k_cnt&(1<<15)?"AND":"OR");
2843
-		uint16_t k_cnt_selected = (k_cnt & 0x3F);
2844
-		if (k_cnt&(1<<15))	// AND
2845
-		{
2846
-			if ((~pad & k_cnt_selected) == k_cnt_selected) NDS_makeIrq(ARMCPU_ARM7,IRQ_BIT_KEYPAD);
2847
-		}
2848
-		else				// OR
2849
-		{
2850
-			if (~pad & k_cnt_selected) NDS_makeIrq(ARMCPU_ARM7,IRQ_BIT_KEYPAD);
2851
-		}
2852
-	}
2853
-
2854
-
2855
-	if(input.touch.isTouch)
2856
-	{
2857
-		nds.touchX = input.touch.touchX;
2858
-		nds.touchY = input.touch.touchY;
2859
-		nds.isTouch = 1;
2860
-
2861
-		MMU.ARM7_REG[0x136] &= 0xBF;
2862
-	}
2863
-	else
2864
-	{
2865
-
2866
-		nds.touchX = 0;
2867
-		nds.touchY = 0;
2868
-		nds.isTouch = 0;
2869
-
2870
-		MMU.ARM7_REG[0x136] |= 0x40;
2871
-	}
2872
-
2873
-
2874
-	if (input.buttons.F && !countLid)
2875
-	{
2876
-		LidClosed = (!LidClosed) & 0x01;
2877
-		if (!LidClosed)
2878
-		{
2879
-		//	SPU_Pause(false);
2880
-			NDS_makeIrq(ARMCPU_ARM7,IRQ_BIT_ARM7_FOLD);
2881
-
2882
-		}
2883
-		//else
2884
-			//SPU_Pause(true);
2885
-
2886
-		countLid = 30;
2887
-	}
2888
-	else
2889
-	{
2890
-		if (countLid > 0)
2891
-			countLid--;
2892
-	}
2893
-
2894
-	uint16_t padExt = (((uint16_t *)MMU.ARM7_REG)[0x136>>1] & 0x0070) |
2895
-		((input.buttons.X ? 0 : 0x80) >> 7) |
2896
-		((input.buttons.Y ? 0 : 0x80) >> 6) |
2897
-		((input.buttons.G ? 0 : 0x80) >> 4) |
2898
-		((LidClosed) << 7) |
2899
-		0x0034;
2900
-
2901
-	((uint16_t *)MMU.ARM7_REG)[0x136>>1] = (uint16_t)padExt;
2902
-
2903
-	InputDisplayString=MakeInputDisplayString(padExt, pad);
2904
-
2905
-	//put into the format we want for the movie system
2906
-	//fRLDUTSBAYXWEg
2907
-	//we don't really need nds.pad anymore, but removing it would be a pain
2908
-
2909
- 	nds.pad =
2910
-		((input.buttons.R ? 1 : 0) << 12)|
2911
-		((input.buttons.L ? 1 : 0) << 11)|
2912
-		((input.buttons.D ? 1 : 0) << 10)|
2913
-		((input.buttons.U ? 1 : 0) << 9)|
2914
-		((input.buttons.T ? 1 : 0) << 8)|
2915
-		((input.buttons.S ? 1 : 0) << 7)|
2916
-		((input.buttons.B ? 1 : 0) << 6)|
2917
-		((input.buttons.A ? 1 : 0) << 5)|
2918
-		((input.buttons.Y ? 1 : 0) << 4)|
2919
-		((input.buttons.X ? 1 : 0) << 3)|
2920
-		((input.buttons.W ? 1 : 0) << 2)|
2921
-		((input.buttons.E ? 1 : 0) << 1);
2922
-
2923
-	// TODO: low power IRQ
2924
-}*/
2925
-
2926
-
2927
-/*void NDS_suspendProcessingInput(bool suspend)
2928
-{
2929
-	static int suspendCount = 0;
2930
-	if(suspend)
2931
-	{
2932
-		// enter non-processing block
2933
-		assert(validToProcessInput);
2934
-		validToProcessInput = false;
2935
-		suspendCount++;
2936
-	}
2937
-	else if(suspendCount)
2938
-	{
2939
-		// exit non-processing block
2940
-		validToProcessInput = true;
2941
-		suspendCount--;
2942
-	}
2943
-	else
2944
-	{
2945
-		// unwound past first time -> not processing
2946
-		validToProcessInput = false;
2947
-	}
2948
-}*/
2949
-
2950
-
2951
-/*void emu_halt() {
2952
-	//printf("halting emu: ARM9 PC=%08X/%08X, ARM7 PC=%08X/%08X\n", NDS_ARM9.R[15], NDS_ARM9.instruct_adr, NDS_ARM7.R[15], NDS_ARM7.instruct_adr);
2953
-	execute = false;
2954
-#ifdef LOG_ARM9
2955
-	if (fp_dis9)
2956
-	{
2957
-		char buf[256] = { 0 };
2958
-		sprintf(buf, "halting emu: ARM9 PC=%08X/%08X\n", NDS_ARM9.R[15], NDS_ARM9.instruct_adr);
2959
-		fwrite(buf, 1, strlen(buf), fp_dis9);
2960
-		INFO("ARM9 halted\n");
2961
-	}
2962
-#endif
2963
-
2964
-#ifdef LOG_ARM7
2965
-	if (fp_dis7)
2966
-	{
2967
-		char buf[256] = { 0 };
2968
-		sprintf(buf, "halting emu: ARM7 PC=%08X/%08X\n", NDS_ARM7.R[15], NDS_ARM7.instruct_adr);
2969
-		fwrite(buf, 1, strlen(buf), fp_dis7);
2970
-		INFO("ARM7 halted\n");
2971
-	}
2972
-#endif
2973
-}*/
2974
-
2975
-//returns true if exmemcnt specifies satisfactory parameters for the device, which calls this function
2976
-/*bool ValidateSlot2Access(uint32_t procnum, uint32_t demandSRAMSpeed, uint32_t demand1stROMSpeed, uint32_t demand2ndROMSpeed, int clockbits)
2977
-{
2978
-	static const uint32_t _sramSpeeds[] = {10,8,6,18};
2979
-	static const uint32_t _rom1Speeds[] = {10,8,6,18};
2980
-	static const uint32_t _rom2Speeds[] = {6,4};
2981
-	uint16_t exmemcnt = T1ReadWord(MMU.MMU_MEM[procnum][0x40], 0x204);
2982
-	uint16_t exmemcnt9 = T1ReadWord(MMU.MMU_MEM[ARMCPU_ARM9][0x40], 0x204);
2983
-	uint32_t arm7access = (exmemcnt9 & EXMEMCNT_MASK_SLOT2_ARM7);
2984
-	uint32_t sramSpeed = _sramSpeeds[(exmemcnt & EXMEMCNT_MASK_SLOT2_SRAM_TIME)];
2985
-	uint32_t romSpeed1 = _rom1Speeds[(exmemcnt & EXMEMCNT_MASK_SLOT2_ROM_1ST_TIME)>>2];
2986
-	uint32_t romSpeed2 = _rom2Speeds[(exmemcnt & EXMEMCNT_MASK_SLOT2_ROM_2ND_TIME)>>4];
2987
-	uint32_t curclockbits = (exmemcnt & EXMEMCNT_MASK_SLOT2_CLOCKRATE)>>5;
2988
-
2989
-	if(procnum==ARMCPU_ARM9 && arm7access) return false;
2990
-	if(procnum==ARMCPU_ARM7 && !arm7access) return false;
2991
-
2992
-	//what we're interested in here is whether the rom/ram are too low -> too fast. then accesses won't have enough time to work.
2993
-	//i'm not sure if this gives us enough flexibility, but it is good enough for now.
2994
-	//should make the arguments to this function bitmasks later if we need better.
2995
-	if(sramSpeed < demandSRAMSpeed) return false;
2996
-	if(romSpeed1 < demand1stROMSpeed) return false;
2997
-	if(romSpeed2 < demand2ndROMSpeed) return false;
2998
-
2999
-	if(clockbits != -1 && clockbits != (int)curclockbits) return false;
3000
-
3001
-	return true;
3002
-}*/
3003
-
3004
-//these templates needed to be instantiated manually
1197
+// these templates needed to be instantiated manually
3005 1198
 template void NDS_exec<false>(int32_t nb);
3006 1199
 template void NDS_exec<true>(int32_t nb);
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,3006 @@
1
+/*
2
+	Copyright (C) 2006 yopyop
3
+	Copyright (C) 2008-2012 DeSmuME team
4
+
5
+	This file is free software: you can redistribute it and/or modify
6
+	it under the terms of the GNU General Public License as published by
7
+	the Free Software Foundation, either version 2 of the License, or
8
+	(at your option) any later version.
9
+
10
+	This file is distributed in the hope that it will be useful,
11
+	but WITHOUT ANY WARRANTY; without even the implied warranty of
12
+	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13
+	GNU General Public License for more details.
14
+
15
+	You should have received a copy of the GNU General Public License
16
+	along with the this software.  If not, see <http://www.gnu.org/licenses/>.
17
+*/
18
+
19
+#include <algorithm>
20
+#include <cstring>
21
+#include <cstdlib>
22
+#include <cmath>
23
+#include <zlib.h>
24
+
25
+#include "common.h"
26
+#include "NDSSystem.h"
27
+//#include "render3D.h"
28
+#include "MMU.h"
29
+//#include "ROMReader.h"
30
+//#include "gfx3d.h"
31
+//#include "utils/decrypt/decrypt.h"
32
+//#include "utils/decrypt/crc.h"
33
+#include "bios.h"
34
+//#include "debug.h"
35
+//#include "cheatSystem.h"
36
+//#include "movie.h"
37
+//#include "Disassembler.h"
38
+#include "readwrite.h"
39
+//#include "debug.h"
40
+#include "firmware.h"
41
+#include "version.h"
42
+#include "slot1.h"
43
+
44
+#include "path.h"
45
+
46
+//#define LOG_ARM9
47
+//#define LOG_ARM7
48
+//bool dolog = false;
49
+//#define LOG_TO_FILE
50
+//#define LOG_TO_FILE_REGS
51
+
52
+//===============================================================
53
+//FILE *fp_dis7 = NULL;
54
+//FILE *fp_dis9 = NULL;
55
+
56
+PathInfo path;
57
+
58
+TCommonSettings CommonSettings;
59
+//static BaseDriver _stub_driver;
60
+//BaseDriver* driver = &_stub_driver;
61
+//std::string InputDisplayString;
62
+
63
+//static bool LidClosed = false;
64
+//static uint8_t	countLid = 0;
65
+
66
+GameInfo gameInfo;
67
+NDSSystem nds;
68
+CFIRMWARE	*firmware = NULL;
69
+//ADVANsCEne     advsc;
70
+
71
+bool singleStep;
72
+//bool nds_debug_continuing[2];
73
+//int lagframecounter;
74
+//int LagFrameFlag;
75
+//int lastLag;
76
+//int TotalLagFrames;
77
+
78
+//TSCalInfo TSCal;
79
+
80
+namespace DLDI
81
+{
82
+	bool tryPatch(void* data, size_t size);
83
+}
84
+
85
+/*void Desmume_InitOnce()
86
+{
87
+	static bool initOnce = false;
88
+	if(initOnce) return;
89
+	initOnce = true;*/
90
+
91
+/*#ifdef HAVE_LIBAGG
92
+	extern void Agg_init(); //no need to include just for this
93
+	Agg_init();
94
+#endif*/
95
+//}
96
+
97
+#ifdef GDB_STUB
98
+int NDS_Init( struct armcpu_memory_iface *arm9_mem_if,
99
+struct armcpu_ctrl_iface **arm9_ctrl_iface,
100
+struct armcpu_memory_iface *arm7_mem_if,
101
+struct armcpu_ctrl_iface **arm7_ctrl_iface) {
102
+#else
103
+int NDS_Init() {
104
+#endif
105
+	//nds.idleFrameCounter = 0;
106
+	//memset(nds.runCycleCollector,0,sizeof(nds.runCycleCollector));
107
+	MMU_Init();
108
+	nds.VCount = 0;
109
+
110
+	//got to print this somewhere..
111
+	printf("%s\n", EMU_DESMUME_NAME_AND_VERSION());
112
+
113
+	/*if (Screen_Init(GFXCORE_DUMMY) != 0)
114
+		return -1;*/
115
+
116
+	//gfx3d_init();
117
+
118
+#ifdef GDB_STUB
119
+	armcpu_new(&NDS_ARM7,1, arm7_mem_if, arm7_ctrl_iface);
120
+	armcpu_new(&NDS_ARM9,0, arm9_mem_if, arm9_ctrl_iface);
121
+#else
122
+	armcpu_new(&NDS_ARM7,1);
123
+	armcpu_new(&NDS_ARM9,0);
124
+#endif
125
+
126
+	if (SPU_Init(SNDCORE_DUMMY, 740) != 0)
127
+		return -1;
128
+
129
+	//WIFI_Init() ;
130
+
131
+	// Init calibration info
132
+	//TSCal.adc.x1 = 0x0200;
133
+	//TSCal.adc.y1 = 0x0200;
134
+	//TSCal.scr.x1 = 0x20 + 1; // calibration screen coords are 1-based,
135
+	//TSCal.scr.y1 = 0x20 + 1; // either that or NDS_getADCTouchPosX/Y are wrong.
136
+	//TSCal.adc.x2 = 0x0E00;
137
+	//TSCal.adc.y2 = 0x0800;
138
+	//TSCal.scr.x2 = 0xE0 + 1;
139
+	//TSCal.scr.y2 = 0x80 + 1;
140
+	//TSCal.adc.width = (TSCal.adc.x2 - TSCal.adc.x1);
141
+	//TSCal.adc.height = (TSCal.adc.y2 - TSCal.adc.y1);
142
+	//TSCal.scr.width = (TSCal.scr.x2 - TSCal.scr.x1);
143
+	//TSCal.scr.height = (TSCal.scr.y2 - TSCal.scr.y1);
144
+
145
+	//cheats = new CHEATS();
146
+	//cheatSearch = new CHEATSEARCH();
147
+
148
+	return 0;
149
+}
150
+
151
+void NDS_DeInit() {
152
+	if(MMU.CART_ROM != MMU.UNUSED_RAM)
153
+		NDS_FreeROM();
154
+
155
+	SPU_DeInit();
156
+	//Screen_DeInit();
157
+	MMU_DeInit();
158
+	//gpu3D->NDS_3D_Close();
159
+
160
+	//WIFI_DeInit();
161
+	/*if (cheats)
162
+		delete cheats;*/
163
+	/*if (cheatSearch)
164
+		delete cheatSearch;*/
165
+
166
+#ifdef LOG_ARM7
167
+	if (fp_dis7 != NULL)
168
+	{
169
+		fclose(fp_dis7);
170
+		fp_dis7 = NULL;
171
+	}
172
+#endif
173
+
174
+#ifdef LOG_ARM9
175
+	if (fp_dis9 != NULL)
176
+	{
177
+		fclose(fp_dis9);
178
+		fp_dis9 = NULL;
179
+	}
180
+#endif
181
+}
182
+
183
+bool NDS_SetROM(uint8_t * rom, uint32_t mask)
184
+{
185
+	MMU_setRom(rom, mask);
186
+
187
+	return true;
188
+}
189
+
190
+NDS_header * NDS_getROMHeader()
191
+{
192
+	if(MMU.CART_ROM == MMU.UNUSED_RAM) return NULL;
193
+	NDS_header * header = new NDS_header;
194
+
195
+	memcpy(header->gameTile, MMU.CART_ROM, 12);
196
+	memcpy(header->gameCode, MMU.CART_ROM + 12, 4);
197
+	header->makerCode = T1ReadWord(MMU.CART_ROM, 16);
198
+	header->unitCode = MMU.CART_ROM[18];
199
+	header->deviceCode = MMU.CART_ROM[19];
200
+	header->cardSize = MMU.CART_ROM[20];
201
+	memcpy(header->cardInfo, MMU.CART_ROM + 21, 8);
202
+	header->flags = MMU.CART_ROM[29];
203
+	header->romversion = MMU.CART_ROM[30];
204
+	header->ARM9src = T1ReadLong(MMU.CART_ROM, 32);
205
+	header->ARM9exe = T1ReadLong(MMU.CART_ROM, 36);
206
+	header->ARM9cpy = T1ReadLong(MMU.CART_ROM, 40);
207
+	header->ARM9binSize = T1ReadLong(MMU.CART_ROM, 44);
208
+	header->ARM7src = T1ReadLong(MMU.CART_ROM, 48);
209
+	header->ARM7exe = T1ReadLong(MMU.CART_ROM, 52);
210
+	header->ARM7cpy = T1ReadLong(MMU.CART_ROM, 56);
211
+	header->ARM7binSize = T1ReadLong(MMU.CART_ROM, 60);
212
+	header->FNameTblOff = T1ReadLong(MMU.CART_ROM, 64);
213
+	header->FNameTblSize = T1ReadLong(MMU.CART_ROM, 68);
214
+	header->FATOff = T1ReadLong(MMU.CART_ROM, 72);
215
+	header->FATSize = T1ReadLong(MMU.CART_ROM, 76);
216
+	header->ARM9OverlayOff = T1ReadLong(MMU.CART_ROM, 80);
217
+	header->ARM9OverlaySize = T1ReadLong(MMU.CART_ROM, 84);
218
+	header->ARM7OverlayOff = T1ReadLong(MMU.CART_ROM, 88);
219
+	header->ARM7OverlaySize = T1ReadLong(MMU.CART_ROM, 92);
220
+	header->unknown2a = T1ReadLong(MMU.CART_ROM, 96);
221
+	header->unknown2b = T1ReadLong(MMU.CART_ROM, 100);
222
+	header->IconOff = T1ReadLong(MMU.CART_ROM, 104);
223
+	header->CRC16 = T1ReadWord(MMU.CART_ROM, 108);
224
+	header->ROMtimeout = T1ReadWord(MMU.CART_ROM, 110);
225
+	header->ARM9unk = T1ReadLong(MMU.CART_ROM, 112);
226
+	header->ARM7unk = T1ReadLong(MMU.CART_ROM, 116);
227
+	memcpy(header->unknown3c, MMU.CART_ROM + 120, 8);
228
+	header->ROMSize = T1ReadLong(MMU.CART_ROM, 128);
229
+	header->HeaderSize = T1ReadLong(MMU.CART_ROM, 132);
230
+	memcpy(header->unknown5, MMU.CART_ROM + 136, 56);
231
+	memcpy(header->logo, MMU.CART_ROM + 192, 156);
232
+	header->logoCRC16 = T1ReadWord(MMU.CART_ROM, 348);
233
+	header->headerCRC16 = T1ReadWord(MMU.CART_ROM, 350);
234
+	memcpy(header->reserved, MMU.CART_ROM + 352, std::min(160, (int)gameInfo.romsize - 352));
235
+
236
+	return header;
237
+}
238
+
239
+
240
+
241
+
242
+/*void debug()
243
+{
244
+	//if(NDS_ARM9.R[15]==0x020520DC) emu_halt();
245
+	//DSLinux
246
+	//if(NDS_ARM9.CPSR.bits.mode == 0) emu_halt();
247
+	//if((NDS_ARM9.R[15]&0xFFFFF000)==0) emu_halt();
248
+	//if((NDS_ARM9.R[15]==0x0201B4F4)&&(NDS_ARM9.R[1]==0x0)) emu_halt();
249
+	//AOE
250
+	//if((NDS_ARM9.R[15]==0x01FFE194)&&(NDS_ARM9.R[0]==0)) emu_halt();
251
+	//if((NDS_ARM9.R[15]==0x01FFE134)&&(NDS_ARM9.R[0]==0)) emu_halt();
252
+
253
+	//BBMAN
254
+	//if(NDS_ARM9.R[15]==0x02098B4C) emu_halt();
255
+	//if(NDS_ARM9.R[15]==0x02004924) emu_halt();
256
+	//if(NDS_ARM9.R[15]==0x02004890) emu_halt();
257
+
258
+	//if(NDS_ARM9.R[15]==0x0202B800) emu_halt();
259
+	//if(NDS_ARM9.R[15]==0x0202B3DC) emu_halt();
260
+	//if((NDS_ARM9.R[1]==0x9AC29AC1)&&(!fait)) {emu_halt();fait = true;}
261
+	//if(NDS_ARM9.R[1]==0x0400004A) {emu_halt();fait = true;}
262
+	if(NDS_ARM9.R[4]==0x2E33373C) emu_halt();
263
+	if(NDS_ARM9.R[15]==0x02036668) //emu_halt();
264
+	{
265
+	nds.logcount++;
266
+	sprintf(logbuf, "%d %08X", nds.logcount, NDS_ARM9.R[13]);
267
+	log::ajouter(logbuf);
268
+	if(nds.logcount==89) execute=false;
269
+	}
270
+	//if(NDS_ARM9.instruction==0) emu_halt();
271
+	//if((NDS_ARM9.R[15]>>28)) emu_halt();
272
+}*/
273
+
274
+//#define DSGBA_LOADER_SIZE 512
275
+/*enum
276
+{
277
+	ROM_NDS = 0,
278
+	ROM_DSGBA
279
+};*/
280
+
281
+#if 0 /* not used */
282
+//http://www.aggregate.org/MAGIC/#Population%20Count%20(Ones%20Count)
283
+static uint32_t ones32(uint32_t x)
284
+{
285
+	/* 32-bit recursive reduction using SWAR...
286
+	but first step is mapping 2-bit values
287
+	into sum of 2 1-bit values in sneaky way
288
+	*/
289
+	x -= ((x >> 1) & 0x55555555);
290
+	x = (((x >> 2) & 0x33333333) + (x & 0x33333333));
291
+	x = (((x >> 4) + x) & 0x0f0f0f0f);
292
+	x += (x >> 8);
293
+	x += (x >> 16);
294
+	return x & 0x0000003f;
295
+}
296
+#endif
297
+
298
+RomBanner::RomBanner(bool defaultInit)
299
+{
300
+	if(!defaultInit) return;
301
+	version = 1; //Version  (0001h)
302
+	crc16 = 0; //CRC16 across entries 020h..83Fh
303
+	memset(reserved,0,sizeof(reserved));
304
+	memset(bitmap,0,sizeof(bitmap));
305
+	memset(palette,0,sizeof(palette));
306
+	memset(titles,0,sizeof(titles));
307
+	memset(end0xFF,0,sizeof(end0xFF));
308
+}
309
+
310
+/*bool GameInfo::hasRomBanner()
311
+{
312
+	if(header.IconOff + sizeof(RomBanner) > romsize)
313
+		return false;
314
+	else return true;
315
+}*/
316
+
317
+/*const RomBanner& GameInfo::getRomBanner()
318
+{
319
+	//we may not have a valid banner. return a default one
320
+	if(!hasRomBanner())
321
+	{
322
+		static RomBanner defaultBanner(true);
323
+		return defaultBanner;
324
+	}
325
+
326
+	return *(RomBanner*)(romdata+header.IconOff);
327
+}*/
328
+
329
+/*void GameInfo::populate()
330
+{
331
+	const char *regions[] = {	"JPFSEDIRKH",
332
+								"JPN",
333
+								"EUR",
334
+								"FRA",
335
+								"ESP",
336
+								"USA",
337
+								"NOE",
338
+								"ITA",
339
+								"RUS",
340
+								"KOR",
341
+								"HOL",
342
+
343
+	};
344
+
345
+	NDS_header * _header = NDS_getROMHeader();
346
+	header = *_header;
347
+	delete _header;
348
+
349
+	memset(ROMserial, 0, sizeof(ROMserial));
350
+	memset(ROMname, 0, sizeof(ROMname));
351
+
352
+	if (
353
+		//Option 1. - look for this instruction in the game title
354
+		//(did this ever work?)
355
+		//(header->gameTile[0] == 0x2E) &&
356
+		//(header->gameTile[1] == 0x00) &&
357
+		//(header->gameTile[2] == 0x00) &&
358
+		//(header->gameTile[3] == 0xEA)
359
+		//) &&
360
+		//option 2. - look for gamecode #### (default for ndstool)
361
+		//or an invalid gamecode
362
+		(
363
+			((header.gameCode[0] == 0x23) &&
364
+			(header.gameCode[1] == 0x23) &&
365
+			(header.gameCode[2] == 0x23) &&
366
+			(header.gameCode[3] == 0x23)
367
+			) ||
368
+			(header.gameCode[0] == 0x00)
369
+		)
370
+		&&
371
+			header.makerCode == 0x0
372
+		)
373
+	{
374
+		//we can't really make a serial for a homebrew game that hasnt set a game code
375
+		strcpy(ROMserial, "Homebrew");
376
+	}
377
+	else
378
+	{
379
+		strcpy(ROMserial,"NTR-    -");
380
+		memcpy(ROMserial+4, header.gameCode, 4);
381
+
382
+		uint32_t region = (uint32_t)(std::max<int32_t>(strchr(regions[0],header.gameCode[3]) - regions[0] + 1, 0));
383
+		if (region != 0)
384
+			strcat(ROMserial, regions[region]);
385
+		else
386
+			strcat(ROMserial, "Unknown");
387
+	}
388
+
389
+	//rom name is probably set even in homebrew
390
+	memset(ROMname, 0, sizeof(ROMname));
391
+	memcpy(ROMname, header.gameTile, 12);
392
+	trim(ROMname,20);
393
+
394
+		if(header.IconOff < romsize)
395
+		{
396
+			uint8_t num = (T1ReadByte((uint8_t*)romdata, header.IconOff) == 1)?6:7;
397
+			for (int i = 0; i < num; i++)
398
+			{
399
+				wcstombs(ROMfullName[i], (wchar_t *)(romdata+header.IconOff+0x240+(i*0x100)), 0x100);
400
+				trim(ROMfullName[i]);
401
+			}
402
+		}
403
+
404
+	//this may look like a poor heuristic for detecting homebrew, but it is actually pretty good.
405
+	//setting your own game code is stupid, so homebrew should just leave it.
406
+	//however, non-devkitARM-default makefiles may not have set this.
407
+	isHomebrew = !memcmp(header.gameCode,"####",4);
408
+}*/
409
+
410
+/*#ifdef _WINDOWS
411
+
412
+//static std::vector<char> buffer;
413
+//static std::vector<char> v;
414
+
415
+static void loadrom(std::string fname) {
416
+
417
+	FILE* inf = fopen(fname.c_str(),"rb");
418
+	if(!inf) return;
419
+
420
+	fseek(inf,0,SEEK_END);
421
+	int size = ftell(inf);
422
+	fseek(inf,0,SEEK_SET);
423
+
424
+	gameInfo.resize(size);
425
+	fread(gameInfo.romdata,1,size,inf);
426
+	gameInfo.fillGap();
427
+
428
+	fclose(inf);
429
+}
430
+
431
+static int rom_init_path(const char *filename, const char *logicalFilename)
432
+{
433
+	int	type = ROM_NDS;
434
+
435
+	path.init(logicalFilename);
436
+
437
+	if ( path.isdsgba(path.path)) {
438
+		type = ROM_DSGBA;
439
+		loadrom(path.path);
440
+	}
441
+	else if ( !strcasecmp(path.extension().c_str(), "nds")) {
442
+		type = ROM_NDS;
443
+		loadrom(path.path); //n.b. this does nothing if the file can't be found (i.e. if it was an extracted tempfile)...
444
+		//...but since the data was extracted to gameInfo then it is ok
445
+	}
446
+	//ds.gba in archives, it's already been loaded into memory at this point
447
+	else if (path.isdsgba(std::string(logicalFilename))) {
448
+		type = ROM_DSGBA;
449
+	} else {
450
+		//well, try to load it as an nds rom anyway
451
+		type = ROM_NDS;
452
+		loadrom(path.path);
453
+	}
454
+
455
+	if(type == ROM_DSGBA)
456
+	{
457
+		std::vector<char> v(gameInfo.romdata + DSGBA_LOADER_SIZE, gameInfo.romdata + gameInfo.romsize);
458
+		gameInfo.loadData(&v[0],gameInfo.romsize - DSGBA_LOADER_SIZE);
459
+	}
460
+
461
+	//check that size is at least the size of the header
462
+	if (gameInfo.romsize < 352) {
463
+		return -1;
464
+	}
465
+
466
+	return 1;
467
+}
468
+#else
469
+static int rom_init_path(const char *filename, const char *logicalFilename)
470
+{
471
+	int			ret;
472
+	int			type;
473
+	ROMReader_struct	*reader;
474
+	void			*file;
475
+	uint32_t			size;
476
+	char			*noext;
477
+
478
+	noext = strdup(filename);
479
+	reader = ROMReaderInit(&noext);
480
+	free(noext);
481
+
482
+	if (logicalFilename)
483
+		path.init(logicalFilename);
484
+	else
485
+		path.init(filename);
486
+
487
+	if (!strcasecmp(path.extension().c_str(), "zip"))
488
+		type = ROM_NDS;
489
+	else if (!strcasecmp(path.extension().c_str(), "nds"))
490
+		type = ROM_NDS;
491
+	else if (path.isdsgba(path.path))
492
+		type = ROM_DSGBA;
493
+	else
494
+		type = ROM_NDS;
495
+
496
+	file = reader->Init(filename);
497
+	if (!file)
498
+	{
499
+		reader->DeInit(file);
500
+		return -1;
501
+	}
502
+
503
+	size = reader->Size(file);
504
+
505
+	if(type == ROM_DSGBA)
506
+	{
507
+		reader->Seek(file, DSGBA_LOADER_SIZE, SEEK_SET);
508
+		size -= DSGBA_LOADER_SIZE;
509
+	}
510
+
511
+	//check that size is at least the size of the header
512
+	if (size < 352) {
513
+		reader->DeInit(file);
514
+		return -1;
515
+	}
516
+
517
+	// Make sure old ROM is freed first(at least this way we won't be eating
518
+	// up a ton of ram before the old ROM is freed)
519
+	if(MMU.CART_ROM != MMU.UNUSED_RAM)
520
+		NDS_FreeROM();
521
+
522
+	gameInfo.resize(size);
523
+	ret = reader->Read(file, gameInfo.romdata, size);
524
+	gameInfo.fillGap();
525
+	reader->DeInit(file);
526
+
527
+	return ret;
528
+}
529
+#endif*/
530
+
531
+/*int NDS_LoadROM(const char *filename, const char *logicalFilename)
532
+{
533
+	int	ret;
534
+	char	buf[MAX_PATH];
535
+
536
+	if (filename == NULL)
537
+		return -1;
538
+
539
+	ret = rom_init_path(filename, logicalFilename);
540
+	if (ret < 1)
541
+		return ret;
542
+
543
+	//decrypt if necessary..
544
+	//but this is untested and suspected to fail on big endian, so lets not support this on big endian
545
+#ifndef WORDS_BIGENDIAN
546
+	bool okRom = DecryptSecureArea((uint8_t*)gameInfo.romdata,gameInfo.romsize);
547
+
548
+	if(!okRom) {
549
+		printf("Specified file is not a valid rom\n");
550
+		return -1;
551
+	}
552
+#endif
553
+
554
+	if (cheatSearch)
555
+		cheatSearch->close();
556
+	FCEUI_StopMovie();
557
+
558
+	MMU_unsetRom();
559
+	NDS_SetROM((uint8_t*)gameInfo.romdata, gameInfo.mask);
560
+
561
+	gameInfo.populate();
562
+	gameInfo.crc = crc32(0,(uint8_t*)gameInfo.romdata,gameInfo.romsize);
563
+	//INFO("\nROM game code: %c%c%c%c\n", gameInfo.header.gameCode[0], gameInfo.header.gameCode[1], gameInfo.header.gameCode[2], gameInfo.header.gameCode[3]);
564
+	//INFO("ROM crc: %08X\n", gameInfo.crc);
565
+	//INFO("ROM serial: %s\n", gameInfo.ROMserial);
566
+	//INFO("ROM internal name: %s\n", gameInfo.ROMname);
567
+
568
+	memset(buf, 0, MAX_PATH);
569
+	strcpy(buf, path.pathToModule);
570
+	strcat(buf, "desmume.ddb");							// DeSmuME database	:)
571
+	advsc.setDatabase(buf);
572
+	buf[0] = gameInfo.header.gameCode[0];
573
+	buf[1] = gameInfo.header.gameCode[1];
574
+	buf[2] = gameInfo.header.gameCode[2];
575
+	buf[3] = gameInfo.header.gameCode[3];
576
+	buf[4] = 0;
577
+	if (advsc.checkDB(buf))
578
+	{
579
+		u8 sv = advsc.getSaveType();
580
+		printf("ADVANsCEne database:\n");
581
+		printf("\t* ROM save type: ");
582
+		if (sv == 0xFF)
583
+			printf("Unknown");
584
+		else
585
+			if (sv == 0xFE)
586
+				printf("None");
587
+			else
588
+			{
589
+				printf("%s", save_names[sv]);
590
+				if (CommonSettings.autodetectBackupMethod == 1)
591
+					backup_setManualBackupType(sv+1);
592
+			}
593
+		printf("\n\t* ROM crc: %08X\n", advsc.getCRC32());
594
+	}
595
+	printf("\n");
596
+
597
+	//for homebrew, try auto-patching DLDI. should be benign if there is no DLDI or if it fails
598
+	if(gameInfo.isHomebrew)
599
+		DLDI::tryPatch((void*)gameInfo.romdata, gameInfo.romsize);
600
+
601
+	memset(buf, 0, MAX_PATH);
602
+	path.getpathnoext(path.BATTERY, buf);
603
+	strcat(buf, ".dsv");							// DeSmuME memory card	:)
604
+	MMU_new.backupDevice.load_rom(buf);
605
+
606
+	memset(buf, 0, MAX_PATH);
607
+	path.getpathnoext(path.CHEATS, buf);
608
+	strcat(buf, ".dct");							// DeSmuME cheat		:)
609
+	cheats->init(buf);
610
+
611
+	NDS_Reset();
612
+
613
+	return ret;
614
+}*/
615
+
616
+void NDS_FreeROM()
617
+{
618
+	//FCEUI_StopMovie();
619
+	if ((uint8_t*)MMU.CART_ROM == (uint8_t*)gameInfo.romdata)
620
+		gameInfo.romdata = NULL;
621
+	if (MMU.CART_ROM != MMU.UNUSED_RAM)
622
+		delete [] MMU.CART_ROM;
623
+	MMU_unsetRom();
624
+}
625
+
626
+
627
+
628
+/*int NDS_ImportSave(const char *filename)
629
+{
630
+	if (strlen(filename) < 4)
631
+		return 0;
632
+
633
+	if (memcmp(filename+strlen(filename)-4, ".duc", 4) == 0)
634
+		return MMU_new.backupDevice.load_duc(filename);
635
+	else
636
+		if (MMU_new.backupDevice.load_no_gba(filename))
637
+			return 1;
638
+		else
639
+			return MMU_new.backupDevice.load_raw(filename);
640
+
641
+	//return 0;
642
+}*/
643
+
644
+/*bool NDS_ExportSave(const char *filename)
645
+{
646
+	if (strlen(filename) < 4)
647
+		return false;
648
+
649
+	if (memcmp(filename+strlen(filename)-5, ".sav*", 5) == 0)
650
+	{
651
+		char tmp[MAX_PATH];
652
+		memset(tmp, 0, MAX_PATH);
653
+		strcpy(tmp, filename);
654
+		tmp[strlen(tmp)-1] = 0;
655
+		return MMU_new.backupDevice.save_no_gba(tmp);
656
+	}
657
+
658
+	if (memcmp(filename+strlen(filename)-4, ".sav", 4) == 0)
659
+		return MMU_new.backupDevice.save_raw(filename);
660
+
661
+	return false;
662
+}*/
663
+
664
+/*static int WritePNGChunk(FILE *fp, uint32 size, const char *type, const uint8 *data)
665
+{
666
+	uint32 crc;
667
+
668
+	uint8 tempo[4];
669
+
670
+	tempo[0]=size>>24;
671
+	tempo[1]=size>>16;
672
+	tempo[2]=size>>8;
673
+	tempo[3]=size;
674
+
675
+	if(fwrite(tempo,4,1,fp)!=1)
676
+		return 0;
677
+	if(fwrite(type,4,1,fp)!=1)
678
+		return 0;
679
+
680
+	if(size)
681
+		if(fwrite(data,1,size,fp)!=size)
682
+			return 0;
683
+
684
+	crc = crc32(0,(uint8 *)type,4);
685
+	if(size)
686
+		crc = crc32(crc,data,size);
687
+
688
+	tempo[0]=crc>>24;
689
+	tempo[1]=crc>>16;
690
+	tempo[2]=crc>>8;
691
+	tempo[3]=crc;
692
+
693
+	if(fwrite(tempo,4,1,fp)!=1)
694
+		return 0;
695
+	return 1;
696
+}*/
697
+/*int NDS_WritePNG(const char *fname)
698
+{
699
+	int x, y;
700
+	int width=256;
701
+	int height=192*2;
702
+	uint16_t * bmp = (uint16_t *)GPU_screen;
703
+	FILE *pp=NULL;
704
+	uint8 *compmem = NULL;
705
+	uLongf compmemsize = (uLongf)( (height * (width + 1) * 3 * 1.001 + 1) + 12 );
706
+
707
+	if(!(compmem=(uint8 *)malloc(compmemsize)))
708
+		return 0;
709
+
710
+	if(!(pp=fopen(fname, "wb")))
711
+	{
712
+		goto PNGerr;
713
+	}
714
+	{
715
+		const uint8 header[8]={137,80,78,71,13,10,26,10};
716
+		if(fwrite(header,8,1,pp)!=1)
717
+			goto PNGerr;
718
+	}
719
+
720
+	{
721
+		uint8 chunko[13];
722
+
723
+		chunko[0] = width >> 24;		// Width
724
+		chunko[1] = width >> 16;
725
+		chunko[2] = width >> 8;
726
+		chunko[3] = width;
727
+
728
+		chunko[4] = height >> 24;		// Height
729
+		chunko[5] = height >> 16;
730
+		chunko[6] = height >> 8;
731
+		chunko[7] = height;
732
+
733
+		chunko[8]=8;				// 8 bits per sample(24 bits per pixel)
734
+		chunko[9]=2;				// Color type; RGB triplet
735
+		chunko[10]=0;				// compression: deflate
736
+		chunko[11]=0;				// Basic adapative filter set(though none are used).
737
+		chunko[12]=0;				// No interlace.
738
+
739
+		if(!WritePNGChunk(pp,13,"IHDR",chunko))
740
+			goto PNGerr;
741
+	}
742
+
743
+	{
744
+		uint8 *tmp_buffer;
745
+		uint8 *tmp_inc;
746
+		tmp_inc = tmp_buffer = (uint8 *)malloc((width * 3 + 1) * height);
747
+
748
+		for(y=0;y<height;y++)
749
+		{
750
+			*tmp_inc = 0;
751
+			tmp_inc++;
752
+			for(x=0;x<width;x++)
753
+			{
754
+				int r,g,b;
755
+				uint16_t pixel = bmp[y*256+x];
756
+				r = pixel>>10;
757
+				pixel-=r<<10;
758
+				g = pixel>>5;
759
+				pixel-=g<<5;
760
+				b = pixel;
761
+				r*=255/31;
762
+				g*=255/31;
763
+				b*=255/31;
764
+				tmp_inc[0] = b;
765
+				tmp_inc[1] = g;
766
+				tmp_inc[2] = r;
767
+				tmp_inc += 3;
768
+			}
769
+		}
770
+
771
+		if(compress(compmem, &compmemsize, tmp_buffer, height * (width * 3 + 1))!=Z_OK)
772
+		{
773
+			if(tmp_buffer) free(tmp_buffer);
774
+			goto PNGerr;
775
+		}
776
+		if(tmp_buffer) free(tmp_buffer);
777
+		if(!WritePNGChunk(pp,compmemsize,"IDAT",compmem))
778
+			goto PNGerr;
779
+	}
780
+	if(!WritePNGChunk(pp,0,"IEND",0))
781
+		goto PNGerr;
782
+
783
+	free(compmem);
784
+	fclose(pp);
785
+
786
+	return 1;
787
+
788
+PNGerr:
789
+	if(compmem)
790
+		free(compmem);
791
+	if(pp)
792
+		fclose(pp);
793
+	return 0;
794
+}*/
795
+
796
+/*typedef struct
797
+{
798
+	uint32_t size;
799
+	int32_t width;
800
+	int32_t height;
801
+	uint16_t planes;
802
+	uint16_t bpp;
803
+	uint32_t cmptype;
804
+	uint32_t imgsize;
805
+	int32_t hppm;
806
+	int32_t vppm;
807
+	uint32_t numcol;
808
+	uint32_t numimpcol;
809
+} bmpimgheader_struct;
810
+
811
+#include "PACKED.h"
812
+typedef struct
813
+{
814
+	uint16_t id __PACKED;
815
+	uint32_t size __PACKED;
816
+	uint16_t reserved1 __PACKED;
817
+	uint16_t reserved2 __PACKED;
818
+	uint32_t imgoffset __PACKED;
819
+} bmpfileheader_struct;
820
+#include "PACKED_END.h"*/
821
+
822
+/*int NDS_WriteBMP(const char *filename)
823
+{
824
+	bmpfileheader_struct fileheader;
825
+	bmpimgheader_struct imageheader;
826
+	FILE *file;
827
+	int i,j;
828
+	uint16_t * bmp = (uint16_t *)GPU_screen;
829
+	size_t elems_written = 0;
830
+
831
+	memset(&fileheader, 0, sizeof(fileheader));
832
+	fileheader.size = sizeof(fileheader);
833
+	fileheader.id = 'B' | ('M' << 8);
834
+	fileheader.imgoffset = sizeof(fileheader)+sizeof(imageheader);
835
+
836
+	memset(&imageheader, 0, sizeof(imageheader));
837
+	imageheader.size = sizeof(imageheader);
838
+	imageheader.width = 256;
839
+	imageheader.height = 192*2;
840
+	imageheader.planes = 1;
841
+	imageheader.bpp = 24;
842
+	imageheader.cmptype = 0; // None
843
+	imageheader.imgsize = imageheader.width * imageheader.height * 3;
844
+
845
+	if ((file = fopen(filename,"wb")) == NULL)
846
+		return 0;
847
+
848
+	elems_written += fwrite(&fileheader, 1, sizeof(fileheader), file);
849
+	elems_written += fwrite(&imageheader, 1, sizeof(imageheader), file);
850
+
851
+	for(j=0;j<192*2;j++)
852
+	{
853
+		for(i=0;i<256;i++)
854
+		{
855
+			uint8_t r,g,b;
856
+			uint16_t pixel = bmp[(192*2-j-1)*256+i];
857
+			r = pixel>>10;
858
+			pixel-=r<<10;
859
+			g = pixel>>5;
860
+			pixel-=g<<5;
861
+			b = (uint8_t)pixel;
862
+			r*=255/31;
863
+			g*=255/31;
864
+			b*=255/31;
865
+			elems_written += fwrite(&r, 1, sizeof(uint8_t), file);
866
+			elems_written += fwrite(&g, 1, sizeof(uint8_t), file);
867
+			elems_written += fwrite(&b, 1, sizeof(uint8_t), file);
868
+		}
869
+	}
870
+	fclose(file);
871
+
872
+	return 1;
873
+}*/
874
+
875
+/*int NDS_WriteBMP_32bppBuffer(int width, int height, const void* buf, const char *filename)
876
+{
877
+	bmpfileheader_struct fileheader;
878
+	bmpimgheader_struct imageheader;
879
+	FILE *file;
880
+	size_t elems_written = 0;
881
+	memset(&fileheader, 0, sizeof(fileheader));
882
+	fileheader.size = sizeof(fileheader);
883
+	fileheader.id = 'B' | ('M' << 8);
884
+	fileheader.imgoffset = sizeof(fileheader)+sizeof(imageheader);
885
+
886
+	memset(&imageheader, 0, sizeof(imageheader));
887
+	imageheader.size = sizeof(imageheader);
888
+	imageheader.width = width;
889
+	imageheader.height = height;
890
+	imageheader.planes = 1;
891
+	imageheader.bpp = 32;
892
+	imageheader.cmptype = 0; // None
893
+	imageheader.imgsize = imageheader.width * imageheader.height * 4;
894
+
895
+	if ((file = fopen(filename,"wb")) == NULL)
896
+		return 0;
897
+
898
+	elems_written += fwrite(&fileheader, 1, sizeof(fileheader), file);
899
+	elems_written += fwrite(&imageheader, 1, sizeof(imageheader), file);
900
+
901
+	for(int i=0;i<height;i++)
902
+		for(int x=0;x<width;x++)
903
+		{
904
+			uint8_t* pixel = (uint8_t*)buf + (height-i-1)*width*4;
905
+			pixel += (x*4);
906
+			elems_written += fwrite(pixel+2,1,1,file);
907
+			elems_written += fwrite(pixel+1,1,1,file);
908
+			elems_written += fwrite(pixel+0,1,1,file);
909
+			elems_written += fwrite(pixel+3,1,1,file);
910
+		}
911
+	fclose(file);
912
+
913
+	return 1;
914
+}*/
915
+
916
+void NDS_Sleep() { nds.sleeping = true; }
917
+/*void NDS_ToggleCardEject()
918
+{
919
+	if(!nds.cardEjected)
920
+	{
921
+		//staff of kings will test this (it also uses the arm9 0xB8 poll)
922
+		NDS_makeIrq(ARMCPU_ARM7, IRQ_BIT_GC_IREQ_MC);
923
+	}
924
+	nds.cardEjected ^= true;
925
+}*/
926
+
927
+
928
+/*class FrameSkipper
929
+{
930
+public:
931
+	void RequestSkip()
932
+	{
933
+		nextSkip = true;
934
+	}
935
+	void OmitSkip(bool force, bool forceEvenIfCapturing=false)
936
+	{
937
+		nextSkip = false;
938
+		if((force && consecutiveNonCaptures > 30) || forceEvenIfCapturing)
939
+		{
940
+			SkipCur2DFrame = false;
941
+			SkipCur3DFrame = false;
942
+			SkipNext2DFrame = false;
943
+			if(forceEvenIfCapturing)
944
+				consecutiveNonCaptures = 0;
945
+		}
946
+	}
947
+	void Advance()
948
+	{
949
+		bool capturing = false*//*(MainScreen.gpu->dispCapCnt.enabled || (MainScreen.gpu->dispCapCnt.val & 0x80000000))*//*;
950
+
951
+		if(capturing && consecutiveNonCaptures > 30)
952
+		{
953
+			// the worst-looking graphics corruption problems from frameskip
954
+			// are the result of skipping the capture on first frame it turns on.
955
+			// so we do this to handle the capture immediately,
956
+			// despite the risk of 1 frame of 2d/3d mismatch or wrong screen display.
957
+			SkipNext2DFrame = false;
958
+			nextSkip = false;
959
+		}
960
+		else if(*//*lastOffset != MainScreen.offset && *//*lastSkip && !skipped)
961
+		{
962
+			// if we're switching from not skipping to skipping
963
+			// and the screens are also switching around this frame,
964
+			// go for 1 extra frame without skipping.
965
+			// this avoids the scenario where we only draw one of the two screens
966
+			// when a game is switching screens every frame.
967
+			nextSkip = false;
968
+		}
969
+
970
+		if(capturing)
971
+			consecutiveNonCaptures = 0;
972
+		else if(!(consecutiveNonCaptures > 9000)) // arbitrary cap to avoid eventual wrap
973
+			consecutiveNonCaptures++;
974
+		lastLastOffset = lastOffset;
975
+		//lastOffset = MainScreen.offset;
976
+		lastSkip = skipped;
977
+		skipped = nextSkip;
978
+		nextSkip = false;
979
+
980
+		SkipCur2DFrame = SkipNext2DFrame;
981
+		SkipCur3DFrame = skipped;
982
+		SkipNext2DFrame = skipped;
983
+	}
984
+	inline bool ShouldSkip2D()
985
+	{
986
+		return SkipCur2DFrame;
987
+	}
988
+	inline bool ShouldSkip3D()
989
+	{
990
+		return SkipCur3DFrame;
991
+	}
992
+	FrameSkipper()
993
+	{
994
+		nextSkip = false;
995
+		skipped = false;
996
+		lastSkip = false;
997
+		lastOffset = 0;
998
+		SkipCur2DFrame = false;
999
+		SkipCur3DFrame = false;
1000
+		SkipNext2DFrame = false;
1001
+		consecutiveNonCaptures = 0;
1002
+	}
1003
+private:
1004
+	bool nextSkip;
1005
+	bool skipped;
1006
+	bool lastSkip;
1007
+	int lastOffset;
1008
+	int lastLastOffset;
1009
+	int consecutiveNonCaptures;
1010
+	bool SkipCur2DFrame;
1011
+	bool SkipCur3DFrame;
1012
+	bool SkipNext2DFrame;
1013
+};*/
1014
+//static FrameSkipper frameSkipper;
1015
+
1016
+
1017
+/*void NDS_SkipNextFrame() {
1018
+	//if (!driver->AVI_IsRecording()) {
1019
+		//frameSkipper.RequestSkip();
1020
+	//}
1021
+}*/
1022
+/*void NDS_OmitFrameSkip(int force) {
1023
+	//frameSkipper.OmitSkip(force > 0, force > 1);
1024
+}*/
1025
+
1026
+//#define INDEX(i) ((((i)>>16)&0xFF0)|(((i)>>4)&0xF))
1027
+
1028
+
1029
+enum ESI_DISPCNT
1030
+{
1031
+	ESI_DISPCNT_HStart, ESI_DISPCNT_HStartIRQ, ESI_DISPCNT_HDraw, ESI_DISPCNT_HBlank
1032
+};
1033
+
1034
+uint64_t nds_timer;
1035
+uint64_t nds_arm9_timer, nds_arm7_timer;
1036
+
1037
+static const uint64_t kNever = 0xFFFFFFFFFFFFFFFFULL;
1038
+
1039
+struct TSequenceItem
1040
+{
1041
+	uint64_t timestamp;
1042
+	uint32_t param;
1043
+	bool enabled;
1044
+
1045
+	/*virtual void save(EMUFILE* os)
1046
+	{
1047
+		write64le(timestamp,os);
1048
+		write32le(param,os);
1049
+		writebool(enabled,os);
1050
+	}*/
1051
+
1052
+	virtual bool load(EMUFILE* is)
1053
+	{
1054
+		if(read64le(&timestamp,is) != 1) return false;
1055
+		if(read32le(&param,is) != 1) return false;
1056
+		if(readbool(&enabled,is) != 1) return false;
1057
+		return true;
1058
+	}
1059
+
1060
+	inline bool isTriggered()
1061
+	{
1062
+		return enabled && nds_timer >= timestamp;
1063
+	}
1064
+
1065
+	inline uint64_t next()
1066
+	{
1067
+		return timestamp;
1068
+	}
1069
+};
1070
+
1071
+/*struct TSequenceItem_GXFIFO : public TSequenceItem
1072
+{
1073
+	inline bool isTriggered()
1074
+	{
1075
+		return enabled && nds_timer >= MMU.gfx3dCycles;
1076
+	}
1077
+
1078
+	inline void exec()
1079
+	{
1080
+		IF_DEVELOPER(DEBUG_statistics.sequencerExecutionCounters[4]++);
1081
+		while(isTriggered()) {
1082
+			enabled = false;
1083
+			//gfx3d_execute3D();
1084
+		}
1085
+	}
1086
+
1087
+	inline uint64_t next()
1088
+	{
1089
+		if(enabled) return MMU.gfx3dCycles;
1090
+		else return kNever;
1091
+	}
1092
+};*/
1093
+
1094
+template<int procnum, int num> struct TSequenceItem_Timer : public TSequenceItem
1095
+{
1096
+	inline bool isTriggered()
1097
+	{
1098
+		return enabled && nds_timer >= nds.timerCycle[procnum][num];
1099
+	}
1100
+
1101
+	inline void schedule()
1102
+	{
1103
+		enabled = MMU.timerON[procnum][num] && MMU.timerMODE[procnum][num] != 0xFFFF;
1104
+	}
1105
+
1106
+	inline uint64_t next()
1107
+	{
1108
+		return nds.timerCycle[procnum][num];
1109
+	}
1110
+
1111
+	inline void exec()
1112
+	{
1113
+		IF_DEVELOPER(DEBUG_statistics.sequencerExecutionCounters[13+procnum*4+num]++);
1114
+		uint8_t* regs = procnum==0?MMU.ARM9_REG:MMU.ARM7_REG;
1115
+		bool first = true, over;
1116
+		//we'll need to check chained timers..
1117
+		for(int i=num;i<4;i++)
1118
+		{
1119
+			//maybe too many checks if this is here, but we need it here for now
1120
+			if(!MMU.timerON[procnum][i]) return;
1121
+
1122
+			if(MMU.timerMODE[procnum][i] == 0xFFFF)
1123
+			{
1124
+				++(MMU.timer[procnum][i]);
1125
+				over = !MMU.timer[procnum][i];
1126
+			}
1127
+			else
1128
+			{
1129
+				if(!first) break; //this timer isn't chained. break the chain
1130
+				first = false;
1131
+
1132
+				over = true;
1133
+				int remain = 65536 - MMU.timerReload[procnum][i];
1134
+				int ctr=0;
1135
+				while(nds.timerCycle[procnum][i] <= nds_timer) {
1136
+					nds.timerCycle[procnum][i] += (remain << MMU.timerMODE[procnum][i]);
1137
+					ctr++;
1138
+				}
1139
+#ifndef NDEBUG
1140
+				if(ctr>1) {
1141
+					printf("yikes!!!!! please report!\n");
1142
+				}
1143
+#endif
1144
+			}
1145
+
1146
+			if(over)
1147
+			{
1148
+				MMU.timer[procnum][i] = MMU.timerReload[procnum][i];
1149
+				if(T1ReadWord(regs, 0x102 + i*4) & 0x40)
1150
+				{
1151
+					NDS_makeIrq(procnum, IRQ_BIT_TIMER_0 + i);
1152
+				}
1153
+			}
1154
+			else
1155
+				break; //no more chained timers to trigger. we're done here
1156
+		}
1157
+	}
1158
+};
1159
+
1160
+template<int procnum, int chan> struct TSequenceItem_DMA : public TSequenceItem
1161
+{
1162
+	DmaController* controller;
1163
+
1164
+	inline bool isTriggered()
1165
+	{
1166
+		return controller->dmaCheck && nds_timer>= controller->nextEvent;
1167
+	}
1168
+
1169
+	inline bool isEnabled() {
1170
+		return controller->dmaCheck?true:false;
1171
+	}
1172
+
1173
+	inline uint64_t next()
1174
+	{
1175
+		return controller->nextEvent;
1176
+	}
1177
+
1178
+	inline void exec()
1179
+	{
1180
+		IF_DEVELOPER(DEBUG_statistics.sequencerExecutionCounters[5+procnum*4+chan]++);
1181
+
1182
+		//if (nds.freezeBus) return;
1183
+
1184
+		//printf("exec from TSequenceItem_DMA: %d %d\n",procnum,chan);
1185
+		controller->exec();
1186
+//		//give gxfifo dmas a chance to re-trigger
1187
+//		if(MMU.DMAStartTime[procnum][chan] == EDMAMode_GXFifo) {
1188
+//			MMU.DMAing[procnum][chan] = false;
1189
+//			if (gxFIFO.size <= 127)
1190
+//			{
1191
+//				execHardware_doDma(procnum,chan,EDMAMode_GXFifo);
1192
+//				if (MMU.DMACompleted[procnum][chan])
1193
+//					goto docomplete;
1194
+//				else return;
1195
+//			}
1196
+//		}
1197
+//
1198
+//docomplete:
1199
+//		if (MMU.DMACompleted[procnum][chan])
1200
+//		{
1201
+//			uint8_t* regs = procnum==0?MMU.ARM9_REG:MMU.ARM7_REG;
1202
+//
1203
+//			//disable the channel
1204
+//			if(MMU.DMAStartTime[procnum][chan] != EDMAMode_GXFifo) {
1205
+//				T1WriteLong(regs, 0xB8 + (0xC*chan), T1ReadLong(regs, 0xB8 + (0xC*chan)) & 0x7FFFFFFF);
1206
+//				MMU.DMACrt[procnum][chan] &= 0x7FFFFFFF; //blehhh i hate this shit being mirrored in memory
1207
+//			}
1208
+//
1209
+//			if((MMU.DMACrt[procnum][chan])&(1<<30)) {
1210
+//				if(procnum==0) NDS_makeARM9Int(8+chan);
1211
+//				else NDS_makeARM7Int(8+chan);
1212
+//			}
1213
+//
1214
+//			MMU.DMAing[procnum][chan] = false;
1215
+//		}
1216
+
1217
+	}
1218
+};
1219
+
1220
+struct TSequenceItem_divider : public TSequenceItem
1221
+{
1222
+	inline bool isTriggered()
1223
+	{
1224
+		return MMU.divRunning && nds_timer >= MMU.divCycles;
1225
+	}
1226
+
1227
+	bool isEnabled() { return MMU.divRunning!=0; }
1228
+
1229
+	inline uint64_t next()
1230
+	{
1231
+		return MMU.divCycles;
1232
+	}
1233
+
1234
+	void exec()
1235
+	{
1236
+		IF_DEVELOPER(DEBUG_statistics.sequencerExecutionCounters[2]++);
1237
+		MMU_new.div.busy = 0;
1238
+#ifdef _WIN64
1239
+		T1WriteQuad(MMU.MMU_MEM[ARMCPU_ARM9][0x40], 0x2A0, MMU.divResult);
1240
+		T1WriteQuad(MMU.MMU_MEM[ARMCPU_ARM9][0x40], 0x2A8, MMU.divMod);
1241
+#else
1242
+		T1WriteLong(MMU.MMU_MEM[ARMCPU_ARM9][0x40], 0x2A0, (uint32_t)MMU.divResult);
1243
+		T1WriteLong(MMU.MMU_MEM[ARMCPU_ARM9][0x40], 0x2A4, (uint32_t)(MMU.divResult >> 32));
1244
+		T1WriteLong(MMU.MMU_MEM[ARMCPU_ARM9][0x40], 0x2A8, (uint32_t)MMU.divMod);
1245
+		T1WriteLong(MMU.MMU_MEM[ARMCPU_ARM9][0x40], 0x2AC, (uint32_t)(MMU.divMod >> 32));
1246
+#endif
1247
+		MMU.divRunning = false;
1248
+	}
1249
+
1250
+};
1251
+
1252
+struct TSequenceItem_sqrtunit : public TSequenceItem
1253
+{
1254
+	inline bool isTriggered()
1255
+	{
1256
+		return MMU.sqrtRunning && nds_timer >= MMU.sqrtCycles;
1257
+	}
1258
+
1259
+	bool isEnabled() { return MMU.sqrtRunning!=0; }
1260
+
1261
+	inline uint64_t next()
1262
+	{
1263
+		return MMU.sqrtCycles;
1264
+	}
1265
+
1266
+	inline void exec()
1267
+	{
1268
+		IF_DEVELOPER(DEBUG_statistics.sequencerExecutionCounters[3]++);
1269
+		MMU_new.sqrt.busy = 0;
1270
+		T1WriteLong(MMU.MMU_MEM[ARMCPU_ARM9][0x40], 0x2B4, MMU.sqrtResult);
1271
+		MMU.sqrtRunning = false;
1272
+	}
1273
+
1274
+};
1275
+
1276
+struct Sequencer
1277
+{
1278
+	bool nds_vblankEnded;
1279
+	bool reschedule;
1280
+	TSequenceItem dispcnt;
1281
+	TSequenceItem wifi;
1282
+	TSequenceItem_divider divider;
1283
+	TSequenceItem_sqrtunit sqrtunit;
1284
+	TSequenceItem/*_GXFIFO*/ gxfifo;
1285
+	TSequenceItem_DMA<0,0> dma_0_0; TSequenceItem_DMA<0,1> dma_0_1;
1286
+	TSequenceItem_DMA<0,2> dma_0_2; TSequenceItem_DMA<0,3> dma_0_3;
1287
+	TSequenceItem_DMA<1,0> dma_1_0; TSequenceItem_DMA<1,1> dma_1_1;
1288
+	TSequenceItem_DMA<1,2> dma_1_2; TSequenceItem_DMA<1,3> dma_1_3;
1289
+	TSequenceItem_Timer<0,0> timer_0_0; TSequenceItem_Timer<0,1> timer_0_1;
1290
+	TSequenceItem_Timer<0,2> timer_0_2; TSequenceItem_Timer<0,3> timer_0_3;
1291
+	TSequenceItem_Timer<1,0> timer_1_0; TSequenceItem_Timer<1,1> timer_1_1;
1292
+	TSequenceItem_Timer<1,2> timer_1_2; TSequenceItem_Timer<1,3> timer_1_3;
1293
+
1294
+	void init();
1295
+
1296
+	void execHardware();
1297
+	uint64_t findNext();
1298
+
1299
+	/*void save(EMUFILE* os)
1300
+	{
1301
+		write64le(nds_timer,os);
1302
+		write64le(nds_arm9_timer,os);
1303
+		write64le(nds_arm7_timer,os);
1304
+		dispcnt.save(os);
1305
+		divider.save(os);
1306
+		sqrtunit.save(os);
1307
+		gxfifo.save(os);
1308
+		wifi.save(os);
1309
+#define SAVE(I,X,Y) I##_##X##_##Y .save(os);
1310
+		SAVE(timer,0,0); SAVE(timer,0,1); SAVE(timer,0,2); SAVE(timer,0,3);
1311
+		SAVE(timer,1,0); SAVE(timer,1,1); SAVE(timer,1,2); SAVE(timer,1,3);
1312
+		SAVE(dma,0,0); SAVE(dma,0,1); SAVE(dma,0,2); SAVE(dma,0,3);
1313
+		SAVE(dma,1,0); SAVE(dma,1,1); SAVE(dma,1,2); SAVE(dma,1,3);
1314
+#undef SAVE
1315
+	}*/
1316
+
1317
+	bool load(EMUFILE* is, int version)
1318
+	{
1319
+		if(read64le(&nds_timer,is) != 1) return false;
1320
+		if(read64le(&nds_arm9_timer,is) != 1) return false;
1321
+		if(read64le(&nds_arm7_timer,is) != 1) return false;
1322
+		if(!dispcnt.load(is)) return false;
1323
+		if(!divider.load(is)) return false;
1324
+		if(!sqrtunit.load(is)) return false;
1325
+		if(!gxfifo.load(is)) return false;
1326
+		if(version >= 1) if(!wifi.load(is)) return false;
1327
+#define LOAD(I,X,Y) if(!I##_##X##_##Y .load(is)) return false;
1328
+		LOAD(timer,0,0); LOAD(timer,0,1); LOAD(timer,0,2); LOAD(timer,0,3);
1329
+		LOAD(timer,1,0); LOAD(timer,1,1); LOAD(timer,1,2); LOAD(timer,1,3);
1330
+		LOAD(dma,0,0); LOAD(dma,0,1); LOAD(dma,0,2); LOAD(dma,0,3);
1331
+		LOAD(dma,1,0); LOAD(dma,1,1); LOAD(dma,1,2); LOAD(dma,1,3);
1332
+#undef LOAD
1333
+
1334
+		return true;
1335
+	}
1336
+
1337
+} sequencer;
1338
+
1339
+/*void NDS_RescheduleGXFIFO(uint32_t cost)
1340
+{
1341
+	//if(!sequencer.gxfifo.enabled) {
1342
+		//MMU.gfx3dCycles = nds_timer;
1343
+		//sequencer.gxfifo.enabled = true;
1344
+	//}
1345
+	//MMU.gfx3dCycles += cost;
1346
+	NDS_Reschedule();
1347
+}*/
1348
+
1349
+void NDS_RescheduleTimers()
1350
+{
1351
+#define check(X,Y) sequencer.timer_##X##_##Y .schedule();
1352
+	check(0,0); check(0,1); check(0,2); check(0,3);
1353
+	check(1,0); check(1,1); check(1,2); check(1,3);
1354
+#undef check
1355
+
1356
+	NDS_Reschedule();
1357
+}
1358
+
1359
+void NDS_RescheduleDMA()
1360
+{
1361
+	//TBD
1362
+	NDS_Reschedule();
1363
+
1364
+}
1365
+
1366
+static void initSchedule()
1367
+{
1368
+	sequencer.init();
1369
+
1370
+	//begin at the very end of the last scanline
1371
+	//so that at t=0 we can increment to scanline=0
1372
+	nds.VCount = 262;
1373
+
1374
+	sequencer.nds_vblankEnded = false;
1375
+}
1376
+
1377
+
1378
+// 2196372 ~= (ARM7_CLOCK << 16) / 1000000
1379
+// This value makes more sense to me, because:
1380
+// ARM7_CLOCK   = 33.51 mhz
1381
+//				= 33513982 cycles per second
1382
+// 				= 33.513982 cycles per microsecond
1383
+//const uint64_t kWifiCycles = 34*2;
1384
+//(this isn't very precise. I don't think it needs to be)
1385
+
1386
+void Sequencer::init()
1387
+{
1388
+	NDS_RescheduleTimers();
1389
+	NDS_RescheduleDMA();
1390
+
1391
+	reschedule = false;
1392
+	nds_timer = 0;
1393
+	nds_arm9_timer = 0;
1394
+	nds_arm7_timer = 0;
1395
+
1396
+	dispcnt.enabled = true;
1397
+	dispcnt.param = ESI_DISPCNT_HStart;
1398
+	dispcnt.timestamp = 0;
1399
+
1400
+	//gxfifo.enabled = false;
1401
+
1402
+	dma_0_0.controller = &MMU_new.dma[0][0];
1403
+	dma_0_1.controller = &MMU_new.dma[0][1];
1404
+	dma_0_2.controller = &MMU_new.dma[0][2];
1405
+	dma_0_3.controller = &MMU_new.dma[0][3];
1406
+	dma_1_0.controller = &MMU_new.dma[1][0];
1407
+	dma_1_1.controller = &MMU_new.dma[1][1];
1408
+	dma_1_2.controller = &MMU_new.dma[1][2];
1409
+	dma_1_3.controller = &MMU_new.dma[1][3];
1410
+
1411
+
1412
+	/*#ifdef EXPERIMENTAL_WIFI_COMM
1413
+	wifi.enabled = true;
1414
+	wifi.timestamp = kWifiCycles;
1415
+	#else
1416
+	wifi.enabled = false;
1417
+	#endif*/
1418
+}
1419
+
1420
+//this isnt helping much right now. work on it later
1421
+//#include "utils/task.h"
1422
+//Task taskSubGpu(true);
1423
+//void* renderSubScreen(void*)
1424
+//{
1425
+//	GPU_RenderLine(&SubScreen, nds.VCount, SkipCur2DFrame);
1426
+//	return NULL;
1427
+//}
1428
+
1429
+static void execHardware_hblank()
1430
+{
1431
+	//this logic keeps moving around.
1432
+	//now, we try and give the game as much time as possible to finish doing its work for the scanline,
1433
+	//by drawing scanline N at the end of drawing time (but before subsequent interrupt or hdma-driven events happen)
1434
+	//don't try to do this at the end of the scanline, because some games (sonic classics) may use hblank IRQ to set
1435
+	//scroll regs for the next scanline
1436
+	if(nds.VCount<192)
1437
+	{
1438
+		//taskSubGpu.execute(renderSubScreen,NULL);
1439
+		//GPU_RenderLine(&MainScreen, nds.VCount, frameSkipper.ShouldSkip2D());
1440
+		//GPU_RenderLine(&SubScreen, nds.VCount, frameSkipper.ShouldSkip2D());
1441
+		//taskSubGpu.finish();
1442
+
1443
+		//trigger hblank dmas
1444
+		//but notice, we do that just after we finished drawing the line
1445
+		//(values copied by this hdma should not be used until the next scanline)
1446
+		triggerDma(EDMAMode_HBlank);
1447
+	}
1448
+
1449
+	if(nds.VCount==262)
1450
+	{
1451
+		//we need to trigger one last hblank dma since
1452
+		//a. we're sort of lagged behind by one scanline
1453
+		//b. i think that 193 hblanks actually fire (one for the hblank in scanline 262)
1454
+		//this is demonstrated by NSMB splot-parallaxing clouds
1455
+		//for some reason the game will setup two hdma scroll register buffers
1456
+		//to be run consecutively, and unless we do this, the second buffer will be offset by one scanline
1457
+		//causing a glitch in the 0th scanline
1458
+		//triggerDma(EDMAMode_HBlank);
1459
+
1460
+		//BUT! this was removed in order to make glitches in megaman zero collection (mmz 4 1st level) work.
1461
+		//and, it seems that it is no longer necessary in nsmb. perhaps something else fixed it
1462
+	}
1463
+
1464
+
1465
+	//turn on hblank status bit
1466
+	T1WriteWord(MMU.ARM9_REG, 4, T1ReadWord(MMU.ARM9_REG, 4) | 2);
1467
+	T1WriteWord(MMU.ARM7_REG, 4, T1ReadWord(MMU.ARM7_REG, 4) | 2);
1468
+
1469
+	//fire hblank interrupts if necessary
1470
+	if(T1ReadWord(MMU.ARM9_REG, 4) & 0x10) NDS_makeIrq(ARMCPU_ARM9,IRQ_BIT_LCD_HBLANK);
1471
+	if(T1ReadWord(MMU.ARM7_REG, 4) & 0x10) NDS_makeIrq(ARMCPU_ARM7,IRQ_BIT_LCD_HBLANK);
1472
+
1473
+	//emulation housekeeping. for some reason we always do this at hblank,
1474
+	//even though it sounds more reasonable to do it at hstart
1475
+	SPU_Emulate_core();
1476
+	//driver->AVI_SoundUpdate(SPU_core->outbuf,spu_core_samples);
1477
+	//WAV_WavSoundUpdate(SPU_core->outbuf,spu_core_samples);
1478
+}
1479
+
1480
+static void execHardware_hstart_vblankEnd()
1481
+{
1482
+	sequencer.nds_vblankEnded = true;
1483
+	sequencer.reschedule = true;
1484
+
1485
+	//turn off vblank status bit
1486
+	T1WriteWord(MMU.ARM9_REG, 4, T1ReadWord(MMU.ARM9_REG, 4) & ~1);
1487
+	T1WriteWord(MMU.ARM7_REG, 4, T1ReadWord(MMU.ARM7_REG, 4) & ~1);
1488
+
1489
+	//some emulation housekeeping
1490
+	//frameSkipper.Advance();
1491
+}
1492
+
1493
+static void execHardware_hstart_vblankStart()
1494
+{
1495
+	//printf("--------VBLANK!!!--------\n");
1496
+
1497
+	//fire vblank interrupts if necessary
1498
+	for(int i=0;i<2;i++)
1499
+		if(MMU.reg_IF_pending[i] & (1<<IRQ_BIT_LCD_VBLANK))
1500
+		{
1501
+			MMU.reg_IF_pending[i] &= ~(1<<IRQ_BIT_LCD_VBLANK);
1502
+			NDS_makeIrq(i,IRQ_BIT_LCD_VBLANK);
1503
+		}
1504
+
1505
+	//trigger vblank dmas
1506
+	triggerDma(EDMAMode_VBlank);
1507
+
1508
+	//tracking for arm9 load average
1509
+	//nds.runCycleCollector[0][nds.idleFrameCounter] = 1120380-nds.idleCycles[0];
1510
+	//nds.runCycleCollector[1][nds.idleFrameCounter] = 1120380-nds.idleCycles[1];
1511
+	//nds.idleFrameCounter++;
1512
+	//nds.idleFrameCounter &= 15;
1513
+	//nds.idleCycles[0] = 0;
1514
+	//nds.idleCycles[1] = 0;
1515
+}
1516
+
1517
+static uint16_t execHardware_gen_vmatch_goal()
1518
+{
1519
+	uint16_t vmatch = T1ReadWord(MMU.ARM9_REG, 4);
1520
+	vmatch = ((vmatch>>8)|((vmatch<<1)&(1<<8)));
1521
+	return vmatch;
1522
+}
1523
+
1524
+static void execHardware_hstart_vcount_irq()
1525
+{
1526
+	//trigger pending VMATCH irqs
1527
+	if(MMU.reg_IF_pending[ARMCPU_ARM9] & (1<<IRQ_BIT_LCD_VMATCH))
1528
+	{
1529
+		MMU.reg_IF_pending[ARMCPU_ARM9] &= ~(1<<IRQ_BIT_LCD_VMATCH);
1530
+		NDS_makeIrq(ARMCPU_ARM9,IRQ_BIT_LCD_VMATCH);
1531
+	}
1532
+	if(MMU.reg_IF_pending[ARMCPU_ARM7] & (1<<IRQ_BIT_LCD_VMATCH))
1533
+	{
1534
+		MMU.reg_IF_pending[ARMCPU_ARM7] &= ~(1<<IRQ_BIT_LCD_VMATCH);
1535
+		NDS_makeIrq(ARMCPU_ARM7,IRQ_BIT_LCD_VMATCH);
1536
+	}
1537
+}
1538
+
1539
+static void execHardware_hstart_vcount()
1540
+{
1541
+	uint16_t vmatch = execHardware_gen_vmatch_goal();
1542
+	if(nds.VCount==vmatch)
1543
+	{
1544
+		//arm9 vmatch
1545
+		T1WriteWord(MMU.ARM9_REG, 4, T1ReadWord(MMU.ARM9_REG, 4) | 4);
1546
+		if(T1ReadWord(MMU.ARM9_REG, 4) & 32) {
1547
+			MMU.reg_IF_pending[ARMCPU_ARM9] |= (1<<IRQ_BIT_LCD_VMATCH);
1548
+		}
1549
+	}
1550
+	else
1551
+		T1WriteWord(MMU.ARM9_REG, 4, T1ReadWord(MMU.ARM9_REG, 4) & 0xFFFB);
1552
+
1553
+	vmatch = T1ReadWord(MMU.ARM7_REG, 4);
1554
+	vmatch = ((vmatch>>8)|((vmatch<<1)&(1<<8)));
1555
+	if(nds.VCount==vmatch)
1556
+	{
1557
+		//arm7 vmatch
1558
+		T1WriteWord(MMU.ARM7_REG, 4, T1ReadWord(MMU.ARM7_REG, 4) | 4);
1559
+		if(T1ReadWord(MMU.ARM7_REG, 4) & 32)
1560
+			MMU.reg_IF_pending[ARMCPU_ARM7] |= (1<<IRQ_BIT_LCD_VMATCH);
1561
+	}
1562
+	else
1563
+		T1WriteWord(MMU.ARM7_REG, 4, T1ReadWord(MMU.ARM7_REG, 4) & 0xFFFB);
1564
+}
1565
+
1566
+static void execHardware_hdraw()
1567
+{
1568
+	//due to hacks in our selection of rendering time, we do not actually render here as intended.
1569
+	//consider changing this if there is some problem with raster fx timing but check the documentation near the gpu rendering calls
1570
+	//to make sure you check for regressions (nsmb, sonic classics, et al)
1571
+}
1572
+
1573
+static void execHardware_hstart_irq()
1574
+{
1575
+	//this function very soon after the registers get updated to trigger IRQs
1576
+	//this is necessary to fix "egokoro kyoushitsu" which idles waiting for vcount=192, which never happens due to a long vblank irq
1577
+	//100% accurate emulation would require the read of VCOUNT to be in the pipeline already with the irq coming in behind it, thus
1578
+	//allowing the vcount to register as 192 occasionally (maybe about 1 out of 28 frames)
1579
+	//the actual length of the delay is in execHardware() where the events are scheduled
1580
+	sequencer.reschedule = true;
1581
+	if(nds.VCount==192)
1582
+	{
1583
+		//when the vcount hits 192, vblank begins
1584
+		execHardware_hstart_vblankStart();
1585
+	}
1586
+
1587
+	execHardware_hstart_vcount_irq();
1588
+}
1589
+
1590
+static void execHardware_hstart()
1591
+{
1592
+	nds.VCount++;
1593
+
1594
+	//end of 3d vblank
1595
+	//this should be 214, but we are going to be generous for games with tight timing
1596
+	//they shouldnt be changing any textures at 262 but they might accidentally still be at 214
1597
+	//so..
1598
+	/*if((CommonSettings.rigorous_timing && nds.VCount==214) || (!CommonSettings.rigorous_timing && nds.VCount==262))
1599
+	{
1600
+		gfx3d_VBlankEndSignal(frameSkipper.ShouldSkip3D());
1601
+	}*/
1602
+
1603
+	if(nds.VCount==263)
1604
+	{
1605
+		//when the vcount hits 263 it rolls over to 0
1606
+		nds.VCount=0;
1607
+	}
1608
+	if(nds.VCount==262)
1609
+	{
1610
+		//when the vcount hits 262, vblank ends (oam pre-renders by one scanline)
1611
+		execHardware_hstart_vblankEnd();
1612
+	}
1613
+	/*else if(nds.VCount==191)
1614
+	{
1615
+		//when the vcount hits 191, the 3d vblank occurs (maybe because OAM doesnt need to run anymore, so we can power it down, and give the 3d as much time as possible?)
1616
+		gfx3d_VBlankSignal();
1617
+	}*/
1618
+	else if(nds.VCount==192)
1619
+	{
1620
+		//turn on vblank status bit
1621
+		T1WriteWord(MMU.ARM9_REG, 4, T1ReadWord(MMU.ARM9_REG, 4) | 1);
1622
+		T1WriteWord(MMU.ARM7_REG, 4, T1ReadWord(MMU.ARM7_REG, 4) | 1);
1623
+
1624
+		//check whether we'll need to fire vblank irqs
1625
+		if(T1ReadWord(MMU.ARM9_REG, 4) & 0x8) MMU.reg_IF_pending[ARMCPU_ARM9] |= (1<<IRQ_BIT_LCD_VBLANK);
1626
+		if(T1ReadWord(MMU.ARM7_REG, 4) & 0x8) MMU.reg_IF_pending[ARMCPU_ARM7] |= (1<<IRQ_BIT_LCD_VBLANK);
1627
+	}
1628
+
1629
+	//write the new vcount
1630
+	T1WriteWord(MMU.ARM9_REG, 6, static_cast<uint16_t>(nds.VCount));
1631
+	T1WriteWord(MMU.ARM9_REG, 0x1006, static_cast<uint16_t>(nds.VCount));
1632
+	T1WriteWord(MMU.ARM7_REG, 6, static_cast<uint16_t>(nds.VCount));
1633
+	T1WriteWord(MMU.ARM7_REG, 0x1006, static_cast<uint16_t>(nds.VCount));
1634
+
1635
+	//turn off hblank status bit
1636
+	T1WriteWord(MMU.ARM9_REG, 4, T1ReadWord(MMU.ARM9_REG, 4) & 0xFFFD);
1637
+	T1WriteWord(MMU.ARM7_REG, 4, T1ReadWord(MMU.ARM7_REG, 4) & 0xFFFD);
1638
+
1639
+	//handle vcount status
1640
+	execHardware_hstart_vcount();
1641
+
1642
+	//trigger hstart dmas
1643
+	triggerDma(EDMAMode_HStart);
1644
+
1645
+	if(nds.VCount<192)
1646
+	{
1647
+		//this is hacky.
1648
+		//there is a corresponding hack in doDMA.
1649
+		//it should be driven by a fifo (and generate just in time as the scanline is displayed)
1650
+		//but that isnt even possible until we have some sort of sub-scanline timing.
1651
+		//it may not be necessary.
1652
+		triggerDma(EDMAMode_MemDisplay);
1653
+	}
1654
+}
1655
+
1656
+void NDS_Reschedule()
1657
+{
1658
+	IF_DEVELOPER(if(!sequencer.reschedule) DEBUG_statistics.sequencerExecutionCounters[0]++;);
1659
+	sequencer.reschedule = true;
1660
+}
1661
+
1662
+/*inline uint32_t _fast_min32(uint32_t a, uint32_t b, uint32_t c, uint32_t d)
1663
+{
1664
+	return (( ((int32_t)(a-b)) >> (32-1)) & (c^d)) ^ d;
1665
+}*/
1666
+
1667
+inline uint64_t _fast_min(uint64_t a, uint64_t b)
1668
+{
1669
+	//you might find that this is faster on a 64bit system; someone should try it
1670
+	//http://aggregate.org/MAGIC/#Integer%20Selection
1671
+	//uint64_t ret = (((((s64)(a-b)) >> (64-1)) & (a^b)) ^ b);
1672
+	//assert(ret==min(a,b));
1673
+	//return ret;
1674
+
1675
+	//but this ends up being the fastest on 32bits
1676
+	return a<b?a:b;
1677
+
1678
+	//just for the record, I tried to do the 64bit math on a 32bit proc
1679
+	//using sse2 and it was really slow
1680
+	//__m128i __a; __a.m128i_u64[0] = a;
1681
+	//__m128i __b; __b.m128i_u64[0] = b;
1682
+	//__m128i xorval = _mm_xor_si128(__a,__b);
1683
+	//__m128i temp = _mm_sub_epi64(__a,__b);
1684
+	//temp.m128i_i64[0] >>= 63; //no 64bit shra in sse2, what a disappointment
1685
+	//temp = _mm_and_si128(temp,xorval);
1686
+	//temp = _mm_xor_si128(temp,__b);
1687
+	//return temp.m128i_u64[0];
1688
+}
1689
+
1690
+
1691
+
1692
+uint64_t Sequencer::findNext()
1693
+{
1694
+	//this one is always enabled so dont bother to check it
1695
+	uint64_t next = dispcnt.next();
1696
+
1697
+	if(divider.isEnabled()) next = _fast_min(next,divider.next());
1698
+	if(sqrtunit.isEnabled()) next = _fast_min(next,sqrtunit.next());
1699
+	//if(gxfifo.enabled) next = _fast_min(next,gxfifo.next());
1700
+
1701
+#ifdef EXPERIMENTAL_WIFI_COMM
1702
+	next = _fast_min(next,wifi.next());
1703
+#endif
1704
+
1705
+#define test(X,Y) if(dma_##X##_##Y .isEnabled()) next = _fast_min(next,dma_##X##_##Y .next());
1706
+	test(0,0); test(0,1); test(0,2); test(0,3);
1707
+	test(1,0); test(1,1); test(1,2); test(1,3);
1708
+#undef test
1709
+#define test(X,Y) if(timer_##X##_##Y .enabled) next = _fast_min(next,timer_##X##_##Y .next());
1710
+	test(0,0); test(0,1); test(0,2); test(0,3);
1711
+	test(1,0); test(1,1); test(1,2); test(1,3);
1712
+#undef test
1713
+
1714
+	return next;
1715
+}
1716
+
1717
+void Sequencer::execHardware()
1718
+{
1719
+	if(dispcnt.isTriggered())
1720
+	{
1721
+
1722
+		IF_DEVELOPER(DEBUG_statistics.sequencerExecutionCounters[1]++);
1723
+
1724
+		switch(dispcnt.param)
1725
+		{
1726
+		case ESI_DISPCNT_HStart:
1727
+			execHardware_hstart();
1728
+			//(used to be 3168)
1729
+			//hstart is actually 8 dots before the visible drawing begins
1730
+			//we're going to run 1 here and then run 7 in the next case
1731
+			dispcnt.timestamp += 1*6*2;
1732
+			dispcnt.param = ESI_DISPCNT_HStartIRQ;
1733
+			break;
1734
+		case ESI_DISPCNT_HStartIRQ:
1735
+			execHardware_hstart_irq();
1736
+			dispcnt.timestamp += 7*6*2;
1737
+			dispcnt.param = ESI_DISPCNT_HDraw;
1738
+			break;
1739
+
1740
+		case ESI_DISPCNT_HDraw:
1741
+			execHardware_hdraw();
1742
+			//duration of non-blanking period is ~1606 clocks (gbatek agrees) [but says its different on arm7]
1743
+			//im gonna call this 267 dots = 267*6=1602
1744
+			//so, this event lasts 267 dots minus the 8 dot preroll
1745
+			dispcnt.timestamp += (267-8)*6*2;
1746
+			dispcnt.param = ESI_DISPCNT_HBlank;
1747
+			break;
1748
+
1749
+		case ESI_DISPCNT_HBlank:
1750
+			execHardware_hblank();
1751
+			//(once this was 1092 or 1092/12=91 dots.)
1752
+			//there are surely 355 dots per scanline, less 267 for non-blanking period. the rest is hblank and then after that is hstart
1753
+			dispcnt.timestamp += (355-267)*6*2;
1754
+			dispcnt.param = ESI_DISPCNT_HStart;
1755
+			break;
1756
+		}
1757
+	}
1758
+
1759
+#ifdef EXPERIMENTAL_WIFI_COMM
1760
+	if(wifi.isTriggered())
1761
+	{
1762
+		WIFI_usTrigger();
1763
+		wifi.timestamp += kWifiCycles;
1764
+	}
1765
+#endif
1766
+
1767
+	if(divider.isTriggered()) divider.exec();
1768
+	if(sqrtunit.isTriggered()) sqrtunit.exec();
1769
+	//if(gxfifo.isTriggered()) gxfifo.exec();
1770
+
1771
+
1772
+#define test(X,Y) if(dma_##X##_##Y .isTriggered()) dma_##X##_##Y .exec();
1773
+	test(0,0); test(0,1); test(0,2); test(0,3);
1774
+	test(1,0); test(1,1); test(1,2); test(1,3);
1775
+#undef test
1776
+#define test(X,Y) if(timer_##X##_##Y .enabled) if(timer_##X##_##Y .isTriggered()) timer_##X##_##Y .exec();
1777
+	test(0,0); test(0,1); test(0,2); test(0,3);
1778
+	test(1,0); test(1,1); test(1,2); test(1,3);
1779
+#undef test
1780
+}
1781
+
1782
+void execHardware_interrupts();
1783
+
1784
+//static void saveUserInput(EMUFILE* os);
1785
+static bool loadUserInput(EMUFILE* is, int version);
1786
+
1787
+/*void nds_savestate(EMUFILE* os)
1788
+{
1789
+	//version
1790
+	write32le(3,os);
1791
+
1792
+	//sequencer.save(os);
1793
+
1794
+	saveUserInput(os);
1795
+
1796
+	write32le(LidClosed,os);
1797
+	write8le(countLid,os);
1798
+}*/
1799
+
1800
+bool nds_loadstate(EMUFILE* is, int)
1801
+{
1802
+	// this isn't part of the savestate loading logic, but
1803
+	// don't skip the next frame after loading a savestate
1804
+	//frameSkipper.OmitSkip(true, true);
1805
+
1806
+	//read version
1807
+	uint32_t version;
1808
+	if(read32le(&version,is) != 1) return false;
1809
+
1810
+	if(version > 3) return false;
1811
+
1812
+	bool temp = true;
1813
+	temp &= sequencer.load(is, version);
1814
+	if(version <= 1 || !temp) return temp;
1815
+	temp &= loadUserInput(is, version);
1816
+
1817
+	if(version < 3) return temp;
1818
+
1819
+	uint32_t tmpu32;
1820
+	read32le(&tmpu32,is);
1821
+	uint8_t tmpu8;
1822
+	read8le(&tmpu8,is);
1823
+
1824
+	return temp;
1825
+}
1826
+
1827
+/*inline void arm9log()
1828
+{
1829
+#ifdef LOG_ARM9
1830
+	if(dolog)
1831
+	{
1832
+		char dasmbuf[4096];
1833
+		if(NDS_ARM9.CPSR.bits.T)
1834
+			des_thumb_instructions_set[((NDS_ARM9.instruction)>>6)&1023](NDS_ARM9.instruct_adr, NDS_ARM9.instruction, dasmbuf);
1835
+		else
1836
+			des_arm_instructions_set[INDEX(NDS_ARM9.instruction)](NDS_ARM9.instruct_adr, NDS_ARM9.instruction, dasmbuf);
1837
+
1838
+#ifdef LOG_TO_FILE
1839
+		if (!fp_dis9) return;
1840
+#ifdef LOG_TO_FILE_REGS
1841
+		fprintf(fp_dis9, "\t\t;R0:%08X R1:%08X R2:%08X R3:%08X R4:%08X R5:%08X R6:%08X R7:%08X R8:%08X R9:%08X\n\t\t;R10:%08X R11:%08X R12:%08X R13:%08X R14:%08X R15:%08X| next %08X, N:%i Z:%i C:%i V:%i\n",
1842
+			NDS_ARM9.R[0],  NDS_ARM9.R[1],  NDS_ARM9.R[2],  NDS_ARM9.R[3],  NDS_ARM9.R[4],  NDS_ARM9.R[5],  NDS_ARM9.R[6],  NDS_ARM9.R[7],
1843
+			NDS_ARM9.R[8],  NDS_ARM9.R[9],  NDS_ARM9.R[10],  NDS_ARM9.R[11],  NDS_ARM9.R[12],  NDS_ARM9.R[13],  NDS_ARM9.R[14],  NDS_ARM9.R[15],
1844
+			NDS_ARM9.next_instruction, NDS_ARM9.CPSR.bits.N, NDS_ARM9.CPSR.bits.Z, NDS_ARM9.CPSR.bits.C, NDS_ARM9.CPSR.bits.V);
1845
+#endif
1846
+		fprintf(fp_dis9, "%s %08X\t%08X \t%s\n", NDS_ARM9.CPSR.bits.T?"THUMB":"ARM", NDS_ARM9.instruct_adr, NDS_ARM9.instruction, dasmbuf);*/
1847
+		/*if (NDS_ARM9.instruction == 0)
1848
+		{
1849
+			dolog = false;
1850
+			INFO("Disassembler is stopped\n");
1851
+		}*/
1852
+/*#else
1853
+		printf("%05d:%03d %12lld 9:%08X %08X %-30s R00:%08X R01:%08X R02:%08X R03:%08X R04:%08X R05:%08X R06:%08X R07:%08X R08:%08X R09:%08X R10:%08X R11:%08X R12:%08X R13:%08X R14:%08X R15:%08X\n",
1854
+			currFrameCounter, nds.VCount, nds_timer,
1855
+			NDS_ARM9.instruct_adr,NDS_ARM9.instruction, dasmbuf,
1856
+			NDS_ARM9.R[0],  NDS_ARM9.R[1],  NDS_ARM9.R[2],  NDS_ARM9.R[3],  NDS_ARM9.R[4],  NDS_ARM9.R[5],  NDS_ARM9.R[6],  NDS_ARM9.R[7],
1857
+			NDS_ARM9.R[8],  NDS_ARM9.R[9],  NDS_ARM9.R[10],  NDS_ARM9.R[11],  NDS_ARM9.R[12],  NDS_ARM9.R[13],  NDS_ARM9.R[14],  NDS_ARM9.R[15]);
1858
+#endif
1859
+	}
1860
+#endif
1861
+}*/
1862
+
1863
+/*inline void arm7log()
1864
+{
1865
+#ifdef LOG_ARM7
1866
+	if(dolog)
1867
+	{
1868
+		char dasmbuf[4096];
1869
+		if(NDS_ARM7.CPSR.bits.T)
1870
+			des_thumb_instructions_set[((NDS_ARM7.instruction)>>6)&1023](NDS_ARM7.instruct_adr, NDS_ARM7.instruction, dasmbuf);
1871
+		else
1872
+			des_arm_instructions_set[INDEX(NDS_ARM7.instruction)](NDS_ARM7.instruct_adr, NDS_ARM7.instruction, dasmbuf);
1873
+#ifdef LOG_TO_FILE
1874
+		if (!fp_dis7) return;
1875
+#ifdef LOG_TO_FILE_REGS
1876
+		fprintf(fp_dis7, "\t\t;R0:%08X R1:%08X R2:%08X R3:%08X R4:%08X R5:%08X R6:%08X R7:%08X R8:%08X R9:%08X\n\t\t;R10:%08X R11:%08X R12:%08X R13:%08X R14:%08X R15:%08X| next %08X, N:%i Z:%i C:%i V:%i\n",
1877
+			NDS_ARM7.R[0],  NDS_ARM7.R[1],  NDS_ARM7.R[2],  NDS_ARM7.R[3],  NDS_ARM7.R[4],  NDS_ARM7.R[5],  NDS_ARM7.R[6],  NDS_ARM7.R[7],
1878
+			NDS_ARM7.R[8],  NDS_ARM7.R[9],  NDS_ARM7.R[10],  NDS_ARM7.R[11],  NDS_ARM7.R[12],  NDS_ARM7.R[13],  NDS_ARM7.R[14],  NDS_ARM7.R[15],
1879
+			NDS_ARM7.next_instruction, NDS_ARM7.CPSR.bits.N, NDS_ARM7.CPSR.bits.Z, NDS_ARM7.CPSR.bits.C, NDS_ARM7.CPSR.bits.V);
1880
+#endif
1881
+		fprintf(fp_dis7, "%s %08X\t%08X \t%s\n", NDS_ARM7.CPSR.bits.T?"THUMB":"ARM", NDS_ARM7.instruct_adr, NDS_ARM7.instruction, dasmbuf);*/
1882
+		/*if (NDS_ARM7.instruction == 0)
1883
+		{
1884
+			dolog = false;
1885
+			INFO("Disassembler is stopped\n");
1886
+		}*/
1887
+/*#else
1888
+		printf("%05d:%03d %12lld 7:%08X %08X %-30s R00:%08X R01:%08X R02:%08X R03:%08X R04:%08X R05:%08X R06:%08X R07:%08X R08:%08X R09:%08X R10:%08X R11:%08X R12:%08X R13:%08X R14:%08X R15:%08X\n",
1889
+			currFrameCounter, nds.VCount, nds_timer,
1890
+			NDS_ARM7.instruct_adr,NDS_ARM7.instruction, dasmbuf,
1891
+			NDS_ARM7.R[0],  NDS_ARM7.R[1],  NDS_ARM7.R[2],  NDS_ARM7.R[3],  NDS_ARM7.R[4],  NDS_ARM7.R[5],  NDS_ARM7.R[6],  NDS_ARM7.R[7],
1892
+			NDS_ARM7.R[8],  NDS_ARM7.R[9],  NDS_ARM7.R[10],  NDS_ARM7.R[11],  NDS_ARM7.R[12],  NDS_ARM7.R[13],  NDS_ARM7.R[14],  NDS_ARM7.R[15]);
1893
+#endif
1894
+	}
1895
+#endif
1896
+}*/
1897
+
1898
+//these have not been tuned very well yet.
1899
+static const int kMaxWork = 4000;
1900
+static const int kIrqWait = 4000;
1901
+
1902
+
1903
+template<bool doarm9, bool doarm7>
1904
+static inline int32_t minarmtime(int32_t arm9, int32_t arm7)
1905
+{
1906
+	if(doarm9)
1907
+	{
1908
+		if(doarm7)
1909
+			return std::min(arm9,arm7);
1910
+		else
1911
+			return arm9;
1912
+	}
1913
+	else
1914
+		return arm7;
1915
+}
1916
+
1917
+template<bool doarm9, bool doarm7>
1918
+static /*donotinline*/ std::pair<int32_t,int32_t> armInnerLoop(
1919
+	const uint64_t nds_timer_base, const int32_t s32next, int32_t arm9, int32_t arm7)
1920
+{
1921
+	int32_t timer = minarmtime<doarm9,doarm7>(arm9,arm7);
1922
+	while(timer < s32next && !sequencer.reschedule && execute)
1923
+	{
1924
+		if(doarm9 && (!doarm7 || arm9 <= timer))
1925
+		{
1926
+			if(!NDS_ARM9.waitIRQ&&!nds.freezeBus)
1927
+			{
1928
+				//arm9log();
1929
+				arm9 += armcpu_exec<ARMCPU_ARM9>();
1930
+				#ifdef DEVELOPER
1931
+					nds_debug_continuing[0] = false;
1932
+				#endif
1933
+			}
1934
+			else
1935
+			{
1936
+				//int32_t temp = arm9;
1937
+				arm9 = std::min(s32next, arm9 + kIrqWait);
1938
+				//nds.idleCycles[0] += arm9-temp;
1939
+				//if (gxFIFO.size < 255) nds.freezeBus = false;
1940
+			}
1941
+		}
1942
+		if(doarm7 && (!doarm9 || arm7 <= timer))
1943
+		{
1944
+			if(!NDS_ARM7.waitIRQ&&!nds.freezeBus)
1945
+			{
1946
+				//arm7log();
1947
+				arm7 += (armcpu_exec<ARMCPU_ARM7>()<<1);
1948
+				#ifdef DEVELOPER
1949
+					nds_debug_continuing[1] = false;
1950
+				#endif
1951
+			}
1952
+			else
1953
+			{
1954
+				//int32_t temp = arm7;
1955
+				arm7 = std::min(s32next, arm7 + kIrqWait);
1956
+				//nds.idleCycles[1] += arm7-temp;
1957
+				if(arm7 == s32next)
1958
+				{
1959
+					nds_timer = nds_timer_base + minarmtime<doarm9,false>(arm9,arm7);
1960
+					return armInnerLoop<doarm9,false>(nds_timer_base, s32next, arm9, arm7);
1961
+				}
1962
+			}
1963
+		}
1964
+
1965
+		timer = minarmtime<doarm9,doarm7>(arm9,arm7);
1966
+		nds_timer = nds_timer_base + timer;
1967
+	}
1968
+
1969
+	return std::make_pair(arm9, arm7);
1970
+}
1971
+
1972
+/*void NDS_debug_break()
1973
+{
1974
+	NDS_ARM9.stalled = NDS_ARM7.stalled = 1;
1975
+
1976
+	//triggers an immediate exit from the cpu loop
1977
+	NDS_Reschedule();
1978
+}*/
1979
+
1980
+/*void NDS_debug_continue()
1981
+{
1982
+	NDS_ARM9.stalled = NDS_ARM7.stalled = 0;
1983
+}*/
1984
+
1985
+/*void NDS_debug_step()
1986
+{
1987
+	NDS_debug_continue();
1988
+	singleStep = true;
1989
+}*/
1990
+
1991
+template<bool FORCE>
1992
+void NDS_exec(int32_t)
1993
+{
1994
+	//LagFrameFlag=1;
1995
+
1996
+	/*if((currFrameCounter&63) == 0)
1997
+		MMU_new.backupDevice.lazy_flush();*/
1998
+
1999
+	sequencer.nds_vblankEnded = false;
2000
+
2001
+	//nds.cpuloopIterationCount = 0;
2002
+
2003
+	IF_DEVELOPER(for(int i=0;i<32;i++) DEBUG_statistics.sequencerExecutionCounters[i] = 0);
2004
+
2005
+	if(nds.sleeping)
2006
+	{
2007
+		//speculative code: if ANY irq happens, wake up the arm7.
2008
+		//I think the arm7 program analyzes the system and may decide not to wake up
2009
+		//if it is dissatisfied with the conditions
2010
+		if((MMU.reg_IE[1] & MMU.gen_IF<1>()))
2011
+		{
2012
+			nds.sleeping = false;
2013
+		}
2014
+	}
2015
+	else
2016
+	{
2017
+		for(;;)
2018
+		{
2019
+			//trap the debug-stalled condition
2020
+			#ifdef DEVELOPER
2021
+				singleStep = false;
2022
+				//(gdb stub doesnt yet know how to trigger these immediately by calling reschedule)
2023
+				while((NDS_ARM9.stalled || NDS_ARM7.stalled) && execute)
2024
+				{
2025
+					driver->EMU_DebugIdleUpdate();
2026
+					nds_debug_continuing[0] = nds_debug_continuing[1] = true;
2027
+				}
2028
+			#endif
2029
+
2030
+			//nds.cpuloopIterationCount++;
2031
+			sequencer.execHardware();
2032
+
2033
+			//break out once per frame
2034
+			if(sequencer.nds_vblankEnded) break;
2035
+			//it should be benign to execute execHardware in the next frame,
2036
+			//since there won't be anything for it to do (everything should be scheduled in the future)
2037
+
2038
+			//bail in case the system halted
2039
+			if(!execute) break;
2040
+
2041
+			execHardware_interrupts();
2042
+
2043
+			//find next work unit:
2044
+			uint64_t next = sequencer.findNext();
2045
+			next = std::min(next,nds_timer+kMaxWork); //lets set an upper limit for now
2046
+
2047
+			//printf("%d\n",(next-nds_timer));
2048
+
2049
+			sequencer.reschedule = false;
2050
+
2051
+			//cast these down to 32bits so that things run faster on 32bit procs
2052
+			uint64_t nds_timer_base = nds_timer;
2053
+			int32_t arm9 = (int32_t)(nds_arm9_timer-nds_timer);
2054
+			int32_t arm7 = (int32_t)(nds_arm7_timer-nds_timer);
2055
+			int32_t s32next = (int32_t)(next-nds_timer);
2056
+
2057
+			#ifdef DEVELOPER
2058
+				if(singleStep)
2059
+				{
2060
+					s32next = 1;
2061
+				}
2062
+			#endif
2063
+
2064
+			std::pair<int32_t,int32_t> arm9arm7 = armInnerLoop<true,true>(nds_timer_base,s32next,arm9,arm7);
2065
+
2066
+			#ifdef DEVELOPER
2067
+				if(singleStep)
2068
+				{
2069
+					NDS_ARM9.stalled = NDS_ARM7.stalled = 1;
2070
+				}
2071
+			#endif
2072
+
2073
+			arm9 = arm9arm7.first;
2074
+			arm7 = arm9arm7.second;
2075
+			nds_arm7_timer = nds_timer_base+arm7;
2076
+			nds_arm9_timer = nds_timer_base+arm9;
2077
+
2078
+#ifndef NDEBUG
2079
+			//what we find here is dependent on the timing constants above
2080
+			//if(nds_timer>next && (nds_timer-next)>22)
2081
+			//	printf("curious. please report: over by %d\n",(int)(nds_timer-next));
2082
+#endif
2083
+
2084
+			//if we were waiting for an irq, don't wait too long:
2085
+			//let's re-analyze it after this hardware event (this rolls back a big burst of irq waiting which may have been interrupted by a resynch)
2086
+			if(NDS_ARM9.waitIRQ)
2087
+			{
2088
+				//nds.idleCycles[0] -= (int32_t)(nds_arm9_timer-nds_timer);
2089
+				nds_arm9_timer = nds_timer;
2090
+			}
2091
+			if(NDS_ARM7.waitIRQ)
2092
+			{
2093
+				//nds.idleCycles[1] -= (int32_t)(nds_arm7_timer-nds_timer);
2094
+				nds_arm7_timer = nds_timer;
2095
+			}
2096
+		}
2097
+	}
2098
+
2099
+	//DEBUG_statistics.printSequencerExecutionCounters();
2100
+	//DEBUG_statistics.print();
2101
+
2102
+	//end of frame emulation housekeeping
2103
+	/*if(LagFrameFlag)
2104
+	{
2105
+		lagframecounter++;
2106
+		TotalLagFrames++;
2107
+	}
2108
+	else
2109
+	{
2110
+		lastLag = lagframecounter;
2111
+		lagframecounter = 0;
2112
+	}*/
2113
+	//currFrameCounter++;
2114
+	//DEBUG_Notify.NextFrame();
2115
+	/*if (cheats)
2116
+		cheats->process();*/
2117
+}
2118
+
2119
+template<int PROCNUM> static void execHardware_interrupts_core()
2120
+{
2121
+	uint32_t IF = MMU.gen_IF<PROCNUM>();
2122
+	uint32_t IE = MMU.reg_IE[PROCNUM];
2123
+	uint32_t masked = IF & IE;
2124
+	if(ARMPROC.halt_IE_and_IF && masked)
2125
+	{
2126
+		ARMPROC.halt_IE_and_IF = false;
2127
+		ARMPROC.waitIRQ = false;
2128
+	}
2129
+
2130
+	if(masked && MMU.reg_IME[PROCNUM] && !ARMPROC.CPSR.bits.I)
2131
+	{
2132
+		//printf("Executing IRQ on procnum %d with IF = %08X and IE = %08X\n",PROCNUM,IF,IE);
2133
+		armcpu_irqException(&ARMPROC);
2134
+	}
2135
+}
2136
+
2137
+void execHardware_interrupts()
2138
+{
2139
+	execHardware_interrupts_core<ARMCPU_ARM9>();
2140
+	execHardware_interrupts_core<ARMCPU_ARM7>();
2141
+}
2142
+
2143
+//static void resetUserInput();
2144
+
2145
+//bool _HACK_DONT_STOPMOVIE = false;
2146
+void NDS_Reset()
2147
+{
2148
+	singleStep = false;
2149
+	//nds_debug_continuing[0] = nds_debug_continuing[1] = false;
2150
+	uint32_t src = 0;
2151
+	uint32_t dst = 0;
2152
+	bool fw_success = false;
2153
+	FILE* inf = NULL;
2154
+	NDS_header * header = NDS_getROMHeader();
2155
+
2156
+	//DEBUG_reset();
2157
+
2158
+	if (!header) return ;
2159
+
2160
+	nds.sleeping = false;
2161
+	nds.cardEjected = false;
2162
+	nds.freezeBus = 0;
2163
+	//nds.power1.lcd = nds.power1.gpuMain = nds.power1.gfx3d_render = nds.power1.gfx3d_geometry = nds.power1.gpuSub = nds.power1.dispswap = 1;
2164
+	//nds.power2.speakers = 1;
2165
+	//nds.power2.wifi = 0;
2166
+
2167
+	nds_timer = 0;
2168
+	nds_arm9_timer = 0;
2169
+	nds_arm7_timer = 0;
2170
+
2171
+	/*if(movieMode != MOVIEMODE_INACTIVE && !_HACK_DONT_STOPMOVIE)
2172
+		movie_reset_command = true;*/
2173
+
2174
+	/*if(movieMode == MOVIEMODE_INACTIVE) {
2175
+		//currFrameCounter = 0;
2176
+		lagframecounter = 0;
2177
+		LagFrameFlag = 0;
2178
+		lastLag = 0;
2179
+		TotalLagFrames = 0;
2180
+	}*/
2181
+
2182
+	SPU_DeInit();
2183
+
2184
+	MMU_Reset();
2185
+
2186
+	//put random garbage in vram for homebrew games, to help mimic the situation where libnds does not clear out junk
2187
+	//which the card's launcher may or may not have left behind
2188
+  //1. retail games dont clear TCM, so why should we jumble it and expect homebrew to clear it?
2189
+  //2. some retail games _dont boot_ if main memory is jumbled. wha...?
2190
+  //3. clearing this is not as useful as tracking uninitialized reads in dev+ builds
2191
+  //4. the vram clearing causes lots of graphical corruptions in badly coded homebrews. this reduces compatibility substantially
2192
+  //conclusion: disable it for now and bring it back as an option
2193
+	//if(gameInfo.isHomebrew)
2194
+	//{
2195
+	//	uint32_t w=100000,x=99,y=117,z=19382173;
2196
+	//	CTASSERT(sizeof(MMU.ARM9_LCD) < sizeof(MMU.MAIN_MEM));
2197
+	//	CTASSERT(sizeof(MMU.ARM9_VMEM) < sizeof(MMU.MAIN_MEM));
2198
+	//	CTASSERT(sizeof(MMU.ARM9_ITCM) < sizeof(MMU.MAIN_MEM));
2199
+	//	CTASSERT(sizeof(MMU.ARM9_DTCM) < sizeof(MMU.MAIN_MEM));
2200
+	//	for(int i=0;i<sizeof(MMU.MAIN_MEM);i++)
2201
+	//	{
2202
+	//		uint32_t t= (x^(x<<11));
2203
+	//		x=y;
2204
+	//		y=z;
2205
+	//		z=w;
2206
+	//		t = (w= (w^(w>>19))^(t^(t>>8)));
2207
+	//		//MMU.MAIN_MEM[i] = t;
2208
+	//		if (i<sizeof(MMU.ARM9_LCD)) MMU.ARM9_LCD[i] = t;
2209
+	//		if (i<sizeof(MMU.ARM9_VMEM)) MMU.ARM9_VMEM[i] = t;
2210
+	//		//if (i<sizeof(MMU.ARM9_ITCM)) MMU.ARM9_ITCM[i] = t;
2211
+	//		//if (i<sizeof(MMU.ARM9_DTCM)) MMU.ARM9_DTCM[i] = t;
2212
+	//	}
2213
+	//}
2214
+
2215
+	NDS_ARM7.BIOS_loaded = false;
2216
+	NDS_ARM9.BIOS_loaded = false;
2217
+	memset(MMU.ARM7_BIOS, 0, sizeof(MMU.ARM7_BIOS));
2218
+	memset(MMU.ARM9_BIOS, 0, sizeof(MMU.ARM9_BIOS));
2219
+
2220
+	//ARM7 BIOS IRQ HANDLER
2221
+	if(CommonSettings.UseExtBIOS == true)
2222
+		inf = fopen(CommonSettings.ARM7BIOS,"rb");
2223
+	else
2224
+		inf = NULL;
2225
+
2226
+	if(inf)
2227
+	{
2228
+		if (fread(MMU.ARM7_BIOS,1,16384,inf) == 16384) NDS_ARM7.BIOS_loaded = true;
2229
+		fclose(inf);
2230
+
2231
+		if((CommonSettings.SWIFromBIOS) && (NDS_ARM7.BIOS_loaded)) NDS_ARM7.swi_tab = 0;
2232
+		else NDS_ARM7.swi_tab = ARM7_swi_tab;
2233
+
2234
+		if (CommonSettings.PatchSWI3)
2235
+			_MMU_write16<ARMCPU_ARM7>(0x00002F08, 0x4770);
2236
+
2237
+		//INFO("ARM7 BIOS is %s.\n", NDS_ARM7.BIOS_loaded?"loaded":"failed");
2238
+	}
2239
+	else
2240
+	{
2241
+		NDS_ARM7.swi_tab = ARM7_swi_tab;
2242
+
2243
+#if 0
2244
+		// TODO
2245
+		T1WriteLong(MMU.ARM7_BIOS, 0x0000, 0xEAFFFFFE);		// loop for Reset !!!
2246
+		T1WriteLong(MMU.ARM7_BIOS, 0x0004, 0xEAFFFFFE);		// loop for Undef instr expection
2247
+		T1WriteLong(MMU.ARM7_BIOS, 0x0008, 0xEA00009C);		// SWI
2248
+		T1WriteLong(MMU.ARM7_BIOS, 0x000C, 0xEAFFFFFE);		// loop for Prefetch Abort
2249
+		T1WriteLong(MMU.ARM7_BIOS, 0x0010, 0xEAFFFFFE);		// loop for Data Abort
2250
+		T1WriteLong(MMU.ARM7_BIOS, 0x0014, 0x00000000);		// Reserved
2251
+		T1WriteLong(MMU.ARM7_BIOS, 0x001C, 0x00000000);		// Fast IRQ
2252
+#endif
2253
+		T1WriteLong(MMU.ARM7_BIOS, 0x0000, 0xE25EF002);
2254
+		T1WriteLong(MMU.ARM7_BIOS, 0x0018, 0xEA000000);
2255
+		T1WriteLong(MMU.ARM7_BIOS, 0x0020, 0xE92D500F);
2256
+		T1WriteLong(MMU.ARM7_BIOS, 0x0024, 0xE3A00301);
2257
+		T1WriteLong(MMU.ARM7_BIOS, 0x0028, 0xE28FE000);
2258
+		T1WriteLong(MMU.ARM7_BIOS, 0x002C, 0xE510F004);
2259
+		T1WriteLong(MMU.ARM7_BIOS, 0x0030, 0xE8BD500F);
2260
+		T1WriteLong(MMU.ARM7_BIOS, 0x0034, 0xE25EF004);
2261
+	}
2262
+
2263
+	//ARM9 BIOS IRQ HANDLER
2264
+	if(CommonSettings.UseExtBIOS == true)
2265
+		inf = fopen(CommonSettings.ARM9BIOS,"rb");
2266
+	else
2267
+		inf = NULL;
2268
+
2269
+	if(inf)
2270
+	{
2271
+		if (fread(MMU.ARM9_BIOS,1,4096,inf) == 4096) NDS_ARM9.BIOS_loaded = true;
2272
+		fclose(inf);
2273
+
2274
+		if((CommonSettings.SWIFromBIOS) && (NDS_ARM9.BIOS_loaded)) NDS_ARM9.swi_tab = 0;
2275
+		else NDS_ARM9.swi_tab = ARM9_swi_tab;
2276
+
2277
+		if (CommonSettings.PatchSWI3)
2278
+			_MMU_write16<ARMCPU_ARM9>(0xFFFF07CC, 0x4770);
2279
+
2280
+		//INFO("ARM9 BIOS is %s.\n", NDS_ARM9.BIOS_loaded?"loaded":"failed");
2281
+	}
2282
+	else
2283
+	{
2284
+		NDS_ARM9.swi_tab = ARM9_swi_tab;
2285
+
2286
+		//bios chains data abort to fast irq
2287
+
2288
+		//exception vectors:
2289
+		T1WriteLong(MMU.ARM9_BIOS, 0x0000, 0xEAFFFFFE);		// (infinite loop for) Reset !!!
2290
+		//T1WriteLong(MMU.ARM9_BIOS, 0x0004, 0xEAFFFFFE);		// (infinite loop for) Undefined instruction
2291
+		T1WriteLong(MMU.ARM9_BIOS, 0x0004, 0xEA000004);		// Undefined instruction -> Fast IRQ (just guessing)
2292
+		T1WriteLong(MMU.ARM9_BIOS, 0x0008, 0xEA00009C);		// SWI -> ?????
2293
+		T1WriteLong(MMU.ARM9_BIOS, 0x000C, 0xEAFFFFFE);		// (infinite loop for) Prefetch Abort
2294
+		T1WriteLong(MMU.ARM9_BIOS, 0x0010, 0xEA000001);		// Data Abort -> Fast IRQ
2295
+		T1WriteLong(MMU.ARM9_BIOS, 0x0014, 0x00000000);		// Reserved
2296
+		T1WriteLong(MMU.ARM9_BIOS, 0x0018, 0xEA000095);		// Normal IRQ -> 0x0274
2297
+		T1WriteLong(MMU.ARM9_BIOS, 0x001C, 0xEA00009D);		// Fast IRQ -> 0x0298
2298
+
2299
+		// logo (do some games fail to boot without this? example?)
2300
+		for (int t = 0; t < 0x9C; t++)
2301
+			MMU.ARM9_BIOS[t + 0x20] = logo_data[t];
2302
+
2303
+		//...0xBC:
2304
+
2305
+		//(now what goes in this gap??)
2306
+
2307
+		//IRQ handler: get dtcm address and jump to a vector in it
2308
+		T1WriteLong(MMU.ARM9_BIOS, 0x0274, 0xE92D500F); //STMDB SP!, {R0-R3,R12,LR}
2309
+		T1WriteLong(MMU.ARM9_BIOS, 0x0278, 0xEE190F11); //MRC CP15, 0, R0, CR9, CR1, 0
2310
+		T1WriteLong(MMU.ARM9_BIOS, 0x027C, 0xE1A00620); //MOV R0, R0, LSR #C
2311
+		T1WriteLong(MMU.ARM9_BIOS, 0x0280, 0xE1A00600); //MOV R0, R0, LSL #C
2312
+		T1WriteLong(MMU.ARM9_BIOS, 0x0284, 0xE2800C40); //ADD R0, R0, #4000
2313
+		T1WriteLong(MMU.ARM9_BIOS, 0x0288, 0xE28FE000); //ADD LR, PC, #0
2314
+		T1WriteLong(MMU.ARM9_BIOS, 0x028C, 0xE510F004); //LDR PC, [R0, -#4]
2315
+
2316
+		//????
2317
+		T1WriteLong(MMU.ARM9_BIOS, 0x0290, 0xE8BD500F); //LDMIA SP!, {R0-R3,R12,LR}
2318
+		T1WriteLong(MMU.ARM9_BIOS, 0x0294, 0xE25EF004); //SUBS PC, LR, #4
2319
+
2320
+		//-------
2321
+		//FIQ and abort exception handler
2322
+		//TODO - this code is copied from the bios. refactor it
2323
+		//friendly reminder: to calculate an immediate offset: encoded = (desired_address-cur_address-8)
2324
+
2325
+		T1WriteLong(MMU.ARM9_BIOS, 0x0298, 0xE10FD000); //MRS SP, CPSR
2326
+		T1WriteLong(MMU.ARM9_BIOS, 0x029C, 0xE38DD0C0); //ORR SP, SP, #C0
2327
+
2328
+		T1WriteLong(MMU.ARM9_BIOS, 0x02A0, 0xE12FF00D); //MSR CPSR_fsxc, SP
2329
+		T1WriteLong(MMU.ARM9_BIOS, 0x02A4, 0xE59FD000 | (0x2D4-0x2A4-8)); //LDR SP, [FFFF02D4]
2330
+		T1WriteLong(MMU.ARM9_BIOS, 0x02A8, 0xE28DD001); //ADD SP, SP, #1
2331
+		T1WriteLong(MMU.ARM9_BIOS, 0x02AC, 0xE92D5000); //STMDB SP!, {R12,LR}
2332
+
2333
+		T1WriteLong(MMU.ARM9_BIOS, 0x02B0, 0xE14FE000); //MRS LR, SPSR
2334
+		T1WriteLong(MMU.ARM9_BIOS, 0x02B4, 0xEE11CF10); //MRC CP15, 0, R12, CR1, CR0, 0
2335
+		T1WriteLong(MMU.ARM9_BIOS, 0x02B8, 0xE92D5000); //STMDB SP!, {R12,LR}
2336
+		T1WriteLong(MMU.ARM9_BIOS, 0x02BC, 0xE3CCC001); //BIC R12, R12, #1
2337
+
2338
+		T1WriteLong(MMU.ARM9_BIOS, 0x02C0, 0xEE01CF10); //MCR CP15, 0, R12, CR1, CR0, 0
2339
+		T1WriteLong(MMU.ARM9_BIOS, 0x02C4, 0xE3CDC001); //BIC R12, SP, #1
2340
+		T1WriteLong(MMU.ARM9_BIOS, 0x02C8, 0xE59CC010); //LDR R12, [R12, #10]
2341
+		T1WriteLong(MMU.ARM9_BIOS, 0x02CC, 0xE35C0000); //CMP R12, #0
2342
+
2343
+		T1WriteLong(MMU.ARM9_BIOS, 0x02D0, 0x112FFF3C); //BLXNE R12
2344
+		T1WriteLong(MMU.ARM9_BIOS, 0x02D4, 0x027FFD9C); //0x027FFD9C
2345
+		//---------
2346
+
2347
+	}
2348
+
2349
+#ifdef LOG_ARM7
2350
+	if (fp_dis7 != NULL)
2351
+	{
2352
+		fclose(fp_dis7);
2353
+		fp_dis7 = NULL;
2354
+	}
2355
+	fp_dis7 = fopen("D:\\desmume_dis7.asm", "w");
2356
+#endif
2357
+
2358
+#ifdef LOG_ARM9
2359
+	if (fp_dis9 != NULL)
2360
+	{
2361
+		fclose(fp_dis9);
2362
+		fp_dis9 = NULL;
2363
+	}
2364
+	fp_dis9 = fopen("D:\\desmume_dis9.asm", "w");
2365
+#endif
2366
+
2367
+	if (firmware)
2368
+	{
2369
+		delete firmware;
2370
+		firmware = NULL;
2371
+	}
2372
+	firmware = new CFIRMWARE();
2373
+	fw_success = firmware->load();
2374
+	if (NDS_ARM7.BIOS_loaded && NDS_ARM9.BIOS_loaded && CommonSettings.BootFromFirmware && fw_success)
2375
+	{
2376
+		// Copy secure area to memory if needed
2377
+		if ((header->ARM9src >= 0x4000) && (header->ARM9src < 0x8000))
2378
+		{
2379
+			src = header->ARM9src;
2380
+			dst = header->ARM9cpy;
2381
+
2382
+			uint32_t size = (0x8000 - src) >> 2;
2383
+			//INFO("Copy secure area from 0x%08X to 0x%08X (size %i/0x%08X)\n", src, dst, size, size);
2384
+			for (uint32_t i = 0; i < size; i++)
2385
+			{
2386
+				_MMU_write32<ARMCPU_ARM9>(dst, T1ReadLong(MMU.CART_ROM, src));
2387
+				src += 4; dst += 4;
2388
+			}
2389
+		}
2390
+
2391
+		if (firmware->patched)
2392
+		{
2393
+			armcpu_init(&NDS_ARM7, 0x00000008);
2394
+			armcpu_init(&NDS_ARM9, 0xFFFF0008);
2395
+		}
2396
+		else
2397
+		{
2398
+			//INFO("Booting at ARM9: 0x%08X, ARM7: 0x%08X\n", firmware->ARM9bootAddr, firmware->ARM7bootAddr);
2399
+			// need for firmware
2400
+			//armcpu_init(&NDS_ARM7, 0x00000008);
2401
+			//armcpu_init(&NDS_ARM9, 0xFFFF0008);
2402
+			armcpu_init(&NDS_ARM7, firmware->ARM7bootAddr);
2403
+			armcpu_init(&NDS_ARM9, firmware->ARM9bootAddr);
2404
+		}
2405
+
2406
+			_MMU_write08<ARMCPU_ARM9>(0x04000300, 0);
2407
+			_MMU_write08<ARMCPU_ARM7>(0x04000300, 0);
2408
+	}
2409
+	else
2410
+	{
2411
+		src = header->ARM9src;
2412
+		dst = header->ARM9cpy;
2413
+
2414
+		for(uint32_t i = 0; i < (header->ARM9binSize>>2); ++i)
2415
+		{
2416
+			_MMU_write32<ARMCPU_ARM9>(dst, T1ReadLong(MMU.CART_ROM, src));
2417
+			dst += 4;
2418
+			src += 4;
2419
+		}
2420
+
2421
+		src = header->ARM7src;
2422
+		dst = header->ARM7cpy;
2423
+
2424
+		for(uint32_t i = 0; i < (header->ARM7binSize>>2); ++i)
2425
+		{
2426
+			_MMU_write32<ARMCPU_ARM7>(dst, T1ReadLong(MMU.CART_ROM, src));
2427
+			dst += 4;
2428
+			src += 4;
2429
+		}
2430
+
2431
+		armcpu_init(&NDS_ARM7, header->ARM7exe);
2432
+		armcpu_init(&NDS_ARM9, header->ARM9exe);
2433
+
2434
+		_MMU_write08<ARMCPU_ARM9>(REG_POSTFLG, 1);
2435
+		_MMU_write08<ARMCPU_ARM7>(REG_POSTFLG, 1);
2436
+	}
2437
+	//bitbox 4k demo is so stripped down it relies on default stack values
2438
+	//otherwise the arm7 will crash before making a sound
2439
+	//(these according to gbatek softreset bios docs)
2440
+	NDS_ARM7.R13_svc = 0x0380FFDC;
2441
+	NDS_ARM7.R13_irq = 0x0380FFB0;
2442
+	NDS_ARM7.R13_usr = 0x0380FF00;
2443
+	NDS_ARM7.R[13] = NDS_ARM7.R13_usr;
2444
+	//and let's set these for the arm9 while we're at it, though we have no proof
2445
+	NDS_ARM9.R13_svc = 0x00803FC0;
2446
+	NDS_ARM9.R13_irq = 0x00803FA0;
2447
+	NDS_ARM9.R13_usr = 0x00803EC0;
2448
+	NDS_ARM9.R13_abt = NDS_ARM9.R13_usr; //?????
2449
+	//I think it is wrong to take gbatek's "SYS" and put it in USR--maybe USR doesnt matter.
2450
+	//i think SYS is all the misc modes. please verify by setting nonsensical stack values for USR here
2451
+	NDS_ARM9.R[13] = NDS_ARM9.R13_usr;
2452
+	//n.b.: im not sure about all these, I dont know enough about arm9 svc/irq/etc modes
2453
+	//and how theyre named in desmume to match them up correctly. i just guessed.
2454
+
2455
+	//nds.wifiCycle = 0;
2456
+	memset(nds.timerCycle, 0, sizeof(uint64_t) * 2 * 4);
2457
+	nds.old = 0;
2458
+	//nds.touchX = nds.touchY = 0;
2459
+	//nds.isTouch = 0;
2460
+	//nds.debugConsole = CommonSettings.DebugConsole;
2461
+	//nds.ensataEmulation = CommonSettings.EnsataEmulation;
2462
+	//nds.ensataHandshake = ENSATA_HANDSHAKE_none;
2463
+	//nds.ensataIpcSyncCounter = 0;
2464
+	SetupMMU(/*nds.Is_DebugConsole()*/false,nds.Is_DSI());
2465
+
2466
+	_MMU_write16<ARMCPU_ARM9>(REG_KEYINPUT, 0x3FF);
2467
+	_MMU_write16<ARMCPU_ARM7>(REG_KEYINPUT, 0x3FF);
2468
+	_MMU_write08<ARMCPU_ARM7>(REG_EXTKEYIN, 0x43);
2469
+
2470
+	//LidClosed = false;
2471
+	//countLid = 0;
2472
+
2473
+	//resetUserInput();
2474
+
2475
+	//Setup a copy of the firmware user settings in memory.
2476
+	//(this is what the DS firmware would do).
2477
+	{
2478
+		uint8_t temp_buffer[NDS_FW_USER_SETTINGS_MEM_BYTE_COUNT];
2479
+		int fw_index;
2480
+
2481
+		if ( copy_firmware_user_data( temp_buffer, &MMU.fw.data[0])) {
2482
+			for ( fw_index = 0; fw_index < NDS_FW_USER_SETTINGS_MEM_BYTE_COUNT; fw_index++)
2483
+				_MMU_write08<ARMCPU_ARM9>(0x027FFC80 + fw_index, temp_buffer[fw_index]);
2484
+		}
2485
+	}
2486
+
2487
+	// Copy the whole header to Main RAM 0x27FFE00 on startup. (http://nocash.emubase.de/gbatek.htm#dscartridgeheader)
2488
+	//once upon a time this copied 0x90 more. this was thought to be wrong, and changed.
2489
+	if(nds.Is_DSI())
2490
+	{
2491
+		//dsi needs this copied later in memory. there are probably a number of things that  get copied to a later location in memory.. thats where the NDS consoles tend to stash stuff.
2492
+		for (int i = 0; i < ((0x170)/4); i++)
2493
+			_MMU_write32<ARMCPU_ARM9>(0x02FFFE00+i*4, LE_TO_LOCAL_32(((uint32_t*)MMU.CART_ROM)[i]));
2494
+	}
2495
+	else
2496
+	{
2497
+		for (int i = 0; i < ((0x170)/4); i++)
2498
+			_MMU_write32<ARMCPU_ARM9>(0x027FFE00+i*4, LE_TO_LOCAL_32(((uint32_t*)MMU.CART_ROM)[i]));
2499
+	}
2500
+
2501
+	// Write the header checksum to memory (the firmware needs it to see the cart)
2502
+	_MMU_write16<ARMCPU_ARM9>(0x027FF808, T1ReadWord(MMU.CART_ROM, 0x15E));
2503
+
2504
+	//--------------------------------
2505
+	//setup the homebrew argv
2506
+	//this is useful for nitrofs apps which are emulating themselves via cflash
2507
+	//struct __argv {
2508
+	//	int argvMagic;		//!< argv magic number, set to 0x5f617267 ('_arg') if valid
2509
+	//	char *commandLine;	//!< base address of command line, set of null terminated strings
2510
+	//	int length;			//!< total length of command line
2511
+	//	int argc;			//!< internal use, number of arguments
2512
+	//	char **argv;		//!< internal use, argv pointer
2513
+	//};
2514
+	std::string rompath = "fat:/" + path.RomName;
2515
+	const uint32_t kCommandline = 0x027E0000;
2516
+	//const uint32_t kCommandline = 0x027FFF84;
2517
+
2518
+	//
2519
+	_MMU_write32<ARMCPU_ARM9>(0x02FFFE70, 0x5f617267);
2520
+	_MMU_write32<ARMCPU_ARM9>(0x02FFFE74, kCommandline); //(commandline starts here)
2521
+	_MMU_write32<ARMCPU_ARM9>(0x02FFFE78, rompath.size()+1);
2522
+	//0x027FFF7C (argc)
2523
+	//0x027FFF80 (argv)
2524
+	for(size_t i=0;i<rompath.size();i++)
2525
+		_MMU_write08<ARMCPU_ARM9>(kCommandline+i, rompath[i]);
2526
+	_MMU_write08<ARMCPU_ARM9>(kCommandline+rompath.size(), 0);
2527
+	//--------------------------------
2528
+
2529
+	if ((firmware->patched) && (CommonSettings.UseExtBIOS == true) && (CommonSettings.BootFromFirmware == true) && (fw_success == true))
2530
+	{
2531
+		// HACK! for flashme
2532
+		_MMU_write32<ARMCPU_ARM9>(0x27FFE24, firmware->ARM9bootAddr);
2533
+		_MMU_write32<ARMCPU_ARM7>(0x27FFE34, firmware->ARM7bootAddr);
2534
+	}
2535
+
2536
+	// make system think it's booted from card -- EXTREMELY IMPORTANT!!! Thanks to cReDiAr
2537
+	_MMU_write08<ARMCPU_ARM9>(0x02FFFC40,0x1);
2538
+	_MMU_write08<ARMCPU_ARM7>(0x02FFFC40,0x1);
2539
+
2540
+	// Save touchscreen calibration info in a structure
2541
+	// so we can easily access it at any time
2542
+	//TSCal.adc.x1 = _MMU_read16<ARMCPU_ARM7>(0x027FFC80 + 0x58);
2543
+	//TSCal.adc.y1 = _MMU_read16<ARMCPU_ARM7>(0x027FFC80 + 0x5A);
2544
+	//TSCal.scr.x1 = _MMU_read08<ARMCPU_ARM7>(0x027FFC80 + 0x5C);
2545
+	//TSCal.scr.y1 = _MMU_read08<ARMCPU_ARM7>(0x027FFC80 + 0x5D);
2546
+	//TSCal.adc.x2 = _MMU_read16<ARMCPU_ARM7>(0x027FFC80 + 0x5E);
2547
+	//TSCal.adc.y2 = _MMU_read16<ARMCPU_ARM7>(0x027FFC80 + 0x60);
2548
+	//TSCal.scr.x2 = _MMU_read08<ARMCPU_ARM7>(0x027FFC80 + 0x62);
2549
+	//TSCal.scr.y2 = _MMU_read08<ARMCPU_ARM7>(0x027FFC80 + 0x63);
2550
+
2551
+	//TSCal.adc.width = (TSCal.adc.x2 - TSCal.adc.x1);
2552
+	//TSCal.adc.height = (TSCal.adc.y2 - TSCal.adc.y1);
2553
+	//TSCal.scr.width = (TSCal.scr.x2 - TSCal.scr.x1);
2554
+	//TSCal.scr.height = (TSCal.scr.y2 - TSCal.scr.y1);
2555
+
2556
+	//MainScreen.offset = 0;
2557
+	//SubScreen.offset = 192;
2558
+
2559
+	//_MMU_write32[ARMCPU_ARM9](0x02007FFC, 0xE92D4030);
2560
+
2561
+	delete header;
2562
+
2563
+	//Screen_Reset();
2564
+	//gfx3d_reset();
2565
+	//gpu3D->NDS_3D_Reset();
2566
+	//slot1Reset();
2567
+
2568
+	//WIFI_Reset();
2569
+
2570
+	//memcpy(FW_Mac, (MMU.fw.data + 0x36), 6);
2571
+
2572
+	initSchedule();
2573
+
2574
+	SPU_ReInit();
2575
+}
2576
+
2577
+/*static std::string MakeInputDisplayString(uint16_t pad, const std::string* Buttons, int count) {
2578
+    std::string s;
2579
+    for (int x = 0; x < count; x++) {
2580
+        if (pad & (1 << x))
2581
+            s.append(Buttons[x].size(), ' ');
2582
+        else
2583
+            s += Buttons[x];
2584
+    }
2585
+    return s;
2586
+}*/
2587
+
2588
+/*static std::string MakeInputDisplayString(uint16_t pad, uint16_t padExt) {
2589
+    const std::string Buttons[] = {"A", "B", "Sl", "St", "R", "L", "U", "D", "Rs", "Ls"};
2590
+    const std::string Ext[] = {"X", "Y"};
2591
+
2592
+    std::string s = MakeInputDisplayString(pad, Ext, ARRAY_SIZE(Ext));
2593
+    s += MakeInputDisplayString(padExt, Buttons, ARRAY_SIZE(Buttons));
2594
+
2595
+    return s;
2596
+}*/
2597
+
2598
+
2599
+//buttonstruct<bool> Turbo;
2600
+buttonstruct<int> TurboTime;
2601
+//buttonstruct<bool> AutoHold;
2602
+
2603
+/*void ClearAutoHold() {
2604
+
2605
+	for (uint32_t i=0; i < ARRAY_SIZE(AutoHold.array); i++) {
2606
+		AutoHold.array[i]=false;
2607
+	}
2608
+}*/
2609
+
2610
+
2611
+/*inline uint16_t NDS_getADCTouchPosX(uint16_t scrX)
2612
+{
2613
+	// this is a little iffy,
2614
+	// we're basically adjusting the ADC results to
2615
+	// compensate for how they will be interpreted.
2616
+	// the actual system doesn't do this transformation.
2617
+	int rv = (scrX - TSCal.scr.x1 + 1) * TSCal.adc.width / TSCal.scr.width + TSCal.adc.x1;
2618
+	rv = min(0xFFF, max(0, rv));
2619
+	return (uint16_t)rv;
2620
+}*/
2621
+/*inline uint16_t NDS_getADCTouchPosY(uint16_t scrY)
2622
+{
2623
+	int rv = (scrY - TSCal.scr.y1 + 1) * TSCal.adc.height / TSCal.scr.height + TSCal.adc.y1;
2624
+	rv = min(0xFFF, max(0, rv));
2625
+	return (uint16_t)rv;
2626
+}*/
2627
+
2628
+//static UserInput rawUserInput = {}; // requested input, generally what the user is physically pressing
2629
+static UserInput intermediateUserInput; // intermediate buffer for modifications (seperated from finalUserInput for safety reasons)
2630
+static UserInput finalUserInput; // what gets sent to the game and possibly recorded
2631
+bool validToProcessInput = false;
2632
+
2633
+/*const UserInput& NDS_getRawUserInput()
2634
+{
2635
+	return rawUserInput;
2636
+}*/
2637
+/*UserInput& NDS_getProcessingUserInput()
2638
+{
2639
+	assert(validToProcessInput);
2640
+	return intermediateUserInput;
2641
+}*/
2642
+/*bool NDS_isProcessingUserInput()
2643
+{
2644
+	return validToProcessInput;
2645
+}*/
2646
+/*const UserInput& NDS_getFinalUserInput()
2647
+{
2648
+	return finalUserInput;
2649
+}*/
2650
+
2651
+
2652
+/*static void saveUserInput(EMUFILE* os, UserInput& input)
2653
+{
2654
+	os->fwrite((const char*)input.buttons.array, 14);
2655
+	writebool(input.touch.isTouch, os);
2656
+	write16le(input.touch.touchX, os);
2657
+	write16le(input.touch.touchY, os);
2658
+	write32le(input.mic.micButtonPressed, os);
2659
+}*/
2660
+static bool loadUserInput(EMUFILE* is, UserInput& input, int)
2661
+{
2662
+	is->fread((char*)input.buttons.array, 14);
2663
+	readbool(&input.touch.isTouch, is);
2664
+	read16le(&input.touch.touchX, is);
2665
+	read16le(&input.touch.touchY, is);
2666
+	read32le(&input.mic.micButtonPressed, is);
2667
+	return true;
2668
+}
2669
+/*static void resetUserInput(UserInput& input)
2670
+{
2671
+	memset(&input, 0, sizeof(UserInput));
2672
+}*/
2673
+// (userinput is kind of a misnomer, e.g. finalUserInput has to mirror nds.pad, nds.touchX, etc.)
2674
+/*static void saveUserInput(EMUFILE* os)
2675
+{
2676
+	saveUserInput(os, finalUserInput);
2677
+	saveUserInput(os, intermediateUserInput); // saved in case a savestate is made during input processing (which Lua could do if nothing else)
2678
+	writebool(validToProcessInput, os);
2679
+	for(int i = 0; i < 14; i++)
2680
+		write32le(TurboTime.array[i], os); // saved to make autofire more tolerable to use with re-recording
2681
+}*/
2682
+static bool loadUserInput(EMUFILE* is, int version)
2683
+{
2684
+	bool rv = true;
2685
+	rv &= loadUserInput(is, finalUserInput, version);
2686
+	rv &= loadUserInput(is, intermediateUserInput, version);
2687
+	readbool(&validToProcessInput, is);
2688
+	for(int i = 0; i < 14; i++)
2689
+		read32le((uint32_t*)&TurboTime.array[i], is);
2690
+	return rv;
2691
+}
2692
+/*static void resetUserInput()
2693
+{
2694
+	resetUserInput(finalUserInput);
2695
+	resetUserInput(intermediateUserInput);
2696
+}*/
2697
+
2698
+/*static inline void gotInputRequest()
2699
+{
2700
+	// nobody should set the raw input while we're processing the input.
2701
+	// it might not screw anything up but it would be completely useless.
2702
+	assert(!validToProcessInput);
2703
+}*/
2704
+
2705
+/*void NDS_setPad(bool R,bool L,bool D,bool U,bool T,bool S,bool B,bool A,bool Y,bool X,bool W,bool E,bool G, bool F)
2706
+{
2707
+	gotInputRequest();
2708
+	UserButtons& rawButtons = rawUserInput.buttons;
2709
+	rawButtons.R = R;
2710
+	rawButtons.L = L;
2711
+	rawButtons.D = D;
2712
+	rawButtons.U = U;
2713
+	rawButtons.T = T;
2714
+	rawButtons.S = S;
2715
+	rawButtons.B = B;
2716
+	rawButtons.A = A;
2717
+	rawButtons.Y = Y;
2718
+	rawButtons.X = X;
2719
+	rawButtons.W = W;
2720
+	rawButtons.E = E;
2721
+	rawButtons.G = G;
2722
+	rawButtons.F = F;
2723
+}*/
2724
+/*void NDS_setTouchPos(uint16_t x, uint16_t y)
2725
+{
2726
+	gotInputRequest();
2727
+	rawUserInput.touch.touchX = NDS_getADCTouchPosX(x);
2728
+	rawUserInput.touch.touchY = NDS_getADCTouchPosY(y);
2729
+	rawUserInput.touch.isTouch = true;*/
2730
+
2731
+	/*if(movieMode != MOVIEMODE_INACTIVE && movieMode != MOVIEMODE_FINISHED)
2732
+	{
2733
+		// just in case, since the movie only stores 8 bits per touch coord
2734
+		rawUserInput.touch.touchX &= 0x0FF0;
2735
+		rawUserInput.touch.touchY &= 0x0FF0;
2736
+	}*/
2737
+/*
2738
+#ifndef WIN32
2739
+	// FIXME: this code should be deleted from here,
2740
+	// other platforms should call NDS_beginProcessingInput,NDS_endProcessingInput once per frame instead
2741
+	// (see the function called "StepRunLoop_Core" in src/windows/main.cpp),
2742
+	// but I'm leaving this here for now since I can't test those other platforms myself.
2743
+	nds.touchX = rawUserInput.touch.touchX;
2744
+	nds.touchY = rawUserInput.touch.touchY;
2745
+	nds.isTouch = 1;
2746
+	MMU.ARM7_REG[0x136] &= 0xBF;
2747
+#endif
2748
+}*/
2749
+/*void NDS_releaseTouch()
2750
+{
2751
+	gotInputRequest();
2752
+	rawUserInput.touch.touchX = 0;
2753
+	rawUserInput.touch.touchY = 0;
2754
+	rawUserInput.touch.isTouch = false;
2755
+
2756
+#ifndef WIN32
2757
+	// FIXME: this code should be deleted from here,
2758
+	// other platforms should call NDS_beginProcessingInput,NDS_endProcessingInput once per frame instead
2759
+	// (see the function called "StepRunLoop_Core" in src/windows/main.cpp),
2760
+	// but I'm leaving this here for now since I can't test those other platforms myself.
2761
+	nds.touchX = 0;
2762
+	nds.touchY = 0;
2763
+	nds.isTouch = 0;
2764
+	MMU.ARM7_REG[0x136] |= 0x40;
2765
+#endif
2766
+}*/
2767
+/*void NDS_setMic(bool pressed)
2768
+{
2769
+	gotInputRequest();
2770
+	rawUserInput.mic.micButtonPressed = (pressed ? true : false);
2771
+}*/
2772
+
2773
+
2774
+//static void NDS_applyFinalInput();
2775
+
2776
+
2777
+/*void NDS_beginProcessingInput()
2778
+{
2779
+	// start off from the raw input
2780
+	intermediateUserInput = rawUserInput;
2781
+
2782
+	// processing is valid now
2783
+	validToProcessInput = true;
2784
+}*/
2785
+
2786
+/*void NDS_endProcessingInput()
2787
+{
2788
+	// transfer the processed input
2789
+	finalUserInput = intermediateUserInput;
2790
+
2791
+	// processing is invalid now
2792
+	validToProcessInput = false;
2793
+
2794
+	// use the final input for a few things right away
2795
+	NDS_applyFinalInput();
2796
+}*/
2797
+
2798
+
2799
+
2800
+
2801
+
2802
+
2803
+
2804
+
2805
+/*static void NDS_applyFinalInput()
2806
+{
2807
+	const UserInput& input = NDS_getFinalUserInput();
2808
+
2809
+	uint16_t	pad	= (0 |
2810
+		((input.buttons.A ? 0 : 0x80) >> 7) |
2811
+		((input.buttons.B ? 0 : 0x80) >> 6) |
2812
+		((input.buttons.T ? 0 : 0x80) >> 5) |
2813
+		((input.buttons.S ? 0 : 0x80) >> 4) |
2814
+		((input.buttons.R ? 0 : 0x80) >> 3) |
2815
+		((input.buttons.L ? 0 : 0x80) >> 2) |
2816
+		((input.buttons.U ? 0 : 0x80) >> 1) |
2817
+		((input.buttons.D ? 0 : 0x80)     ) |
2818
+		((input.buttons.E ? 0 : 0x80) << 1) |
2819
+		((input.buttons.W ? 0 : 0x80) << 2)) ;
2820
+
2821
+	((uint16_t *)MMU.ARM9_REG)[0x130>>1] = (uint16_t)pad;
2822
+	((uint16_t *)MMU.ARM7_REG)[0x130>>1] = (uint16_t)pad;
2823
+
2824
+	uint16_t k_cnt = ((uint16_t *)MMU.ARM9_REG)[0x132>>1];
2825
+	if ( k_cnt & (1<<14))
2826
+	{
2827
+		//INFO("ARM9: KeyPad IRQ (pad 0x%04X, cnt 0x%04X (condition %s))\n", pad, k_cnt, k_cnt&(1<<15)?"AND":"OR");
2828
+		uint16_t k_cnt_selected = (k_cnt & 0x3F);
2829
+		if (k_cnt&(1<<15))	// AND
2830
+		{
2831
+			if ((~pad & k_cnt_selected) == k_cnt_selected) NDS_makeIrq(ARMCPU_ARM9,IRQ_BIT_KEYPAD);
2832
+		}
2833
+		else				// OR
2834
+		{
2835
+			if (~pad & k_cnt_selected) NDS_makeIrq(ARMCPU_ARM9,IRQ_BIT_KEYPAD);
2836
+		}
2837
+	}
2838
+
2839
+	k_cnt = ((uint16_t *)MMU.ARM7_REG)[0x132>>1];
2840
+	if ( k_cnt & (1<<14))
2841
+	{
2842
+		//INFO("ARM7: KeyPad IRQ (pad 0x%04X, cnt 0x%04X (condition %s))\n", pad, k_cnt, k_cnt&(1<<15)?"AND":"OR");
2843
+		uint16_t k_cnt_selected = (k_cnt & 0x3F);
2844
+		if (k_cnt&(1<<15))	// AND
2845
+		{
2846
+			if ((~pad & k_cnt_selected) == k_cnt_selected) NDS_makeIrq(ARMCPU_ARM7,IRQ_BIT_KEYPAD);
2847
+		}
2848
+		else				// OR
2849
+		{
2850
+			if (~pad & k_cnt_selected) NDS_makeIrq(ARMCPU_ARM7,IRQ_BIT_KEYPAD);
2851
+		}
2852
+	}
2853
+
2854
+
2855
+	if(input.touch.isTouch)
2856
+	{
2857
+		nds.touchX = input.touch.touchX;
2858
+		nds.touchY = input.touch.touchY;
2859
+		nds.isTouch = 1;
2860
+
2861
+		MMU.ARM7_REG[0x136] &= 0xBF;
2862
+	}
2863
+	else
2864
+	{
2865
+
2866
+		nds.touchX = 0;
2867
+		nds.touchY = 0;
2868
+		nds.isTouch = 0;
2869
+
2870
+		MMU.ARM7_REG[0x136] |= 0x40;
2871
+	}
2872
+
2873
+
2874
+	if (input.buttons.F && !countLid)
2875
+	{
2876
+		LidClosed = (!LidClosed) & 0x01;
2877
+		if (!LidClosed)
2878
+		{
2879
+		//	SPU_Pause(false);
2880
+			NDS_makeIrq(ARMCPU_ARM7,IRQ_BIT_ARM7_FOLD);
2881
+
2882
+		}
2883
+		//else
2884
+			//SPU_Pause(true);
2885
+
2886
+		countLid = 30;
2887
+	}
2888
+	else
2889
+	{
2890
+		if (countLid > 0)
2891
+			countLid--;
2892
+	}
2893
+
2894
+	uint16_t padExt = (((uint16_t *)MMU.ARM7_REG)[0x136>>1] & 0x0070) |
2895
+		((input.buttons.X ? 0 : 0x80) >> 7) |
2896
+		((input.buttons.Y ? 0 : 0x80) >> 6) |
2897
+		((input.buttons.G ? 0 : 0x80) >> 4) |
2898
+		((LidClosed) << 7) |
2899
+		0x0034;
2900
+
2901
+	((uint16_t *)MMU.ARM7_REG)[0x136>>1] = (uint16_t)padExt;
2902
+
2903
+	InputDisplayString=MakeInputDisplayString(padExt, pad);
2904
+
2905
+	//put into the format we want for the movie system
2906
+	//fRLDUTSBAYXWEg
2907
+	//we don't really need nds.pad anymore, but removing it would be a pain
2908
+
2909
+ 	nds.pad =
2910
+		((input.buttons.R ? 1 : 0) << 12)|
2911
+		((input.buttons.L ? 1 : 0) << 11)|
2912
+		((input.buttons.D ? 1 : 0) << 10)|
2913
+		((input.buttons.U ? 1 : 0) << 9)|
2914
+		((input.buttons.T ? 1 : 0) << 8)|
2915
+		((input.buttons.S ? 1 : 0) << 7)|
2916
+		((input.buttons.B ? 1 : 0) << 6)|
2917
+		((input.buttons.A ? 1 : 0) << 5)|
2918
+		((input.buttons.Y ? 1 : 0) << 4)|
2919
+		((input.buttons.X ? 1 : 0) << 3)|
2920
+		((input.buttons.W ? 1 : 0) << 2)|
2921
+		((input.buttons.E ? 1 : 0) << 1);
2922
+
2923
+	// TODO: low power IRQ
2924
+}*/
2925
+
2926
+
2927
+/*void NDS_suspendProcessingInput(bool suspend)
2928
+{
2929
+	static int suspendCount = 0;
2930
+	if(suspend)
2931
+	{
2932
+		// enter non-processing block
2933
+		assert(validToProcessInput);
2934
+		validToProcessInput = false;
2935
+		suspendCount++;
2936
+	}
2937
+	else if(suspendCount)
2938
+	{
2939
+		// exit non-processing block
2940
+		validToProcessInput = true;
2941
+		suspendCount--;
2942
+	}
2943
+	else
2944
+	{
2945
+		// unwound past first time -> not processing
2946
+		validToProcessInput = false;
2947
+	}
2948
+}*/
2949
+
2950
+
2951
+/*void emu_halt() {
2952
+	//printf("halting emu: ARM9 PC=%08X/%08X, ARM7 PC=%08X/%08X\n", NDS_ARM9.R[15], NDS_ARM9.instruct_adr, NDS_ARM7.R[15], NDS_ARM7.instruct_adr);
2953
+	execute = false;
2954
+#ifdef LOG_ARM9
2955
+	if (fp_dis9)
2956
+	{
2957
+		char buf[256] = { 0 };
2958
+		sprintf(buf, "halting emu: ARM9 PC=%08X/%08X\n", NDS_ARM9.R[15], NDS_ARM9.instruct_adr);
2959
+		fwrite(buf, 1, strlen(buf), fp_dis9);
2960
+		INFO("ARM9 halted\n");
2961
+	}
2962
+#endif
2963
+
2964
+#ifdef LOG_ARM7
2965
+	if (fp_dis7)
2966
+	{
2967
+		char buf[256] = { 0 };
2968
+		sprintf(buf, "halting emu: ARM7 PC=%08X/%08X\n", NDS_ARM7.R[15], NDS_ARM7.instruct_adr);
2969
+		fwrite(buf, 1, strlen(buf), fp_dis7);
2970
+		INFO("ARM7 halted\n");
2971
+	}
2972
+#endif
2973
+}*/
2974
+
2975
+//returns true if exmemcnt specifies satisfactory parameters for the device, which calls this function
2976
+/*bool ValidateSlot2Access(uint32_t procnum, uint32_t demandSRAMSpeed, uint32_t demand1stROMSpeed, uint32_t demand2ndROMSpeed, int clockbits)
2977
+{
2978
+	static const uint32_t _sramSpeeds[] = {10,8,6,18};
2979
+	static const uint32_t _rom1Speeds[] = {10,8,6,18};
2980
+	static const uint32_t _rom2Speeds[] = {6,4};
2981
+	uint16_t exmemcnt = T1ReadWord(MMU.MMU_MEM[procnum][0x40], 0x204);
2982
+	uint16_t exmemcnt9 = T1ReadWord(MMU.MMU_MEM[ARMCPU_ARM9][0x40], 0x204);
2983
+	uint32_t arm7access = (exmemcnt9 & EXMEMCNT_MASK_SLOT2_ARM7);
2984
+	uint32_t sramSpeed = _sramSpeeds[(exmemcnt & EXMEMCNT_MASK_SLOT2_SRAM_TIME)];
2985
+	uint32_t romSpeed1 = _rom1Speeds[(exmemcnt & EXMEMCNT_MASK_SLOT2_ROM_1ST_TIME)>>2];
2986
+	uint32_t romSpeed2 = _rom2Speeds[(exmemcnt & EXMEMCNT_MASK_SLOT2_ROM_2ND_TIME)>>4];
2987
+	uint32_t curclockbits = (exmemcnt & EXMEMCNT_MASK_SLOT2_CLOCKRATE)>>5;
2988
+
2989
+	if(procnum==ARMCPU_ARM9 && arm7access) return false;
2990
+	if(procnum==ARMCPU_ARM7 && !arm7access) return false;
2991
+
2992
+	//what we're interested in here is whether the rom/ram are too low -> too fast. then accesses won't have enough time to work.
2993
+	//i'm not sure if this gives us enough flexibility, but it is good enough for now.
2994
+	//should make the arguments to this function bitmasks later if we need better.
2995
+	if(sramSpeed < demandSRAMSpeed) return false;
2996
+	if(romSpeed1 < demand1stROMSpeed) return false;
2997
+	if(romSpeed2 < demand2ndROMSpeed) return false;
2998
+
2999
+	if(clockbits != -1 && clockbits != (int)curclockbits) return false;
3000
+
3001
+	return true;
3002
+}*/
3003
+
3004
+//these templates needed to be instantiated manually
3005
+template void NDS_exec<false>(int32_t nb);
3006
+template void NDS_exec<true>(int32_t nb);