Annotation of generator/main/state.c, revision 1.1.1.1

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: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.