|
|
1.1 ! root 1: /* Generator is (c) James Ponder, 1997-2001 http://www.squish.net/generator/ */ ! 2: ! 3: #include <sys/stat.h> ! 4: #include <unistd.h> ! 5: #include <stdio.h> ! 6: #include <stdlib.h> ! 7: #include <errno.h> ! 8: #include <time.h> ! 9: #include <string.h> ! 10: #include <errno.h> ! 11: ! 12: #include "generator.h" ! 13: #include "snprintf.h" ! 14: ! 15: #include "state.h" ! 16: #include "ui.h" ! 17: #include "cpu68k.h" ! 18: #include "cpuz80.h" ! 19: #include "vdp.h" ! 20: #include "gensound.h" ! 21: #include "gensoundi.h" ! 22: #include "fm.h" ! 23: ! 24: /* ! 25: * NB: ! 26: * states are only loaded/saved at the end of the frame ! 27: * all local values are stored in network / 68k format (big endian) ! 28: */ ! 29: ! 30: struct savestate { ! 31: /* must ensure everything is aligned as expected */ ! 32: char s_majorver[1]; ! 33: char s_minorver[1]; ! 34: char reserved1[2]; /* align */ ! 35: char s_ram[0x10000]; ! 36: char s_vram[0x10000]; ! 37: char s_z80ram[0x2000]; ! 38: char s_cram[0x80]; ! 39: char s_vsram[0x50]; ! 40: char s_68k_regs[4*16]; ! 41: char s_68k_pc[4]; ! 42: char s_68k_sp[4]; ! 43: char s_68k_sr[2]; ! 44: char s_68k_stop[1]; ! 45: char s_68k_pending[1]; ! 46: char s_z80_af[2]; ! 47: char s_z80_bc[2]; ! 48: char s_z80_de[2]; ! 49: char s_z80_hl[2]; ! 50: char s_z80_afprime[2]; ! 51: char s_z80_bcprime[2]; ! 52: char s_z80_deprime[2]; ! 53: char s_z80_hlprime[2]; ! 54: char s_z80_ix[2]; ! 55: char s_z80_iy[2]; ! 56: char s_z80_sp[2]; ! 57: char s_z80_pc[2]; ! 58: char s_z80_i[1]; ! 59: char s_z80_r[1]; ! 60: char s_z80_active[1]; ! 61: char s_z80_halted[1]; /* was reserved in 0.31 */ ! 62: char s_z80_bank[4]; ! 63: char s_fmregs1[256]; ! 64: char s_fmregs2[256]; ! 65: char s_fmaddr1[1]; ! 66: char s_fmaddr2[1]; ! 67: char s_vdp_regs[25]; ! 68: char s_z80_im[1]; /* was reserved in 0.31 */ ! 69: char s_vdp_pal[1]; ! 70: char s_vdp_overseas[1]; ! 71: char s_vdp_ctrlflag[1]; ! 72: char s_vdp_code[1]; ! 73: char s_vdp_first[2]; /* possibly only top two bits required here */ ! 74: char s_vdp_second[2]; /* used for unterminated ctrl writes */ ! 75: char s_vdp_dmabytes[4]; ! 76: char s_vdp_address[2]; ! 77: char s_z80_iff1[1]; /* was reserved in 0.31 */ ! 78: char s_z80_iff2[1]; /* was reserved in 0.31 */ ! 79: }; ! 80: ! 81: /*** state_date - return the modification date or 0 for non-existant ***/ ! 82: ! 83: time_t state_date(const int slot) ! 84: { ! 85: char filename[256]; ! 86: struct stat statbuf; ! 87: ! 88: snprintf(filename, sizeof(filename), "%s.gt%d", gen_leafname, slot); ! 89: ! 90: if (stat(filename, &statbuf) != 0) ! 91: return 0; ! 92: return statbuf.st_mtime; ! 93: } ! 94: ! 95: /*** state_load - load the given slot ***/ ! 96: ! 97: int state_load(const int slot) ! 98: { ! 99: char filename[256]; ! 100: struct savestate *ssp; ! 101: char *ss; ! 102: struct stat statbuf; ! 103: FILE *f, *a; ! 104: int i; ! 105: ! 106: snprintf(filename, sizeof(filename), "%s.gt%d", gen_leafname, slot); ! 107: if (stat(filename, &statbuf) != 0) ! 108: return -1; ! 109: ! 110: if ((ss = malloc(statbuf.st_size)) == NULL) { ! 111: LOG_CRITICAL(("Failed to allocate memory whilst loading '%s'", ! 112: filename)); ! 113: return -1; ! 114: } ! 115: if ((f = fopen(filename, "rb")) == NULL) { ! 116: LOG_CRITICAL(("Failed to open '%s': %s", filename, strerror(errno))); ! 117: return -1; ! 118: } ! 119: if (fread(ss, statbuf.st_size, 1, f) != 1) { ! 120: if (feof(f)) { ! 121: LOG_CRITICAL(("EOF whilst reading GTR file '%s'", filename)); ! 122: return -1; ! 123: } ! 124: LOG_CRITICAL(("Error whilst reading GTR file '%s': %s", filename, ! 125: strerror(errno))); ! 126: return -1; ! 127: } ! 128: fclose(f); ! 129: ! 130: ssp = (struct savestate *)ss; ! 131: ! 132: if (ssp->s_majorver[0] != 1) { ! 133: LOG_CRITICAL(("GTR file '%s' is version %d, and we're version 1", ! 134: filename, ssp->s_majorver)); ! 135: return -1; ! 136: } ! 137: if (statbuf.st_size != sizeof(struct savestate)) { ! 138: LOG_CRITICAL(("GTR file '%s' is corrupt - it is not %d bytes long", ! 139: filename, sizeof(struct savestate))); ! 140: return -1; ! 141: } ! 142: ! 143: gen_reset(); ! 144: memcpy(cpu68k_ram, ssp->s_ram, sizeof(ssp->s_ram)); ! 145: memcpy(vdp_vram, ssp->s_vram, sizeof(ssp->s_vram)); ! 146: memcpy(cpuz80_ram, ssp->s_z80ram, sizeof(ssp->s_z80ram)); ! 147: memcpy(vdp_cram, ssp->s_cram, sizeof(ssp->s_cram)); ! 148: memcpy(vdp_vsram, ssp->s_vsram, sizeof(ssp->s_vsram)); ! 149: for (i = 0; i < 16; i++) ! 150: regs.regs[i] = LOCENDIAN32(((uint32 *)ssp->s_68k_regs)[i]); ! 151: regs.pc = LOCENDIAN32(*(uint32 *)ssp->s_68k_pc); ! 152: regs.sp = LOCENDIAN32(*(uint32 *)ssp->s_68k_sp); ! 153: regs.sr.sr_int = LOCENDIAN16(*(uint16 *)ssp->s_68k_sr); ! 154: regs.stop = ssp->s_68k_stop[0]; ! 155: regs.pending = ssp->s_68k_pending[0]; ! 156: #ifdef RAZE ! 157: z80_set_reg(Z80_REG_AF, LOCENDIAN16(*(uint16 *)ssp->s_z80_af)); ! 158: z80_set_reg(Z80_REG_BC, LOCENDIAN16(*(uint16 *)ssp->s_z80_bc)); ! 159: z80_set_reg(Z80_REG_DE, LOCENDIAN16(*(uint16 *)ssp->s_z80_de)); ! 160: z80_set_reg(Z80_REG_HL, LOCENDIAN16(*(uint16 *)ssp->s_z80_hl)); ! 161: z80_set_reg(Z80_REG_AF2, LOCENDIAN16(*(uint16 *)ssp->s_z80_afprime)); ! 162: z80_set_reg(Z80_REG_BC2, LOCENDIAN16(*(uint16 *)ssp->s_z80_bcprime)); ! 163: z80_set_reg(Z80_REG_DE2, LOCENDIAN16(*(uint16 *)ssp->s_z80_deprime)); ! 164: z80_set_reg(Z80_REG_HL2, LOCENDIAN16(*(uint16 *)ssp->s_z80_hlprime)); ! 165: z80_set_reg(Z80_REG_IX, LOCENDIAN16(*(uint16 *)ssp->s_z80_ix)); ! 166: z80_set_reg(Z80_REG_IY, LOCENDIAN16(*(uint16 *)ssp->s_z80_iy)); ! 167: z80_set_reg(Z80_REG_SP, LOCENDIAN16(*(uint16 *)ssp->s_z80_sp)); ! 168: z80_set_reg(Z80_REG_PC, LOCENDIAN16(*(uint16 *)ssp->s_z80_pc)); ! 169: z80_set_reg(Z80_REG_IFF1, ssp->s_z80_iff1[0]); ! 170: z80_set_reg(Z80_REG_IFF2, ssp->s_z80_iff2[0]); ! 171: z80_set_reg(Z80_REG_IR, ssp->s_z80_i[0]<<8 | ssp->s_z80_r[0]); ! 172: z80_set_reg(Z80_REG_IM, ssp->s_z80_im[0]); ! 173: z80_set_reg(Z80_REG_Halted, ssp->s_z80_halted[0]); ! 174: /* FIX: ! 175: Z80_REG_IRQVector, 0x00 to 0xff ! 176: Z80_REG_IRQLine, boolean - 1 or 0 ! 177: */ ! 178: #else ! 179: cpuz80_z80.z80af = LOCENDIAN16(*(uint16 *)ssp->s_z80_af); ! 180: cpuz80_z80.z80bc = LOCENDIAN16(*(uint16 *)ssp->s_z80_bc); ! 181: cpuz80_z80.z80de = LOCENDIAN16(*(uint16 *)ssp->s_z80_de); ! 182: cpuz80_z80.z80hl = LOCENDIAN16(*(uint16 *)ssp->s_z80_hl); ! 183: cpuz80_z80.z80afprime = LOCENDIAN16(*(uint16 *)ssp->s_z80_afprime); ! 184: cpuz80_z80.z80bcprime = LOCENDIAN16(*(uint16 *)ssp->s_z80_bcprime); ! 185: cpuz80_z80.z80deprime = LOCENDIAN16(*(uint16 *)ssp->s_z80_deprime); ! 186: cpuz80_z80.z80hlprime = LOCENDIAN16(*(uint16 *)ssp->s_z80_hlprime); ! 187: cpuz80_z80.z80ix = LOCENDIAN16(*(uint16 *)ssp->s_z80_ix); ! 188: cpuz80_z80.z80iy = LOCENDIAN16(*(uint16 *)ssp->s_z80_iy); ! 189: cpuz80_z80.z80sp = LOCENDIAN16(*(uint16 *)ssp->s_z80_sp); ! 190: cpuz80_z80.z80pc = LOCENDIAN16(*(uint16 *)ssp->s_z80_pc); ! 191: cpuz80_z80.z80i = ssp->s_z80_i[0]; ! 192: cpuz80_z80.z80r = ssp->s_z80_r[0]; ! 193: cpuz80_z80.z80inInterrupt = ssp->s_z80_iff1[0]; ! 194: cpuz80_z80.z80interruptState = ssp->s_z80_iff2[0]; ! 195: cpuz80_z80.z80interruptMode = ssp->s_z80_im[0]; ! 196: cpuz80_z80.z80halted = ssp->s_z80_halted[0]; ! 197: /* FIX: ! 198: c -> z80intAddr = z80intAddr; ! 199: c -> z80nmiAddr = z80nmiAddr; ! 200: */ ! 201: #endif ! 202: cpuz80_bank = LOCENDIAN32(*(uint32 *)ssp->s_z80_bank); ! 203: ! 204: ! 205: memcpy(vdp_reg, ssp->s_vdp_regs, sizeof(ssp->s_vdp_regs)); ! 206: vdp_pal = ssp->s_vdp_pal[0]; ! 207: vdp_overseas = ssp->s_vdp_overseas[0]; ! 208: vdp_ctrlflag = ssp->s_vdp_ctrlflag[0]; ! 209: vdp_code = ssp->s_vdp_code[0]; ! 210: vdp_first = LOCENDIAN16(*(uint16 *)ssp->s_vdp_first); ! 211: vdp_second = LOCENDIAN16(*(uint16 *)ssp->s_vdp_second); ! 212: vdp_dmabytes = LOCENDIAN32(*(uint32 *)ssp->s_vdp_dmabytes); ! 213: vdp_address = LOCENDIAN16(*(uint16 *)ssp->s_vdp_address); ! 214: ! 215: /* reset some other run-time stuff that isn't important enough to save */ ! 216: vdp_setupvideo(); ! 217: vdp_dmabusy = vdp_dmabytes > 0 ? 1 : 0; ! 218: ! 219: for (i = 0; i < 256; i++) { ! 220: soundi_ym2612store(0, i); ! 221: soundi_ym2612store(1, ssp->s_fmregs1[i]); ! 222: soundi_ym2612store(2, i); ! 223: soundi_ym2612store(3, ssp->s_fmregs2[i]); ! 224: } ! 225: soundi_ym2612store(0, ssp->s_fmaddr1[0]); ! 226: soundi_ym2612store(1, ssp->s_fmaddr2[0]); ! 227: cpuz80_updatecontext(); ! 228: return 0; ! 229: } ! 230: ! 231: /*** state_save - save to the given slot ***/ ! 232: ! 233: int state_save(const int slot) ! 234: { ! 235: char filename[256]; ! 236: struct savestate ss; ! 237: struct savestate *ssp = &ss; /* I want a pointer like the load routines */ ! 238: struct stat statbuf; ! 239: FILE *f, *a; ! 240: int i; ! 241: ! 242: snprintf(filename, sizeof(filename), "%s.gt%d", gen_leafname, slot); ! 243: if ((f = fopen(filename, "wb")) == NULL) { ! 244: LOG_CRITICAL(("Failed to open '%s' for writing: %s", ! 245: filename, strerror(errno))); ! 246: return -1; ! 247: } ! 248: memset(ssp, 0, sizeof(ss)); ! 249: ssp->s_majorver[0] = 1; ! 250: ssp->s_minorver[0] = 2; ! 251: memcpy(ssp->s_ram, cpu68k_ram, sizeof(ssp->s_ram)); ! 252: memcpy(ssp->s_vram, vdp_vram, sizeof(ssp->s_vram)); ! 253: memcpy(ssp->s_z80ram, cpuz80_ram, sizeof(ssp->s_z80ram)); ! 254: memcpy(ssp->s_cram, vdp_cram, sizeof(ssp->s_cram)); ! 255: memcpy(ssp->s_vsram, vdp_vsram, sizeof(ssp->s_vsram)); ! 256: for (i = 0; i < 16; i++) ! 257: ((uint32 *)ssp->s_68k_regs)[i] = LOCENDIAN32(regs.regs[i]); ! 258: *(uint32 *)ssp->s_68k_pc = LOCENDIAN32(regs.pc); ! 259: *(uint32 *)ssp->s_68k_sp = LOCENDIAN32(regs.sp); ! 260: *(uint16 *)ssp->s_68k_sr = LOCENDIAN16(regs.sr.sr_int); ! 261: ssp->s_68k_stop[0] = regs.stop; ! 262: ssp->s_68k_pending[0] = regs.pending; ! 263: #ifdef RAZE ! 264: *(uint16 *)ssp->s_z80_af = LOCENDIAN16(z80_get_reg(Z80_REG_AF)); ! 265: *(uint16 *)ssp->s_z80_bc = LOCENDIAN16(z80_get_reg(Z80_REG_BC)); ! 266: *(uint16 *)ssp->s_z80_de = LOCENDIAN16(z80_get_reg(Z80_REG_DE)); ! 267: *(uint16 *)ssp->s_z80_hl = LOCENDIAN16(z80_get_reg(Z80_REG_HL)); ! 268: *(uint16 *)ssp->s_z80_afprime = LOCENDIAN16(z80_get_reg(Z80_REG_AF2)); ! 269: *(uint16 *)ssp->s_z80_bcprime = LOCENDIAN16(z80_get_reg(Z80_REG_BC2)); ! 270: *(uint16 *)ssp->s_z80_deprime = LOCENDIAN16(z80_get_reg(Z80_REG_DE2)); ! 271: *(uint16 *)ssp->s_z80_hlprime = LOCENDIAN16(z80_get_reg(Z80_REG_HL2)); ! 272: *(uint16 *)ssp->s_z80_ix = LOCENDIAN16(z80_get_reg(Z80_REG_IX)); ! 273: *(uint16 *)ssp->s_z80_iy = LOCENDIAN16(z80_get_reg(Z80_REG_IY)); ! 274: *(uint16 *)ssp->s_z80_sp = LOCENDIAN16(z80_get_reg(Z80_REG_SP)); ! 275: *(uint16 *)ssp->s_z80_pc = LOCENDIAN16(z80_get_reg(Z80_REG_PC)); ! 276: ssp->s_z80_i[0] = (z80_get_reg(Z80_REG_IR) >> 8) & 0xff; ! 277: ssp->s_z80_r[0] = z80_get_reg(Z80_REG_IR) & 0xff; ! 278: ssp->s_z80_iff1[0] = z80_get_reg(Z80_REG_IFF1); ! 279: ssp->s_z80_iff2[0] = z80_get_reg(Z80_REG_IFF2); ! 280: ssp->s_z80_im[0] = z80_get_reg(Z80_REG_IM); ! 281: #else ! 282: *(uint16 *)ssp->s_z80_af = LOCENDIAN16(cpuz80_z80.z80af); ! 283: *(uint16 *)ssp->s_z80_bc = LOCENDIAN16(cpuz80_z80.z80bc); ! 284: *(uint16 *)ssp->s_z80_de = LOCENDIAN16(cpuz80_z80.z80de); ! 285: *(uint16 *)ssp->s_z80_hl = LOCENDIAN16(cpuz80_z80.z80hl); ! 286: *(uint16 *)ssp->s_z80_afprime = LOCENDIAN16(cpuz80_z80.z80afprime); ! 287: *(uint16 *)ssp->s_z80_bcprime = LOCENDIAN16(cpuz80_z80.z80bcprime); ! 288: *(uint16 *)ssp->s_z80_deprime = LOCENDIAN16(cpuz80_z80.z80deprime); ! 289: *(uint16 *)ssp->s_z80_hlprime = LOCENDIAN16(cpuz80_z80.z80hlprime); ! 290: *(uint16 *)ssp->s_z80_ix = LOCENDIAN16(cpuz80_z80.z80ix); ! 291: *(uint16 *)ssp->s_z80_iy = LOCENDIAN16(cpuz80_z80.z80iy); ! 292: *(uint16 *)ssp->s_z80_sp = LOCENDIAN16(cpuz80_z80.z80sp); ! 293: *(uint16 *)ssp->s_z80_pc = LOCENDIAN16(cpuz80_z80.z80pc); ! 294: ssp->s_z80_i[0] = cpuz80_z80.z80i; ! 295: ssp->s_z80_r[0] = cpuz80_z80.z80r; ! 296: ssp->s_z80_iff1[0] = cpuz80_z80.z80inInterrupt; ! 297: ssp->s_z80_iff2[0] = cpuz80_z80.z80interruptState; ! 298: ssp->s_z80_im[0] = cpuz80_z80.z80interruptMode; ! 299: ssp->s_z80_halted[0] = cpuz80_z80.z80halted; ! 300: #endif ! 301: *(uint32 *)ssp->s_z80_bank = LOCENDIAN32(cpuz80_bank); ! 302: memcpy(ssp->s_vdp_regs, vdp_reg, sizeof(ssp->s_vdp_regs)); ! 303: ssp->s_vdp_pal[0] = vdp_pal; ! 304: ssp->s_vdp_overseas[0] = vdp_overseas; ! 305: ssp->s_vdp_ctrlflag[0] = vdp_ctrlflag; ! 306: ssp->s_vdp_code[0] = vdp_code; ! 307: *(uint16 *)ssp->s_vdp_first = LOCENDIAN16(vdp_first); ! 308: *(uint16 *)ssp->s_vdp_second = LOCENDIAN16(vdp_second); ! 309: *(uint32 *)ssp->s_vdp_dmabytes = LOCENDIAN32(vdp_dmabytes); ! 310: *(uint16 *)ssp->s_vdp_address = LOCENDIAN16(vdp_address); ! 311: memcpy(ssp->s_fmregs1, soundi_regs1, sizeof(ssp->s_fmregs1)); ! 312: memcpy(ssp->s_fmregs2, soundi_regs2, sizeof(ssp->s_fmregs2)); ! 313: ssp->s_fmaddr1[0] = soundi_address1; ! 314: ssp->s_fmaddr2[0] = soundi_address2; ! 315: if (fwrite(ssp, sizeof(ss), 1, f) != 1) { ! 316: LOG_CRITICAL(("Error whilst writing GTR file '%s': %s", filename, ! 317: strerror(errno))); ! 318: return -1; ! 319: } ! 320: fclose(f); ! 321: return 0; ! 322: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.