state.c 20 KB

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