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 1
deleted file mode 100644
... ...
@@ -1,1856 +0,0 @@
1
-/*
2
-	Copyright (C) 2006 Normmatt
3
-	Copyright (C) 2006 Theo Berkau
4
-	Copyright (C) 2007 Pascal Giard
5
-	Copyright (C) 2008-2012 DeSmuME team
6
-
7
-	This file is free software: you can redistribute it and/or modify
8
-	it under the terms of the GNU General Public License as published by
9
-	the Free Software Foundation, either version 2 of the License, or
10
-	(at your option) any later version.
11
-
12
-	This file is distributed in the hope that it will be useful,
13
-	but WITHOUT ANY WARRANTY; without even the implied warranty of
14
-	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15
-	GNU General Public License for more details.
16
-
17
-	You should have received a copy of the GNU General Public License
18
-	along with the this software.  If not, see <http://www.gnu.org/licenses/>.
19
-*/
20
-
21
-#include <stack>
22
-#include <set>
23
-#include <fstream>
24
-#include <cstdio>
25
-#include <cstring>
26
-#include <ctime>
27
-#include <sys/stat.h>
28
-#ifdef HAVE_LIBZ
29
-#include <zlib.h>
30
-#endif
31
-#include "saves.h"
32
-#include "MMU.h"
33
-#include "NDSSystem.h"
34
-//#include "render3D.h"
35
-#include "cp15.h"
36
-//#include "GPU_osd.h"
37
-#include "version.h"
38
-
39
-#include "readwrite.h"
40
-//#include "gfx3d.h"
41
-//#include "movie.h"
42
-//#include "mic.h"
43
-#include "MMU_timing.h"
44
-
45
-#include "path.h"
46
-
47
-#ifdef _WINDOWS
48
-//#include "main.h"
49
-#endif
50
-
51
-//int lastSaveState = 0;		//Keeps track of last savestate used for quick save/load functions
52
-
53
-//void*v is actually a void** which will be indirected before reading
54
-//since this isnt supported right now, it is declared in here to make things compile
55
-//#define SS_INDIRECT            0x80000000
56
-
57
-//savestates_t savestates[NB_STATES];
58
-
59
-#define SAVESTATE_VERSION       12
60
-static const char* magic = "DeSmuME SState\0";
61
-
62
-//a savestate chunk loader can set this if it wants to permit a silent failure (for compatibility)
63
-static bool SAV_silent_fail_flag;
64
-
65
-SFORMAT SF_ARM7[]={
66
-	{ "7INS", 4, 1, &NDS_ARM7.instruction },
67
-	{ "7INA", 4, 1, &NDS_ARM7.instruct_adr },
68
-	{ "7INN", 4, 1, &NDS_ARM7.next_instruction },
69
-	{ "7REG", 4,16, NDS_ARM7.R },
70
-	{ "7CPS", 4, 1, &NDS_ARM7.CPSR },
71
-	{ "7SPS", 4, 1, &NDS_ARM7.SPSR },
72
-	{ "7DUS", 4, 1, &NDS_ARM7.R13_usr },
73
-	{ "7EUS", 4, 1, &NDS_ARM7.R14_usr },
74
-	{ "7DSV", 4, 1, &NDS_ARM7.R13_svc },
75
-	{ "7ESV", 4, 1, &NDS_ARM7.R14_svc },
76
-	{ "7DAB", 4, 1, &NDS_ARM7.R13_abt },
77
-	{ "7EAB", 4, 1, &NDS_ARM7.R14_abt },
78
-	{ "7DUN", 4, 1, &NDS_ARM7.R13_und },
79
-	{ "7EUN", 4, 1, &NDS_ARM7.R14_und },
80
-	{ "7DIR", 4, 1, &NDS_ARM7.R13_irq },
81
-	{ "7EIR", 4, 1, &NDS_ARM7.R14_irq },
82
-	{ "78FI", 4, 1, &NDS_ARM7.R8_fiq },
83
-	{ "79FI", 4, 1, &NDS_ARM7.R9_fiq },
84
-	{ "7AFI", 4, 1, &NDS_ARM7.R10_fiq },
85
-	{ "7BFI", 4, 1, &NDS_ARM7.R11_fiq },
86
-	{ "7CFI", 4, 1, &NDS_ARM7.R12_fiq },
87
-	{ "7DFI", 4, 1, &NDS_ARM7.R13_fiq },
88
-	{ "7EFI", 4, 1, &NDS_ARM7.R14_fiq },
89
-	{ "7SVC", 4, 1, &NDS_ARM7.SPSR_svc },
90
-	{ "7ABT", 4, 1, &NDS_ARM7.SPSR_abt },
91
-	{ "7UND", 4, 1, &NDS_ARM7.SPSR_und },
92
-	{ "7IRQ", 4, 1, &NDS_ARM7.SPSR_irq },
93
-	{ "7FIQ", 4, 1, &NDS_ARM7.SPSR_fiq },
94
-	{ "7int", 4, 1, &NDS_ARM7.intVector },
95
-	{ "7LDT", 1, 1, &NDS_ARM7.LDTBit },
96
-	{ "7Wai", 4, 1, &NDS_ARM7.waitIRQ },
97
-	{ "7hef", 4, 1, &NDS_ARM7.halt_IE_and_IF },
98
-	{ "7iws", 1, 1, &NDS_ARM7.intrWaitARM_state },
99
-	{ NULL, 0, 0, NULL }
100
-};
101
-
102
-SFORMAT SF_ARM9[]={
103
-	{ "9INS", 4, 1, &NDS_ARM9.instruction},
104
-	{ "9INA", 4, 1, &NDS_ARM9.instruct_adr},
105
-	{ "9INN", 4, 1, &NDS_ARM9.next_instruction},
106
-	{ "9REG", 4,16, NDS_ARM9.R},
107
-	{ "9CPS", 4, 1, &NDS_ARM9.CPSR},
108
-	{ "9SPS", 4, 1, &NDS_ARM9.SPSR},
109
-	{ "9DUS", 4, 1, &NDS_ARM9.R13_usr},
110
-	{ "9EUS", 4, 1, &NDS_ARM9.R14_usr},
111
-	{ "9DSV", 4, 1, &NDS_ARM9.R13_svc},
112
-	{ "9ESV", 4, 1, &NDS_ARM9.R14_svc},
113
-	{ "9DAB", 4, 1, &NDS_ARM9.R13_abt},
114
-	{ "9EAB", 4, 1, &NDS_ARM9.R14_abt},
115
-	{ "9DUN", 4, 1, &NDS_ARM9.R13_und},
116
-	{ "9EUN", 4, 1, &NDS_ARM9.R14_und},
117
-	{ "9DIR", 4, 1, &NDS_ARM9.R13_irq},
118
-	{ "9EIR", 4, 1, &NDS_ARM9.R14_irq},
119
-	{ "98FI", 4, 1, &NDS_ARM9.R8_fiq},
120
-	{ "99FI", 4, 1, &NDS_ARM9.R9_fiq},
121
-	{ "9AFI", 4, 1, &NDS_ARM9.R10_fiq},
122
-	{ "9BFI", 4, 1, &NDS_ARM9.R11_fiq},
123
-	{ "9CFI", 4, 1, &NDS_ARM9.R12_fiq},
124
-	{ "9DFI", 4, 1, &NDS_ARM9.R13_fiq},
125
-	{ "9EFI", 4, 1, &NDS_ARM9.R14_fiq},
126
-	{ "9SVC", 4, 1, &NDS_ARM9.SPSR_svc},
127
-	{ "9ABT", 4, 1, &NDS_ARM9.SPSR_abt},
128
-	{ "9UND", 4, 1, &NDS_ARM9.SPSR_und},
129
-	{ "9IRQ", 4, 1, &NDS_ARM9.SPSR_irq},
130
-	{ "9FIQ", 4, 1, &NDS_ARM9.SPSR_fiq},
131
-	{ "9int", 4, 1, &NDS_ARM9.intVector},
132
-	{ "9LDT", 1, 1, &NDS_ARM9.LDTBit},
133
-	{ "9Wai", 4, 1, &NDS_ARM9.waitIRQ},
134
-	{ "9hef", 4, 1, &NDS_ARM9.halt_IE_and_IF },
135
-	{ "9iws", 1, 1, &NDS_ARM7.intrWaitARM_state },
136
-	{ NULL, 0, 0, NULL }
137
-};
138
-
139
-SFORMAT SF_MEM[]={
140
-	{ "ITCM", 1, sizeof(MMU.ARM9_ITCM),   MMU.ARM9_ITCM},
141
-	{ "DTCM", 1, sizeof(MMU.ARM9_DTCM),   MMU.ARM9_DTCM},
142
-
143
-	 //for legacy purposes, WRAX is a separate variable. shouldnt be a problem.
144
-	{ "WRAM", 1, 0x400000, MMU.MAIN_MEM},
145
-	{ "WRAX", 1, 0x400000, MMU.MAIN_MEM+0x400000},
146
-
147
-	//NOTE - this is not as large as the allocated memory.
148
-	//the memory is overlarge due to the way our memory map system is setup
149
-	//but there are actually no more registers than this
150
-	{ "9REG", 1, 0x2000,   MMU.ARM9_REG},
151
-
152
-	{ "VMEM", 1, sizeof(MMU.ARM9_VMEM),    MMU.ARM9_VMEM},
153
-	{ "OAMS", 1, sizeof(MMU.ARM9_OAM),    MMU.ARM9_OAM},
154
-
155
-	//this size is specially chosen to avoid saving the blank space at the end
156
-	{ "LCDM", 1, 0xA4000,		MMU.ARM9_LCD},
157
-	{ NULL, 0, 0, NULL }
158
-};
159
-
160
-SFORMAT SF_NDS[]={
161
-	//{ "_WCY", 4, 1, &nds.wifiCycle},
162
-	{ "_TCY", 8, 8, nds.timerCycle},
163
-	{ "_VCT", 4, 1, &nds.VCount},
164
-	{ "_OLD", 4, 1, &nds.old},
165
-	{ "_TPX", 2, 1, NULL},
166
-	{ "_TPY", 2, 1, NULL},
167
-	{ "_TPB", 4, 1, NULL},
168
-	{ "_DBG", 4, 1, NULL},
169
-	{ "_ENS", 4, 1, NULL},
170
-	{ "_ENH", 4, 1, NULL},
171
-	{ "_ENI", 4, 1, NULL},
172
-	{ "_SLP", 4, 1, &nds.sleeping},
173
-	{ "_FBS", 4, 1, &nds.freezeBus},
174
-	{ "_CEJ", 4, 1, &nds.cardEjected},
175
-	{ "_P00", 1, 1, NULL},
176
-	{ "_P01", 1, 1, NULL},
177
-	//{ "_P02", 1, 1, &nds.power1.gfx3d_render},
178
-	//{ "_P03", 1, 1, &nds.power1.gfx3d_geometry},
179
-	{ "_P04", 1, 1, NULL},
180
-	{ "_P05", 1, 1, NULL},
181
-	{ "_P06", 1, 1, NULL},
182
-	//{ "_P07", 1, 1, &nds.power2.wifi},
183
-	{ NULL, 0, 0, NULL }
184
-};
185
-
186
-SFORMAT SF_MMU[]={
187
-	{ "M7BI", 1, sizeof(MMU.ARM7_BIOS), MMU.ARM7_BIOS},
188
-	{ "M7ER", 1, sizeof(MMU.ARM7_ERAM), MMU.ARM7_ERAM},
189
-	{ "M7RG", 1, sizeof(MMU.ARM7_REG), MMU.ARM7_REG},
190
-	{ "M7WI", 1, sizeof(MMU.ARM7_WIRAM), MMU.ARM7_WIRAM},
191
-	{ "MSWI", 1, sizeof(MMU.SWIRAM), MMU.SWIRAM},
192
-	{ "M9RW", 1, 1,       &MMU.ARM9_RW_MODE},
193
-	{ "MDTC", 4, 1,       &MMU.DTCMRegion},
194
-	{ "MITC", 4, 1,       &MMU.ITCMRegion},
195
-	{ "MTIM", 2, 8,       MMU.timer},
196
-	{ "MTMO", 4, 8,       MMU.timerMODE},
197
-	{ "MTON", 4, 8,       MMU.timerON},
198
-	{ "MTRN", 4, 8,       MMU.timerRUN},
199
-	{ "MTRL", 2, 8,       MMU.timerReload},
200
-	{ "MIME", 4, 2,       MMU.reg_IME},
201
-	{ "MIE_", 4, 2,       MMU.reg_IE},
202
-	{ "MIF_", 4, 2,       MMU.reg_IF_bits},
203
-
204
-	//{ "MGXC", 8, 1,       &MMU.gfx3dCycles},
205
-
206
-	{ "M_SX", 1, 2,       &MMU.SPI_CNT},
207
-	{ "M_SC", 1, 2,       &MMU.SPI_CMD},
208
-	{ "MASX", 1, 2,       &MMU.AUX_SPI_CNT},
209
-	{ "MASC", 1, 2,       &MMU.AUX_SPI_CMD},
210
-
211
-	{ "MDV1", 4, 1,       &MMU.divRunning},
212
-	{ "MDV2", 8, 1,       &MMU.divResult},
213
-	{ "MDV3", 8, 1,       &MMU.divMod},
214
-	{ "MDV5", 8, 1,       &MMU.divCycles},
215
-
216
-	{ "MSQ1", 4, 1,       &MMU.sqrtRunning},
217
-	{ "MSQ2", 4, 1,       &MMU.sqrtResult},
218
-	{ "MSQ4", 8, 1,       &MMU.sqrtCycles},
219
-
220
-	//begin memory chips
221
-	{ "BUCO", 1, 1,       &MMU.fw.com},
222
-	{ "BUAD", 4, 1,       &MMU.fw.addr},
223
-	{ "BUAS", 1, 1,       &MMU.fw.addr_shift},
224
-	{ "BUAZ", 1, 1,       &MMU.fw.addr_size},
225
-	{ "BUWE", 4, 1,       &MMU.fw.write_enable},
226
-	{ "BUWR", 4, 1,       &MMU.fw.writeable_buffer},
227
-	//end memory chips
228
-
229
-	{ "MC0A", 4, 1,       &MMU.dscard[0].address},
230
-	{ "MC0T", 4, 1,       &MMU.dscard[0].transfer_count},
231
-	{ "MC1A", 4, 1,       &MMU.dscard[1].address},
232
-	{ "MC1T", 4, 1,       &MMU.dscard[1].transfer_count},
233
-	//{ "MCHT", 4, 1,       &MMU.CheckTimers},
234
-	//{ "MCHD", 4, 1,       &MMU.CheckDMAs},
235
-
236
-	//fifos
237
-	{ "F0TH", 1, 1,       &ipc_fifo[0].head},
238
-	{ "F0TL", 1, 1,       &ipc_fifo[0].tail},
239
-	{ "F0SZ", 1, 1,       &ipc_fifo[0].size},
240
-	{ "F0BF", 4, 16,      ipc_fifo[0].buf},
241
-	{ "F1TH", 1, 1,       &ipc_fifo[1].head},
242
-	{ "F1TL", 1, 1,       &ipc_fifo[1].tail},
243
-	{ "F1SZ", 1, 1,       &ipc_fifo[1].size},
244
-	{ "F1BF", 4, 16,      ipc_fifo[1].buf},
245
-
246
-	{ "FDHD", 4, 1,       NULL},
247
-	{ "FDTL", 4, 1,       NULL},
248
-	{ "FDBF", 4, 0x6000,  NULL},
249
-
250
-	{ "PMCN", 1, 1,			&MMU.powerMan_CntReg},
251
-	{ "PMCW", 4, 1,			&MMU.powerMan_CntRegWritten},
252
-	{ "PMCR", 1, 5,			&MMU.powerMan_Reg},
253
-
254
-	{ "MR3D", 4, 1,		NULL},
255
-
256
-	{ NULL, 0, 0, NULL }
257
-};
258
-
259
-/*static uint32_t tmpu32;
260
-SFORMAT SF_MOVIE[]={
261
-	{ "FRAC", 4, 1, &tmpu32},
262
-	{ "LAGC", 4, 1, &tmpu32},
263
-	{ NULL, 0, 0, NULL }
264
-};*/
265
-
266
-/*static void mmu_savestate(EMUFILE* os)
267
-{
268
-	uint32_t version = 5;
269
-	write32le(version,os);
270
-
271
-	//version 2:
272
-	MMU_new.backupDevice.save_state(os);
273
-
274
-	//version 3:
275
-	MMU_new.gxstat.savestate(os);
276
-	for(int i=0;i<2;i++)
277
-		for(int j=0;j<4;j++)
278
-			MMU_new.dma[i][j].savestate(os);
279
-
280
-	MMU_timing.arm9codeFetch.savestate(os, version);
281
-	MMU_timing.arm9dataFetch.savestate(os, version);
282
-	MMU_timing.arm7codeFetch.savestate(os, version);
283
-	MMU_timing.arm7dataFetch.savestate(os, version);
284
-	MMU_timing.arm9codeCache.savestate(os, version);
285
-	MMU_timing.arm9dataCache.savestate(os, version);
286
-
287
-	//version 4:
288
-	MMU_new.sqrt.savestate(os);
289
-	MMU_new.div.savestate(os);
290
-}*/
291
-
292
-/*static uint16_t tmpu16;
293
-static uint16_t tmpu16_array3[3];
294
-static uint8_t tmpu8;
295
-static uint8_t tmpu8_array3[3];
296
-static uint32_t tmpu32_array3[3];
297
-static uint8_t tmpu8_array6[6];
298
-static uint64_t tmpu64;
299
-static uint8_t tmpu8_array105[105];
300
-static uint16_t tmpu16_array4096[0x1000];
301
-static uint16_t tmpu16_array2048[0x800];
302
-static uint8_t tmpu8_array4096[4096];
303
-SFORMAT SF_WIFI[]={
304
-	{ "W000", 4, 1, &tmpu32},
305
-	{ "W010", 4, 1, &tmpu32},
306
-
307
-	{ "W020", 2, 1, &tmpu16},
308
-	{ "W030", 2, 1, &tmpu16},
309
-
310
-	{ "W040", 2, 1, &tmpu16},
311
-	{ "W050", 2, 1, &tmpu16},
312
-
313
-	{ "W060", 2, 1, &tmpu16},
314
-	{ "W070", 2, 1, &tmpu16},
315
-	{ "W080", 4, 1, &tmpu32},
316
-
317
-	{ "W090", 2, 3, tmpu16_array3},
318
-	{ "W100", 2, 1, &tmpu16},
319
-	{ "W110", 2, 1, &tmpu16},
320
-	{ "W120", 2, 1, &tmpu16},
321
-	{ "W130", 2, 1, &tmpu16},
322
-	{ "W140", 4, 1, &tmpu32},
323
-	{ "W150", 1, 1, &tmpu8},
324
-	{ "W160", 1, 3, tmpu8_array3},
325
-	{ "W170", 4, 3, tmpu32_array3},
326
-	{ "W180", 4, 3, tmpu32_array3},
327
-	{ "W190", 4, 3, tmpu32_array3},
328
-
329
-	{ "W200", 2, 1, &tmpu16},
330
-	{ "W210", 2, 1, &tmpu16},
331
-
332
-	{ "W220", 1, 6, tmpu8_array6},
333
-	{ "W230", 1, 6, tmpu8_array6},
334
-
335
-	{ "W240", 2, 1, &tmpu16},
336
-	{ "W250", 2, 1, &tmpu16},
337
-	{ "W260", 2, 1, &tmpu16},
338
-
339
-	{ "W270", 4, 1, &tmpu32},
340
-	{ "W280", 8, 1, &tmpu64},
341
-	{ "W290", 4, 1, &tmpu32},
342
-	{ "W300", 8, 1, &tmpu64},
343
-	{ "W310", 4, 1, &tmpu32},
344
-	{ "W320", 2, 1, &tmpu16},
345
-	{ "W330", 4, 1, &tmpu32},
346
-
347
-	{ "WR00", 4, 1, &tmpu32},
348
-	{ "WR01", 4, 1, &tmpu32},
349
-	{ "WR02", 4, 1, &tmpu32},
350
-	{ "WR03", 4, 1, &tmpu32},
351
-	{ "WR04", 4, 1, &tmpu32},
352
-	{ "WR05", 4, 1, &tmpu32},
353
-	{ "WR06", 4, 1, &tmpu32},
354
-	{ "WR07", 4, 1, &tmpu32},
355
-	{ "WR08", 4, 1, &tmpu32},
356
-	{ "WR09", 4, 1, &tmpu32},
357
-	{ "WR10", 4, 1, &tmpu32},
358
-	{ "WR11", 4, 1, &tmpu32},
359
-	{ "WR12", 4, 1, &tmpu32},
360
-
361
-	{ "W340", 1, 105, tmpu8_array105},
362
-
363
-	{ "W350", 2, 1, &tmpu16},
364
-	{ "W360", 2, 1, &tmpu16},
365
-	{ "W370", 4, 1, &tmpu32},
366
-	{ "W380", 2, 1, &tmpu16},
367
-
368
-	{ "W400", 2, 0x1000, tmpu16_array4096},
369
-	{ "W410", 2, 1, &tmpu16},
370
-	{ "W420", 2, 1, &tmpu16},
371
-	{ "W430", 2, 1, &tmpu16},
372
-	{ "W460", 2, 1, &tmpu16},
373
-	{ "W470", 2, 1, &tmpu16},
374
-	{ "W480", 2, 1, &tmpu16},
375
-	{ "W490", 2, 1, &tmpu16},
376
-	{ "W500", 2, 1, &tmpu16},
377
-	{ "W510", 2, 1, &tmpu16},
378
-	{ "W520", 2, 1, &tmpu16},
379
-	{ "W530", 2, 1, &tmpu16},
380
-	{ "W540", 2, 1, &tmpu16},
381
-
382
-	{ "W550", 4, 1, &tmpu32},
383
-	{ "W560", 4, 1, &tmpu32},
384
-	{ "W570", 4, 1, &tmpu32},
385
-
386
-	{ "W580", 2, 0x800, tmpu16_array2048},
387
-	{ "W590", 2, 1, &tmpu16},
388
-
389
-	{ "WX00", 8, 1, &tmpu64},
390
-	{ "WX10", 1, 4096, tmpu8_array4096},
391
-	{ "WX20", 4, 1, &tmpu32},
392
-	{ "WX30", 4, 1, &tmpu32},
393
-	{ "WX40", 4, 1, &tmpu32},
394
-
395
-	{ NULL, 0, 0, NULL }
396
-};*/
397
-
398
-static bool mmu_loadstate(EMUFILE* is, int)
399
-{
400
-	//read version
401
-	uint32_t version;
402
-	if(read32le(&version,is) != 1) return false;
403
-
404
-	if(version == 0 || version == 1)
405
-	{
406
-		uint32_t bupmem_size = 0;
407
-		uint32_t addr_size = 0xFFFFFFFF;
408
-
409
-		if(version == 0)
410
-		{
411
-			//version 0 was buggy and didnt save the type.
412
-			//it would silently fail if there was a size mismatch
413
-			SAV_silent_fail_flag = true;
414
-			if(read32le(&bupmem_size,is) != 1) return false;
415
-			//if(bupmem_size != MMU.bupmem.size) return false; //mismatch between current initialized and saved size
416
-			addr_size = BackupDevice::addr_size_for_old_save_size(bupmem_size);
417
-		}
418
-		else if(version == 1)
419
-		{
420
-			//version 1 reinitializes the save system with the type that was saved
421
-			uint32_t bupmem_type;
422
-			if(read32le(&bupmem_type,is) != 1) return false;
423
-			if(read32le(&bupmem_size,is) != 1) return false;
424
-			addr_size = BackupDevice::addr_size_for_old_save_type(bupmem_type);
425
-			if(addr_size == 0xFFFFFFFF)
426
-				addr_size = BackupDevice::addr_size_for_old_save_size(bupmem_size);
427
-		}
428
-
429
-		if(addr_size == 0xFFFFFFFF)
430
-			return false;
431
-
432
-		uint8_t* temp = new uint8_t[bupmem_size];
433
-		is->fread((char*)temp,bupmem_size);
434
-		MMU_new.backupDevice.load_old_state(addr_size,temp,bupmem_size);
435
-		delete[] temp;
436
-		if(is->fail()) return false;
437
-	}
438
-
439
-	if(version < 2) return true;
440
-
441
-	bool ok = MMU_new.backupDevice.load_state(is);
442
-
443
-	if(version < 3) return true;
444
-
445
-	ok &= MMU_new.gxstat.loadstate(is);
446
-
447
-	for(int i=0;i<2;i++)
448
-		for(int j=0;j<4;j++)
449
-			ok &= MMU_new.dma[i][j].loadstate(is);
450
-
451
-	ok &= MMU_timing.arm9codeFetch.loadstate(is, version);
452
-	ok &= MMU_timing.arm9dataFetch.loadstate(is, version);
453
-	ok &= MMU_timing.arm7codeFetch.loadstate(is, version);
454
-	ok &= MMU_timing.arm7dataFetch.loadstate(is, version);
455
-	ok &= MMU_timing.arm9codeCache.loadstate(is, version);
456
-	ok &= MMU_timing.arm9dataCache.loadstate(is, version);
457
-
458
-	if(version < 4) return true;
459
-
460
-	ok &= MMU_new.sqrt.loadstate(is,version);
461
-	ok &= MMU_new.div.loadstate(is,version);
462
-
463
-	//to prevent old savestates from confusing IF bits, mask out ones which had been stored but should have been generated
464
-	MMU.reg_IF_bits[0] &= ~0x00200000;
465
-	MMU.reg_IF_bits[1] &= ~0x00000000;
466
-
467
-	//MMU_new.gxstat.fifo_low = gxFIFO.size <= 127;
468
-	//MMU_new.gxstat.fifo_empty = gxFIFO.size == 0;
469
-
470
-	/*if(version < 5)
471
-		MMU.reg_DISP3DCNT_bits = T1ReadWord(MMU.ARM9_REG,0x60);*/
472
-
473
-	return ok;
474
-}
475
-
476
-/*static void cp15_saveone(armcp15_t *cp15, EMUFILE* os)
477
-{
478
-	write32le(cp15->IDCode,os);
479
-	write32le(cp15->cacheType,os);
480
-    write32le(cp15->TCMSize,os);
481
-    write32le(cp15->ctrl,os);
482
-    write32le(cp15->DCConfig,os);
483
-    write32le(cp15->ICConfig,os);
484
-    write32le(cp15->writeBuffCtrl,os);
485
-    write32le(cp15->und,os);
486
-    write32le(cp15->DaccessPerm,os);
487
-    write32le(cp15->IaccessPerm,os);
488
-    write32le(cp15->protectBaseSize0,os);
489
-    write32le(cp15->protectBaseSize1,os);
490
-    write32le(cp15->protectBaseSize2,os);
491
-    write32le(cp15->protectBaseSize3,os);
492
-    write32le(cp15->protectBaseSize4,os);
493
-    write32le(cp15->protectBaseSize5,os);
494
-    write32le(cp15->protectBaseSize6,os);
495
-    write32le(cp15->protectBaseSize7,os);
496
-    write32le(cp15->cacheOp,os);
497
-    write32le(cp15->DcacheLock,os);
498
-    write32le(cp15->IcacheLock,os);
499
-    write32le(cp15->ITCMRegion,os);
500
-    write32le(cp15->DTCMRegion,os);
501
-    write32le(cp15->processID,os);
502
-    write32le(cp15->RAM_TAG,os);
503
-    write32le(cp15->testState,os);
504
-    write32le(cp15->cacheDbg,os);
505
-    for(int i=0;i<8;i++) write32le(cp15->regionWriteMask_USR[i],os);
506
-    for(int i=0;i<8;i++) write32le(cp15->regionWriteMask_SYS[i],os);
507
-    for(int i=0;i<8;i++) write32le(cp15->regionReadMask_USR[i],os);
508
-    for(int i=0;i<8;i++) write32le(cp15->regionReadMask_SYS[i],os);
509
-    for(int i=0;i<8;i++) write32le(cp15->regionExecuteMask_USR[i],os);
510
-    for(int i=0;i<8;i++) write32le(cp15->regionExecuteMask_SYS[i],os);
511
-    for(int i=0;i<8;i++) write32le(cp15->regionWriteSet_USR[i],os);
512
-    for(int i=0;i<8;i++) write32le(cp15->regionWriteSet_SYS[i],os);
513
-    for(int i=0;i<8;i++) write32le(cp15->regionReadSet_USR[i],os);
514
-    for(int i=0;i<8;i++) write32le(cp15->regionReadSet_SYS[i],os);
515
-    for(int i=0;i<8;i++) write32le(cp15->regionExecuteSet_USR[i],os);
516
-    for(int i=0;i<8;i++) write32le(cp15->regionExecuteSet_SYS[i],os);
517
-}*/
518
-
519
-/*static void cp15_savestate(EMUFILE* os)
520
-{
521
-	//version
522
-	write32le(1,os);
523
-
524
-	cp15_saveone((armcp15_t *)NDS_ARM9.coproc[15],os);
525
-	//ARM7 not have coprocessor
526
-	//cp15_saveone((armcp15_t *)NDS_ARM7.coproc[15],os);
527
-}*/
528
-
529
-static bool cp15_loadone(armcp15_t *cp15, EMUFILE* is)
530
-{
531
-	if(!read32le(&cp15->IDCode,is)) return false;
532
-	if(!read32le(&cp15->cacheType,is)) return false;
533
-    if(!read32le(&cp15->TCMSize,is)) return false;
534
-    if(!read32le(&cp15->ctrl,is)) return false;
535
-    if(!read32le(&cp15->DCConfig,is)) return false;
536
-    if(!read32le(&cp15->ICConfig,is)) return false;
537
-    if(!read32le(&cp15->writeBuffCtrl,is)) return false;
538
-    if(!read32le(&cp15->und,is)) return false;
539
-    if(!read32le(&cp15->DaccessPerm,is)) return false;
540
-    if(!read32le(&cp15->IaccessPerm,is)) return false;
541
-    if(!read32le(&cp15->protectBaseSize0,is)) return false;
542
-    if(!read32le(&cp15->protectBaseSize1,is)) return false;
543
-    if(!read32le(&cp15->protectBaseSize2,is)) return false;
544
-    if(!read32le(&cp15->protectBaseSize3,is)) return false;
545
-    if(!read32le(&cp15->protectBaseSize4,is)) return false;
546
-    if(!read32le(&cp15->protectBaseSize5,is)) return false;
547
-    if(!read32le(&cp15->protectBaseSize6,is)) return false;
548
-    if(!read32le(&cp15->protectBaseSize7,is)) return false;
549
-    if(!read32le(&cp15->cacheOp,is)) return false;
550
-    if(!read32le(&cp15->DcacheLock,is)) return false;
551
-    if(!read32le(&cp15->IcacheLock,is)) return false;
552
-    if(!read32le(&cp15->ITCMRegion,is)) return false;
553
-    if(!read32le(&cp15->DTCMRegion,is)) return false;
554
-    if(!read32le(&cp15->processID,is)) return false;
555
-    if(!read32le(&cp15->RAM_TAG,is)) return false;
556
-    if(!read32le(&cp15->testState,is)) return false;
557
-    if(!read32le(&cp15->cacheDbg,is)) return false;
558
-    for(int i=0;i<8;i++) if(!read32le(&cp15->regionWriteMask_USR[i],is)) return false;
559
-    for(int i=0;i<8;i++) if(!read32le(&cp15->regionWriteMask_SYS[i],is)) return false;
560
-    for(int i=0;i<8;i++) if(!read32le(&cp15->regionReadMask_USR[i],is)) return false;
561
-    for(int i=0;i<8;i++) if(!read32le(&cp15->regionReadMask_SYS[i],is)) return false;
562
-    for(int i=0;i<8;i++) if(!read32le(&cp15->regionExecuteMask_USR[i],is)) return false;
563
-    for(int i=0;i<8;i++) if(!read32le(&cp15->regionExecuteMask_SYS[i],is)) return false;
564
-    for(int i=0;i<8;i++) if(!read32le(&cp15->regionWriteSet_USR[i],is)) return false;
565
-    for(int i=0;i<8;i++) if(!read32le(&cp15->regionWriteSet_SYS[i],is)) return false;
566
-    for(int i=0;i<8;i++) if(!read32le(&cp15->regionReadSet_USR[i],is)) return false;
567
-    for(int i=0;i<8;i++) if(!read32le(&cp15->regionReadSet_SYS[i],is)) return false;
568
-    for(int i=0;i<8;i++) if(!read32le(&cp15->regionExecuteSet_USR[i],is)) return false;
569
-    for(int i=0;i<8;i++) if(!read32le(&cp15->regionExecuteSet_SYS[i],is)) return false;
570
-
571
-    return true;
572
-}
573
-
574
-static bool cp15_loadstate(EMUFILE* is, int)
575
-{
576
-	//read version
577
-	uint32_t version;
578
-	if(read32le(&version,is) != 1) return false;
579
-	if(version > 1) return false;
580
-
581
-	if(!cp15_loadone((armcp15_t *)NDS_ARM9.coproc[15],is)) return false;
582
-
583
-	if(version == 0)
584
-	{
585
-		//ARM7 not have coprocessor
586
-		uint8_t *tmp_buf = new uint8_t [sizeof(armcp15_t)];
587
-		if (!tmp_buf) return false;
588
-		if(!cp15_loadone((armcp15_t *)tmp_buf,is)) return false;
589
-		delete [] tmp_buf;
590
-		tmp_buf = NULL;
591
-	}
592
-
593
-	return true;
594
-}
595
-
596
-
597
-
598
-/* Format time and convert to string */
599
-/*static char * format_time(time_t cal_time)
600
-{
601
-  struct tm *time_struct;
602
-  static char str[64];
603
-
604
-  time_struct=localtime(&cal_time);
605
-  strftime(str, sizeof str, "%d-%b-%Y %H:%M:%S", time_struct);
606
-
607
-  return str;
608
-}*/
609
-
610
-/*void clear_savestates()
611
-{
612
-  uint8_t i;
613
-  for( i = 0; i < NB_STATES; i++ )
614
-    savestates[i].exists = false;
615
-}*/
616
-
617
-// Scan for existing savestates and update struct
618
-/*void scan_savestates()
619
-{
620
-  struct stat sbuf;
621
-  char filename[MAX_PATH+1];
622
-
623
-  clear_savestates();
624
-
625
-  for(int i = 0; i < NB_STATES; i++ )
626
-    {
627
-     path.getpathnoext(path.STATES, filename);
628
-
629
-	  if (strlen(filename) + strlen(".dst") + strlen("-2147483648")*/ /* = biggest string for i */ /*>MAX_PATH) return ;
630
-      sprintf(filename+strlen(filename), ".ds%d", i);
631
-      if( stat(filename,&sbuf) == -1 ) continue;
632
-      savestates[i].exists = true;
633
-      strncpy(savestates[i].date, format_time(sbuf.st_mtime),40);
634
-	  savestates[i].date[40-1] = '\0';
635
-    }
636
-
637
-  return ;
638
-}*/
639
-
640
-/*void savestate_slot(int num)
641
-{
642
-   struct stat sbuf;
643
-   char filename[MAX_PATH+1];
644
-
645
-	lastSaveState = num;		//Set last savestate used
646
-
647
-    path.getpathnoext(path.STATES, filename);
648
-
649
-   if (strlen(filename) + strlen(".dsx") + strlen("-2147483648")*/ /* = biggest string for num *//* >MAX_PATH) return ;
650
-   sprintf(filename+strlen(filename), ".ds%d", num);*/
651
-
652
-   /*if (savestate_save(filename))
653
-   {
654
-	   osd->setLineColor(255, 255, 255);
655
-	   osd->addLine("Saved to %i slot", num);
656
-   }
657
-   else
658
-   {
659
-	   osd->setLineColor(255, 0, 0);
660
-	   osd->addLine("Error saving %i slot", num);
661
-	   return;
662
-   }*/
663
-
664
-   /*if (num >= 0 && num < NB_STATES)
665
-   {
666
-	   if (stat(filename,&sbuf) != -1)
667
-	   {
668
-		   savestates[num].exists = true;
669
-		   strncpy(savestates[num].date, format_time(sbuf.st_mtime),40);
670
-		   savestates[num].date[40-1] = '\0';
671
-	   }
672
-   }
673
-}*/
674
-
675
-/*void loadstate_slot(int num)
676
-{
677
-   char filename[MAX_PATH];
678
-
679
-   lastSaveState = num;		//Set last savestate used
680
-
681
-    path.getpathnoext(path.STATES, filename);
682
-
683
-   if (strlen(filename) + strlen(".dsx") + strlen("-2147483648")*/ /* = biggest string for num *//* >MAX_PATH) return ;
684
-   sprintf(filename+strlen(filename), ".ds%d", num);*/
685
-   /*if (savestate_load(filename))
686
-   {
687
-	   osd->setLineColor(255, 255, 255);
688
-	   osd->addLine("Loaded from %i slot", num);
689
-   }
690
-   else
691
-   {
692
-	   osd->setLineColor(255, 0, 0);
693
-	   osd->addLine("Error loading %i slot", num);
694
-   }*/
695
-//}
696
-
697
-
698
-// note: guessSF is so we don't have to do a linear search through the SFORMAT array every time
699
-// in the (most common) case that we already know where the next entry is.
700
-static const SFORMAT *CheckS(const SFORMAT *guessSF, const SFORMAT *firstSF, uint32_t size, uint32_t count, char *desc)
701
-{
702
-	const SFORMAT *sf = guessSF ? guessSF : firstSF;
703
-	while(sf->v)
704
-	{
705
-		//NOT SUPPORTED RIGHT NOW
706
-		//if(sf->size==~0)		// Link to another SFORMAT structure.
707
-		//{
708
-		//	SFORMAT *tmp;
709
-		//	if((tmp= CheckS((SFORMAT *)sf->v, tsize, desc) ))
710
-		//		return tmp;
711
-		//	sf++;
712
-		//	continue;
713
-		//}
714
-		if(!memcmp(desc,sf->desc,4))
715
-		{
716
-			if(sf->size != size || sf->count != count)
717
-				return 0;
718
-			return sf;
719
-		}
720
-
721
-		// failed to find it, have to keep iterating
722
-		if(guessSF)
723
-		{
724
-			sf = firstSF;
725
-			guessSF = NULL;
726
-		}
727
-		else
728
-		{
729
-			sf++;
730
-		}
731
-	}
732
-	return 0;
733
-}
734
-
735
-
736
-static bool ReadStateChunk(EMUFILE* is, const SFORMAT *sf, int size)
737
-{
738
-	const SFORMAT *tmp = NULL;
739
-	const SFORMAT *guessSF = NULL;
740
-	size_t temp = is->ftell();
741
-
742
-	while(is->ftell()<temp+size)
743
-	{
744
-		uint32_t sz, count;
745
-
746
-		char toa[4];
747
-		is->fread(toa,4);
748
-		if(is->fail())
749
-			return false;
750
-
751
-		if(!read32le(&sz,is)) return false;
752
-		if(!read32le(&count,is)) return false;
753
-
754
-		if((tmp=CheckS(guessSF,sf,sz,count,toa)))
755
-		{
756
-		#ifdef LOCAL_LE
757
-			// no need to ever loop one at a time if not flipping byte order
758
-			is->fread((char *)tmp->v,sz*count);
759
-		#else
760
-			if(sz == 1) {
761
-				//special case: read a huge byte array
762
-				is->fread((char *)tmp->v,count);
763
-			} else {
764
-				for(unsigned int i=0;i<count;i++)
765
-				{
766
-					is->fread((char *)tmp->v + i*sz,sz);
767
-                    FlipByteOrder((uint8_t*)tmp->v + i*sz,sz);
768
-				}
769
-			}
770
-		#endif
771
-			guessSF = tmp + 1;
772
-		}
773
-		else
774
-		{
775
-			is->fseek(sz*count,SEEK_CUR);
776
-			guessSF = NULL;
777
-		}
778
-	} // while(...)
779
-	return true;
780
-}
781
-
782
-
783
-
784
-/*static int SubWrite(EMUFILE* os, const SFORMAT *sf)
785
-{
786
-	uint32_t acc=0;
787
-
788
-#ifdef DEBUG
789
-	std::set<std::string> keyset;
790
-#endif
791
-
792
-	const SFORMAT* temp = sf;
793
-	while(temp->v) {
794
-		const SFORMAT* seek = sf;
795
-		while(seek->v && seek != temp) {
796
-			if(!strcmp(seek->desc,temp->desc)) {
797
-				printf("ERROR! duplicated chunk name: %s\n", temp->desc);
798
-			}
799
-			seek++;
800
-		}
801
-		temp++;
802
-	}
803
-
804
-	while(sf->v)
805
-	{
806
-		//not supported right now
807
-		//if(sf->size==~0)		//Link to another struct
808
-		//{
809
-		//	uint32_t tmp;
810
-
811
-		//	if(!(tmp=SubWrite(os,(SFORMAT *)sf->v)))
812
-		//		return 0;
813
-		//	acc+=tmp;
814
-		//	sf++;
815
-		//	continue;
816
-		//}
817
-
818
-		int count = sf->count;
819
-		int size = sf->size;
820
-
821
-        //add size of current node to the accumulator
822
-		acc += 4 + sizeof(sf->size) + sizeof(sf->count);
823
-		acc += count * size;
824
-
825
-		if(os)			//Are we writing or calculating the size of this block?
826
-		{
827
-			os->fwrite(sf->desc,4);
828
-			write32le(sf->size,os);
829
-			write32le(sf->count,os);
830
-
831
-			#ifdef DEBUG
832
-			//make sure we dont dup any keys
833
-			if(keyset.find(sf->desc) != keyset.end())
834
-			{
835
-				printf("duplicate save key!\n");
836
-				assert(false);
837
-			}
838
-			keyset.insert(sf->desc);
839
-			#endif
840
-
841
-
842
-		#ifdef LOCAL_LE
843
-			// no need to ever loop one at a time if not flipping byte order
844
-			os->fwrite((char *)sf->v,size*count);
845
-		#else
846
-			if(size == 1) {
847
-				//special case: write a huge byte array
848
-				os->fwrite((char *)sf->v,count);
849
-			} else {
850
-				for(int i=0;i<count;i++) {
851
-					FlipByteOrder((uint8_t*)sf->v + i*size, size);
852
-					os->fwrite((char*)sf->v + i*size,size);
853
-					//Now restore the original byte order.
854
-					FlipByteOrder((uint8_t*)sf->v + i*size, size);
855
-				}
856
-			}
857
-		#endif
858
-		}
859
-		sf++;
860
-	}
861
-
862
-	return acc;
863
-}*/
864
-
865
-/*static int savestate_WriteChunk(EMUFILE* os, int type, const SFORMAT *sf)
866
-{
867
-	write32le(type,os);
868
-	if(!sf) return 4;
869
-	int bsize = SubWrite((EMUFILE*)0,sf);
870
-	write32le(bsize,os);
871
-
872
-	if(!SubWrite(os,sf))
873
-	{
874
-		return 8;
875
-	}
876
-	return bsize+8;
877
-}*/
878
-
879
-/*static void savestate_WriteChunk(EMUFILE* os, int type, void (*saveproc)(EMUFILE* os))
880
-{
881
-	uint32_t pos1 = os->ftell();
882
-
883
-	//write the type, size(placeholder), and data
884
-	write32le(type,os);
885
-	os->fseek(4, SEEK_CUR); // skip the size, we write that later
886
-	saveproc(os);
887
-
888
-	//get the size
889
-	uint32_t pos2 = os->ftell();
890
-	assert(pos2 != (uint32_t)-1); // if this assert fails, saveproc did something bad
891
-	uint32_t size = (pos2 - pos1) - (2 * sizeof(uint32_t));
892
-
893
-	//fill in the actual size
894
-	os->fseek(pos1 + sizeof(uint32_t),SEEK_SET);
895
-	write32le(size,os);
896
-	os->fseek(pos2,SEEK_SET);*/
897
-
898
-/*
899
-// old version of this function,
900
-// for reference in case the new one above starts misbehaving somehow:
901
-
902
-	// - this is retarded. why not write placeholders for size and then write directly to the stream
903
-	//and then go back and fill them in
904
-
905
-	//get the size
906
-	memorystream mstemp;
907
-	saveproc(&mstemp);
908
-	mstemp.flush();
909
-	uint32_t size = mstemp.size();
910
-
911
-	//write the type, size, and data
912
-	write32le(type,os);
913
-	write32le(size,os);
914
-	os->write(mstemp.buf(),size);
915
-*/
916
-//}
917
-
918
-//static void writechunks(EMUFILE* os);
919
-
920
-/*bool savestate_save(EMUFILE* outstream, int compressionLevel)
921
-{
922
-	#ifndef HAVE_LIBZ
923
-	compressionLevel = Z_NO_COMPRESSION;
924
-	#endif
925
-
926
-	EMUFILE_MEMORY ms;
927
-	EMUFILE* os;
928
-
929
-	if(compressionLevel != Z_NO_COMPRESSION)
930
-	{
931
-		//generate the savestate in memory first
932
-		os = (EMUFILE*)&ms;
933
-		writechunks(os);
934
-	}
935
-	else
936
-	{
937
-		os = outstream;
938
-		os->fseek(32,SEEK_SET); //skip the header
939
-		writechunks(os);
940
-	}
941
-
942
-	//save the length of the file
943
-	uint32_t len = os->ftell();
944
-
945
-	uint32_t comprlen = 0xFFFFFFFF;
946
-	uint8_t* cbuf;
947
-
948
-	//compress the data
949
-	int error = Z_OK;
950
-	if(compressionLevel != Z_NO_COMPRESSION)
951
-	{
952
-		cbuf = ms.buf();
953
-		uLongf comprlen2;
954
-		//worst case compression.
955
-		//zlib says "0.1% larger than sourceLen plus 12 bytes"
956
-		comprlen = (len>>9)+12 + len;
957
-		cbuf = new uint8_t[comprlen];
958
-		// Workaround to make it compile under linux 64bit
959
-		comprlen2 = comprlen;
960
-		//error = compress2(cbuf,&comprlen2,ms.buf(),len,compressionLevel);
961
-		comprlen = (uint32_t)comprlen2;
962
-	}
963
-
964
-	//dump the header
965
-	outstream->fseek(0,SEEK_SET);
966
-	outstream->fwrite(magic,16);
967
-	write32le(SAVESTATE_VERSION,outstream);
968
-	write32le(EMU_DESMUME_VERSION_NUMERIC(),outstream); //desmume version
969
-	write32le(len,outstream); //uncompressed length
970
-	write32le(comprlen,outstream); //compressed length (-1 if it is not compressed)
971
-
972
-	if(compressionLevel != Z_NO_COMPRESSION)
973
-	{
974
-		outstream->fwrite((char*)cbuf,comprlen==(uint32_t)-1?len:comprlen);
975
-		delete[] cbuf;
976
-	}
977
-
978
-	return error == Z_OK;
979
-}*/
980
-
981
-/*bool savestate_save (const char *file_name)
982
-{
983
-	EMUFILE_MEMORY ms;
984
-	size_t elems_written;
985
-#ifdef HAVE_LIBZ
986
-	if(!savestate_save(&ms, Z_DEFAULT_COMPRESSION))
987
-#else
988
-	if(!savestate_save(&ms, 0))
989
-#endif
990
-		return false;
991
-	FILE* file = fopen(file_name,"wb");
992
-	if(file)
993
-	{
994
-		elems_written = fwrite(ms.buf(),1,ms.size(),file);
995
-		fclose(file);
996
-		return elems_written == ms.size();
997
-	} else return false;
998
-}*/
999
-
1000
-//extern SFORMAT SF_RTC[];
1001
-
1002
-/*static void writechunks(EMUFILE* os) {
1003
-	savestate_WriteChunk(os,1,SF_ARM9);
1004
-	savestate_WriteChunk(os,2,SF_ARM7);
1005
-	savestate_WriteChunk(os,3,cp15_savestate);
1006
-	savestate_WriteChunk(os,4,SF_MEM);
1007
-	savestate_WriteChunk(os,5,SF_NDS);
1008
-	savestate_WriteChunk(os,51,nds_savestate);
1009
-	savestate_WriteChunk(os,60,SF_MMU);
1010
-	savestate_WriteChunk(os,61,mmu_savestate);
1011
-	//savestate_WriteChunk(os,7,gpu_savestate);
1012
-	savestate_WriteChunk(os,8,spu_savestate);
1013
-	//savestate_WriteChunk(os,81,mic_savestate);
1014
-	//savestate_WriteChunk(os,90,SF_GFX3D);
1015
-	//savestate_WriteChunk(os,91,gfx3d_savestate);
1016
-	//savestate_WriteChunk(os,100,SF_MOVIE);
1017
-	//savestate_WriteChunk(os,101,mov_savestate);
1018
-	//savestate_WriteChunk(os,110,SF_WIFI);
1019
-	//savestate_WriteChunk(os,120,SF_RTC);
1020
-	savestate_WriteChunk(os,0xFFFFFFFF,(SFORMAT*)0);
1021
-}*/
1022
-
1023
-/*static bool fake_gpu_loadstate(EMUFILE* is, int size)
1024
-{
1025
-	//read version
1026
-	uint32_t version;
1027
-
1028
-	//sigh.. shouldve used a new version number
1029
-	if(size == 256*192*2*2)
1030
-		version = 0;
1031
-	else if(size== 0x30024)
1032
-	{
1033
-		read32le(&version,is);
1034
-		version = 1;
1035
-	}
1036
-	else
1037
-		if(read32le(&version,is) != 1) return false;
1038
-
1039
-
1040
-	if(version<0||version>1) return false;
1041
-
1042
-	uint8_t tmpu8_array[4*256*192];
1043
-	is->fread((char*)tmpu8_array,sizeof(tmpu8_array));
1044
-
1045
-	if(version==1)
1046
-	{
1047
-		uint32_t tmpu32;
1048
-		for (int i = 0; i < 8; ++i)
1049
-			read32le(&tmpu32, is);*/
1050
-		/*read32le(&MainScreen.gpu->affineInfo[0].x,is);
1051
-		read32le(&MainScreen.gpu->affineInfo[0].y,is);
1052
-		read32le(&MainScreen.gpu->affineInfo[1].x,is);
1053
-		read32le(&MainScreen.gpu->affineInfo[1].y,is);
1054
-		read32le(&SubScreen.gpu->affineInfo[0].x,is);
1055
-		read32le(&SubScreen.gpu->affineInfo[0].y,is);
1056
-		read32le(&SubScreen.gpu->affineInfo[1].x,is);
1057
-		read32le(&SubScreen.gpu->affineInfo[1].y,is);*/
1058
-		//removed per nitsuja feedback. anyway, this same thing will happen almost immediately in gpu line=0
1059
-		//MainScreen.gpu->refreshAffineStartRegs(-1,-1);
1060
-		//SubScreen.gpu->refreshAffineStartRegs(-1,-1);
1061
-	/*}
1062
-
1063
-	//MainScreen.gpu->updateBLDALPHA();
1064
-	//SubScreen.gpu->updateBLDALPHA();
1065
-	return !is->fail();
1066
-}*/
1067
-
1068
-/*static bool fake_mic_loadstate(EMUFILE* is, int size)
1069
-{
1070
-	uint32_t version;
1071
-	if(read32le(&version,is) != 1) return false;
1072
-	if(version > 1 || version == 0) { is->fseek(size-4, SEEK_CUR); return true; }
1073
-
1074
-	uint8_t tmpu8_Array[2][4096];
1075
-	is->fread((char*)tmpu8_Array[0], 4096);
1076
-	is->fread((char*)tmpu8_Array[1], 4096);
1077
-	uint16_t tmpu16;
1078
-	read16le(&tmpu16,is);
1079
-	uint8_t tmpu8;
1080
-	read8le(&tmpu8,is);
1081
-	read8le(&tmpu8,is);
1082
-	uint32_t tmpu32;
1083
-	read32le(&tmpu32,is);
1084
-	return true;
1085
-}*/
1086
-
1087
-/*static uint32_t tmpu32_array16[16];
1088
-static uint32_t tmpu32_array64[64];
1089
-static uint32_t tmpu32_array4[4];
1090
-static uint16_t tmpu16_array6[6];
1091
-static uint8_t tmpu8_array4[4];
1092
-static uint16_t tmpu16_array32[32];
1093
-static uint8_t tmpu8_array128[128];
1094
-static uint8_t tmpu8_arrayAlot[4*256*192];
1095
-SFORMAT SF_GFX3D[]={
1096
-	{ "GCTL", 4, 1, &tmpu32}, // no longer regenerated indirectly, see comment in loadstate()
1097
-	{ "GPAT", 4, 1, &tmpu32},
1098
-	{ "GPAP", 4, 1, &tmpu32},
1099
-	{ "GINB", 4, 1, &tmpu32},
1100
-	{ "GTFM", 4, 1, &tmpu32},
1101
-	{ "GTPA", 4, 1, &tmpu32},
1102
-	{ "GMOD", 4, 1, &tmpu32},
1103
-	{ "GMTM", 4,16, tmpu32_array16},
1104
-	{ "GMCU", 4,64, tmpu32_array64},
1105
-	{ "ML4I", 1, 1, &tmpu8},
1106
-	{ "ML3I", 1, 1, &tmpu8},
1107
-	{ "MM4I", 1, 1, &tmpu8},
1108
-	{ "MM3I", 1, 1, &tmpu8},
1109
-	{ "MMxI", 1, 1, &tmpu8},
1110
-	{ "GSCO", 4, 1, tmpu32_array4},
1111
-	{ "GCOI", 1, 1, &tmpu8},
1112
-	{ "GVFM", 4, 1, &tmpu32},
1113
-	{ "GTRN", 4, 4, tmpu32_array4},
1114
-	{ "GTRI", 1, 1, &tmpu8},
1115
-	{ "GSCA", 4, 4, tmpu32_array4},
1116
-	{ "GSCI", 1, 1, &tmpu8},
1117
-	{ "G_T_", 4, 1, &tmpu32},
1118
-	{ "G_S_", 4, 1, &tmpu32},
1119
-	{ "GL_T", 4, 1, &tmpu32},
1120
-	{ "GL_S", 4, 1, &tmpu32},
1121
-	{ "GLCM", 4, 1, &tmpu32},
1122
-	{ "GLIN", 4, 1, &tmpu32},
1123
-	{ "GLI2", 4, 1, &tmpu32},
1124
-	{ "GLSB", 4, 1, &tmpu32},
1125
-	{ "GLBT", 4, 1, &tmpu32},
1126
-	{ "GLPT", 4, 1, &tmpu32},
1127
-	{ "GLPC", 4, 4, tmpu32_array4},
1128
-	{ "GBTC", 2, 6, tmpu16_array6},
1129
-	{ "GFHE", 4, 1, &gxFIFO.head},
1130
-	{ "GFTA", 4, 1, &gxFIFO.tail},
1131
-	{ "GFSZ", 4, 1, &gxFIFO.size},
1132
-	{ "GFCM", 1, HACK_GXIFO_SIZE, &gxFIFO.cmd[0]},
1133
-	{ "GFPM", 4, HACK_GXIFO_SIZE, &gxFIFO.param[0]},
1134
-	{ "GPHE", 1, 1, &gxPIPE.head},
1135
-	{ "GPTA", 1, 1, &gxPIPE.tail},
1136
-	{ "GPSZ", 1, 1, &gxPIPE.size},
1137
-	{ "GPCM", 1, 4, &gxPIPE.cmd[0]},
1138
-	{ "GPPM", 4, 4, &gxPIPE.param[0]},
1139
-	{ "GCOL", 1, 4, &tmpu8_array4},
1140
-	{ "GLCO", 4, 4, tmpu32_array4},
1141
-	{ "GLDI", 4, 4, tmpu32_array4},
1142
-	{ "GMDI", 2, 1, &tmpu16},
1143
-	{ "GMAM", 2, 1, &tmpu16},
1144
-	{ "GMSP", 2, 1, &tmpu16},
1145
-	{ "GMEM", 2, 1, &tmpu16},
1146
-	{ "GFLP", 4, 1, &tmpu32},
1147
-	{ "GDRP", 4, 1, &tmpu32},
1148
-	{ "GSET", 4, 1, &tmpu32},
1149
-	{ "GSEA", 4, 1, &tmpu32},
1150
-	{ "GSEB", 4, 1, &tmpu32},
1151
-	{ "GSEX", 4, 1, &tmpu32},
1152
-	{ "GSEE", 4, 1, &tmpu32},
1153
-	{ "GSEC", 4, 1, &tmpu32},
1154
-	{ "GSEF", 4, 1, &tmpu32},
1155
-	{ "GSEO", 4, 1, &tmpu32},
1156
-	{ "GFSH", 4, 1, &tmpu32},
1157
-	{ "GSSH", 4, 1, &tmpu32},
1158
-	{ "GSWB", 4, 1, &tmpu32},
1159
-	{ "GSSM", 4, 1, &tmpu32},
1160
-	{ "GSAR", 1, 1, &tmpu8},
1161
-	{ "GSVP", 4, 1, &tmpu32},
1162
-	{ "GSCC", 4, 1, &tmpu32},
1163
-	{ "GSCD", 4, 1, &tmpu32},
1164
-	{ "GSFC", 4, 4, tmpu32_array4},
1165
-	{ "GSFO", 4, 1, &tmpu32},
1166
-	{ "GST4", 2, 32, tmpu16_array32},
1167
-	{ "GSSU", 1, 128, tmpu8_array128},
1168
-	{ "GSSI", 4, 1, &tmpu32},
1169
-	{ "GSAF", 4, 1, &tmpu32},
1170
-	{ "GSPF", 4, 1, &tmpu32},
1171
-	//------------------------
1172
-	{ "GTST", 4, 1, &tmpu32},
1173
-	{ "GTVC", 4, 1, &tmpu32},
1174
-	{ "GTVM", 4, 4, tmpu32_array4},
1175
-	{ "GTVF", 4, 1, &tmpu32},
1176
-	{ "G3CX", 1, 4*256*192, tmpu8_arrayAlot},
1177
-	{ 0 }
1178
-};*/
1179
-
1180
-/*static uint8_t tmpu8_array8[8];
1181
-static SFORMAT SF_RTC[]={
1182
-	{ "R000", 1, 1, &tmpu8},
1183
-	{ "R010", 1, 1, &tmpu8},
1184
-	{ "R020", 1, 1, &tmpu8},
1185
-	{ "R030", 1, 1, &tmpu8},
1186
-
1187
-	{ "R040", 1, 1, &tmpu8},
1188
-	{ "R050", 1, 1, &tmpu8},
1189
-	{ "R060", 1, 1, &tmpu8},
1190
-	{ "R070", 1, 1, &tmpu8},
1191
-	{ "R080", 1, 1, &tmpu8},
1192
-	{ "R090", 1, 1, &tmpu8},
1193
-	{ "R100", 1, 1, &tmpu8},
1194
-	{ "R110", 2, 1, &tmpu16},
1195
-
1196
-	{ "R120", 1, 1, &tmpu8},
1197
-	{ "R130", 1, 1, &tmpu8},
1198
-	{ "R140", 1, 1, &tmpu8},
1199
-	{ "R150", 1, 8, tmpu8_array8},
1200
-
1201
-	{ "R160", 1, 8, tmpu8_array8},
1202
-
1203
-	{ NULL, 0, 0, NULL }
1204
-};*/
1205
-
1206
-/*static bool fake_gfx_hardware_loadstate(EMUFILE *f)
1207
-{
1208
-	uint32_t version;
1209
-	if(read32le(&version,f) != 1) return false;
1210
-	if(version != 0) return false;
1211
-
1212
-	uint32_t tempsize;
1213
-	read32le(&tempsize,f);
1214
-	uint32_t commandCursor = 4-tempsize;
1215
-	//for(uint32_t i=0;i<commandCursor;i++) commandsPending[i].command = 0;
1216
-	uint8_t tmpu8;
1217
-	for(uint32_t i=commandCursor;i<4;i++) read8le(&commandsPending[i].command&tmpu8,f);
1218
-	read32le(&tempsize,f);
1219
-	//for(uint32_t i=0;i<commandCursor;i++) commandsPending[i].countdown = 0;
1220
-	for(uint32_t i=commandCursor;i<4;i++) read8le(&commandsPending[i].countdown&tmpu8,f);
1221
-
1222
-	read8le(&countdown&tmpu8,f);
1223
-
1224
-	return true;
1225
-}*/
1226
-
1227
-/*static bool fake_gfx3d_loadstate(EMUFILE* is, int size)
1228
-{
1229
-	int version;
1230
-	if(read32le(&version,is) != 1) return false;
1231
-	if(size==8) version = 0;
1232
-
1233
-
1234
-	//gfx3d_glPolygonAttrib_cache();
1235
-	//gfx3d_glTexImage_cache();
1236
-	//gfx3d_glLightDirection_cache(0);
1237
-	//gfx3d_glLightDirection_cache(1);
1238
-	//gfx3d_glLightDirection_cache(2);
1239
-	//gfx3d_glLightDirection_cache(3);
1240
-
1241
-	//jiggle the lists. and also wipe them. this is clearly not the best thing to be doing.
1242
-	//listTwiddle = 0;
1243
-	//polylist = &polylists[listTwiddle];
1244
-	//vertlist = &vertlists[listTwiddle];
1245
-
1246
-#define OSREAD(x) is->fread((char*)&(x),sizeof((x)));
1247
-	if(version>=1)
1248
-	{
1249
-		int tmpint;
1250
-		//OSREAD(vertlist->count);
1251
-		//OSREAD(tmpint);
1252
-		is->fread(&tmpint, sizeof(int));
1253
-		//for(int i=0;i<vertlist->count;i++)
1254
-		for (int i = 0; i < tmpint; ++i)
1255
-		{
1256
-			//vertlist->list[i].load(is);
1257
-			float tmpfloat;
1258
-			uint8_t tmpu8;
1259
-			for (int j = 0; j < 6; ++j)
1260
-				//OSREAD(tmpfloat);
1261
-				is->fread(&tmpfloat, sizeof(float));
1262
-			for (int j = 0; j < 3; ++j)
1263
-				//OSREAD(tmpu8);
1264
-				is->fread(&tmpu8, sizeof(uint8_t));
1265
-			for (int j = 0; j < 3; ++j)
1266
-				//OSREAD(tmpfloat);
1267
-				is->fread(&tmpfloat, sizeof(float));
1268
-		}
1269
-		//OSREAD(polylist->count);
1270
-		//OSREAD(tmpint);
1271
-		is->fread(&tmpint, sizeof(int));
1272
-		//for(int i=0;i<polylist->count;i++)
1273
-		for (int i = 0; i < tmpint; ++i)
1274
-		{
1275
-			//polylist->list[i].load(is);
1276
-			int tmpint2;
1277
-			uint16_t tmpu16;
1278
-			uint32_t tmpu32;
1279
-			float tmpfloat;
1280
-			//OSREAD(tmpint2);
1281
-			is->fread(&tmpint2, sizeof(int));
1282
-			for (int j = 0; j < 4; ++j)
1283
-				//OSREAD(tmpu16);
1284
-				is->fread(&tmpu16, sizeof(uint16_t));
1285
-			for (int j = 0; j < 4; ++j)
1286
-				//OSREAD(tmpu32);
1287
-				is->fread(&tmpu32, sizeof(uint32_t));
1288
-			for (int j = 0; j < 2; ++j)
1289
-				//OSREAD(tmpfloat);
1290
-				is->fread(&tmpfloat, sizeof(float));
1291
-		}
1292
-	}
1293
-
1294
-	if(version>=2)
1295
-	{
1296
-		for(int i=0;i<4;i++)
1297
-		{
1298
-			uint32_t tmpu32;
1299
-			//OSREAD(mtxStack[i].position);
1300
-			//OSREAD(tmpu32);
1301
-			is->fread(&tmpu32, sizeof(uint32_t));*/
1302
-			/*for(int j=0;j<mtxStack[i].size*16;j++)
1303
-				OSREAD(mtxStack[i].matrix[j]);*/
1304
-			//if (!i || i == 3)
1305
-				/*for (int j = 0; j < (!i || i == 3 ? 1 : 31) * 16; ++j)
1306
-					//OSREAD(tmpu32)
1307
-					is->fread(&tmpu32, sizeof(uint32_t));
1308
-			//else
1309
-				//for (int j = 0; j < 31 * 16; ++j)
1310
-					//OSREAD(tmpu32);
1311
-		}
1312
-	}
1313
-
1314
-	if(version>=3) {
1315
-		fake_gfx_hardware_loadstate(is);
1316
-	}*/
1317
-
1318
-	/*gfx3d.polylist = &polylists[listTwiddle^1];
1319
-	gfx3d.vertlist = &vertlists[listTwiddle^1];
1320
-	gfx3d.polylist->count=0;
1321
-	gfx3d.vertlist->count=0;*/
1322
-
1323
-	/*if(version >= 4)
1324
-	{
1325
-		uint32_t tmpu32_array16[16];
1326
-		//OSREAD(cacheLightDirection);
1327
-		//OSREAD(tmpu32_array16);
1328
-		is->fread(tmpu32_array16, sizeof(tmpu32_array16));
1329
-		//OSREAD(cacheHalfVector);
1330
-		//OSREAD(tmpu32_array16);
1331
-		is->fread(tmpu32_array16, sizeof(tmpu32_array16));
1332
-	}
1333
-
1334
-	return true;
1335
-}*/
1336
-
1337
-//static void fake_MovieRecord_parsePad(EMUFILE* fp/*, uint16_t& pad*/)
1338
-/*{
1339
-
1340
-	char buf[13];
1341
-	fp->fread(buf,13);*/
1342
-	/*pad = 0;
1343
-	for(int i=0;i<13;i++)
1344
-	{
1345
-		pad <<= 1;
1346
-		pad |= ((buf[i]=='.'||buf[i]==' ')?0:1);
1347
-	}*/
1348
-//}
1349
-
1350
-/*static void fake_MovieRecord_parse(MovieData* md, EMUFILE* fp)
1351
-{
1352
-	//by the time we get in here, the initial pipe has already been extracted
1353
-
1354
-	//extract the commands
1355
-	uint8_t tmpu8 = u32DecFromIstream(fp);
1356
-
1357
-	fp->fgetc(); //eat the pipe
1358
-
1359
-	fake_MovieRecord_parsePad(fp*//*, pad*///);
1360
-	/*touch.x*///tmpu8 = u32DecFromIstream(fp);
1361
-	/*touch.y*///tmpu8 = u32DecFromIstream(fp);
1362
-	/*touch.touch*///tmpu8 = u32DecFromIstream(fp);
1363
-
1364
-	/*fp->fgetc(); //eat the pipe
1365
-
1366
-	//should be left at a newline
1367
-}*/
1368
-
1369
-/*static bool fake_LoadFM2(MovieData& movieData, EMUFILE* fp, int size, bool stopAfterHeader)
1370
-{
1371
-	//TODO - start with something different. like 'desmume movie version 1"
1372
-	int curr = fp->ftell();
1373
-
1374
-	//movie must start with "version 1"
1375
-	char buf[9];
1376
-	curr = fp->ftell();
1377
-	fp->fread(buf,9);
1378
-	fp->fseek(curr, SEEK_SET);
1379
-//	if(fp->fail()) return false;
1380
-	if(memcmp(buf,"version 1",9))
1381
-		return false;
1382
-
1383
-	std::string key,value;
1384
-	enum {
1385
-		NEWLINE, KEY, SEPARATOR, VALUE, RECORD, COMMENT
1386
-	} state = NEWLINE;
1387
-	bool bail = false;
1388
-	for(;;)
1389
-	{
1390
-		bool iswhitespace, isrecchar, isnewline;
1391
-		int c;
1392
-		if(size--<=0) goto bail;
1393
-		c = fp->fgetc();
1394
-		if(c == -1)
1395
-			goto bail;
1396
-		iswhitespace = (c==' '||c=='\t');
1397
-		isrecchar = (c=='|');
1398
-		isnewline = (c==10||c==13);
1399
-		if(isrecchar && movieData.binaryFlag && !stopAfterHeader)
1400
-		{
1401
-			LoadFM2_binarychunk(movieData, fp, size);
1402
-			return true;
1403
-		}
1404
-		switch(state)
1405
-		{
1406
-		case NEWLINE:
1407
-			if(isnewline) goto done;
1408
-			if(iswhitespace) goto done;
1409
-			if(isrecchar)
1410
-				goto dorecord;
1411
-			//must be a key
1412
-			key = "";
1413
-			value = "";
1414
-			goto dokey;
1415
-			break;
1416
-		case RECORD:
1417
-			{
1418
-				dorecord:
1419
-				if (stopAfterHeader) return true;
1420
-				//int currcount = movieData.records.size();
1421
-				//movieData.records.resize(currcount+1);
1422
-				int preparse = fp->ftell();
1423
-				//movieData.records[currcount].parse(&movieData, fp);
1424
-				fake_MovieRecord_parse(fp);
1425
-				int postparse = fp->ftell();
1426
-				size -= (postparse-preparse);
1427
-				state = NEWLINE;
1428
-				break;
1429
-			}
1430
-
1431
-		case KEY:
1432
-			dokey: //dookie
1433
-			state = KEY;
1434
-			if(iswhitespace) goto doseparator;
1435
-			if(isnewline) goto commit;
1436
-			key += c;
1437
-			break;
1438
-		case SEPARATOR:
1439
-			doseparator:
1440
-			state = SEPARATOR;
1441
-			if(isnewline) goto commit;
1442
-			if(!iswhitespace) goto dovalue;
1443
-			break;
1444
-		case VALUE:
1445
-			dovalue:
1446
-			state = VALUE;
1447
-			if(isnewline) goto commit;
1448
-			value += c;
1449
-			break;
1450
-		case COMMENT:
1451
-		default:
1452
-			break;
1453
-		}
1454
-		goto done;
1455
-
1456
-		bail:
1457
-		bail = true;
1458
-		if(state == VALUE) goto commit;
1459
-		goto done;
1460
-		commit:
1461
-		//movieData.installValue(key,value);
1462
-		state = NEWLINE;
1463
-		done: ;
1464
-		if(bail) break;
1465
-	}
1466
-
1467
-	return true;
1468
-}*/
1469
-
1470
-/*static bool fake_mov_loadstate(EMUFILE* fp, int size)
1471
-{
1472
-	//load_successful = false;
1473
-	static const int kMOVI = 0x49564F4D;
1474
-	static const int kNOMO = 0x4F4D4F4E;
1475
-
1476
-	uint32_t cookie;
1477
-	if(read32le(&cookie,fp) != 1) return false;
1478
-	if(cookie == kNOMO)
1479
-	{*/
1480
-		/*if(movieMode == MOVIEMODE_RECORD || movieMode == MOVIEMODE_PLAY)
1481
-			FinishPlayback();*/
1482
-		/*return true;
1483
-	}
1484
-	else if(cookie != kMOVI)
1485
-		return false;
1486
-
1487
-	size -= 4;*/
1488
-
1489
-	/*if (!movie_readonly && autoMovieBackup && freshMovie) //If auto-backup is on, movie has not been altered this session and the movie is in read+write mode
1490
-	{
1491
-		FCEUI_MakeBackupMovie(false);	//Backup the movie before the contents get altered, but do not display messages
1492
-	}*/
1493
-
1494
-	//a little rule: cant load states in read+write mode with a movie from an archive.
1495
-	//so we are going to switch it to readonly mode in that case
1496
-//	if(!movie_readonly
1497
-//		//*&& FCEU_isFileInArchive(curMovieFilename)*/
1498
-//		) {
1499
-//		FCEU_PrintError("Cannot loadstate in Read+Write with movie from archive. Movie is now Read-Only.");
1500
-//		movie_readonly = true;
1501
-//	}
1502
-
1503
-	//MovieData tempMovieData = MovieData();
1504
-	//int curr = fp->ftell();
1505
-	//if(!LoadFM2(tempMovieData, fp, size, false)) {
1506
-	/*if (!fake_LoadFM2(fp, size, false)) {*/
1507
-
1508
-	//	is->seekg((uint32_t)curr+size);
1509
-	/*	extern bool FCEU_state_loading_old_format;
1510
-		if(FCEU_state_loading_old_format) {
1511
-			if(movieMode == MOVIEMODE_PLAY || movieMode == MOVIEMODE_RECORD) {
1512
-				FCEUI_StopMovie();
1513
-				FCEU_PrintError("You have tried to use an old savestate while playing a movie. This is unsupported (since the old savestate has old-format movie data in it which can't be converted on the fly)");
1514
-			}
1515
-		}*/
1516
-		/*return false;
1517
-	}*/
1518
-
1519
-	//complex TAS logic for when a savestate is loaded:
1520
-	//----------------
1521
-	//if we are playing or recording and toggled read-only:
1522
-	//  then, the movie we are playing must match the guid of the one stored in the savestate or else error.
1523
-	//  the savestate is assumed to be in the same timeline as the current movie.
1524
-	//  if the current movie is not long enough to get to the savestate's frame#, then it is an error.
1525
-	//  the movie contained in the savestate will be discarded.
1526
-	//  the emulator will be put into play mode.
1527
-	//if we are playing or recording and toggled read+write
1528
-	//  then, the movie we are playing must match the guid of the one stored in the savestate or else error.
1529
-	//  the movie contained in the savestate will be loaded into memory
1530
-	//  the frames in the movie after the savestate frame will be discarded
1531
-	//  the in-memory movie will have its rerecord count incremented
1532
-	//  the in-memory movie will be dumped to disk as fcm.
1533
-	//  the emulator will be put into record mode.
1534
-	//if we are doing neither:
1535
-	//  then, we must discard this movie and just load the savestate
1536
-
1537
-
1538
-	/*if(movieMode != MOVIEMODE_INACTIVE)
1539
-	{
1540
-		//handle moviefile mismatch
1541
-		if(tempMovieData.guid != currMovieData.guid)
1542
-		{
1543
-			//mbg 8/18/08 - this code  can be used to turn the error message into an OK/CANCEL
1544
-			#ifdef WIN32
1545
-				//std::string msg = "There is a mismatch between savestate's movie and current movie.\ncurrent: " + currMovieData.guid.toString() + "\nsavestate: " + tempMovieData.guid.toString() + "\n\nThis means that you have loaded a savestate belonging to a different movie than the one you are playing now.\n\nContinue loading this savestate anyway?";
1546
-				//extern HWND pwindow;
1547
-				//int result = MessageBox(pwindow,msg.c_str(),"Error loading savestate",MB_OKCANCEL);
1548
-				//if(result == IDCANCEL)
1549
-				//	return false;
1550
-			#else
1551
-				FCEU_PrintError("Mismatch between savestate's movie and current movie.\ncurrent: %s\nsavestate: %s\n",currMovieData.guid.toString().c_str(),tempMovieData.guid.toString().c_str());
1552
-				return false;
1553
-			#endif
1554
-		}
1555
-
1556
-		closeRecordingMovie();
1557
-
1558
-		if(!movie_readonly)
1559
-		{
1560
-			currMovieData = tempMovieData;
1561
-			currMovieData.rerecordCount = currRerecordCount;
1562
-		}
1563
-
1564
-		if(currFrameCounter > (int)currMovieData.records.size())
1565
-		{
1566
-			// if the frame counter is longer than our current movie,
1567
-			// switch to "finished" mode.
1568
-			// this is a mode that behaves like "inactive"
1569
-			// except it permits switching to play/record by loading an earlier savestate.
1570
-			// (and we continue to store the finished movie in savestates made while finished)
1571
-			osd->setLineColor(255,0,0); // let's make the text red too to hopefully catch the user's attention a bit.
1572
-			FinishPlayback();
1573
-			osd->setLineColor(255,255,255);
1574
-
1575
-			//FCEU_PrintError("Savestate is from a frame (%d) after the final frame in the movie (%d). This is not permitted.", currFrameCounter, currMovieData.records.size()-1);
1576
-			//return false;
1577
-		}
1578
-		else if(movie_readonly)
1579
-		{
1580
-			//-------------------------------------------------------------
1581
-			//this code would reload the movie from disk. allegedly it is helpful to hexers, but
1582
-			//it is way too slow with dsm format. so it is only here as a reminder, and in case someone
1583
-			//wants to play with it
1584
-			//-------------------------------------------------------------
1585
-			//{
1586
-			//	fstream fs (curMovieFilename);
1587
-			//	if(!LoadFM2(tempMovieData, &fs, INT_MAX, false))
1588
-			//	{
1589
-			//		FCEU_PrintError("Failed to reload DSM after loading savestate");
1590
-			//	}
1591
-			//	fs.close();
1592
-			//	currMovieData = tempMovieData;
1593
-			//}
1594
-			//-------------------------------------------------------------
1595
-
1596
-			movieMode = MOVIEMODE_PLAY;
1597
-		}
1598
-		else
1599
-		{
1600
-		//	#ifdef _S9XLUA_H
1601
-		//	if(!FCEU_LuaRerecordCountSkip())
1602
-				currRerecordCount++;
1603
-		//	#endif
1604
-
1605
-			currMovieData.rerecordCount = currRerecordCount;
1606
-			currMovieData.truncateAt(currFrameCounter);
1607
-
1608
-			openRecordingMovie(curMovieFilename);
1609
-			if(!osRecordingMovie)
1610
-			{
1611
-			   osd->setLineColor(255, 0, 0);
1612
-			   osd->addLine("Can't save movie file!");
1613
-			}
1614
-
1615
-			//printf("DUMPING MOVIE: %d FRAMES\n",currMovieData.records.size());
1616
-			currMovieData.dump(osRecordingMovie, false);
1617
-			movieMode = MOVIEMODE_RECORD;
1618
-		}
1619
-	}
1620
-
1621
-	load_successful = true;
1622
-	freshMovie = false;*/
1623
-
1624
-	//// Maximus: Show the last input combination entered from the
1625
-	//// movie within the state
1626
-	//if(current!=0) // <- mz: only if playing or recording a movie
1627
-	//	memcpy(&cur_input_display, joop, 4);
1628
-
1629
-	/*return true;
1630
-}*/
1631
-
1632
-static bool ReadStateChunks(EMUFILE* is, int32_t totalsize)
1633
-{
1634
-	bool ret = true;
1635
-	while(totalsize > 0)
1636
-	{
1637
-		uint32_t size;
1638
-		uint32_t t;
1639
-		if(!read32le(&t,is))  { ret=false; break; }
1640
-		if(t == 0xFFFFFFFF) goto done;
1641
-		if(!read32le(&size,is))  { ret=false; break; }
1642
-		switch(t)
1643
-		{
1644
-			case 1: if(!ReadStateChunk(is,SF_ARM9,size)) ret=false; break;
1645
-			case 2: if(!ReadStateChunk(is,SF_ARM7,size)) ret=false; break;
1646
-			case 3: if(!cp15_loadstate(is,size)) ret=false; break;
1647
-			case 4: if(!ReadStateChunk(is,SF_MEM,size)) ret=false; break;
1648
-			case 5: if(!ReadStateChunk(is,SF_NDS,size)) ret=false; break;
1649
-			case 51: if(!nds_loadstate(is,size)) ret=false; break;
1650
-			case 60: if(!ReadStateChunk(is,SF_MMU,size)) ret=false; break;
1651
-			case 61: if(!mmu_loadstate(is,size)) ret=false; break;
1652
-			case 7: /*if(!fake_gpu_loadstate(is,size)) ret=false;*/ break;
1653
-			case 8: if(!spu_loadstate(is,size)) ret=false; break;
1654
-			case 81:/* if(!fake_mic_loadstate(is,size)) ret=false; break;*/
1655
-			case 90:/* if(!ReadStateChunk(is,SF_GFX3D,size)) ret=false; break;*/
1656
-			case 91:/* if(!fake_gfx3d_loadstate(is,size)) ret=false; break;*/
1657
-			case 100:/* if(!ReadStateChunk(is,SF_MOVIE, size)) ret=false; break;*/
1658
-			case 101:/* if(!fake_mov_loadstate(is, size)) ret=false; break;*/
1659
-			case 110:/* if(!ReadStateChunk(is,SF_WIFI,size)) ret=false; break;*/
1660
-			case 120:/* if(!ReadStateChunk(is,SF_RTC,size)) ret=false;*/ break;
1661
-			default:
1662
-				ret=false;
1663
-				break;
1664
-		}
1665
-		if(!ret)
1666
-			return false;
1667
-	}
1668
-done:
1669
-
1670
-	return ret;
1671
-}
1672
-
1673
-void loadstate()
1674
-{
1675
-    // This should regenerate the vram banks
1676
-    for (int i = 0; i < 0xA; i++)
1677
-       _MMU_write08<ARMCPU_ARM9>(0x04000240+i, _MMU_read08<ARMCPU_ARM9>(0x04000240+i));
1678
-
1679
-    // This should regenerate the graphics power control register
1680
-    _MMU_write16<ARMCPU_ARM9>(0x04000304, _MMU_read16<ARMCPU_ARM9>(0x04000304));
1681
-
1682
-	// This should regenerate the graphics configuration
1683
-	//zero 27-jul-09 : was formerly up to 7F but that wrote to dispfifo which is dumb (one of nitsuja's desynch bugs [that he found, not caused])
1684
-	//so then i brought it down to 66 but this resulted in a conceptual bug with affine start registers, which shouldnt get regenerated
1685
-	//so then i just made this exhaustive list
1686
- //   for (int i = REG_BASE_DISPA; i<=REG_BASE_DISPA + 0x66; i+=2)
1687
-	//_MMU_write16<ARMCPU_ARM9>(i, _MMU_read16<ARMCPU_ARM9>(i));
1688
- //   for (int i = REG_BASE_DISPB; i<=REG_BASE_DISPB + 0x7F; i+=2)
1689
-	//_MMU_write16<ARMCPU_ARM9>(i, _MMU_read16<ARMCPU_ARM9>(i));
1690
-	static const uint8_t mainRegenAddr[] = {0x00,0x02,0x08,0x0a,0x0c,0x0e,0x40,0x42,0x44,0x46,0x48,0x4a,0x4c,0x50,0x52,0x54,0x64,0x66,0x6c};
1691
-	static const uint8_t subRegenAddr[] =  {0x00,0x02,0x08,0x0a,0x0c,0x0e,0x40,0x42,0x44,0x46,0x48,0x4a,0x4c,0x50,0x52,0x54,0x6c};
1692
-	for(uint32_t i=0;i<ARRAY_SIZE(mainRegenAddr);i++)
1693
-		_MMU_write16<ARMCPU_ARM9>(REG_BASE_DISPA+mainRegenAddr[i], _MMU_read16<ARMCPU_ARM9>(REG_BASE_DISPA+mainRegenAddr[i]));
1694
-	for(uint32_t i=0;i<ARRAY_SIZE(subRegenAddr);i++)
1695
-		_MMU_write16<ARMCPU_ARM9>(REG_BASE_DISPB+subRegenAddr[i], _MMU_read16<ARMCPU_ARM9>(REG_BASE_DISPB+subRegenAddr[i]));
1696
-	// no need to restore 0x60 since control and MMU.ARM9_REG are both in the savestates, and restoring it could mess up the ack bits anyway
1697
-
1698
-	SetupMMU(/*nds.Is_DebugConsole()*/false,nds.Is_DSI());
1699
-
1700
-	//execute = !driver->EMU_IsEmulationPaused();
1701
-	execute = true;
1702
-}
1703
-
1704
-bool savestate_load(EMUFILE* is)
1705
-{
1706
-	SAV_silent_fail_flag = false;
1707
-	char header[16];
1708
-	is->fread(header,16);
1709
-	if(is->fail() || memcmp(header,magic,16))
1710
-		return false;
1711
-
1712
-	uint32_t ssversion,dversion,len,comprlen;
1713
-	if(!read32le(&ssversion,is)) return false;
1714
-	if(!read32le(&dversion,is)) return false;
1715
-	if(!read32le(&len,is)) return false;
1716
-	if(!read32le(&comprlen,is)) return false;
1717
-
1718
-	if(ssversion != SAVESTATE_VERSION) return false;
1719
-
1720
-	std::vector<uint8_t> buf(len);
1721
-
1722
-	if(comprlen != 0xFFFFFFFF) {
1723
-#ifndef HAVE_LIBZ
1724
-		//without libz, we can't decompress this savestate
1725
-		return false;
1726
-#endif
1727
-		std::vector<char> cbuf(comprlen);
1728
-		is->fread(&cbuf[0],comprlen);
1729
-		if(is->fail()) return false;
1730
-
1731
-#ifdef HAVE_LIBZ
1732
-		uLongf uncomprlen = len;
1733
-		int error = uncompress((uint8_t*)&buf[0],&uncomprlen,(uint8_t*)&cbuf[0],comprlen);
1734
-		if(error != Z_OK || uncomprlen != len)
1735
-			return false;
1736
-#endif
1737
-	} else {
1738
-		is->fread((char*)&buf[0],len-32);
1739
-	}
1740
-
1741
-	//GO!! READ THE SAVESTATE
1742
-	//THERE IS NO GOING BACK NOW
1743
-	//reset the emulator first to clean out the host's state
1744
-
1745
-	//while the series of resets below should work,
1746
-	//we are testing the robustness of the savestate system with this full reset.
1747
-	//the full reset wipes more things, so we can make sure that they are being restored correctly
1748
-	//extern bool _HACK_DONT_STOPMOVIE;
1749
-	//_HACK_DONT_STOPMOVIE = true;
1750
-	NDS_Reset();
1751
-	//_HACK_DONT_STOPMOVIE = false;
1752
-
1753
-	//reset some options to their old defaults which werent saved
1754
-	//nds.debugConsole = false;
1755
-
1756
-	//GPU_Reset(MainScreen.gpu, 0);
1757
-	//GPU_Reset(SubScreen.gpu, 1);
1758
-	//gfx3d_reset();
1759
-	//gpu3D->NDS_3D_Reset();
1760
-	//SPU_Reset();
1761
-
1762
-	EMUFILE_MEMORY mstemp(&buf);
1763
-	bool x = ReadStateChunks(&mstemp,(int32_t)len);
1764
-
1765
-	if(!x && !SAV_silent_fail_flag)
1766
-	{
1767
-		printf("Error loading savestate. It failed halfway through;\nSince there is no savestate backup system, your current game session is wrecked");
1768
-#ifdef _WINDOWS
1769
-		//HACK! we really need a better way to handle this kind of feedback
1770
-		MessageBoxA(0,"Error loading savestate. It failed halfway through;\nSince there is no savestate backup system, your current game session is wrecked",0,0);
1771
-#endif
1772
-		return false;
1773
-	}
1774
-
1775
-	loadstate();
1776
-
1777
-	/*if((nds.debugConsole!=0) != CommonSettings.DebugConsole) {
1778
-		printf("WARNING: forcing console debug mode to: debugmode=%s\n",nds.debugConsole?"true":"false");
1779
-	}*/
1780
-
1781
-	return true;
1782
-}
1783
-
1784
-/*bool savestate_load(const char *file_name)
1785
-{
1786
-	EMUFILE_FILE f(file_name,"rb");
1787
-	if(f.fail()) return false;
1788
-
1789
-	return savestate_load(&f);
1790
-}*/
1791
-
1792
-//static std::stack<EMUFILE_MEMORY*> rewindFreeList;
1793
-//static std::vector<EMUFILE_MEMORY*> rewindbuffer;
1794
-
1795
-//int rewindstates = 16;
1796
-//int rewindinterval = 4;
1797
-
1798
-/*void rewindsave () {*/
1799
-
1800
-	/*if(currFrameCounter % rewindinterval)
1801
-		return;*/
1802
-
1803
-	//printf("rewindsave"); printf("%d%s", currFrameCounter, "\n");
1804
-
1805
-
1806
-	/*EMUFILE_MEMORY *ms;
1807
-	if(!rewindFreeList.empty()) {
1808
-		ms = rewindFreeList.top();
1809
-		rewindFreeList.pop();
1810
-	} else {
1811
-		ms = new EMUFILE_MEMORY(1024*1024*12);
1812
-	}
1813
-
1814
-	if(!savestate_save(ms, Z_NO_COMPRESSION))
1815
-		return;
1816
-
1817
-	rewindbuffer.push_back(ms);
1818
-
1819
-	if((int)rewindbuffer.size() > rewindstates) {
1820
-		delete *rewindbuffer.begin();
1821
-		rewindbuffer.erase(rewindbuffer.begin());
1822
-	}
1823
-}*/
1824
-
1825
-/*void dorewind()
1826
-{*/
1827
-
1828
-	/*if(currFrameCounter % rewindinterval)
1829
-		return;*/
1830
-
1831
-	//printf("rewind\n");
1832
-
1833
-	/*nds.debugConsole = false;
1834
-
1835
-	int size = rewindbuffer.size();
1836
-
1837
-	if(size < 1) {
1838
-		printf("rewind buffer empty\n");
1839
-		return;
1840
-	}
1841
-
1842
-	printf("%d", size);
1843
-
1844
-	EMUFILE_MEMORY* loadms = rewindbuffer[size-1];
1845
-	loadms->fseek(32, SEEK_SET);
1846
-
1847
-	ReadStateChunks(loadms,loadms->size()-32);
1848
-	loadstate();
1849
-
1850
-	if(rewindbuffer.size()>1)
1851
-	{
1852
-		rewindFreeList.push(loadms);
1853
-		rewindbuffer.pop_back();
1854
-	}
1855
-
1856
-}*/
Browse code

