state.c 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758
  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. memset(buff, 0, sizeof(buff));
  208. SekPackCpu(buff, 0);
  209. CHECKED_WRITE_BUFF(CHUNK_M68K, buff);
  210. CHECKED_WRITE_BUFF(CHUNK_RAM, PicoMem.ram);
  211. CHECKED_WRITE_BUFF(CHUNK_VSRAM, PicoMem.vsram);
  212. CHECKED_WRITE_BUFF(CHUNK_IOPORTS, PicoMem.ioports);
  213. ym2612_pack_state();
  214. CHECKED_WRITE(CHUNK_FM, 0x200+4, ym2612_regs);
  215. }
  216. else {
  217. CHECKED_WRITE_BUFF(CHUNK_SMS, Pico.ms);
  218. }
  219. CHECKED_WRITE_BUFF(CHUNK_VRAM, PicoMem.vram);
  220. CHECKED_WRITE_BUFF(CHUNK_ZRAM, PicoMem.zram);
  221. CHECKED_WRITE_BUFF(CHUNK_CRAM, PicoMem.cram);
  222. CHECKED_WRITE_BUFF(CHUNK_MISC, Pico.m);
  223. CHECKED_WRITE_BUFF(CHUNK_VIDEO, Pico.video);
  224. z80_pack(buff_z80);
  225. CHECKED_WRITE_BUFF(CHUNK_Z80, buff_z80);
  226. CHECKED_WRITE(CHUNK_PSG, 28*4, sn76496_regs);
  227. if (PicoIn.AHW & PAHW_MCD)
  228. {
  229. buf2 = malloc(CHUNK_LIMIT_W);
  230. if (buf2 == NULL)
  231. return -1;
  232. memset(buff, 0, sizeof(buff));
  233. SekPackCpu(buff, 1);
  234. if (Pico_mcd->s68k_regs[3] & 4) // 1M mode?
  235. wram_1M_to_2M(Pico_mcd->word_ram2M);
  236. memcpy(&Pico_mcd->m.hint_vector, Pico_mcd->bios + 0x72,
  237. sizeof(Pico_mcd->m.hint_vector));
  238. CHECKED_WRITE_BUFF(CHUNK_S68K, buff);
  239. CHECKED_WRITE_BUFF(CHUNK_PRG_RAM, Pico_mcd->prg_ram);
  240. CHECKED_WRITE_BUFF(CHUNK_WORD_RAM, Pico_mcd->word_ram2M); // in 2M format
  241. CHECKED_WRITE_BUFF(CHUNK_PCM_RAM, Pico_mcd->pcm_ram);
  242. CHECKED_WRITE_BUFF(CHUNK_BRAM, Pico_mcd->bram);
  243. CHECKED_WRITE_BUFF(CHUNK_GA_REGS, Pico_mcd->s68k_regs); // GA regs, not CPU regs
  244. CHECKED_WRITE_BUFF(CHUNK_PCM, Pico_mcd->pcm);
  245. CHECKED_WRITE_BUFF(CHUNK_MISC_CD, Pico_mcd->m);
  246. memset(buff, 0, 0x40);
  247. memcpy(buff, pcd_event_times, sizeof(pcd_event_times));
  248. CHECKED_WRITE(CHUNK_CD_EVT, 0x40, buff);
  249. len = gfx_context_save(buf2);
  250. CHECKED_WRITE(CHUNK_CD_GFX, len, buf2);
  251. len = cdc_context_save(buf2);
  252. CHECKED_WRITE(CHUNK_CD_CDC, len, buf2);
  253. len = cdd_context_save(buf2);
  254. CHECKED_WRITE(CHUNK_CD_CDD, len, buf2);
  255. if (Pico_mcd->s68k_regs[3] & 4) // convert back
  256. wram_2M_to_1M(Pico_mcd->word_ram2M);
  257. }
  258. #ifndef NO_32X
  259. if (PicoIn.AHW & PAHW_32X)
  260. {
  261. unsigned char cpubuff[SH2_STATE_SIZE];
  262. memset(cpubuff, 0, sizeof(cpubuff));
  263. sh2_pack(&sh2s[0], cpubuff);
  264. CHECKED_WRITE_BUFF(CHUNK_MSH2, cpubuff);
  265. CHECKED_WRITE_BUFF(CHUNK_MSH2_DATA, sh2s[0].data_array);
  266. CHECKED_WRITE_BUFF(CHUNK_MSH2_PERI, sh2s[0].peri_regs);
  267. sh2_pack(&sh2s[1], cpubuff);
  268. CHECKED_WRITE_BUFF(CHUNK_SSH2, cpubuff);
  269. CHECKED_WRITE_BUFF(CHUNK_SSH2_DATA, sh2s[1].data_array);
  270. CHECKED_WRITE_BUFF(CHUNK_SSH2_PERI, sh2s[1].peri_regs);
  271. CHECKED_WRITE_BUFF(CHUNK_32XSYS, Pico32x);
  272. CHECKED_WRITE_BUFF(CHUNK_M68K_BIOS, Pico32xMem->m68k_rom);
  273. CHECKED_WRITE_BUFF(CHUNK_MSH2_BIOS, Pico32xMem->sh2_rom_m);
  274. CHECKED_WRITE_BUFF(CHUNK_SSH2_BIOS, Pico32xMem->sh2_rom_s);
  275. CHECKED_WRITE_BUFF(CHUNK_SDRAM, Pico32xMem->sdram);
  276. CHECKED_WRITE_BUFF(CHUNK_DRAM, Pico32xMem->dram);
  277. CHECKED_WRITE_BUFF(CHUNK_32XPAL, Pico32xMem->pal);
  278. memset(buff, 0, 0x40);
  279. memcpy(buff, p32x_event_times, sizeof(p32x_event_times));
  280. CHECKED_WRITE(CHUNK_32X_EVT, 0x40, buff);
  281. }
  282. #endif
  283. if (carthw_chunks != NULL)
  284. {
  285. carthw_state_chunk *chwc;
  286. if (PicoStateProgressCB)
  287. PicoStateProgressCB("Saving.. cart hw state");
  288. for (chwc = carthw_chunks; chwc->ptr != NULL; chwc++)
  289. CHECKED_WRITE(chwc->chunk, chwc->size, chwc->ptr);
  290. }
  291. retval = 0;
  292. out:
  293. if (buf2 != NULL)
  294. free(buf2);
  295. return retval;
  296. }
  297. static int g_read_offs = 0;
  298. #define R_ERROR_RETURN(error) \
  299. { \
  300. elprintf(EL_STATUS, "load_state @ %x: " error, g_read_offs); \
  301. goto out; \
  302. }
  303. // when is eof really set?
  304. #define CHECKED_READ(len,data) { \
  305. if (areaRead(data, 1, len, file) != len) { \
  306. if (len == 1 && areaEof(file)) goto readend; \
  307. R_ERROR_RETURN("areaRead: premature EOF\n"); \
  308. } \
  309. g_read_offs += len; \
  310. }
  311. #define CHECKED_READ2(len2,data) { \
  312. if (len2 != len) { \
  313. elprintf(EL_STATUS, "unexpected len %i, wanted %i (%s)", len, len2, #len2); \
  314. if (len > len2) R_ERROR_RETURN("failed."); \
  315. /* else read anyway and hope for the best.. */ \
  316. } \
  317. CHECKED_READ(len, data); \
  318. }
  319. #define CHECKED_READ_BUFF(buff) CHECKED_READ2(sizeof(buff), &buff);
  320. #define CHUNK_LIMIT_R 0x10960 // sizeof(old_cdc)
  321. #define CHECKED_READ_LIM(data) { \
  322. if (len > CHUNK_LIMIT_R) \
  323. R_ERROR_RETURN("chunk size over limit."); \
  324. CHECKED_READ(len, data); \
  325. }
  326. static int state_load(void *file)
  327. {
  328. unsigned char buff_m68k[0x60], buff_s68k[0x60];
  329. unsigned char buff_z80[Z80_STATE_SIZE];
  330. unsigned char buff_sh2[SH2_STATE_SIZE];
  331. unsigned char *buf = NULL;
  332. unsigned char chunk;
  333. void *ym2612_regs;
  334. int len_check;
  335. int retval = -1;
  336. char header[8];
  337. int ver, len;
  338. memset(buff_m68k, 0, sizeof(buff_m68k));
  339. memset(buff_s68k, 0, sizeof(buff_s68k));
  340. memset(buff_z80, 0, sizeof(buff_z80));
  341. buf = malloc(CHUNK_LIMIT_R);
  342. if (buf == NULL)
  343. return -1;
  344. g_read_offs = 0;
  345. CHECKED_READ(8, header);
  346. if (strncmp(header, "PicoSMCD", 8) && strncmp(header, "PicoSEXT", 8))
  347. R_ERROR_RETURN("bad header");
  348. CHECKED_READ(4, &ver);
  349. memset(pcd_event_times, 0, sizeof(pcd_event_times));
  350. memset(p32x_event_times, 0, sizeof(p32x_event_times));
  351. while (!areaEof(file))
  352. {
  353. len_check = 0;
  354. CHECKED_READ(1, &chunk);
  355. CHECKED_READ(4, &len);
  356. if (len < 0 || len > 1024*512) R_ERROR_RETURN("bad length");
  357. if (CHUNK_S68K <= chunk && chunk <= CHUNK_MISC_CD && !(PicoIn.AHW & PAHW_MCD))
  358. R_ERROR_RETURN("cd chunk in non CD state?");
  359. if (CHUNK_32X_FIRST <= chunk && chunk <= CHUNK_32X_LAST && !(PicoIn.AHW & PAHW_32X))
  360. Pico32xStartup();
  361. switch (chunk)
  362. {
  363. case CHUNK_M68K:
  364. CHECKED_READ_BUFF(buff_m68k);
  365. break;
  366. case CHUNK_Z80:
  367. CHECKED_READ_BUFF(buff_z80);
  368. break;
  369. case CHUNK_RAM: CHECKED_READ_BUFF(PicoMem.ram); break;
  370. case CHUNK_VRAM: CHECKED_READ_BUFF(PicoMem.vram); break;
  371. case CHUNK_ZRAM: CHECKED_READ_BUFF(PicoMem.zram); break;
  372. case CHUNK_CRAM: CHECKED_READ_BUFF(PicoMem.cram); break;
  373. case CHUNK_VSRAM: CHECKED_READ_BUFF(PicoMem.vsram); break;
  374. case CHUNK_MISC: CHECKED_READ_BUFF(Pico.m); break;
  375. case CHUNK_VIDEO: CHECKED_READ_BUFF(Pico.video); break;
  376. case CHUNK_IOPORTS: CHECKED_READ_BUFF(PicoMem.ioports); break;
  377. case CHUNK_PSG: CHECKED_READ2(28*4, sn76496_regs); break;
  378. case CHUNK_FM:
  379. ym2612_regs = YM2612GetRegs();
  380. CHECKED_READ2(0x200+4, ym2612_regs);
  381. ym2612_unpack_state();
  382. break;
  383. case CHUNK_SMS:
  384. CHECKED_READ_BUFF(Pico.ms);
  385. break;
  386. // cd stuff
  387. case CHUNK_S68K:
  388. CHECKED_READ_BUFF(buff_s68k);
  389. break;
  390. case CHUNK_PRG_RAM: CHECKED_READ_BUFF(Pico_mcd->prg_ram); break;
  391. case CHUNK_WORD_RAM: CHECKED_READ_BUFF(Pico_mcd->word_ram2M); break;
  392. case CHUNK_PCM_RAM: CHECKED_READ_BUFF(Pico_mcd->pcm_ram); break;
  393. case CHUNK_BRAM: CHECKED_READ_BUFF(Pico_mcd->bram); break;
  394. case CHUNK_GA_REGS: CHECKED_READ_BUFF(Pico_mcd->s68k_regs); break;
  395. case CHUNK_PCM: CHECKED_READ_BUFF(Pico_mcd->pcm); break;
  396. case CHUNK_MISC_CD: CHECKED_READ_BUFF(Pico_mcd->m); break;
  397. case CHUNK_CD_EVT:
  398. CHECKED_READ2(0x40, buf);
  399. memcpy(pcd_event_times, buf, sizeof(pcd_event_times));
  400. break;
  401. case CHUNK_CD_GFX:
  402. CHECKED_READ_LIM(buf);
  403. len_check = gfx_context_load(buf);
  404. break;
  405. case CHUNK_CD_CDC:
  406. CHECKED_READ_LIM(buf);
  407. len_check = cdc_context_load(buf);
  408. break;
  409. case CHUNK_CD_CDD:
  410. CHECKED_READ_LIM(buf);
  411. len_check = cdd_context_load(buf);
  412. break;
  413. // old, to be removed:
  414. case CHUNK_CDC:
  415. CHECKED_READ_LIM(buf);
  416. cdc_context_load_old(buf);
  417. break;
  418. case CHUNK_SCD:
  419. CHECKED_READ_LIM(buf);
  420. cdd_context_load_old(buf);
  421. break;
  422. // 32x stuff
  423. #ifndef NO_32X
  424. case CHUNK_MSH2:
  425. CHECKED_READ_BUFF(buff_sh2);
  426. sh2_unpack(&sh2s[0], buff_sh2);
  427. break;
  428. case CHUNK_SSH2:
  429. CHECKED_READ_BUFF(buff_sh2);
  430. sh2_unpack(&sh2s[1], buff_sh2);
  431. break;
  432. case CHUNK_MSH2_DATA: CHECKED_READ_BUFF(sh2s[0].data_array); break;
  433. case CHUNK_MSH2_PERI: CHECKED_READ_BUFF(sh2s[0].peri_regs); break;
  434. case CHUNK_SSH2_DATA: CHECKED_READ_BUFF(sh2s[1].data_array); break;
  435. case CHUNK_SSH2_PERI: CHECKED_READ_BUFF(sh2s[1].peri_regs); break;
  436. case CHUNK_32XSYS: CHECKED_READ_BUFF(Pico32x); break;
  437. case CHUNK_M68K_BIOS: CHECKED_READ_BUFF(Pico32xMem->m68k_rom); break;
  438. case CHUNK_MSH2_BIOS: CHECKED_READ_BUFF(Pico32xMem->sh2_rom_m); break;
  439. case CHUNK_SSH2_BIOS: CHECKED_READ_BUFF(Pico32xMem->sh2_rom_s); break;
  440. case CHUNK_SDRAM: CHECKED_READ_BUFF(Pico32xMem->sdram); break;
  441. case CHUNK_DRAM: CHECKED_READ_BUFF(Pico32xMem->dram); break;
  442. case CHUNK_32XPAL: CHECKED_READ_BUFF(Pico32xMem->pal); break;
  443. case CHUNK_32X_EVT:
  444. CHECKED_READ2(0x40, buf);
  445. memcpy(p32x_event_times, buf, sizeof(p32x_event_times));
  446. break;
  447. #endif
  448. default:
  449. if (carthw_chunks != NULL)
  450. {
  451. carthw_state_chunk *chwc;
  452. for (chwc = carthw_chunks; chwc->ptr != NULL; chwc++) {
  453. if (chwc->chunk == chunk) {
  454. CHECKED_READ2(chwc->size, chwc->ptr);
  455. goto breakswitch;
  456. }
  457. }
  458. }
  459. elprintf(EL_STATUS, "load_state: skipping unknown chunk %i of size %i", chunk, len);
  460. areaSeek(file, len, SEEK_CUR);
  461. break;
  462. }
  463. breakswitch:
  464. if (len_check != 0 && len_check != len)
  465. elprintf(EL_STATUS, "load_state: chunk %d has bad len %d/%d",
  466. len, len_check);
  467. }
  468. readend:
  469. if (PicoIn.AHW & PAHW_SMS)
  470. PicoStateLoadedMS();
  471. if (PicoIn.AHW & PAHW_32X)
  472. Pico32xStateLoaded(1);
  473. if (PicoLoadStateHook != NULL)
  474. PicoLoadStateHook();
  475. // must unpack 68k and z80 after banks are set up
  476. if (!(PicoIn.AHW & PAHW_SMS))
  477. SekUnpackCpu(buff_m68k, 0);
  478. if (PicoIn.AHW & PAHW_MCD)
  479. SekUnpackCpu(buff_s68k, 1);
  480. z80_unpack(buff_z80);
  481. // due to dep from 68k cycles..
  482. Pico.t.m68c_aim = Pico.t.m68c_cnt;
  483. if (PicoIn.AHW & PAHW_32X)
  484. Pico32xStateLoaded(0);
  485. if (PicoIn.AHW & PAHW_MCD)
  486. {
  487. SekCycleAimS68k = SekCycleCntS68k;
  488. pcd_state_loaded();
  489. }
  490. Pico.m.dirtyPal = 1;
  491. Pico.video.status &= ~(SR_VB | SR_F);
  492. Pico.video.status |= ((Pico.video.reg[1] >> 3) ^ SR_VB) & SR_VB;
  493. Pico.video.status |= (Pico.video.pending_ints << 2) & SR_F;
  494. retval = 0;
  495. out:
  496. free(buf);
  497. return retval;
  498. }
  499. static int state_load_gfx(void *file)
  500. {
  501. int ver, len, found = 0, to_find = 4;
  502. char buff[8];
  503. if (PicoIn.AHW & PAHW_32X)
  504. to_find += 2;
  505. g_read_offs = 0;
  506. CHECKED_READ(8, buff);
  507. if (strncmp((char *)buff, "PicoSMCD", 8) && strncmp((char *)buff, "PicoSEXT", 8))
  508. R_ERROR_RETURN("bad header");
  509. CHECKED_READ(4, &ver);
  510. while (!areaEof(file) && found < to_find)
  511. {
  512. CHECKED_READ(1, buff);
  513. CHECKED_READ(4, &len);
  514. if (len < 0 || len > 1024*512) R_ERROR_RETURN("bad length");
  515. if (buff[0] > CHUNK_FM && buff[0] <= CHUNK_MISC_CD && !(PicoIn.AHW & PAHW_MCD))
  516. R_ERROR_RETURN("cd chunk in non CD state?");
  517. switch (buff[0])
  518. {
  519. case CHUNK_VRAM: CHECKED_READ_BUFF(PicoMem.vram); found++; break;
  520. case CHUNK_CRAM: CHECKED_READ_BUFF(PicoMem.cram); found++; break;
  521. case CHUNK_VSRAM: CHECKED_READ_BUFF(PicoMem.vsram); found++; break;
  522. case CHUNK_VIDEO: CHECKED_READ_BUFF(Pico.video); found++; break;
  523. #ifndef NO_32X
  524. case CHUNK_DRAM:
  525. if (Pico32xMem != NULL)
  526. CHECKED_READ_BUFF(Pico32xMem->dram);
  527. break;
  528. case CHUNK_32XPAL:
  529. if (Pico32xMem != NULL)
  530. CHECKED_READ_BUFF(Pico32xMem->pal);
  531. Pico32x.dirty_pal = 1;
  532. break;
  533. case CHUNK_32XSYS:
  534. CHECKED_READ_BUFF(Pico32x);
  535. break;
  536. #endif
  537. default:
  538. areaSeek(file, len, SEEK_CUR);
  539. break;
  540. }
  541. }
  542. out:
  543. readend:
  544. return 0;
  545. }
  546. static int pico_state_internal(void *afile, int is_save)
  547. {
  548. int ret;
  549. if (is_save)
  550. ret = state_save(afile);
  551. else
  552. ret = state_load(afile);
  553. return ret;
  554. }
  555. int PicoState(const char *fname, int is_save)
  556. {
  557. void *afile = NULL;
  558. int ret;
  559. afile = open_save_file(fname, is_save);
  560. if (afile == NULL)
  561. return -1;
  562. ret = pico_state_internal(afile, is_save);
  563. areaClose(afile);
  564. return ret;
  565. }
  566. int PicoStateFP(void *afile, int is_save,
  567. arearw *read, arearw *write, areaeof *eof, areaseek *seek)
  568. {
  569. areaRead = read;
  570. areaWrite = write;
  571. areaEof = eof;
  572. areaSeek = seek;
  573. areaClose = NULL;
  574. return pico_state_internal(afile, is_save);
  575. }
  576. int PicoStateLoadGfx(const char *fname)
  577. {
  578. void *afile;
  579. int ret;
  580. afile = open_save_file(fname, 0);
  581. if (afile == NULL)
  582. return -1;
  583. ret = state_load_gfx(afile);
  584. if (ret != 0) {
  585. // assume legacy
  586. areaSeek(afile, 0x10020, SEEK_SET); // skip header and RAM
  587. areaRead(PicoMem.vram, 1, sizeof(PicoMem.vram), afile);
  588. areaSeek(afile, 0x2000, SEEK_CUR);
  589. areaRead(PicoMem.cram, 1, sizeof(PicoMem.cram), afile);
  590. areaRead(PicoMem.vsram, 1, sizeof(PicoMem.vsram), afile);
  591. areaSeek(afile, 0x221a0, SEEK_SET);
  592. areaRead(&Pico.video, 1, sizeof(Pico.video), afile);
  593. }
  594. areaClose(afile);
  595. return 0;
  596. }
  597. // tmp state
  598. struct PicoTmp
  599. {
  600. unsigned short vram[0x8000];
  601. unsigned short cram[0x40];
  602. unsigned short vsram[0x40];
  603. //struct PicoMisc m;
  604. struct PicoVideo video;
  605. struct {
  606. struct Pico32x p32x;
  607. unsigned short dram[2][0x20000/2];
  608. unsigned short pal[0x100];
  609. } t32x;
  610. };
  611. // returns data ptr to free() or PicoTmpStateRestore()
  612. void *PicoTmpStateSave(void)
  613. {
  614. // gfx only for now
  615. struct PicoTmp *t = malloc(sizeof(*t));
  616. if (t == NULL)
  617. return NULL;
  618. memcpy(t->vram, PicoMem.vram, sizeof(PicoMem.vram));
  619. memcpy(t->cram, PicoMem.cram, sizeof(PicoMem.cram));
  620. memcpy(t->vsram, PicoMem.vsram, sizeof(PicoMem.vsram));
  621. memcpy(&t->video, &Pico.video, sizeof(Pico.video));
  622. #ifndef NO_32X
  623. if (PicoIn.AHW & PAHW_32X) {
  624. memcpy(&t->t32x.p32x, &Pico32x, sizeof(Pico32x));
  625. memcpy(t->t32x.dram, Pico32xMem->dram, sizeof(Pico32xMem->dram));
  626. memcpy(t->t32x.pal, Pico32xMem->pal, sizeof(Pico32xMem->pal));
  627. }
  628. #endif
  629. return t;
  630. }
  631. void PicoTmpStateRestore(void *data)
  632. {
  633. struct PicoTmp *t = data;
  634. if (t == NULL)
  635. return;
  636. memcpy(PicoMem.vram, t->vram, sizeof(PicoMem.vram));
  637. memcpy(PicoMem.cram, t->cram, sizeof(PicoMem.cram));
  638. memcpy(PicoMem.vsram, t->vsram, sizeof(PicoMem.vsram));
  639. memcpy(&Pico.video, &t->video, sizeof(Pico.video));
  640. Pico.m.dirtyPal = 1;
  641. #ifndef NO_32X
  642. if (PicoIn.AHW & PAHW_32X) {
  643. memcpy(&Pico32x, &t->t32x.p32x, sizeof(Pico32x));
  644. memcpy(Pico32xMem->dram, t->t32x.dram, sizeof(Pico32xMem->dram));
  645. memcpy(Pico32xMem->pal, t->t32x.pal, sizeof(Pico32xMem->pal));
  646. Pico32x.dirty_pal = 1;
  647. }
  648. #endif
  649. }
  650. // vim:shiftwidth=2:ts=2:expandtab