state.c 21 KB

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