state.c 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807
  1. /*
  2. * PicoDrive
  3. * (C) notaz, 2010
  4. *
  5. * This work is licensed under the terms of MAME license.
  6. * See COPYING file in the top-level directory.
  7. */
  8. #include "pico_int.h"
  9. #include <zlib.h>
  10. #include "../cpu/sh2/sh2.h"
  11. #include "sound/ym2612.h"
  12. #include "state.h"
  13. // sn76496
  14. extern int *sn76496_regs;
  15. static arearw *areaRead;
  16. static arearw *areaWrite;
  17. static areaeof *areaEof;
  18. static areaseek *areaSeek;
  19. static areaclose *areaClose;
  20. carthw_state_chunk *carthw_chunks;
  21. void (*PicoStateProgressCB)(const char *str);
  22. void (*PicoLoadStateHook)(void);
  23. /* I/O functions */
  24. static size_t gzRead2(void *p, size_t _size, size_t _n, void *file)
  25. {
  26. return gzread(file, p, _size * _n);
  27. }
  28. static size_t gzWrite2(void *p, size_t _size, size_t _n, void *file)
  29. {
  30. return gzwrite(file, p, _size * _n);
  31. }
  32. static void set_cbs(int gz)
  33. {
  34. if (gz) {
  35. areaRead = gzRead2;
  36. areaWrite = gzWrite2;
  37. areaEof = (areaeof *) gzeof;
  38. areaSeek = (areaseek *) gzseek;
  39. areaClose = (areaclose *) gzclose;
  40. } else {
  41. areaRead = (arearw *) fread;
  42. areaWrite = (arearw *) fwrite;
  43. areaEof = (areaeof *) feof;
  44. areaSeek = (areaseek *) fseek;
  45. areaClose = (areaclose *) fclose;
  46. }
  47. }
  48. static void *open_save_file(const char *fname, int is_save)
  49. {
  50. int len = strlen(fname);
  51. void *afile = NULL;
  52. if (len > 3 && strcmp(fname + len - 3, ".gz") == 0)
  53. {
  54. if ( (afile = gzopen(fname, is_save ? "wb" : "rb")) ) {
  55. set_cbs(1);
  56. if (is_save)
  57. gzsetparams(afile, 9, Z_DEFAULT_STRATEGY);
  58. }
  59. }
  60. else
  61. {
  62. if ( (afile = fopen(fname, is_save ? "wb" : "rb")) ) {
  63. set_cbs(0);
  64. }
  65. }
  66. return afile;
  67. }
  68. // legacy savestate loading
  69. #define SCANP(f, x) areaRead(&Pico.x, sizeof(Pico.x), 1, f)
  70. static int state_load_legacy(void *file)
  71. {
  72. unsigned char head[32];
  73. unsigned char cpu[0x60];
  74. unsigned char cpu_z80[Z80_STATE_SIZE];
  75. void *ym2612_regs;
  76. int ok;
  77. memset(&cpu,0,sizeof(cpu));
  78. memset(&cpu_z80,0,sizeof(cpu_z80));
  79. memset(head, 0, sizeof(head));
  80. areaRead(head, sizeof(head), 1, file);
  81. if (strcmp((char *)head, "Pico") != 0)
  82. return -1;
  83. elprintf(EL_STATUS, "legacy savestate");
  84. // Scan all the memory areas:
  85. SCANP(file, ram);
  86. SCANP(file, vram);
  87. SCANP(file, zram);
  88. SCANP(file, cram);
  89. SCANP(file, vsram);
  90. // Pack, scan and unpack the cpu data:
  91. areaRead(cpu, sizeof(cpu), 1, file);
  92. SekUnpackCpu(cpu, 0);
  93. SCANP(file, m);
  94. SCANP(file, video);
  95. ok = areaRead(cpu_z80, sizeof(cpu_z80), 1, file) == sizeof(cpu_z80);
  96. // do not unpack if we fail to load z80 state
  97. if (!ok) z80_reset();
  98. else z80_unpack(cpu_z80);
  99. ym2612_regs = YM2612GetRegs();
  100. areaRead(sn76496_regs, 28*4, 1, file);
  101. areaRead(ym2612_regs, 0x200+4, 1, file);
  102. ym2612_unpack_state();
  103. return 0;
  104. }
  105. // ---------------------------------------------------------------------------
  106. typedef enum {
  107. CHUNK_M68K = 1,
  108. CHUNK_RAM,
  109. CHUNK_VRAM,
  110. CHUNK_ZRAM,
  111. CHUNK_CRAM, // 5
  112. CHUNK_VSRAM,
  113. CHUNK_MISC,
  114. CHUNK_VIDEO,
  115. CHUNK_Z80,
  116. CHUNK_PSG, // 10
  117. CHUNK_FM,
  118. // CD stuff
  119. CHUNK_S68K,
  120. CHUNK_PRG_RAM,
  121. CHUNK_WORD_RAM,
  122. CHUNK_PCM_RAM, // 15
  123. CHUNK_BRAM,
  124. CHUNK_GA_REGS,
  125. CHUNK_PCM,
  126. CHUNK_CDC, // old
  127. CHUNK_CDD, // 20 old
  128. CHUNK_SCD, // old
  129. CHUNK_RC, // old
  130. CHUNK_MISC_CD,
  131. //
  132. CHUNK_IOPORTS, // versions < 1.70 did not save that..
  133. CHUNK_SMS, // 25
  134. // 32x
  135. CHUNK_MSH2,
  136. CHUNK_MSH2_DATA,
  137. CHUNK_MSH2_PERI,
  138. CHUNK_SSH2,
  139. CHUNK_SSH2_DATA, // 30
  140. CHUNK_SSH2_PERI,
  141. CHUNK_32XSYS,
  142. CHUNK_M68K_BIOS,
  143. CHUNK_MSH2_BIOS,
  144. CHUNK_SSH2_BIOS, // 35
  145. CHUNK_SDRAM,
  146. CHUNK_DRAM,
  147. CHUNK_32XPAL,
  148. CHUNK_32X_EVT,
  149. CHUNK_32X_FIRST = CHUNK_MSH2,
  150. CHUNK_32X_LAST = CHUNK_32X_EVT,
  151. // add new stuff here
  152. CHUNK_CD_EVT = 50,
  153. CHUNK_CD_GFX,
  154. CHUNK_CD_CDC,
  155. CHUNK_CD_CDD,
  156. //
  157. CHUNK_DEFAULT_COUNT,
  158. CHUNK_CARTHW_ = CHUNK_CARTHW, // 64 (defined in PicoInt)
  159. } chunk_name_e;
  160. static const char * const chunk_names[CHUNK_DEFAULT_COUNT] = {
  161. "INVALID!",
  162. "M68K state",
  163. "RAM",
  164. "VRAM",
  165. "ZRAM",
  166. "CRAM", // 5
  167. "VSRAM",
  168. "emu state",
  169. "VIDEO",
  170. "Z80 state",
  171. "PSG", // 10
  172. "FM",
  173. // CD stuff
  174. "S68K state",
  175. "PRG_RAM",
  176. "WORD_RAM",
  177. "PCM_RAM", // 15
  178. "BRAM",
  179. "GATE ARRAY regs",
  180. "PCM state",
  181. "CDC",
  182. "CDD", // 20
  183. "SCD",
  184. "GFX chip",
  185. "MCD state",
  186. //
  187. "IO",
  188. "SMS state", // 25
  189. // 32x
  190. "MSH2",
  191. "MSH2 data",
  192. "MSH2 peri",
  193. "SSH2",
  194. "SSH2 data", // 30
  195. "SSH2 peri",
  196. "32X system regs",
  197. "M68K BIOS",
  198. "MSH2 BIOS",
  199. "SSH2 BIOS", // 35
  200. "SDRAM",
  201. "DRAM",
  202. "PAL",
  203. "events",
  204. };
  205. static int write_chunk(chunk_name_e name, int len, void *data, void *file)
  206. {
  207. size_t bwritten = 0;
  208. bwritten += areaWrite(&name, 1, 1, file);
  209. bwritten += areaWrite(&len, 1, 4, file);
  210. bwritten += areaWrite(data, 1, len, file);
  211. return (bwritten == len + 4 + 1);
  212. }
  213. #define CHUNK_LIMIT_W 18772 // sizeof(cdc)
  214. #define CHECKED_WRITE(name,len,data) { \
  215. if (PicoStateProgressCB && name < CHUNK_DEFAULT_COUNT && chunk_names[name]) { \
  216. strncpy(sbuff + 9, chunk_names[name], sizeof(sbuff) - 9); \
  217. PicoStateProgressCB(sbuff); \
  218. } \
  219. if (data == buf2 && len > CHUNK_LIMIT_W) \
  220. goto out; \
  221. if (!write_chunk(name, len, data, file)) \
  222. goto out; \
  223. }
  224. #define CHECKED_WRITE_BUFF(name,buff) { \
  225. if (PicoStateProgressCB && name < CHUNK_DEFAULT_COUNT && chunk_names[name]) { \
  226. strncpy(sbuff + 9, chunk_names[name], sizeof(sbuff) - 9); \
  227. PicoStateProgressCB(sbuff); \
  228. } \
  229. if (!write_chunk(name, sizeof(buff), &buff, file)) \
  230. goto out; \
  231. }
  232. static int state_save(void *file)
  233. {
  234. char sbuff[32] = "Saving.. ";
  235. unsigned char buff[0x60], buff_z80[Z80_STATE_SIZE];
  236. void *ym2612_regs = YM2612GetRegs();
  237. void *buf2 = NULL;
  238. int ver = 0x0191; // not really used..
  239. int retval = -1;
  240. int len;
  241. areaWrite("PicoSEXT", 1, 8, file);
  242. areaWrite(&ver, 1, 4, file);
  243. if (!(PicoAHW & PAHW_SMS)) {
  244. memset(buff, 0, sizeof(buff));
  245. SekPackCpu(buff, 0);
  246. CHECKED_WRITE_BUFF(CHUNK_M68K, buff);
  247. CHECKED_WRITE_BUFF(CHUNK_RAM, Pico.ram);
  248. CHECKED_WRITE_BUFF(CHUNK_VSRAM, Pico.vsram);
  249. CHECKED_WRITE_BUFF(CHUNK_IOPORTS, Pico.ioports);
  250. ym2612_pack_state();
  251. CHECKED_WRITE(CHUNK_FM, 0x200+4, ym2612_regs);
  252. }
  253. else {
  254. CHECKED_WRITE_BUFF(CHUNK_SMS, Pico.ms);
  255. }
  256. CHECKED_WRITE_BUFF(CHUNK_VRAM, Pico.vram);
  257. CHECKED_WRITE_BUFF(CHUNK_ZRAM, Pico.zram);
  258. CHECKED_WRITE_BUFF(CHUNK_CRAM, Pico.cram);
  259. CHECKED_WRITE_BUFF(CHUNK_MISC, Pico.m);
  260. CHECKED_WRITE_BUFF(CHUNK_VIDEO, Pico.video);
  261. z80_pack(buff_z80);
  262. CHECKED_WRITE_BUFF(CHUNK_Z80, buff_z80);
  263. CHECKED_WRITE(CHUNK_PSG, 28*4, sn76496_regs);
  264. if (PicoAHW & PAHW_MCD)
  265. {
  266. buf2 = malloc(CHUNK_LIMIT_W);
  267. if (buf2 == NULL)
  268. return -1;
  269. memset(buff, 0, sizeof(buff));
  270. SekPackCpu(buff, 1);
  271. if (Pico_mcd->s68k_regs[3] & 4) // 1M mode?
  272. wram_1M_to_2M(Pico_mcd->word_ram2M);
  273. memcpy(&Pico_mcd->m.hint_vector, Pico_mcd->bios + 0x72,
  274. sizeof(Pico_mcd->m.hint_vector));
  275. CHECKED_WRITE_BUFF(CHUNK_S68K, buff);
  276. CHECKED_WRITE_BUFF(CHUNK_PRG_RAM, Pico_mcd->prg_ram);
  277. CHECKED_WRITE_BUFF(CHUNK_WORD_RAM, Pico_mcd->word_ram2M); // in 2M format
  278. CHECKED_WRITE_BUFF(CHUNK_PCM_RAM, Pico_mcd->pcm_ram);
  279. CHECKED_WRITE_BUFF(CHUNK_BRAM, Pico_mcd->bram);
  280. CHECKED_WRITE_BUFF(CHUNK_GA_REGS, Pico_mcd->s68k_regs); // GA regs, not CPU regs
  281. CHECKED_WRITE_BUFF(CHUNK_PCM, Pico_mcd->pcm);
  282. CHECKED_WRITE_BUFF(CHUNK_MISC_CD, Pico_mcd->m);
  283. memset(buff, 0, 0x40);
  284. memcpy(buff, pcd_event_times, sizeof(pcd_event_times));
  285. CHECKED_WRITE(CHUNK_CD_EVT, 0x40, buff);
  286. len = gfx_context_save(buf2);
  287. CHECKED_WRITE(CHUNK_CD_GFX, len, buf2);
  288. len = cdc_context_save(buf2);
  289. CHECKED_WRITE(CHUNK_CD_CDC, len, buf2);
  290. len = cdd_context_save(buf2);
  291. CHECKED_WRITE(CHUNK_CD_CDD, len, buf2);
  292. if (Pico_mcd->s68k_regs[3] & 4) // convert back
  293. wram_2M_to_1M(Pico_mcd->word_ram2M);
  294. }
  295. #ifndef NO_32X
  296. if (PicoAHW & PAHW_32X)
  297. {
  298. unsigned char cpubuff[SH2_STATE_SIZE];
  299. memset(cpubuff, 0, sizeof(cpubuff));
  300. sh2_pack(&sh2s[0], cpubuff);
  301. CHECKED_WRITE_BUFF(CHUNK_MSH2, cpubuff);
  302. CHECKED_WRITE_BUFF(CHUNK_MSH2_DATA, sh2s[0].data_array);
  303. CHECKED_WRITE_BUFF(CHUNK_MSH2_PERI, sh2s[0].peri_regs);
  304. sh2_pack(&sh2s[1], cpubuff);
  305. CHECKED_WRITE_BUFF(CHUNK_SSH2, cpubuff);
  306. CHECKED_WRITE_BUFF(CHUNK_SSH2_DATA, sh2s[1].data_array);
  307. CHECKED_WRITE_BUFF(CHUNK_SSH2_PERI, sh2s[1].peri_regs);
  308. CHECKED_WRITE_BUFF(CHUNK_32XSYS, Pico32x);
  309. CHECKED_WRITE_BUFF(CHUNK_M68K_BIOS, Pico32xMem->m68k_rom);
  310. CHECKED_WRITE_BUFF(CHUNK_MSH2_BIOS, Pico32xMem->sh2_rom_m);
  311. CHECKED_WRITE_BUFF(CHUNK_SSH2_BIOS, Pico32xMem->sh2_rom_s);
  312. CHECKED_WRITE_BUFF(CHUNK_SDRAM, Pico32xMem->sdram);
  313. CHECKED_WRITE_BUFF(CHUNK_DRAM, Pico32xMem->dram);
  314. CHECKED_WRITE_BUFF(CHUNK_32XPAL, Pico32xMem->pal);
  315. memset(buff, 0, 0x40);
  316. memcpy(buff, p32x_event_times, sizeof(p32x_event_times));
  317. CHECKED_WRITE(CHUNK_32X_EVT, 0x40, buff);
  318. }
  319. #endif
  320. if (carthw_chunks != NULL)
  321. {
  322. carthw_state_chunk *chwc;
  323. if (PicoStateProgressCB)
  324. PicoStateProgressCB("Saving.. cart hw state");
  325. for (chwc = carthw_chunks; chwc->ptr != NULL; chwc++)
  326. CHECKED_WRITE(chwc->chunk, chwc->size, chwc->ptr);
  327. }
  328. retval = 0;
  329. out:
  330. if (buf2 != NULL)
  331. free(buf2);
  332. return retval;
  333. }
  334. static int g_read_offs = 0;
  335. #define R_ERROR_RETURN(error) \
  336. { \
  337. elprintf(EL_STATUS, "load_state @ %x: " error, g_read_offs); \
  338. goto out; \
  339. }
  340. // when is eof really set?
  341. #define CHECKED_READ(len,data) { \
  342. if (areaRead(data, 1, len, file) != len) { \
  343. if (len == 1 && areaEof(file)) goto readend; \
  344. R_ERROR_RETURN("areaRead: premature EOF\n"); \
  345. } \
  346. g_read_offs += len; \
  347. }
  348. #define CHECKED_READ2(len2,data) { \
  349. if (len2 != len) { \
  350. elprintf(EL_STATUS, "unexpected len %i, wanted %i (%s)", len, len2, #len2); \
  351. if (len > len2) R_ERROR_RETURN("failed."); \
  352. /* else read anyway and hope for the best.. */ \
  353. } \
  354. CHECKED_READ(len, data); \
  355. }
  356. #define CHECKED_READ_BUFF(buff) CHECKED_READ2(sizeof(buff), &buff);
  357. #define CHUNK_LIMIT_R 0x10960 // sizeof(old_cdc)
  358. #define CHECKED_READ_LIM(data) { \
  359. if (len > CHUNK_LIMIT_R) \
  360. R_ERROR_RETURN("chunk size over limit."); \
  361. CHECKED_READ(len, data); \
  362. }
  363. static int state_load(void *file)
  364. {
  365. unsigned char buff_m68k[0x60], buff_s68k[0x60];
  366. unsigned char buff_z80[Z80_STATE_SIZE];
  367. unsigned char buff_sh2[SH2_STATE_SIZE];
  368. unsigned char *buf = NULL;
  369. unsigned char chunk;
  370. void *ym2612_regs;
  371. int len_check;
  372. int retval = -1;
  373. char header[8];
  374. int ver, len;
  375. memset(buff_m68k, 0, sizeof(buff_m68k));
  376. memset(buff_s68k, 0, sizeof(buff_s68k));
  377. memset(buff_z80, 0, sizeof(buff_z80));
  378. buf = malloc(CHUNK_LIMIT_R);
  379. if (buf == NULL)
  380. return -1;
  381. g_read_offs = 0;
  382. CHECKED_READ(8, header);
  383. if (strncmp(header, "PicoSMCD", 8) && strncmp(header, "PicoSEXT", 8))
  384. R_ERROR_RETURN("bad header");
  385. CHECKED_READ(4, &ver);
  386. memset(pcd_event_times, 0, sizeof(pcd_event_times));
  387. memset(p32x_event_times, 0, sizeof(p32x_event_times));
  388. while (!areaEof(file))
  389. {
  390. len_check = 0;
  391. CHECKED_READ(1, &chunk);
  392. CHECKED_READ(4, &len);
  393. if (len < 0 || len > 1024*512) R_ERROR_RETURN("bad length");
  394. if (CHUNK_S68K <= chunk && chunk <= CHUNK_MISC_CD && !(PicoAHW & PAHW_MCD))
  395. R_ERROR_RETURN("cd chunk in non CD state?");
  396. if (CHUNK_32X_FIRST <= chunk && chunk <= CHUNK_32X_LAST && !(PicoAHW & PAHW_32X))
  397. Pico32xStartup();
  398. switch (chunk)
  399. {
  400. case CHUNK_M68K:
  401. CHECKED_READ_BUFF(buff_m68k);
  402. break;
  403. case CHUNK_Z80:
  404. CHECKED_READ_BUFF(buff_z80);
  405. break;
  406. case CHUNK_RAM: CHECKED_READ_BUFF(Pico.ram); break;
  407. case CHUNK_VRAM: CHECKED_READ_BUFF(Pico.vram); break;
  408. case CHUNK_ZRAM: CHECKED_READ_BUFF(Pico.zram); break;
  409. case CHUNK_CRAM: CHECKED_READ_BUFF(Pico.cram); break;
  410. case CHUNK_VSRAM: CHECKED_READ_BUFF(Pico.vsram); break;
  411. case CHUNK_MISC: CHECKED_READ_BUFF(Pico.m); break;
  412. case CHUNK_VIDEO: CHECKED_READ_BUFF(Pico.video); break;
  413. case CHUNK_IOPORTS: CHECKED_READ_BUFF(Pico.ioports); break;
  414. case CHUNK_PSG: CHECKED_READ2(28*4, sn76496_regs); break;
  415. case CHUNK_FM:
  416. ym2612_regs = YM2612GetRegs();
  417. CHECKED_READ2(0x200+4, ym2612_regs);
  418. ym2612_unpack_state();
  419. break;
  420. case CHUNK_SMS:
  421. CHECKED_READ_BUFF(Pico.ms);
  422. break;
  423. // cd stuff
  424. case CHUNK_S68K:
  425. CHECKED_READ_BUFF(buff_s68k);
  426. break;
  427. case CHUNK_PRG_RAM: CHECKED_READ_BUFF(Pico_mcd->prg_ram); break;
  428. case CHUNK_WORD_RAM: CHECKED_READ_BUFF(Pico_mcd->word_ram2M); break;
  429. case CHUNK_PCM_RAM: CHECKED_READ_BUFF(Pico_mcd->pcm_ram); break;
  430. case CHUNK_BRAM: CHECKED_READ_BUFF(Pico_mcd->bram); break;
  431. case CHUNK_GA_REGS: CHECKED_READ_BUFF(Pico_mcd->s68k_regs); break;
  432. case CHUNK_PCM: CHECKED_READ_BUFF(Pico_mcd->pcm); break;
  433. case CHUNK_MISC_CD: CHECKED_READ_BUFF(Pico_mcd->m); break;
  434. case CHUNK_CD_EVT:
  435. CHECKED_READ2(0x40, buf);
  436. memcpy(pcd_event_times, buf, sizeof(pcd_event_times));
  437. break;
  438. case CHUNK_CD_GFX:
  439. CHECKED_READ_LIM(buf);
  440. len_check = gfx_context_load(buf);
  441. break;
  442. case CHUNK_CD_CDC:
  443. CHECKED_READ_LIM(buf);
  444. len_check = cdc_context_load(buf);
  445. break;
  446. case CHUNK_CD_CDD:
  447. CHECKED_READ_LIM(buf);
  448. len_check = cdd_context_load(buf);
  449. break;
  450. // old, to be removed:
  451. case CHUNK_CDC:
  452. CHECKED_READ_LIM(buf);
  453. cdc_context_load_old(buf);
  454. break;
  455. case CHUNK_SCD:
  456. CHECKED_READ_LIM(buf);
  457. cdd_context_load_old(buf);
  458. break;
  459. // 32x stuff
  460. #ifndef NO_32X
  461. case CHUNK_MSH2:
  462. CHECKED_READ_BUFF(buff_sh2);
  463. sh2_unpack(&sh2s[0], buff_sh2);
  464. break;
  465. case CHUNK_SSH2:
  466. CHECKED_READ_BUFF(buff_sh2);
  467. sh2_unpack(&sh2s[1], buff_sh2);
  468. break;
  469. case CHUNK_MSH2_DATA: CHECKED_READ_BUFF(sh2s[0].data_array); break;
  470. case CHUNK_MSH2_PERI: CHECKED_READ_BUFF(sh2s[0].peri_regs); break;
  471. case CHUNK_SSH2_DATA: CHECKED_READ_BUFF(sh2s[1].data_array); break;
  472. case CHUNK_SSH2_PERI: CHECKED_READ_BUFF(sh2s[1].peri_regs); break;
  473. case CHUNK_32XSYS: CHECKED_READ_BUFF(Pico32x); break;
  474. case CHUNK_M68K_BIOS: CHECKED_READ_BUFF(Pico32xMem->m68k_rom); break;
  475. case CHUNK_MSH2_BIOS: CHECKED_READ_BUFF(Pico32xMem->sh2_rom_m); break;
  476. case CHUNK_SSH2_BIOS: CHECKED_READ_BUFF(Pico32xMem->sh2_rom_s); break;
  477. case CHUNK_SDRAM: CHECKED_READ_BUFF(Pico32xMem->sdram); break;
  478. case CHUNK_DRAM: CHECKED_READ_BUFF(Pico32xMem->dram); break;
  479. case CHUNK_32XPAL: CHECKED_READ_BUFF(Pico32xMem->pal); break;
  480. case CHUNK_32X_EVT:
  481. CHECKED_READ2(0x40, buf);
  482. memcpy(p32x_event_times, buf, sizeof(p32x_event_times));
  483. break;
  484. #endif
  485. default:
  486. if (carthw_chunks != NULL)
  487. {
  488. carthw_state_chunk *chwc;
  489. for (chwc = carthw_chunks; chwc->ptr != NULL; chwc++) {
  490. if (chwc->chunk == chunk) {
  491. CHECKED_READ2(chwc->size, chwc->ptr);
  492. goto breakswitch;
  493. }
  494. }
  495. }
  496. elprintf(EL_STATUS, "load_state: skipping unknown chunk %i of size %i", chunk, len);
  497. areaSeek(file, len, SEEK_CUR);
  498. break;
  499. }
  500. breakswitch:
  501. if (len_check != 0 && len_check != len)
  502. elprintf(EL_STATUS, "load_state: chunk %d has bad len %d/%d",
  503. len, len_check);
  504. }
  505. readend:
  506. if (PicoAHW & PAHW_SMS)
  507. PicoStateLoadedMS();
  508. if (PicoAHW & PAHW_32X)
  509. Pico32xStateLoaded(1);
  510. // must unpack 68k and z80 after banks are set up
  511. if (!(PicoAHW & PAHW_SMS))
  512. SekUnpackCpu(buff_m68k, 0);
  513. if (PicoAHW & PAHW_MCD)
  514. SekUnpackCpu(buff_s68k, 1);
  515. z80_unpack(buff_z80);
  516. // due to dep from 68k cycles..
  517. SekCycleAim = SekCycleCnt;
  518. if (PicoAHW & PAHW_32X)
  519. Pico32xStateLoaded(0);
  520. if (PicoAHW & PAHW_MCD)
  521. {
  522. SekCycleAimS68k = SekCycleCntS68k;
  523. pcd_state_loaded();
  524. }
  525. retval = 0;
  526. out:
  527. free(buf);
  528. return retval;
  529. }
  530. static int state_load_gfx(void *file)
  531. {
  532. int ver, len, found = 0, to_find = 4;
  533. char buff[8];
  534. if (PicoAHW & PAHW_32X)
  535. to_find += 2;
  536. g_read_offs = 0;
  537. CHECKED_READ(8, buff);
  538. if (strncmp((char *)buff, "PicoSMCD", 8) && strncmp((char *)buff, "PicoSEXT", 8))
  539. R_ERROR_RETURN("bad header");
  540. CHECKED_READ(4, &ver);
  541. while (!areaEof(file) && found < to_find)
  542. {
  543. CHECKED_READ(1, buff);
  544. CHECKED_READ(4, &len);
  545. if (len < 0 || len > 1024*512) R_ERROR_RETURN("bad length");
  546. if (buff[0] > CHUNK_FM && buff[0] <= CHUNK_MISC_CD && !(PicoAHW & PAHW_MCD))
  547. R_ERROR_RETURN("cd chunk in non CD state?");
  548. switch (buff[0])
  549. {
  550. case CHUNK_VRAM: CHECKED_READ_BUFF(Pico.vram); found++; break;
  551. case CHUNK_CRAM: CHECKED_READ_BUFF(Pico.cram); found++; break;
  552. case CHUNK_VSRAM: CHECKED_READ_BUFF(Pico.vsram); found++; break;
  553. case CHUNK_VIDEO: CHECKED_READ_BUFF(Pico.video); found++; break;
  554. #ifndef NO_32X
  555. case CHUNK_DRAM:
  556. if (Pico32xMem != NULL)
  557. CHECKED_READ_BUFF(Pico32xMem->dram);
  558. break;
  559. case CHUNK_32XPAL:
  560. if (Pico32xMem != NULL)
  561. CHECKED_READ_BUFF(Pico32xMem->pal);
  562. Pico32x.dirty_pal = 1;
  563. break;
  564. case CHUNK_32XSYS:
  565. CHECKED_READ_BUFF(Pico32x);
  566. break;
  567. #endif
  568. default:
  569. areaSeek(file, len, SEEK_CUR);
  570. break;
  571. }
  572. }
  573. out:
  574. readend:
  575. return 0;
  576. }
  577. static int pico_state_internal(void *afile, int is_save)
  578. {
  579. int ret;
  580. if (is_save)
  581. ret = state_save(afile);
  582. else {
  583. ret = state_load(afile);
  584. if (ret != 0) {
  585. areaSeek(afile, 0, SEEK_SET);
  586. ret = state_load_legacy(afile);
  587. }
  588. if (PicoLoadStateHook != NULL)
  589. PicoLoadStateHook();
  590. Pico.m.dirtyPal = 1;
  591. }
  592. return ret;
  593. }
  594. int PicoState(const char *fname, int is_save)
  595. {
  596. void *afile = NULL;
  597. int ret;
  598. afile = open_save_file(fname, is_save);
  599. if (afile == NULL)
  600. return -1;
  601. ret = pico_state_internal(afile, is_save);
  602. areaClose(afile);
  603. return ret;
  604. }
  605. int PicoStateFP(void *afile, int is_save,
  606. arearw *read, arearw *write, areaeof *eof, areaseek *seek)
  607. {
  608. areaRead = read;
  609. areaWrite = write;
  610. areaEof = eof;
  611. areaSeek = seek;
  612. areaClose = NULL;
  613. return pico_state_internal(afile, is_save);
  614. }
  615. int PicoStateLoadGfx(const char *fname)
  616. {
  617. void *afile;
  618. int ret;
  619. afile = open_save_file(fname, 0);
  620. if (afile == NULL)
  621. return -1;
  622. ret = state_load_gfx(afile);
  623. if (ret != 0) {
  624. // assume legacy
  625. areaSeek(afile, 0x10020, SEEK_SET); // skip header and RAM
  626. areaRead(Pico.vram, 1, sizeof(Pico.vram), afile);
  627. areaSeek(afile, 0x2000, SEEK_CUR);
  628. areaRead(Pico.cram, 1, sizeof(Pico.cram), afile);
  629. areaRead(Pico.vsram, 1, sizeof(Pico.vsram), afile);
  630. areaSeek(afile, 0x221a0, SEEK_SET);
  631. areaRead(&Pico.video, 1, sizeof(Pico.video), afile);
  632. }
  633. areaClose(afile);
  634. return 0;
  635. }
  636. // tmp state
  637. struct PicoTmp
  638. {
  639. unsigned short vram[0x8000];
  640. unsigned short cram[0x40];
  641. unsigned short vsram[0x40];
  642. //struct PicoMisc m;
  643. struct PicoVideo video;
  644. struct {
  645. struct Pico32x p32x;
  646. unsigned short dram[2][0x20000/2];
  647. unsigned short pal[0x100];
  648. } t32x;
  649. };
  650. // returns data ptr to free() or PicoTmpStateRestore()
  651. void *PicoTmpStateSave(void)
  652. {
  653. // gfx only for now
  654. struct PicoTmp *t = malloc(sizeof(*t));
  655. if (t == NULL)
  656. return NULL;
  657. memcpy(t->vram, Pico.vram, sizeof(Pico.vram));
  658. memcpy(t->cram, Pico.cram, sizeof(Pico.cram));
  659. memcpy(t->vsram, Pico.vsram, sizeof(Pico.vsram));
  660. memcpy(&t->video, &Pico.video, sizeof(Pico.video));
  661. #ifndef NO_32X
  662. if (PicoAHW & PAHW_32X) {
  663. memcpy(&t->t32x.p32x, &Pico32x, sizeof(Pico32x));
  664. memcpy(t->t32x.dram, Pico32xMem->dram, sizeof(Pico32xMem->dram));
  665. memcpy(t->t32x.pal, Pico32xMem->pal, sizeof(Pico32xMem->pal));
  666. }
  667. #endif
  668. return t;
  669. }
  670. void PicoTmpStateRestore(void *data)
  671. {
  672. struct PicoTmp *t = data;
  673. if (t == NULL)
  674. return;
  675. memcpy(Pico.vram, t->vram, sizeof(Pico.vram));
  676. memcpy(Pico.cram, t->cram, sizeof(Pico.cram));
  677. memcpy(Pico.vsram, t->vsram, sizeof(Pico.vsram));
  678. memcpy(&Pico.video, &t->video, sizeof(Pico.video));
  679. Pico.m.dirtyPal = 1;
  680. #ifndef NO_32X
  681. if (PicoAHW & PAHW_32X) {
  682. memcpy(&Pico32x, &t->t32x.p32x, sizeof(Pico32x));
  683. memcpy(Pico32xMem->dram, t->t32x.dram, sizeof(Pico32xMem->dram));
  684. memcpy(Pico32xMem->pal, t->t32x.pal, sizeof(Pico32xMem->pal));
  685. Pico32x.dirty_pal = 1;
  686. }
  687. #endif
  688. }
  689. // vim:shiftwidth=2:ts=2:expandtab