Cleanup of some warnings, updating modification dates, using nullptr instead of NULL in some cases.

Naram Qashat authored on 2013/03/30 16:17:42
Showing 1 changed files
... ...
@@ -403,8 +403,8 @@ static bool mmu_loadstate(EMUFILE* is, int)
403 403
 
404 404
 	if(version == 0 || version == 1)
405 405
 	{
406
-		uint32_t bupmem_size;
407
-		uint32_t addr_size;
406
+		uint32_t bupmem_size = 0;
407
+		uint32_t addr_size = 0xFFFFFFFF;
408 408
 
409 409
 		if(version == 0)
410 410
 		{
Browse code

Import actual code.

Naram Qashat authored on 2013/03/26 02:41:19
Showing 1 changed files
1 1
new file mode 100644
... ...
@@ -0,0 +1,1856 @@
1
+/*
2
+	Copyright (C) 2006 Normmatt
3
+	Copyright (C) 2006 Theo Berkau
4
+	Copyright (C) 2007 Pascal Giard
5
+	Copyright (C) 2008-2012 DeSmuME team
6
+
7
+	This file is free software: you can redistribute it and/or modify
8
+	it under the terms of the GNU General Public License as published by
9
+	the Free Software Foundation, either version 2 of the License, or
10
+	(at your option) any later version.
11
+
12
+	This file is distributed in the hope that it will be useful,
13
+	but WITHOUT ANY WARRANTY; without even the implied warranty of
14
+	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15
+	GNU General Public License for more details.
16
+
17
+	You should have received a copy of the GNU General Public License
18
+	along with the this software.  If not, see <http://www.gnu.org/licenses/>.
19
+*/
20
+
21
+#include <stack>
22
+#include <set>
23
+#include <fstream>
24
+#include <cstdio>
25
+#include <cstring>
26
+#include <ctime>
27
+#include <sys/stat.h>
28
+#ifdef HAVE_LIBZ
29
+#include <zlib.h>
30
+#endif
31
+#include "saves.h"
32
+#include "MMU.h"
33
+#include "NDSSystem.h"
34
+//#include "render3D.h"
35
+#include "cp15.h"
36
+//#include "GPU_osd.h"
37
+#include "version.h"
38
+
39
+#include "readwrite.h"
40
+//#include "gfx3d.h"
41
+//#include "movie.h"
42
+//#include "mic.h"
43
+#include "MMU_timing.h"
44
+
45
+#include "path.h"
46
+
47
+#ifdef _WINDOWS
48
+//#include "main.h"
49
+#endif
50
+
51
+//int lastSaveState = 0;		//Keeps track of last savestate used for quick save/load functions
52
+
53
+//void*v is actually a void** which will be indirected before reading
54
+//since this isnt supported right now, it is declared in here to make things compile
55
+//#define SS_INDIRECT            0x80000000
56
+
57
+//savestates_t savestates[NB_STATES];
58
+
59
+#define SAVESTATE_VERSION       12
60
+static const char* magic = "DeSmuME SState\0";
61
+
62
+//a savestate chunk loader can set this if it wants to permit a silent failure (for compatibility)
63
+static bool SAV_silent_fail_flag;
64
+
65
+SFORMAT SF_ARM7[]={
66
+	{ "7INS", 4, 1, &NDS_ARM7.instruction },
67
+	{ "7INA", 4, 1, &NDS_ARM7.instruct_adr },
68
+	{ "7INN", 4, 1, &NDS_ARM7.next_instruction },
69
+	{ "7REG", 4,16, NDS_ARM7.R },
70
+	{ "7CPS", 4, 1, &NDS_ARM7.CPSR },
71
+	{ "7SPS", 4, 1, &NDS_ARM7.SPSR },
72
+	{ "7DUS", 4, 1, &NDS_ARM7.R13_usr },
73
+	{ "7EUS", 4, 1, &NDS_ARM7.R14_usr },
74
+	{ "7DSV", 4, 1, &NDS_ARM7.R13_svc },
75
+	{ "7ESV", 4, 1, &NDS_ARM7.R14_svc },
76
+	{ "7DAB", 4, 1, &NDS_ARM7.R13_abt },
77
+	{ "7EAB", 4, 1, &NDS_ARM7.R14_abt },
78
+	{ "7DUN", 4, 1, &NDS_ARM7.R13_und },
79
+	{ "7EUN", 4, 1, &NDS_ARM7.R14_und },
80
+	{ "7DIR", 4, 1, &NDS_ARM7.R13_irq },
81
+	{ "7EIR", 4, 1, &NDS_ARM7.R14_irq },
82
+	{ "78FI", 4, 1, &NDS_ARM7.R8_fiq },
83
+	{ "79FI", 4, 1, &NDS_ARM7.R9_fiq },
84
+	{ "7AFI", 4, 1, &NDS_ARM7.R10_fiq },
85
+	{ "7BFI", 4, 1, &NDS_ARM7.R11_fiq },
86
+	{ "7CFI", 4, 1, &NDS_ARM7.R12_fiq },
87
+	{ "7DFI", 4, 1, &NDS_ARM7.R13_fiq },
88
+	{ "7EFI", 4, 1, &NDS_ARM7.R14_fiq },
89
+	{ "7SVC", 4, 1, &NDS_ARM7.SPSR_svc },
90
+	{ "7ABT", 4, 1, &NDS_ARM7.SPSR_abt },
91
+	{ "7UND", 4, 1, &NDS_ARM7.SPSR_und },
92
+	{ "7IRQ", 4, 1, &NDS_ARM7.SPSR_irq },
93
+	{ "7FIQ", 4, 1, &NDS_ARM7.SPSR_fiq },
94
+	{ "7int", 4, 1, &NDS_ARM7.intVector },
95
+	{ "7LDT", 1, 1, &NDS_ARM7.LDTBit },
96
+	{ "7Wai", 4, 1, &NDS_ARM7.waitIRQ },
97
+	{ "7hef", 4, 1, &NDS_ARM7.halt_IE_and_IF },
98
+	{ "7iws", 1, 1, &NDS_ARM7.intrWaitARM_state },
99
+	{ NULL, 0, 0, NULL }
100
+};
101
+
102
+SFORMAT SF_ARM9[]={
103
+	{ "9INS", 4, 1, &NDS_ARM9.instruction},
104
+	{ "9INA", 4, 1, &NDS_ARM9.instruct_adr},
105
+	{ "9INN", 4, 1, &NDS_ARM9.next_instruction},
106
+	{ "9REG", 4,16, NDS_ARM9.R},
107
+	{ "9CPS", 4, 1, &NDS_ARM9.CPSR},
108
+	{ "9SPS", 4, 1, &NDS_ARM9.SPSR},
109
+	{ "9DUS", 4, 1, &NDS_ARM9.R13_usr},
110
+	{ "9EUS", 4, 1, &NDS_ARM9.R14_usr},
111
+	{ "9DSV", 4, 1, &NDS_ARM9.R13_svc},
112
+	{ "9ESV", 4, 1, &NDS_ARM9.R14_svc},
113
+	{ "9DAB", 4, 1, &NDS_ARM9.R13_abt},
114
+	{ "9EAB", 4, 1, &NDS_ARM9.R14_abt},
115
+	{ "9DUN", 4, 1, &NDS_ARM9.R13_und},
116
+	{ "9EUN", 4, 1, &NDS_ARM9.R14_und},
117
+	{ "9DIR", 4, 1, &NDS_ARM9.R13_irq},
118
+	{ "9EIR", 4, 1, &NDS_ARM9.R14_irq},
119
+	{ "98FI", 4, 1, &NDS_ARM9.R8_fiq},
120
+	{ "99FI", 4, 1, &NDS_ARM9.R9_fiq},
121
+	{ "9AFI", 4, 1, &NDS_ARM9.R10_fiq},
122
+	{ "9BFI", 4, 1, &NDS_ARM9.R11_fiq},
123
+	{ "9CFI", 4, 1, &NDS_ARM9.R12_fiq},
124
+	{ "9DFI", 4, 1, &NDS_ARM9.R13_fiq},
125
+	{ "9EFI", 4, 1, &NDS_ARM9.R14_fiq},
126
+	{ "9SVC", 4, 1, &NDS_ARM9.SPSR_svc},
127
+	{ "9ABT", 4, 1, &NDS_ARM9.SPSR_abt},
128
+	{ "9UND", 4, 1, &NDS_ARM9.SPSR_und},
129
+	{ "9IRQ", 4, 1, &NDS_ARM9.SPSR_irq},
130
+	{ "9FIQ", 4, 1, &NDS_ARM9.SPSR_fiq},
131
+	{ "9int", 4, 1, &NDS_ARM9.intVector},
132
+	{ "9LDT", 1, 1, &NDS_ARM9.LDTBit},
133
+	{ "9Wai", 4, 1, &NDS_ARM9.waitIRQ},
134
+	{ "9hef", 4, 1, &NDS_ARM9.halt_IE_and_IF },
135
+	{ "9iws", 1, 1, &NDS_ARM7.intrWaitARM_state },
136
+	{ NULL, 0, 0, NULL }
137
+};
138
+
139
+SFORMAT SF_MEM[]={
140
+	{ "ITCM", 1, sizeof(MMU.ARM9_ITCM),   MMU.ARM9_ITCM},
141
+	{ "DTCM", 1, sizeof(MMU.ARM9_DTCM),   MMU.ARM9_DTCM},
142
+
143
+	 //for legacy purposes, WRAX is a separate variable. shouldnt be a problem.
144
+	{ "WRAM", 1, 0x400000, MMU.MAIN_MEM},
145
+	{ "WRAX", 1, 0x400000, MMU.MAIN_MEM+0x400000},
146
+
147
+	//NOTE - this is not as large as the allocated memory.
148
+	//the memory is overlarge due to the way our memory map system is setup
149
+	//but there are actually no more registers than this
150
+	{ "9REG", 1, 0x2000,   MMU.ARM9_REG},
151
+
152
+	{ "VMEM", 1, sizeof(MMU.ARM9_VMEM),    MMU.ARM9_VMEM},
153
+	{ "OAMS", 1, sizeof(MMU.ARM9_OAM),    MMU.ARM9_OAM},
154
+
155
+	//this size is specially chosen to avoid saving the blank space at the end
156
+	{ "LCDM", 1, 0xA4000,		MMU.ARM9_LCD},
157
+	{ NULL, 0, 0, NULL }
158
+};
159
+
160
+SFORMAT SF_NDS[]={
161
+	//{ "_WCY", 4, 1, &nds.wifiCycle},
162
+	{ "_TCY", 8, 8, nds.timerCycle},
163
+	{ "_VCT", 4, 1, &nds.VCount},
164
+	{ "_OLD", 4, 1, &nds.old},
165
+	{ "_TPX", 2, 1, NULL},
166
+	{ "_TPY", 2, 1, NULL},
167
+	{ "_TPB", 4, 1, NULL},
168
+	{ "_DBG", 4, 1, NULL},
169
+	{ "_ENS", 4, 1, NULL},
170
+	{ "_ENH", 4, 1, NULL},
171
+	{ "_ENI", 4, 1, NULL},
172
+	{ "_SLP", 4, 1, &nds.sleeping},
173
+	{ "_FBS", 4, 1, &nds.freezeBus},
174
+	{ "_CEJ", 4, 1, &nds.cardEjected},
175
+	{ "_P00", 1, 1, NULL},
176
+	{ "_P01", 1, 1, NULL},
177
+	//{ "_P02", 1, 1, &nds.power1.gfx3d_render},
178
+	//{ "_P03", 1, 1, &nds.power1.gfx3d_geometry},
179
+	{ "_P04", 1, 1, NULL},
180
+	{ "_P05", 1, 1, NULL},
181
+	{ "_P06", 1, 1, NULL},
182
+	//{ "_P07", 1, 1, &nds.power2.wifi},
183
+	{ NULL, 0, 0, NULL }
184
+};
185
+
186
+SFORMAT SF_MMU[]={
187
+	{ "M7BI", 1, sizeof(MMU.ARM7_BIOS), MMU.ARM7_BIOS},
188
+	{ "M7ER", 1, sizeof(MMU.ARM7_ERAM), MMU.ARM7_ERAM},
189
+	{ "M7RG", 1, sizeof(MMU.ARM7_REG), MMU.ARM7_REG},
190
+	{ "M7WI", 1, sizeof(MMU.ARM7_WIRAM), MMU.ARM7_WIRAM},
191
+	{ "MSWI", 1, sizeof(MMU.SWIRAM), MMU.SWIRAM},
192
+	{ "M9RW", 1, 1,       &MMU.ARM9_RW_MODE},
193
+	{ "MDTC", 4, 1,       &MMU.DTCMRegion},
194
+	{ "MITC", 4, 1,       &MMU.ITCMRegion},
195
+	{ "MTIM", 2, 8,       MMU.timer},
196
+	{ "MTMO", 4, 8,       MMU.timerMODE},
197
+	{ "MTON", 4, 8,       MMU.timerON},
198
+	{ "MTRN", 4, 8,       MMU.timerRUN},
199
+	{ "MTRL", 2, 8,       MMU.timerReload},
200
+	{ "MIME", 4, 2,       MMU.reg_IME},
201
+	{ "MIE_", 4, 2,       MMU.reg_IE},
202
+	{ "MIF_", 4, 2,       MMU.reg_IF_bits},
203
+
204
+	//{ "MGXC", 8, 1,       &MMU.gfx3dCycles},
205
+
206
+	{ "M_SX", 1, 2,       &MMU.SPI_CNT},
207
+	{ "M_SC", 1, 2,       &MMU.SPI_CMD},
208
+	{ "MASX", 1, 2,       &MMU.AUX_SPI_CNT},
209
+	{ "MASC", 1, 2,       &MMU.AUX_SPI_CMD},
210
+
211
+	{ "MDV1", 4, 1,       &MMU.divRunning},
212
+	{ "MDV2", 8, 1,       &MMU.divResult},
213
+	{ "MDV3", 8, 1,       &MMU.divMod},
214
+	{ "MDV5", 8, 1,       &MMU.divCycles},
215
+
216
+	{ "MSQ1", 4, 1,       &MMU.sqrtRunning},
217
+	{ "MSQ2", 4, 1,       &MMU.sqrtResult},
218
+	{ "MSQ4", 8, 1,       &MMU.sqrtCycles},
219
+
220
+	//begin memory chips
221
+	{ "BUCO", 1, 1,       &MMU.fw.com},
222
+	{ "BUAD", 4, 1,       &MMU.fw.addr},
223
+	{ "BUAS", 1, 1,       &MMU.fw.addr_shift},
224
+	{ "BUAZ", 1, 1,       &MMU.fw.addr_size},
225
+	{ "BUWE", 4, 1,       &MMU.fw.write_enable},
226
+	{ "BUWR", 4, 1,       &MMU.fw.writeable_buffer},
227
+	//end memory chips
228
+
229
+	{ "MC0A", 4, 1,       &MMU.dscard[0].address},
230
+	{ "MC0T", 4, 1,       &MMU.dscard[0].transfer_count},
231
+	{ "MC1A", 4, 1,       &MMU.dscard[1].address},
232
+	{ "MC1T", 4, 1,       &MMU.dscard[1].transfer_count},
233
+	//{ "MCHT", 4, 1,       &MMU.CheckTimers},
234
+	//{ "MCHD", 4, 1,       &MMU.CheckDMAs},
235
+
236
+	//fifos
237
+	{ "F0TH", 1, 1,       &ipc_fifo[0].head},
238
+	{ "F0TL", 1, 1,       &ipc_fifo[0].tail},
239
+	{ "F0SZ", 1, 1,       &ipc_fifo[0].size},
240
+	{ "F0BF", 4, 16,      ipc_fifo[0].buf},
241
+	{ "F1TH", 1, 1,       &ipc_fifo[1].head},
242
+	{ "F1TL", 1, 1,       &ipc_fifo[1].tail},
243
+	{ "F1SZ", 1, 1,       &ipc_fifo[1].size},
244
+	{ "F1BF", 4, 16,      ipc_fifo[1].buf},
245
+
246
+	{ "FDHD", 4, 1,       NULL},
247
+	{ "FDTL", 4, 1,       NULL},
248
+	{ "FDBF", 4, 0x6000,  NULL},
249
+
250
+	{ "PMCN", 1, 1,			&MMU.powerMan_CntReg},
251
+	{ "PMCW", 4, 1,			&MMU.powerMan_CntRegWritten},
252
+	{ "PMCR", 1, 5,			&MMU.powerMan_Reg},
253
+
254
+	{ "MR3D", 4, 1,		NULL},
255
+
256
+	{ NULL, 0, 0, NULL }
257
+};
258
+
259
+/*static uint32_t tmpu32;
260
+SFORMAT SF_MOVIE[]={
261
+	{ "FRAC", 4, 1, &tmpu32},
262
+	{ "LAGC", 4, 1, &tmpu32},
263
+	{ NULL, 0, 0, NULL }
264
+};*/
265
+
266
+/*static void mmu_savestate(EMUFILE* os)
267
+{
268
+	uint32_t version = 5;
269
+	write32le(version,os);
270
+
271
+	//version 2:
272
+	MMU_new.backupDevice.save_state(os);
273
+
274
+	//version 3:
275
+	MMU_new.gxstat.savestate(os);
276
+	for(int i=0;i<2;i++)
277
+		for(int j=0;j<4;j++)
278
+			MMU_new.dma[i][j].savestate(os);
279
+
280
+	MMU_timing.arm9codeFetch.savestate(os, version);
281
+	MMU_timing.arm9dataFetch.savestate(os, version);
282
+	MMU_timing.arm7codeFetch.savestate(os, version);
283
+	MMU_timing.arm7dataFetch.savestate(os, version);
284
+	MMU_timing.arm9codeCache.savestate(os, version);
285
+	MMU_timing.arm9dataCache.savestate(os, version);
286
+
287
+	//version 4:
288
+	MMU_new.sqrt.savestate(os);
289
+	MMU_new.div.savestate(os);
290
+}*/
291
+
292
+/*static uint16_t tmpu16;
293
+static uint16_t tmpu16_array3[3];
294
+static uint8_t tmpu8;
295
+static uint8_t tmpu8_array3[3];
296
+static uint32_t tmpu32_array3[3];
297
+static uint8_t tmpu8_array6[6];
298
+static uint64_t tmpu64;
299
+static uint8_t tmpu8_array105[105];
300
+static uint16_t tmpu16_array4096[0x1000];
301
+static uint16_t tmpu16_array2048[0x800];
302
+static uint8_t tmpu8_array4096[4096];
303
+SFORMAT SF_WIFI[]={
304
+	{ "W000", 4, 1, &tmpu32},
305
+	{ "W010", 4, 1, &tmpu32},
306
+
307
+	{ "W020", 2, 1, &tmpu16},
308
+	{ "W030", 2, 1, &tmpu16},
309
+
310
+	{ "W040", 2, 1, &tmpu16},
311
+	{ "W050", 2, 1, &tmpu16},
312
+
313
+	{ "W060", 2, 1, &tmpu16},
314
+	{ "W070", 2, 1, &tmpu16},
315
+	{ "W080", 4, 1, &tmpu32},
316
+
317
+	{ "W090", 2, 3, tmpu16_array3},
318
+	{ "W100", 2, 1, &tmpu16},
319
+	{ "W110", 2, 1, &tmpu16},
320
+	{ "W120", 2, 1, &tmpu16},
321
+	{ "W130", 2, 1, &tmpu16},
322
+	{ "W140", 4, 1, &tmpu32},
323
+	{ "W150", 1, 1, &tmpu8},
324
+	{ "W160", 1, 3, tmpu8_array3},
325
+	{ "W170", 4, 3, tmpu32_array3},
326
+	{ "W180", 4, 3, tmpu32_array3},
327
+	{ "W190", 4, 3, tmpu32_array3},
328
+
329
+	{ "W200", 2, 1, &tmpu16},
330
+	{ "W210", 2, 1, &tmpu16},
331
+
332
+	{ "W220", 1, 6, tmpu8_array6},
333
+	{ "W230", 1, 6, tmpu8_array6},
334
+
335
+	{ "W240", 2, 1, &tmpu16},
336
+	{ "W250", 2, 1, &tmpu16},
337
+	{ "W260", 2, 1, &tmpu16},
338
+
339
+	{ "W270", 4, 1, &tmpu32},
340
+	{ "W280", 8, 1, &tmpu64},
341
+	{ "W290", 4, 1, &tmpu32},
342
+	{ "W300", 8, 1, &tmpu64},
343
+	{ "W310", 4, 1, &tmpu32},
344
+	{ "W320", 2, 1, &tmpu16},
345
+	{ "W330", 4, 1, &tmpu32},
346
+
347
+	{ "WR00", 4, 1, &tmpu32},
348
+	{ "WR01", 4, 1, &tmpu32},
349
+	{ "WR02", 4, 1, &tmpu32},
350
+	{ "WR03", 4, 1, &tmpu32},
351
+	{ "WR04", 4, 1, &tmpu32},
352
+	{ "WR05", 4, 1, &tmpu32},
353
+	{ "WR06", 4, 1, &tmpu32},
354
+	{ "WR07", 4, 1, &tmpu32},
355
+	{ "WR08", 4, 1, &tmpu32},
356
+	{ "WR09", 4, 1, &tmpu32},
357
+	{ "WR10", 4, 1, &tmpu32},
358
+	{ "WR11", 4, 1, &tmpu32},
359
+	{ "WR12", 4, 1, &tmpu32},
360
+
361
+	{ "W340", 1, 105, tmpu8_array105},
362
+
363
+	{ "W350", 2, 1, &tmpu16},
364
+	{ "W360", 2, 1, &tmpu16},
365
+	{ "W370", 4, 1, &tmpu32},
366
+	{ "W380", 2, 1, &tmpu16},
367
+
368
+	{ "W400", 2, 0x1000, tmpu16_array4096},
369
+	{ "W410", 2, 1, &tmpu16},
370
+	{ "W420", 2, 1, &tmpu16},
371
+	{ "W430", 2, 1, &tmpu16},
372
+	{ "W460", 2, 1, &tmpu16},
373
+	{ "W470", 2, 1, &tmpu16},
374
+	{ "W480", 2, 1, &tmpu16},
375
+	{ "W490", 2, 1, &tmpu16},
376
+	{ "W500", 2, 1, &tmpu16},
377
+	{ "W510", 2, 1, &tmpu16},
378
+	{ "W520", 2, 1, &tmpu16},
379
+	{ "W530", 2, 1, &tmpu16},
380
+	{ "W540", 2, 1, &tmpu16},
381
+
382
+	{ "W550", 4, 1, &tmpu32},
383
+	{ "W560", 4, 1, &tmpu32},
384
+	{ "W570", 4, 1, &tmpu32},
385
+
386
+	{ "W580", 2, 0x800, tmpu16_array2048},
387
+	{ "W590", 2, 1, &tmpu16},
388
+
389
+	{ "WX00", 8, 1, &tmpu64},
390
+	{ "WX10", 1, 4096, tmpu8_array4096},
391
+	{ "WX20", 4, 1, &tmpu32},
392
+	{ "WX30", 4, 1, &tmpu32},
393
+	{ "WX40", 4, 1, &tmpu32},
394
+
395
+	{ NULL, 0, 0, NULL }
396
+};*/
397
+
398
+static bool mmu_loadstate(EMUFILE* is, int)
399
+{
400
+	//read version
401
+	uint32_t version;
402
+	if(read32le(&version,is) != 1) return false;
403
+
404
+	if(version == 0 || version == 1)
405
+	{
406
+		uint32_t bupmem_size;
407
+		uint32_t addr_size;
408
+
409
+		if(version == 0)
410
+		{
411
+			//version 0 was buggy and didnt save the type.
412
+			//it would silently fail if there was a size mismatch
413
+			SAV_silent_fail_flag = true;
414
+			if(read32le(&bupmem_size,is) != 1) return false;
415
+			//if(bupmem_size != MMU.bupmem.size) return false; //mismatch between current initialized and saved size
416
+			addr_size = BackupDevice::addr_size_for_old_save_size(bupmem_size);
417
+		}
418
+		else if(version == 1)
419
+		{
420
+			//version 1 reinitializes the save system with the type that was saved
421
+			uint32_t bupmem_type;
422
+			if(read32le(&bupmem_type,is) != 1) return false;
423
+			if(read32le(&bupmem_size,is) != 1) return false;
424
+			addr_size = BackupDevice::addr_size_for_old_save_type(bupmem_type);
425
+			if(addr_size == 0xFFFFFFFF)
426
+				addr_size = BackupDevice::addr_size_for_old_save_size(bupmem_size);
427
+		}
428
+
429
+		if(addr_size == 0xFFFFFFFF)
430
+			return false;
431
+
432
+		uint8_t* temp = new uint8_t[bupmem_size];
433
+		is->fread((char*)temp,bupmem_size);
434
+		MMU_new.backupDevice.load_old_state(addr_size,temp,bupmem_size);
435
+		delete[] temp;
436
+		if(is->fail()) return false;
437
+	}
438
+
439
+	if(version < 2) return true;
440
+
441
+	bool ok = MMU_new.backupDevice.load_state(is);
442
+
443
+	if(version < 3) return true;
444
+
445
+	ok &= MMU_new.gxstat.loadstate(is);
446
+
447
+	for(int i=0;i<2;i++)
448
+		for(int j=0;j<4;j++)
449
+			ok &= MMU_new.dma[i][j].loadstate(is);
450
+
451
+	ok &= MMU_timing.arm9codeFetch.loadstate(is, version);
452
+	ok &= MMU_timing.arm9dataFetch.loadstate(is, version);
453
+	ok &= MMU_timing.arm7codeFetch.loadstate(is, version);
454
+	ok &= MMU_timing.arm7dataFetch.loadstate(is, version);
455
+	ok &= MMU_timing.arm9codeCache.loadstate(is, version);
456
+	ok &= MMU_timing.arm9dataCache.loadstate(is, version);
457
+
458
+	if(version < 4) return true;
459
+
460
+	ok &= MMU_new.sqrt.loadstate(is,version);
461
+	ok &= MMU_new.div.loadstate(is,version);
462
+
463
+	//to prevent old savestates from confusing IF bits, mask out ones which had been stored but should have been generated
464
+	MMU.reg_IF_bits[0] &= ~0x00200000;
465
+	MMU.reg_IF_bits[1] &= ~0x00000000;
466
+
467
+	//MMU_new.gxstat.fifo_low = gxFIFO.size <= 127;
468
+	//MMU_new.gxstat.fifo_empty = gxFIFO.size == 0;
469
+
470
+	/*if(version < 5)
471
+		MMU.reg_DISP3DCNT_bits = T1ReadWord(MMU.ARM9_REG,0x60);*/
472
+
473
+	return ok;
474
+}
475
+
476
+/*static void cp15_saveone(armcp15_t *cp15, EMUFILE* os)
477
+{
478
+	write32le(cp15->IDCode,os);
479
+	write32le(cp15->cacheType,os);
480
+    write32le(cp15->TCMSize,os);
481
+    write32le(cp15->ctrl,os);
482
+    write32le(cp15->DCConfig,os);
483
+    write32le(cp15->ICConfig,os);
484
+    write32le(cp15->writeBuffCtrl,os);
485
+    write32le(cp15->und,os);
486
+    write32le(cp15->DaccessPerm,os);
487
+    write32le(cp15->IaccessPerm,os);
488
+    write32le(cp15->protectBaseSize0,os);
489
+    write32le(cp15->protectBaseSize1,os);
490
+    write32le(cp15->protectBaseSize2,os);
491
+    write32le(cp15->protectBaseSize3,os);
492
+    write32le(cp15->protectBaseSize4,os);
493
+    write32le(cp15->protectBaseSize5,os);
494
+    write32le(cp15->protectBaseSize6,os);
495
+    write32le(cp15->protectBaseSize7,os);
496
+    write32le(cp15->cacheOp,os);
497
+    write32le(cp15->DcacheLock,os);
498
+    write32le(cp15->IcacheLock,os);
499
+    write32le(cp15->ITCMRegion,os);
500
+    write32le(cp15->DTCMRegion,os);
501
+    write32le(cp15->processID,os);
502
+    write32le(cp15->RAM_TAG,os);
503
+    write32le(cp15->testState,os);
504
+    write32le(cp15->cacheDbg,os);
505
+    for(int i=0;i<8;i++) write32le(cp15->regionWriteMask_USR[i],os);
506
+    for(int i=0;i<8;i++) write32le(cp15->regionWriteMask_SYS[i],os);
507
+    for(int i=0;i<8;i++) write32le(cp15->regionReadMask_USR[i],os);
508
+    for(int i=0;i<8;i++) write32le(cp15->regionReadMask_SYS[i],os);
509
+    for(int i=0;i<8;i++) write32le(cp15->regionExecuteMask_USR[i],os);
510
+    for(int i=0;i<8;i++) write32le(cp15->regionExecuteMask_SYS[i],os);
511
+    for(int i=0;i<8;i++) write32le(cp15->regionWriteSet_USR[i],os);
512
+    for(int i=0;i<8;i++) write32le(cp15->regionWriteSet_SYS[i],os);
513
+    for(int i=0;i<8;i++) write32le(cp15->regionReadSet_USR[i],os);
514
+    for(int i=0;i<8;i++) write32le(cp15->regionReadSet_SYS[i],os);
515
+    for(int i=0;i<8;i++) write32le(cp15->regionExecuteSet_USR[i],os);
516
+    for(int i=0;i<8;i++) write32le(cp15->regionExecuteSet_SYS[i],os);
517
+}*/
518
+
519
+/*static void cp15_savestate(EMUFILE* os)
520
+{
521
+	//version
522
+	write32le(1,os);
523
+
524
+	cp15_saveone((armcp15_t *)NDS_ARM9.coproc[15],os);
525
+	//ARM7 not have coprocessor
526
+	//cp15_saveone((armcp15_t *)NDS_ARM7.coproc[15],os);
527
+}*/
528
+
529
+static bool cp15_loadone(armcp15_t *cp15, EMUFILE* is)
530
+{
531
+	if(!read32le(&cp15->IDCode,is)) return false;
532
+	if(!read32le(&cp15->cacheType,is)) return false;
533
+    if(!read32le(&cp15->TCMSize,is)) return false;
534
+    if(!read32le(&cp15->ctrl,is)) return false;
535
+    if(!read32le(&cp15->DCConfig,is)) return false;
536
+    if(!read32le(&cp15->ICConfig,is)) return false;
537
+    if(!read32le(&cp15->writeBuffCtrl,is)) return false;
538
+    if(!read32le(&cp15->und,is)) return false;
539
+    if(!read32le(&cp15->DaccessPerm,is)) return false;
540
+    if(!read32le(&cp15->IaccessPerm,is)) return false;
541
+    if(!read32le(&cp15->protectBaseSize0,is)) return false;
542
+    if(!read32le(&cp15->protectBaseSize1,is)) return false;
543
+    if(!read32le(&cp15->protectBaseSize2,is)) return false;
544
+    if(!read32le(&cp15->protectBaseSize3,is)) return false;
545
+    if(!read32le(&cp15->protectBaseSize4,is)) return false;
546
+    if(!read32le(&cp15->protectBaseSize5,is)) return false;
547
+    if(!read32le(&cp15->protectBaseSize6,is)) return false;
548
+    if(!read32le(&cp15->protectBaseSize7,is)) return false;
549
+    if(!read32le(&cp15->cacheOp,is)) return false;
550
+    if(!read32le(&cp15->DcacheLock,is)) return false;
551
+    if(!read32le(&cp15->IcacheLock,is)) return false;
552
+    if(!read32le(&cp15->ITCMRegion,is)) return false;
553
+    if(!read32le(&cp15->DTCMRegion,is)) return false;
554
+    if(!read32le(&cp15->processID,is)) return false;
555
+    if(!read32le(&cp15->RAM_TAG,is)) return false;
556
+    if(!read32le(&cp15->testState,is)) return false;
557
+    if(!read32le(&cp15->cacheDbg,is)) return false;
558
+    for(int i=0;i<8;i++) if(!read32le(&cp15->regionWriteMask_USR[i],is)) return false;
559
+    for(int i=0;i<8;i++) if(!read32le(&cp15->regionWriteMask_SYS[i],is)) return false;
560
+    for(int i=0;i<8;i++) if(!read32le(&cp15->regionReadMask_USR[i],is)) return false;
561
+    for(int i=0;i<8;i++) if(!read32le(&cp15->regionReadMask_SYS[i],is)) return false;
562
+    for(int i=0;i<8;i++) if(!read32le(&cp15->regionExecuteMask_USR[i],is)) return false;
563
+    for(int i=0;i<8;i++) if(!read32le(&cp15->regionExecuteMask_SYS[i],is)) return false;
564
+    for(int i=0;i<8;i++) if(!read32le(&cp15->regionWriteSet_USR[i],is)) return false;
565
+    for(int i=0;i<8;i++) if(!read32le(&cp15->regionWriteSet_SYS[i],is)) return false;
566
+    for(int i=0;i<8;i++) if(!read32le(&cp15->regionReadSet_USR[i],is)) return false;
567
+    for(int i=0;i<8;i++) if(!read32le(&cp15->regionReadSet_SYS[i],is)) return false;
568
+    for(int i=0;i<8;i++) if(!read32le(&cp15->regionExecuteSet_USR[i],is)) return false;
569
+    for(int i=0;i<8;i++) if(!read32le(&cp15->regionExecuteSet_SYS[i],is)) return false;
570
+
571
+    return true;
572
+}
573
+
574
+static bool cp15_loadstate(EMUFILE* is, int)
575
+{
576
+	//read version
577
+	uint32_t version;
578
+	if(read32le(&version,is) != 1) return false;
579
+	if(version > 1) return false;
580
+
581
+	if(!cp15_loadone((armcp15_t *)NDS_ARM9.coproc[15],is)) return false;
582
+
583
+	if(version == 0)
584
+	{
585
+		//ARM7 not have coprocessor
586
+		uint8_t *tmp_buf = new uint8_t [sizeof(armcp15_t)];
587
+		if (!tmp_buf) return false;
588
+		if(!cp15_loadone((armcp15_t *)tmp_buf,is)) return false;
589
+		delete [] tmp_buf;
590
+		tmp_buf = NULL;
591
+	}
592
+
593
+	return true;
594
+}
595
+
596
+
597
+
598
+/* Format time and convert to string */
599
+/*static char * format_time(time_t cal_time)
600
+{
601
+  struct tm *time_struct;
602
+  static char str[64];
603
+
604
+  time_struct=localtime(&cal_time);
605
+  strftime(str, sizeof str, "%d-%b-%Y %H:%M:%S", time_struct);
606
+
607
+  return str;
608
+}*/
609
+
610
+/*void clear_savestates()
611
+{
612
+  uint8_t i;
613
+  for( i = 0; i < NB_STATES; i++ )
614
+    savestates[i].exists = false;
615
+}*/
616
+
617
+// Scan for existing savestates and update struct
618
+/*void scan_savestates()
619
+{
620
+  struct stat sbuf;
621
+  char filename[MAX_PATH+1];
622
+
623
+  clear_savestates();
624
+
625
+  for(int i = 0; i < NB_STATES; i++ )
626
+    {
627
+     path.getpathnoext(path.STATES, filename);
628
+
629
+	  if (strlen(filename) + strlen(".dst") + strlen("-2147483648")*/ /* = biggest string for i */ /*>MAX_PATH) return ;
630
+      sprintf(filename+strlen(filename), ".ds%d", i);
631
+      if( stat(filename,&sbuf) == -1 ) continue;
632
+      savestates[i].exists = true;
633
+      strncpy(savestates[i].date, format_time(sbuf.st_mtime),40);
634
+	  savestates[i].date[40-1] = '\0';
635
+    }
636
+
637
+  return ;
638
+}*/
639
+
640
+/*void savestate_slot(int num)
641
+{
642
+   struct stat sbuf;
643
+   char filename[MAX_PATH+1];
644
+
645
+	lastSaveState = num;		//Set last savestate used
646
+
647
+    path.getpathnoext(path.STATES, filename);
648
+
649
+   if (strlen(filename) + strlen(".dsx") + strlen("-2147483648")*/ /* = biggest string for num *//* >MAX_PATH) return ;
650
+   sprintf(filename+strlen(filename), ".ds%d", num);*/
651
+
652
+   /*if (savestate_save(filename))
653
+   {
654
+	   osd->setLineColor(255, 255, 255);
655
+	   osd->addLine("Saved to %i slot", num);
656
+   }
657
+   else
658
+   {
659
+	   osd->setLineColor(255, 0, 0);
660
+	   osd->addLine("Error saving %i slot", num);
661
+	   return;
662
+   }*/
663
+
664
+   /*if (num >= 0 && num < NB_STATES)
665
+   {
666
+	   if (stat(filename,&sbuf) != -1)
667
+	   {
668
+		   savestates[num].exists = true;
669
+		   strncpy(savestates[num].date, format_time(sbuf.st_mtime),40);
670
+		   savestates[num].date[40-1] = '\0';
671
+	   }
672
+   }
673
+}*/
674
+
675
+/*void loadstate_slot(int num)
676
+{
677
+   char filename[MAX_PATH];
678
+
679
+   lastSaveState = num;		//Set last savestate used
680
+
681
+    path.getpathnoext(path.STATES, filename);
682
+
683
+   if (strlen(filename) + strlen(".dsx") + strlen("-2147483648")*/ /* = biggest string for num *//* >MAX_PATH) return ;
684
+   sprintf(filename+strlen(filename), ".ds%d", num);*/
685
+   /*if (savestate_load(filename))
686
+   {
687
+	   osd->setLineColor(255, 255, 255);
688
+	   osd->addLine("Loaded from %i slot", num);
689
+   }
690
+   else
691
+   {
692
+	   osd->setLineColor(255, 0, 0);
693
+	   osd->addLine("Error loading %i slot", num);
694
+   }*/
695
+//}
696
+
697
+
698
+// note: guessSF is so we don't have to do a linear search through the SFORMAT array every time
699
+// in the (most common) case that we already know where the next entry is.
700
+static const SFORMAT *CheckS(const SFORMAT *guessSF, const SFORMAT *firstSF, uint32_t size, uint32_t count, char *desc)
701
+{
702
+	const SFORMAT *sf = guessSF ? guessSF : firstSF;
703
+	while(sf->v)
704
+	{
705
+		//NOT SUPPORTED RIGHT NOW
706
+		//if(sf->size==~0)		// Link to another SFORMAT structure.
707
+		//{
708
+		//	SFORMAT *tmp;
709
+		//	if((tmp= CheckS((SFORMAT *)sf->v, tsize, desc) ))
710
+		//		return tmp;
711
+		//	sf++;
712
+		//	continue;
713
+		//}
714
+		if(!memcmp(desc,sf->desc,4))
715
+		{
716
+			if(sf->size != size || sf->count != count)
717
+				return 0;
718
+			return sf;
719
+		}
720
+
721
+		// failed to find it, have to keep iterating
722
+		if(guessSF)
723
+		{
724
+			sf = firstSF;
725
+			guessSF = NULL;
726
+		}
727
+		else
728
+		{
729
+			sf++;
730
+		}
731
+	}
732
+	return 0;
733
+}
734
+
735
+
736
+static bool ReadStateChunk(EMUFILE* is, const SFORMAT *sf, int size)
737
+{
738
+	const SFORMAT *tmp = NULL;
739
+	const SFORMAT *guessSF = NULL;
740
+	size_t temp = is->ftell();
741
+
742
+	while(is->ftell()<temp+size)
743
+	{
744
+		uint32_t sz, count;
745
+
746
+		char toa[4];
747
+		is->fread(toa,4);
748
+		if(is->fail())
749
+			return false;
750
+
751
+		if(!read32le(&sz,is)) return false;
752
+		if(!read32le(&count,is)) return false;
753
+
754
+		if((tmp=CheckS(guessSF,sf,sz,count,toa)))
755
+		{
756
+		#ifdef LOCAL_LE
757
+			// no need to ever loop one at a time if not flipping byte order
758
+			is->fread((char *)tmp->v,sz*count);
759
+		#else
760
+			if(sz == 1) {
761
+				//special case: read a huge byte array
762
+				is->fread((char *)tmp->v,count);
763
+			} else {
764
+				for(unsigned int i=0;i<count;i++)
765
+				{
766
+					is->fread((char *)tmp->v + i*sz,sz);
767
+                    FlipByteOrder((uint8_t*)tmp->v + i*sz,sz);
768
+				}
769
+			}
770
+		#endif
771
+			guessSF = tmp + 1;
772
+		}
773
+		else
774
+		{
775
+			is->fseek(sz*count,SEEK_CUR);
776
+			guessSF = NULL;
777
+		}
778
+	} // while(...)
779
+	return true;
780
+}
781
+
782
+
783
+
784
+/*static int SubWrite(EMUFILE* os, const SFORMAT *sf)
785
+{
786
+	uint32_t acc=0;
787
+
788
+#ifdef DEBUG
789
+	std::set<std::string> keyset;
790
+#endif
791
+
792
+	const SFORMAT* temp = sf;
793
+	while(temp->v) {
794
+		const SFORMAT* seek = sf;
795
+		while(seek->v && seek != temp) {
796
+			if(!strcmp(seek->desc,temp->desc)) {
797
+				printf("ERROR! duplicated chunk name: %s\n", temp->desc);
798
+			}
799
+			seek++;
800
+		}
801
+		temp++;
802
+	}
803
+
804
+	while(sf->v)
805
+	{
806
+		//not supported right now
807
+		//if(sf->size==~0)		//Link to another struct
808
+		//{
809
+		//	uint32_t tmp;
810
+
811
+		//	if(!(tmp=SubWrite(os,(SFORMAT *)sf->v)))
812
+		//		return 0;
813
+		//	acc+=tmp;
814
+		//	sf++;
815
+		//	continue;
816
+		//}
817
+
818
+		int count = sf->count;
819
+		int size = sf->size;
820
+
821
+        //add size of current node to the accumulator
822
+		acc += 4 + sizeof(sf->size) + sizeof(sf->count);
823
+		acc += count * size;
824
+
825
+		if(os)			//Are we writing or calculating the size of this block?
826
+		{
827
+			os->fwrite(sf->desc,4);
828
+			write32le(sf->size,os);
829
+			write32le(sf->count,os);
830
+
831
+			#ifdef DEBUG
832
+			//make sure we dont dup any keys
833
+			if(keyset.find(sf->desc) != keyset.end())
834
+			{
835
+				printf("duplicate save key!\n");
836
+				assert(false);
837
+			}
838
+			keyset.insert(sf->desc);
839
+			#endif
840
+
841
+
842
+		#ifdef LOCAL_LE
843
+			// no need to ever loop one at a time if not flipping byte order
844
+			os->fwrite((char *)sf->v,size*count);
845
+		#else
846
+			if(size == 1) {
847
+				//special case: write a huge byte array
848
+				os->fwrite((char *)sf->v,count);
849
+			} else {
850
+				for(int i=0;i<count;i++) {
851
+					FlipByteOrder((uint8_t*)sf->v + i*size, size);
852
+					os->fwrite((char*)sf->v + i*size,size);
853
+					//Now restore the original byte order.
854
+					FlipByteOrder((uint8_t*)sf->v + i*size, size);
855
+				}
856
+			}
857
+		#endif
858
+		}
859
+		sf++;
860
+	}
861
+
862
+	return acc;
863
+}*/
864
+
865
+/*static int savestate_WriteChunk(EMUFILE* os, int type, const SFORMAT *sf)
866
+{
867
+	write32le(type,os);
868
+	if(!sf) return 4;
869
+	int bsize = SubWrite((EMUFILE*)0,sf);
870
+	write32le(bsize,os);
871
+
872
+	if(!SubWrite(os,sf))
873
+	{
874
+		return 8;
875
+	}
876
+	return bsize+8;
877
+}*/
878
+
879
+/*static void savestate_WriteChunk(EMUFILE* os, int type, void (*saveproc)(EMUFILE* os))
880
+{
881
+	uint32_t pos1 = os->ftell();
882
+
883
+	//write the type, size(placeholder), and data
884
+	write32le(type,os);
885
+	os->fseek(4, SEEK_CUR); // skip the size, we write that later
886
+	saveproc(os);
887
+
888
+	//get the size
889
+	uint32_t pos2 = os->ftell();
890
+	assert(pos2 != (uint32_t)-1); // if this assert fails, saveproc did something bad
891
+	uint32_t size = (pos2 - pos1) - (2 * sizeof(uint32_t));
892
+
893
+	//fill in the actual size
894
+	os->fseek(pos1 + sizeof(uint32_t),SEEK_SET);
895
+	write32le(size,os);
896
+	os->fseek(pos2,SEEK_SET);*/
897
+
898
+/*
899
+// old version of this function,
900
+// for reference in case the new one above starts misbehaving somehow:
901
+
902
+	// - this is retarded. why not write placeholders for size and then write directly to the stream
903
+	//and then go back and fill them in
904
+
905
+	//get the size
906
+	memorystream mstemp;
907
+	saveproc(&mstemp);
908
+	mstemp.flush();
909
+	uint32_t size = mstemp.size();
910
+
911
+	//write the type, size, and data
912
+	write32le(type,os);
913
+	write32le(size,os);
914
+	os->write(mstemp.buf(),size);
915
+*/
916
+//}
917
+
918
+//static void writechunks(EMUFILE* os);
919
+
920
+/*bool savestate_save(EMUFILE* outstream, int compressionLevel)
921
+{
922
+	#ifndef HAVE_LIBZ
923
+	compressionLevel = Z_NO_COMPRESSION;
924
+	#endif
925
+
926
+	EMUFILE_MEMORY ms;
927
+	EMUFILE* os;
928
+
929
+	if(compressionLevel != Z_NO_COMPRESSION)
930
+	{
931
+		//generate the savestate in memory first
932
+		os = (EMUFILE*)&ms;
933
+		writechunks(os);
934
+	}
935
+	else
936
+	{
937
+		os = outstream;
938
+		os->fseek(32,SEEK_SET); //skip the header
939
+		writechunks(os);
940
+	}
941
+
942
+	//save the length of the file
943
+	uint32_t len = os->ftell();
944
+
945
+	uint32_t comprlen = 0xFFFFFFFF;
946
+	uint8_t* cbuf;
947
+
948
+	//compress the data
949
+	int error = Z_OK;
950
+	if(compressionLevel != Z_NO_COMPRESSION)
951
+	{
952
+		cbuf = ms.buf();
953
+		uLongf comprlen2;
954
+		//worst case compression.
955
+		//zlib says "0.1% larger than sourceLen plus 12 bytes"
956
+		comprlen = (len>>9)+12 + len;
957
+		cbuf = new uint8_t[comprlen];
958
+		// Workaround to make it compile under linux 64bit
959
+		comprlen2 = comprlen;
960
+		//error = compress2(cbuf,&comprlen2,ms.buf(),len,compressionLevel);
961
+		comprlen = (uint32_t)comprlen2;
962
+	}
963
+
964
+	//dump the header
965
+	outstream->fseek(0,SEEK_SET);
966
+	outstream->fwrite(magic,16);
967
+	write32le(SAVESTATE_VERSION,outstream);
968
+	write32le(EMU_DESMUME_VERSION_NUMERIC(),outstream); //desmume version
969
+	write32le(len,outstream); //uncompressed length
970
+	write32le(comprlen,outstream); //compressed length (-1 if it is not compressed)
971
+
972
+	if(compressionLevel != Z_NO_COMPRESSION)
973
+	{
974
+		outstream->fwrite((char*)cbuf,comprlen==(uint32_t)-1?len:comprlen);
975
+		delete[] cbuf;
976
+	}
977
+
978
+	return error == Z_OK;
979
+}*/
980
+
981
+/*bool savestate_save (const char *file_name)
982
+{
983
+	EMUFILE_MEMORY ms;
984
+	size_t elems_written;
985
+#ifdef HAVE_LIBZ
986
+	if(!savestate_save(&ms, Z_DEFAULT_COMPRESSION))
987
+#else
988
+	if(!savestate_save(&ms, 0))
989
+#endif
990
+		return false;
991
+	FILE* file = fopen(file_name,"wb");
992
+	if(file)
993
+	{
994
+		elems_written = fwrite(ms.buf(),1,ms.size(),file);
995
+		fclose(file);
996
+		return elems_written == ms.size();
997
+	} else return false;
998
+}*/
999
+
1000
+//extern SFORMAT SF_RTC[];
1001
+
1002
+/*static void writechunks(EMUFILE* os) {
1003
+	savestate_WriteChunk(os,1,SF_ARM9);
1004
+	savestate_WriteChunk(os,2,SF_ARM7);
1005
+	savestate_WriteChunk(os,3,cp15_savestate);
1006
+	savestate_WriteChunk(os,4,SF_MEM);
1007
+	savestate_WriteChunk(os,5,SF_NDS);
1008
+	savestate_WriteChunk(os,51,nds_savestate);
1009
+	savestate_WriteChunk(os,60,SF_MMU);
1010
+	savestate_WriteChunk(os,61,mmu_savestate);
1011
+	//savestate_WriteChunk(os,7,gpu_savestate);
1012
+	savestate_WriteChunk(os,8,spu_savestate);
1013
+	//savestate_WriteChunk(os,81,mic_savestate);
1014
+	//savestate_WriteChunk(os,90,SF_GFX3D);
1015
+	//savestate_WriteChunk(os,91,gfx3d_savestate);
1016
+	//savestate_WriteChunk(os,100,SF_MOVIE);
1017
+	//savestate_WriteChunk(os,101,mov_savestate);
1018
+	//savestate_WriteChunk(os,110,SF_WIFI);
1019
+	//savestate_WriteChunk(os,120,SF_RTC);
1020
+	savestate_WriteChunk(os,0xFFFFFFFF,(SFORMAT*)0);
1021
+}*/
1022
+
1023
+/*static bool fake_gpu_loadstate(EMUFILE* is, int size)
1024
+{
1025
+	//read version
1026
+	uint32_t version;
1027
+
1028
+	//sigh.. shouldve used a new version number
1029
+	if(size == 256*192*2*2)
1030
+		version = 0;
1031
+	else if(size== 0x30024)
1032
+	{
1033
+		read32le(&version,is);
1034
+		version = 1;
1035
+	}
1036
+	else
1037
+		if(read32le(&version,is) != 1) return false;
1038
+
1039
+
1040
+	if(version<0||version>1) return false;
1041
+
1042
+	uint8_t tmpu8_array[4*256*192];
1043
+	is->fread((char*)tmpu8_array,sizeof(tmpu8_array));
1044
+
1045
+	if(version==1)
1046
+	{
1047
+		uint32_t tmpu32;
1048
+		for (int i = 0; i < 8; ++i)
1049
+			read32le(&tmpu32, is);*/
1050
+		/*read32le(&MainScreen.gpu->affineInfo[0].x,is);
1051
+		read32le(&MainScreen.gpu->affineInfo[0].y,is);
1052
+		read32le(&MainScreen.gpu->affineInfo[1].x,is);
1053
+		read32le(&MainScreen.gpu->affineInfo[1].y,is);
1054
+		read32le(&SubScreen.gpu->affineInfo[0].x,is);
1055
+		read32le(&SubScreen.gpu->affineInfo[0].y,is);
1056
+		read32le(&SubScreen.gpu->affineInfo[1].x,is);
1057
+		read32le(&SubScreen.gpu->affineInfo[1].y,is);*/
1058
+		//removed per nitsuja feedback. anyway, this same thing will happen almost immediately in gpu line=0
1059
+		//MainScreen.gpu->refreshAffineStartRegs(-1,-1);
1060
+		//SubScreen.gpu->refreshAffineStartRegs(-1,-1);
1061
+	/*}
1062
+
1063
+	//MainScreen.gpu->updateBLDALPHA();
1064
+	//SubScreen.gpu->updateBLDALPHA();
1065
+	return !is->fail();
1066
+}*/
1067
+
1068
+/*static bool fake_mic_loadstate(EMUFILE* is, int size)
1069
+{
1070
+	uint32_t version;
1071
+	if(read32le(&version,is) != 1) return false;
1072
+	if(version > 1 || version == 0) { is->fseek(size-4, SEEK_CUR); return true; }
1073
+
1074
+	uint8_t tmpu8_Array[2][4096];
1075
+	is->fread((char*)tmpu8_Array[0], 4096);
1076
+	is->fread((char*)tmpu8_Array[1], 4096);
1077
+	uint16_t tmpu16;
1078
+	read16le(&tmpu16,is);
1079
+	uint8_t tmpu8;
1080
+	read8le(&tmpu8,is);
1081
+	read8le(&tmpu8,is);
1082
+	uint32_t tmpu32;
1083
+	read32le(&tmpu32,is);
1084
+	return true;
1085
+}*/
1086
+
1087
+/*static uint32_t tmpu32_array16[16];
1088
+static uint32_t tmpu32_array64[64];
1089
+static uint32_t tmpu32_array4[4];
1090
+static uint16_t tmpu16_array6[6];
1091
+static uint8_t tmpu8_array4[4];
1092
+static uint16_t tmpu16_array32[32];
1093
+static uint8_t tmpu8_array128[128];
1094
+static uint8_t tmpu8_arrayAlot[4*256*192];
1095
+SFORMAT SF_GFX3D[]={
1096
+	{ "GCTL", 4, 1, &tmpu32}, // no longer regenerated indirectly, see comment in loadstate()
1097
+	{ "GPAT", 4, 1, &tmpu32},
1098
+	{ "GPAP", 4, 1, &tmpu32},
1099
+	{ "GINB", 4, 1, &tmpu32},
1100
+	{ "GTFM", 4, 1, &tmpu32},
1101
+	{ "GTPA", 4, 1, &tmpu32},
1102
+	{ "GMOD", 4, 1, &tmpu32},
1103
+	{ "GMTM", 4,16, tmpu32_array16},
1104
+	{ "GMCU", 4,64, tmpu32_array64},
1105
+	{ "ML4I", 1, 1, &tmpu8},
1106
+	{ "ML3I", 1, 1, &tmpu8},
1107
+	{ "MM4I", 1, 1, &tmpu8},
1108
+	{ "MM3I", 1, 1, &tmpu8},
1109
+	{ "MMxI", 1, 1, &tmpu8},
1110
+	{ "GSCO", 4, 1, tmpu32_array4},
1111
+	{ "GCOI", 1, 1, &tmpu8},
1112
+	{ "GVFM", 4, 1, &tmpu32},
1113
+	{ "GTRN", 4, 4, tmpu32_array4},
1114
+	{ "GTRI", 1, 1, &tmpu8},
1115
+	{ "GSCA", 4, 4, tmpu32_array4},
1116
+	{ "GSCI", 1, 1, &tmpu8},
1117
+	{ "G_T_", 4, 1, &tmpu32},
1118
+	{ "G_S_", 4, 1, &tmpu32},
1119
+	{ "GL_T", 4, 1, &tmpu32},
1120
+	{ "GL_S", 4, 1, &tmpu32},
1121
+	{ "GLCM", 4, 1, &tmpu32},
1122
+	{ "GLIN", 4, 1, &tmpu32},
1123
+	{ "GLI2", 4, 1, &tmpu32},
1124
+	{ "GLSB", 4, 1, &tmpu32},
1125
+	{ "GLBT", 4, 1, &tmpu32},
1126
+	{ "GLPT", 4, 1, &tmpu32},
1127
+	{ "GLPC", 4, 4, tmpu32_array4},
1128
+	{ "GBTC", 2, 6, tmpu16_array6},
1129
+	{ "GFHE", 4, 1, &gxFIFO.head},
1130
+	{ "GFTA", 4, 1, &gxFIFO.tail},
1131
+	{ "GFSZ", 4, 1, &gxFIFO.size},
1132
+	{ "GFCM", 1, HACK_GXIFO_SIZE, &gxFIFO.cmd[0]},
1133
+	{ "GFPM", 4, HACK_GXIFO_SIZE, &gxFIFO.param[0]},
1134
+	{ "GPHE", 1, 1, &gxPIPE.head},
1135
+	{ "GPTA", 1, 1, &gxPIPE.tail},
1136
+	{ "GPSZ", 1, 1, &gxPIPE.size},
1137
+	{ "GPCM", 1, 4, &gxPIPE.cmd[0]},
1138
+	{ "GPPM", 4, 4, &gxPIPE.param[0]},
1139
+	{ "GCOL", 1, 4, &tmpu8_array4},
1140
+	{ "GLCO", 4, 4, tmpu32_array4},
1141
+	{ "GLDI", 4, 4, tmpu32_array4},
1142
+	{ "GMDI", 2, 1, &tmpu16},
1143
+	{ "GMAM", 2, 1, &tmpu16},
1144
+	{ "GMSP", 2, 1, &tmpu16},
1145
+	{ "GMEM", 2, 1, &tmpu16},
1146
+	{ "GFLP", 4, 1, &tmpu32},
1147
+	{ "GDRP", 4, 1, &tmpu32},
1148
+	{ "GSET", 4, 1, &tmpu32},
1149
+	{ "GSEA", 4, 1, &tmpu32},
1150
+	{ "GSEB", 4, 1, &tmpu32},
1151
+	{ "GSEX", 4, 1, &tmpu32},
1152
+	{ "GSEE", 4, 1, &tmpu32},
1153
+	{ "GSEC", 4, 1, &tmpu32},
1154
+	{ "GSEF", 4, 1, &tmpu32},
1155
+	{ "GSEO", 4, 1, &tmpu32},
1156
+	{ "GFSH", 4, 1, &tmpu32},
1157
+	{ "GSSH", 4, 1, &tmpu32},
1158
+	{ "GSWB", 4, 1, &tmpu32},
1159
+	{ "GSSM", 4, 1, &tmpu32},
1160
+	{ "GSAR", 1, 1, &tmpu8},
1161
+	{ "GSVP", 4, 1, &tmpu32},
1162
+	{ "GSCC", 4, 1, &tmpu32},
1163
+	{ "GSCD", 4, 1, &tmpu32},
1164
+	{ "GSFC", 4, 4, tmpu32_array4},
1165
+	{ "GSFO", 4, 1, &tmpu32},
1166
+	{ "GST4", 2, 32, tmpu16_array32},
1167
+	{ "GSSU", 1, 128, tmpu8_array128},
1168
+	{ "GSSI", 4, 1, &tmpu32},
1169
+	{ "GSAF", 4, 1, &tmpu32},
1170
+	{ "GSPF", 4, 1, &tmpu32},
1171
+	//------------------------
1172
+	{ "GTST", 4, 1, &tmpu32},
1173
+	{ "GTVC", 4, 1, &tmpu32},
1174
+	{ "GTVM", 4, 4, tmpu32_array4},
1175
+	{ "GTVF", 4, 1, &tmpu32},
1176
+	{ "G3CX", 1, 4*256*192, tmpu8_arrayAlot},
1177
+	{ 0 }
1178
+};*/
1179
+
1180
+/*static uint8_t tmpu8_array8[8];
1181
+static SFORMAT SF_RTC[]={
1182
+	{ "R000", 1, 1, &tmpu8},
1183
+	{ "R010", 1, 1, &tmpu8},
1184
+	{ "R020", 1, 1, &tmpu8},
1185
+	{ "R030", 1, 1, &tmpu8},
1186
+
1187
+	{ "R040", 1, 1, &tmpu8},
1188
+	{ "R050", 1, 1, &tmpu8},
1189
+	{ "R060", 1, 1, &tmpu8},
1190
+	{ "R070", 1, 1, &tmpu8},
1191
+	{ "R080", 1, 1, &tmpu8},
1192
+	{ "R090", 1, 1, &tmpu8},
1193
+	{ "R100", 1, 1, &tmpu8},
1194
+	{ "R110", 2, 1, &tmpu16},
1195
+
1196
+	{ "R120", 1, 1, &tmpu8},
1197
+	{ "R130", 1, 1, &tmpu8},
1198
+	{ "R140", 1, 1, &tmpu8},
1199
+	{ "R150", 1, 8, tmpu8_array8},
1200
+
1201
+	{ "R160", 1, 8, tmpu8_array8},
1202
+
1203
+	{ NULL, 0, 0, NULL }
1204
+};*/
1205
+
1206
+/*static bool fake_gfx_hardware_loadstate(EMUFILE *f)
1207
+{
1208
+	uint32_t version;
1209
+	if(read32le(&version,f) != 1) return false;
1210
+	if(version != 0) return false;
1211
+
1212
+	uint32_t tempsize;
1213
+	read32le(&tempsize,f);
1214
+	uint32_t commandCursor = 4-tempsize;
1215
+	//for(uint32_t i=0;i<commandCursor;i++) commandsPending[i].command = 0;
1216
+	uint8_t tmpu8;
1217
+	for(uint32_t i=commandCursor;i<4;i++) read8le(&commandsPending[i].command&tmpu8,f);
1218
+	read32le(&tempsize,f);
1219
+	//for(uint32_t i=0;i<commandCursor;i++) commandsPending[i].countdown = 0;
1220
+	for(uint32_t i=commandCursor;i<4;i++) read8le(&commandsPending[i].countdown&tmpu8,f);
1221
+
1222
+	read8le(&countdown&tmpu8,f);
1223
+
1224
+	return true;
1225
+}*/
1226
+
1227
+/*static bool fake_gfx3d_loadstate(EMUFILE* is, int size)
1228
+{
1229
+	int version;
1230
+	if(read32le(&version,is) != 1) return false;
1231
+	if(size==8) version = 0;
1232
+
1233
+
1234
+	//gfx3d_glPolygonAttrib_cache();
1235
+	//gfx3d_glTexImage_cache();
1236
+	//gfx3d_glLightDirection_cache(0);
1237
+	//gfx3d_glLightDirection_cache(1);
1238
+	//gfx3d_glLightDirection_cache(2);
1239
+	//gfx3d_glLightDirection_cache(3);
1240
+
1241
+	//jiggle the lists. and also wipe them. this is clearly not the best thing to be doing.
1242
+	//listTwiddle = 0;
1243
+	//polylist = &polylists[listTwiddle];
1244
+	//vertlist = &vertlists[listTwiddle];
1245
+
1246
+#define OSREAD(x) is->fread((char*)&(x),sizeof((x)));
1247
+	if(version>=1)
1248
+	{
1249
+		int tmpint;
1250
+		//OSREAD(vertlist->count);
1251
+		//OSREAD(tmpint);
1252
+		is->fread(&tmpint, sizeof(int));
1253
+		//for(int i=0;i<vertlist->count;i++)
1254
+		for (int i = 0; i < tmpint; ++i)
1255
+		{
1256
+			//vertlist->list[i].load(is);
1257
+			float tmpfloat;
1258
+			uint8_t tmpu8;
1259
+			for (int j = 0; j < 6; ++j)
1260
+				//OSREAD(tmpfloat);
1261
+				is->fread(&tmpfloat, sizeof(float));
1262
+			for (int j = 0; j < 3; ++j)
1263
+				//OSREAD(tmpu8);
1264
+				is->fread(&tmpu8, sizeof(uint8_t));
1265
+			for (int j = 0; j < 3; ++j)
1266
+				//OSREAD(tmpfloat);
1267
+				is->fread(&tmpfloat, sizeof(float));
1268
+		}
1269
+		//OSREAD(polylist->count);
1270
+		//OSREAD(tmpint);
1271
+		is->fread(&tmpint, sizeof(int));
1272
+		//for(int i=0;i<polylist->count;i++)
1273
+		for (int i = 0; i < tmpint; ++i)
1274
+		{
1275
+			//polylist->list[i].load(is);
1276
+			int tmpint2;
1277
+			uint16_t tmpu16;
1278
+			uint32_t tmpu32;
1279
+			float tmpfloat;
1280
+			//OSREAD(tmpint2);
1281
+			is->fread(&tmpint2, sizeof(int));
1282
+			for (int j = 0; j < 4; ++j)
1283
+				//OSREAD(tmpu16);
1284
+				is->fread(&tmpu16, sizeof(uint16_t));
1285
+			for (int j = 0; j < 4; ++j)
1286
+				//OSREAD(tmpu32);
1287
+				is->fread(&tmpu32, sizeof(uint32_t));
1288
+			for (int j = 0; j < 2; ++j)
1289
+				//OSREAD(tmpfloat);
1290
+				is->fread(&tmpfloat, sizeof(float));
1291
+		}
1292
+	}
1293
+
1294
+	if(version>=2)
1295
+	{
1296
+		for(int i=0;i<4;i++)
1297
+		{
1298
+			uint32_t tmpu32;
1299
+			//OSREAD(mtxStack[i].position);
1300
+			//OSREAD(tmpu32);
1301
+			is->fread(&tmpu32, sizeof(uint32_t));*/
1302
+			/*for(int j=0;j<mtxStack[i].size*16;j++)
1303
+				OSREAD(mtxStack[i].matrix[j]);*/
1304
+			//if (!i || i == 3)
1305
+				/*for (int j = 0; j < (!i || i == 3 ? 1 : 31) * 16; ++j)
1306
+					//OSREAD(tmpu32)
1307
+					is->fread(&tmpu32, sizeof(uint32_t));
1308
+			//else
1309
+				//for (int j = 0; j < 31 * 16; ++j)
1310
+					//OSREAD(tmpu32);
1311
+		}
1312
+	}
1313
+
1314
+	if(version>=3) {
1315
+		fake_gfx_hardware_loadstate(is);
1316
+	}*/
1317
+
1318
+	/*gfx3d.polylist = &polylists[listTwiddle^1];
1319
+	gfx3d.vertlist = &vertlists[listTwiddle^1];
1320
+	gfx3d.polylist->count=0;
1321
+	gfx3d.vertlist->count=0;*/
1322
+
1323
+	/*if(version >= 4)
1324
+	{
1325
+		uint32_t tmpu32_array16[16];
1326
+		//OSREAD(cacheLightDirection);
1327
+		//OSREAD(tmpu32_array16);
1328
+		is->fread(tmpu32_array16, sizeof(tmpu32_array16));
1329
+		//OSREAD(cacheHalfVector);
1330
+		//OSREAD(tmpu32_array16);
1331
+		is->fread(tmpu32_array16, sizeof(tmpu32_array16));
1332
+	}
1333
+
1334
+	return true;
1335
+}*/
1336
+
1337
+//static void fake_MovieRecord_parsePad(EMUFILE* fp/*, uint16_t& pad*/)
1338
+/*{
1339
+
1340
+	char buf[13];
1341
+	fp->fread(buf,13);*/
1342
+	/*pad = 0;
1343
+	for(int i=0;i<13;i++)
1344
+	{
1345
+		pad <<= 1;
1346
+		pad |= ((buf[i]=='.'||buf[i]==' ')?0:1);
1347
+	}*/
1348
+//}
1349
+
1350
+/*static void fake_MovieRecord_parse(MovieData* md, EMUFILE* fp)
1351
+{
1352
+	//by the time we get in here, the initial pipe has already been extracted
1353
+
1354
+	//extract the commands
1355
+	uint8_t tmpu8 = u32DecFromIstream(fp);
1356
+
1357
+	fp->fgetc(); //eat the pipe
1358
+
1359
+	fake_MovieRecord_parsePad(fp*//*, pad*///);
1360
+	/*touch.x*///tmpu8 = u32DecFromIstream(fp);
1361
+	/*touch.y*///tmpu8 = u32DecFromIstream(fp);
1362
+	/*touch.touch*///tmpu8 = u32DecFromIstream(fp);
1363
+
1364
+	/*fp->fgetc(); //eat the pipe
1365
+
1366
+	//should be left at a newline
1367
+}*/
1368
+
1369
+/*static bool fake_LoadFM2(MovieData& movieData, EMUFILE* fp, int size, bool stopAfterHeader)
1370
+{
1371
+	//TODO - start with something different. like 'desmume movie version 1"
1372
+	int curr = fp->ftell();
1373
+
1374
+	//movie must start with "version 1"
1375
+	char buf[9];
1376
+	curr = fp->ftell();
1377
+	fp->fread(buf,9);
1378
+	fp->fseek(curr, SEEK_SET);
1379
+//	if(fp->fail()) return false;
1380
+	if(memcmp(buf,"version 1",9))
1381
+		return false;
1382
+
1383
+	std::string key,value;
1384
+	enum {
1385
+		NEWLINE, KEY, SEPARATOR, VALUE, RECORD, COMMENT
1386
+	} state = NEWLINE;
1387
+	bool bail = false;
1388
+	for(;;)
1389
+	{
1390
+		bool iswhitespace, isrecchar, isnewline;
1391
+		int c;
1392
+		if(size--<=0) goto bail;
1393
+		c = fp->fgetc();
1394
+		if(c == -1)
1395
+			goto bail;
1396
+		iswhitespace = (c==' '||c=='\t');
1397
+		isrecchar = (c=='|');
1398
+		isnewline = (c==10||c==13);
1399
+		if(isrecchar && movieData.binaryFlag && !stopAfterHeader)
1400
+		{
1401
+			LoadFM2_binarychunk(movieData, fp, size);
1402
+			return true;
1403
+		}
1404
+		switch(state)
1405
+		{
1406
+		case NEWLINE:
1407
+			if(isnewline) goto done;
1408
+			if(iswhitespace) goto done;
1409
+			if(isrecchar)
1410
+				goto dorecord;
1411
+			//must be a key
1412
+			key = "";
1413
+			value = "";
1414
+			goto dokey;
1415
+			break;
1416
+		case RECORD:
1417
+			{
1418
+				dorecord:
1419
+				if (stopAfterHeader) return true;
1420
+				//int currcount = movieData.records.size();
1421
+				//movieData.records.resize(currcount+1);
1422
+				int preparse = fp->ftell();
1423
+				//movieData.records[currcount].parse(&movieData, fp);
1424
+				fake_MovieRecord_parse(fp);
1425
+				int postparse = fp->ftell();
1426
+				size -= (postparse-preparse);
1427
+				state = NEWLINE;
1428
+				break;
1429
+			}
1430
+
1431
+		case KEY:
1432
+			dokey: //dookie
1433
+			state = KEY;
1434
+			if(iswhitespace) goto doseparator;
1435
+			if(isnewline) goto commit;
1436
+			key += c;
1437
+			break;
1438
+		case SEPARATOR:
1439
+			doseparator:
1440
+			state = SEPARATOR;
1441
+			if(isnewline) goto commit;
1442
+			if(!iswhitespace) goto dovalue;
1443
+			break;
1444
+		case VALUE:
1445
+			dovalue:
1446
+			state = VALUE;
1447
+			if(isnewline) goto commit;
1448
+			value += c;
1449
+			break;
1450
+		case COMMENT:
1451
+		default:
1452
+			break;
1453
+		}
1454
+		goto done;
1455
+
1456
+		bail:
1457
+		bail = true;
1458
+		if(state == VALUE) goto commit;
1459
+		goto done;
1460
+		commit:
1461
+		//movieData.installValue(key,value);
1462
+		state = NEWLINE;
1463
+		done: ;
1464
+		if(bail) break;
1465
+	}
1466
+
1467
+	return true;
1468
+}*/
1469
+
1470
+/*static bool fake_mov_loadstate(EMUFILE* fp, int size)
1471
+{
1472
+	//load_successful = false;
1473
+	static const int kMOVI = 0x49564F4D;
1474
+	static const int kNOMO = 0x4F4D4F4E;
1475
+
1476
+	uint32_t cookie;
1477
+	if(read32le(&cookie,fp) != 1) return false;
1478
+	if(cookie == kNOMO)
1479
+	{*/
1480
+		/*if(movieMode == MOVIEMODE_RECORD || movieMode == MOVIEMODE_PLAY)
1481
+			FinishPlayback();*/
1482
+		/*return true;
1483
+	}
1484
+	else if(cookie != kMOVI)
1485
+		return false;
1486
+
1487
+	size -= 4;*/
1488
+
1489
+	/*if (!movie_readonly && autoMovieBackup && freshMovie) //If auto-backup is on, movie has not been altered this session and the movie is in read+write mode
1490
+	{
1491
+		FCEUI_MakeBackupMovie(false);	//Backup the movie before the contents get altered, but do not display messages
1492
+	}*/
1493
+
1494
+	//a little rule: cant load states in read+write mode with a movie from an archive.
1495
+	//so we are going to switch it to readonly mode in that case
1496
+//	if(!movie_readonly
1497
+//		//*&& FCEU_isFileInArchive(curMovieFilename)*/
1498
+//		) {
1499
+//		FCEU_PrintError("Cannot loadstate in Read+Write with movie from archive. Movie is now Read-Only.");
1500
+//		movie_readonly = true;
1501
+//	}
1502
+
1503
+	//MovieData tempMovieData = MovieData();
1504
+	//int curr = fp->ftell();
1505
+	//if(!LoadFM2(tempMovieData, fp, size, false)) {
1506
+	/*if (!fake_LoadFM2(fp, size, false)) {*/
1507
+
1508
+	//	is->seekg((uint32_t)curr+size);
1509
+	/*	extern bool FCEU_state_loading_old_format;
1510
+		if(FCEU_state_loading_old_format) {
1511
+			if(movieMode == MOVIEMODE_PLAY || movieMode == MOVIEMODE_RECORD) {
1512
+				FCEUI_StopMovie();
1513
+				FCEU_PrintError("You have tried to use an old savestate while playing a movie. This is unsupported (since the old savestate has old-format movie data in it which can't be converted on the fly)");
1514
+			}
1515
+		}*/
1516
+		/*return false;
1517
+	}*/
1518
+
1519
+	//complex TAS logic for when a savestate is loaded:
1520
+	//----------------
1521
+	//if we are playing or recording and toggled read-only:
1522
+	//  then, the movie we are playing must match the guid of the one stored in the savestate or else error.
1523
+	//  the savestate is assumed to be in the same timeline as the current movie.
1524
+	//  if the current movie is not long enough to get to the savestate's frame#, then it is an error.
1525
+	//  the movie contained in the savestate will be discarded.
1526
+	//  the emulator will be put into play mode.
1527
+	//if we are playing or recording and toggled read+write
1528
+	//  then, the movie we are playing must match the guid of the one stored in the savestate or else error.
1529
+	//  the movie contained in the savestate will be loaded into memory
1530
+	//  the frames in the movie after the savestate frame will be discarded
1531
+	//  the in-memory movie will have its rerecord count incremented
1532
+	//  the in-memory movie will be dumped to disk as fcm.
1533
+	//  the emulator will be put into record mode.
1534
+	//if we are doing neither:
1535
+	//  then, we must discard this movie and just load the savestate
1536
+
1537
+
1538
+	/*if(movieMode != MOVIEMODE_INACTIVE)
1539
+	{
1540
+		//handle moviefile mismatch
1541
+		if(tempMovieData.guid != currMovieData.guid)
1542
+		{
1543
+			//mbg 8/18/08 - this code  can be used to turn the error message into an OK/CANCEL
1544
+			#ifdef WIN32
1545
+				//std::string msg = "There is a mismatch between savestate's movie and current movie.\ncurrent: " + currMovieData.guid.toString() + "\nsavestate: " + tempMovieData.guid.toString() + "\n\nThis means that you have loaded a savestate belonging to a different movie than the one you are playing now.\n\nContinue loading this savestate anyway?";
1546
+				//extern HWND pwindow;
1547
+				//int result = MessageBox(pwindow,msg.c_str(),"Error loading savestate",MB_OKCANCEL);
1548
+				//if(result == IDCANCEL)
1549
+				//	return false;
1550
+			#else
1551
+				FCEU_PrintError("Mismatch between savestate's movie and current movie.\ncurrent: %s\nsavestate: %s\n",currMovieData.guid.toString().c_str(),tempMovieData.guid.toString().c_str());
1552
+				return false;
1553
+			#endif
1554
+		}
1555
+
1556
+		closeRecordingMovie();
1557
+
1558
+		if(!movie_readonly)
1559
+		{
1560
+			currMovieData = tempMovieData;
1561
+			currMovieData.rerecordCount = currRerecordCount;
1562
+		}
1563
+
1564
+		if(currFrameCounter > (int)currMovieData.records.size())
1565
+		{
1566
+			// if the frame counter is longer than our current movie,
1567
+			// switch to "finished" mode.
1568
+			// this is a mode that behaves like "inactive"
1569
+			// except it permits switching to play/record by loading an earlier savestate.
1570
+			// (and we continue to store the finished movie in savestates made while finished)
1571
+			osd->setLineColor(255,0,0); // let's make the text red too to hopefully catch the user's attention a bit.
1572
+			FinishPlayback();
1573
+			osd->setLineColor(255,255,255);
1574
+
1575
+			//FCEU_PrintError("Savestate is from a frame (%d) after the final frame in the movie (%d). This is not permitted.", currFrameCounter, currMovieData.records.size()-1);
1576
+			//return false;
1577
+		}
1578
+		else if(movie_readonly)
1579
+		{
1580
+			//-------------------------------------------------------------
1581
+			//this code would reload the movie from disk. allegedly it is helpful to hexers, but
1582
+			//it is way too slow with dsm format. so it is only here as a reminder, and in case someone
1583
+			//wants to play with it
1584
+			//-------------------------------------------------------------
1585
+			//{
1586
+			//	fstream fs (curMovieFilename);
1587
+			//	if(!LoadFM2(tempMovieData, &fs, INT_MAX, false))
1588
+			//	{
1589
+			//		FCEU_PrintError("Failed to reload DSM after loading savestate");
1590
+			//	}
1591
+			//	fs.close();
1592
+			//	currMovieData = tempMovieData;
1593
+			//}
1594
+			//-------------------------------------------------------------
1595
+
1596
+			movieMode = MOVIEMODE_PLAY;
1597
+		}
1598
+		else
1599
+		{
1600
+		//	#ifdef _S9XLUA_H
1601
+		//	if(!FCEU_LuaRerecordCountSkip())
1602
+				currRerecordCount++;
1603
+		//	#endif
1604
+
1605
+			currMovieData.rerecordCount = currRerecordCount;
1606
+			currMovieData.truncateAt(currFrameCounter);
1607
+
1608
+			openRecordingMovie(curMovieFilename);
1609
+			if(!osRecordingMovie)
1610
+			{
1611
+			   osd->setLineColor(255, 0, 0);
1612
+			   osd->addLine("Can't save movie file!");
1613
+			}
1614
+
1615
+			//printf("DUMPING MOVIE: %d FRAMES\n",currMovieData.records.size());
1616
+			currMovieData.dump(osRecordingMovie, false);
1617
+			movieMode = MOVIEMODE_RECORD;
1618
+		}
1619
+	}
1620
+
1621
+	load_successful = true;
1622
+	freshMovie = false;*/
1623
+
1624
+	//// Maximus: Show the last input combination entered from the
1625
+	//// movie within the state
1626
+	//if(current!=0) // <- mz: only if playing or recording a movie
1627
+	//	memcpy(&cur_input_display, joop, 4);
1628
+
1629
+	/*return true;
1630
+}*/
1631
+
1632
+static bool ReadStateChunks(EMUFILE* is, int32_t totalsize)
1633
+{
1634
+	bool ret = true;
1635
+	while(totalsize > 0)
1636
+	{
1637
+		uint32_t size;
1638
+		uint32_t t;
1639
+		if(!read32le(&t,is))  { ret=false; break; }
1640
+		if(t == 0xFFFFFFFF) goto done;
1641
+		if(!read32le(&size,is))  { ret=false; break; }
1642
+		switch(t)
1643
+		{
1644
+			case 1: if(!ReadStateChunk(is,SF_ARM9,size)) ret=false; break;
1645
+			case 2: if(!ReadStateChunk(is,SF_ARM7,size)) ret=false; break;
1646
+			case 3: if(!cp15_loadstate(is,size)) ret=false; break;
1647
+			case 4: if(!ReadStateChunk(is,SF_MEM,size)) ret=false; break;
1648
+			case 5: if(!ReadStateChunk(is,SF_NDS,size)) ret=false; break;
1649
+			case 51: if(!nds_loadstate(is,size)) ret=false; break;
1650
+			case 60: if(!ReadStateChunk(is,SF_MMU,size)) ret=false; break;
1651
+			case 61: if(!mmu_loadstate(is,size)) ret=false; break;
1652
+			case 7: /*if(!fake_gpu_loadstate(is,size)) ret=false;*/ break;
1653
+			case 8: if(!spu_loadstate(is,size)) ret=false; break;
1654
+			case 81:/* if(!fake_mic_loadstate(is,size)) ret=false; break;*/
1655
+			case 90:/* if(!ReadStateChunk(is,SF_GFX3D,size)) ret=false; break;*/
1656
+			case 91:/* if(!fake_gfx3d_loadstate(is,size)) ret=false; break;*/
1657
+			case 100:/* if(!ReadStateChunk(is,SF_MOVIE, size)) ret=false; break;*/
1658
+			case 101:/* if(!fake_mov_loadstate(is, size)) ret=false; break;*/
1659
+			case 110:/* if(!ReadStateChunk(is,SF_WIFI,size)) ret=false; break;*/
1660
+			case 120:/* if(!ReadStateChunk(is,SF_RTC,size)) ret=false;*/ break;
1661
+			default:
1662
+				ret=false;
1663
+				break;
1664
+		}
1665
+		if(!ret)
1666
+			return false;
1667
+	}
1668
+done:
1669
+
1670
+	return ret;
1671
+}
1672
+
1673
+void loadstate()
1674
+{
1675
+    // This should regenerate the vram banks
1676
+    for (int i = 0; i < 0xA; i++)
1677
+       _MMU_write08<ARMCPU_ARM9>(0x04000240+i, _MMU_read08<ARMCPU_ARM9>(0x04000240+i));
1678
+
1679
+    // This should regenerate the graphics power control register
1680
+    _MMU_write16<ARMCPU_ARM9>(0x04000304, _MMU_read16<ARMCPU_ARM9>(0x04000304));
1681
+
1682
+	// This should regenerate the graphics configuration
1683
+	//zero 27-jul-09 : was formerly up to 7F but that wrote to dispfifo which is dumb (one of nitsuja's desynch bugs [that he found, not caused])
1684
+	//so then i brought it down to 66 but this resulted in a conceptual bug with affine start registers, which shouldnt get regenerated
1685
+	//so then i just made this exhaustive list
1686
+ //   for (int i = REG_BASE_DISPA; i<=REG_BASE_DISPA + 0x66; i+=2)
1687
+	//_MMU_write16<ARMCPU_ARM9>(i, _MMU_read16<ARMCPU_ARM9>(i));
1688
+ //   for (int i = REG_BASE_DISPB; i<=REG_BASE_DISPB + 0x7F; i+=2)
1689
+	//_MMU_write16<ARMCPU_ARM9>(i, _MMU_read16<ARMCPU_ARM9>(i));
1690
+	static const uint8_t mainRegenAddr[] = {0x00,0x02,0x08,0x0a,0x0c,0x0e,0x40,0x42,0x44,0x46,0x48,0x4a,0x4c,0x50,0x52,0x54,0x64,0x66,0x6c};
1691
+	static const uint8_t subRegenAddr[] =  {0x00,0x02,0x08,0x0a,0x0c,0x0e,0x40,0x42,0x44,0x46,0x48,0x4a,0x4c,0x50,0x52,0x54,0x6c};
1692
+	for(uint32_t i=0;i<ARRAY_SIZE(mainRegenAddr);i++)
1693
+		_MMU_write16<ARMCPU_ARM9>(REG_BASE_DISPA+mainRegenAddr[i], _MMU_read16<ARMCPU_ARM9>(REG_BASE_DISPA+mainRegenAddr[i]));
1694
+	for(uint32_t i=0;i<ARRAY_SIZE(subRegenAddr);i++)
1695
+		_MMU_write16<ARMCPU_ARM9>(REG_BASE_DISPB+subRegenAddr[i], _MMU_read16<ARMCPU_ARM9>(REG_BASE_DISPB+subRegenAddr[i]));
1696
+	// no need to restore 0x60 since control and MMU.ARM9_REG are both in the savestates, and restoring it could mess up the ack bits anyway
1697
+
1698
+	SetupMMU(/*nds.Is_DebugConsole()*/false,nds.Is_DSI());
1699
+
1700
+	//execute = !driver->EMU_IsEmulationPaused();
1701
+	execute = true;
1702
+}
1703
+
1704
+bool savestate_load(EMUFILE* is)
1705
+{
1706
+	SAV_silent_fail_flag = false;
1707
+	char header[16];
1708
+	is->fread(header,16);
1709
+	if(is->fail() || memcmp(header,magic,16))
1710
+		return false;
1711
+
1712
+	uint32_t ssversion,dversion,len,comprlen;
1713
+	if(!read32le(&ssversion,is)) return false;
1714
+	if(!read32le(&dversion,is)) return false;
1715
+	if(!read32le(&len,is)) return false;
1716
+	if(!read32le(&comprlen,is)) return false;
1717
+
1718
+	if(ssversion != SAVESTATE_VERSION) return false;
1719
+
1720
+	std::vector<uint8_t> buf(len);
1721
+
1722
+	if(comprlen != 0xFFFFFFFF) {
1723
+#ifndef HAVE_LIBZ
1724
+		//without libz, we can't decompress this savestate
1725
+		return false;
1726
+#endif
1727
+		std::vector<char> cbuf(comprlen);
1728
+		is->fread(&cbuf[0],comprlen);
1729
+		if(is->fail()) return false;
1730
+
1731
+#ifdef HAVE_LIBZ
1732
+		uLongf uncomprlen = len;
1733
+		int error = uncompress((uint8_t*)&buf[0],&uncomprlen,(uint8_t*)&cbuf[0],comprlen);
1734
+		if(error != Z_OK || uncomprlen != len)
1735
+			return false;
1736
+#endif
1737
+	} else {
1738
+		is->fread((char*)&buf[0],len-32);
1739
+	}
1740
+
1741
+	//GO!! READ THE SAVESTATE
1742
+	//THERE IS NO GOING BACK NOW
1743
+	//reset the emulator first to clean out the host's state
1744
+
1745
+	//while the series of resets below should work,
1746
+	//we are testing the robustness of the savestate system with this full reset.
1747
+	//the full reset wipes more things, so we can make sure that they are being restored correctly
1748
+	//extern bool _HACK_DONT_STOPMOVIE;
1749
+	//_HACK_DONT_STOPMOVIE = true;
1750
+	NDS_Reset();
1751
+	//_HACK_DONT_STOPMOVIE = false;
1752
+
1753
+	//reset some options to their old defaults which werent saved
1754
+	//nds.debugConsole = false;
1755
+
1756
+	//GPU_Reset(MainScreen.gpu, 0);
1757
+	//GPU_Reset(SubScreen.gpu, 1);
1758
+	//gfx3d_reset();
1759
+	//gpu3D->NDS_3D_Reset();
1760
+	//SPU_Reset();
1761
+
1762
+	EMUFILE_MEMORY mstemp(&buf);
1763
+	bool x = ReadStateChunks(&mstemp,(int32_t)len);
1764
+
1765
+	if(!x && !SAV_silent_fail_flag)
1766
+	{
1767
+		printf("Error loading savestate. It failed halfway through;\nSince there is no savestate backup system, your current game session is wrecked");
1768
+#ifdef _WINDOWS
1769
+		//HACK! we really need a better way to handle this kind of feedback
1770
+		MessageBoxA(0,"Error loading savestate. It failed halfway through;\nSince there is no savestate backup system, your current game session is wrecked",0,0);
1771
+#endif
1772
+		return false;
1773
+	}
1774
+
1775
+	loadstate();
1776
+
1777
+	/*if((nds.debugConsole!=0) != CommonSettings.DebugConsole) {
1778
+		printf("WARNING: forcing console debug mode to: debugmode=%s\n",nds.debugConsole?"true":"false");
1779
+	}*/
1780
+
1781
+	return true;
1782
+}
1783
+
1784
+/*bool savestate_load(const char *file_name)
1785
+{
1786
+	EMUFILE_FILE f(file_name,"rb");
1787
+	if(f.fail()) return false;
1788
+
1789
+	return savestate_load(&f);
1790
+}*/
1791
+
1792
+//static std::stack<EMUFILE_MEMORY*> rewindFreeList;
1793
+//static std::vector<EMUFILE_MEMORY*> rewindbuffer;
1794
+
1795
+//int rewindstates = 16;
1796
+//int rewindinterval = 4;
1797
+
1798
+/*void rewindsave () {*/
1799
+
1800
+	/*if(currFrameCounter % rewindinterval)
1801
+		return;*/
1802
+
1803
+	//printf("rewindsave"); printf("%d%s", currFrameCounter, "\n");
1804
+
1805
+
1806
+	/*EMUFILE_MEMORY *ms;
1807
+	if(!rewindFreeList.empty()) {
1808
+		ms = rewindFreeList.top();
1809
+		rewindFreeList.pop();
1810
+	} else {
1811
+		ms = new EMUFILE_MEMORY(1024*1024*12);
1812
+	}
1813
+
1814
+	if(!savestate_save(ms, Z_NO_COMPRESSION))
1815
+		return;
1816
+
1817
+	rewindbuffer.push_back(ms);
1818
+
1819
+	if((int)rewindbuffer.size() > rewindstates) {
1820
+		delete *rewindbuffer.begin();
1821
+		rewindbuffer.erase(rewindbuffer.begin());
1822
+	}
1823
+}*/
1824
+
1825
+/*void dorewind()
1826
+{*/
1827
+
1828
+	/*if(currFrameCounter % rewindinterval)
1829
+		return;*/
1830
+
1831
+	//printf("rewind\n");
1832
+
1833
+	/*nds.debugConsole = false;
1834
+
1835
+	int size = rewindbuffer.size();
1836
+
1837
+	if(size < 1) {
1838
+		printf("rewind buffer empty\n");
1839
+		return;
1840
+	}
1841
+
1842
+	printf("%d", size);
1843
+
1844
+	EMUFILE_MEMORY* loadms = rewindbuffer[size-1];
1845
+	loadms->fseek(32, SEEK_SET);
1846
+
1847
+	ReadStateChunks(loadms,loadms->size()-32);
1848
+	loadstate();
1849
+
1850
+	if(rewindbuffer.size()>1)
1851
+	{
1852
+		rewindFreeList.push(loadms);
1853
+		rewindbuffer.pop_back();
1854
+	}
1855
+
1856
+}*/