| 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 |
-}*/ |
| 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 |
+}*/ |