state.c 19 KB

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