Annotation of generator/src/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 "snd/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 reserved2[1]; /* align */
                     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 reserved[1]; /* align */
                     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 reserved3[2]; /* align */
                     78: };
                     79: 
                     80: /*** state_date - return the modification date or 0 for non-existant ***/
                     81: 
                     82: time_t state_date(const int slot)
                     83: {
                     84:   char filename[256];
                     85:   struct stat statbuf;
                     86: 
                     87:   snprintf(filename, sizeof(filename), "%s.gt%d", gen_leafname, slot);
                     88: 
                     89:   if (stat(filename, &statbuf) != 0)
                     90:     return 0;
                     91:   return statbuf.st_mtime;
                     92: }
                     93: 
                     94: /*** state_load - load the given slot ***/
                     95: 
                     96: int state_load(const int slot)
                     97: {
                     98:   char filename[256];
                     99:   struct savestate *ssp;
                    100:   char *ss;
                    101:   struct stat statbuf;
                    102:   FILE *f, *a;
                    103:   int i;
                    104: 
                    105:   snprintf(filename, sizeof(filename), "%s.gt%d", gen_leafname, slot);
                    106:   if (stat(filename, &statbuf) != 0)
                    107:     return -1;
                    108: 
                    109:   if ((ss = malloc(statbuf.st_size)) == NULL) {
                    110:     LOG_CRITICAL(("Failed to allocate memory whilst loading '%s'",
                    111:                   filename));
                    112:     return -1;
                    113:   }
                    114:   if ((f = fopen(filename, "rb")) == NULL) {
                    115:     LOG_CRITICAL(("Failed to open '%s': %s", filename, strerror(errno)));
                    116:     return -1;
                    117:   }
                    118:   if (fread(ss, statbuf.st_size, 1, f) != 1) {
                    119:     if (feof(f)) {
                    120:       LOG_CRITICAL(("EOF whilst reading GTR file '%s'", filename));
                    121:       return -1;
                    122:     }
                    123:     LOG_CRITICAL(("Error whilst reading GTR file '%s': %s", filename,
                    124:                  strerror(errno)));
                    125:     return -1;
                    126:   }
                    127:   fclose(f);
                    128: 
                    129:   ssp = (struct savestate *)ss;
                    130: 
                    131:   if (ssp->s_majorver[0] != 1) {
                    132:     LOG_CRITICAL(("GTR file '%s' is version %d, and we're version 1",
                    133:                   filename, ssp->s_majorver));
                    134:     return -1;
                    135:   }
                    136:   if (statbuf.st_size != sizeof(struct savestate)) {
                    137:     LOG_CRITICAL(("GTR file '%s' is corrupt - it is not %d bytes long",
                    138:                   filename, sizeof(struct savestate)));
                    139:     return -1;
                    140:   }
                    141: 
                    142:   gen_reset();
                    143:   memcpy(cpu68k_ram, ssp->s_ram, sizeof(ssp->s_ram));
                    144:   memcpy(vdp_vram, ssp->s_vram, sizeof(ssp->s_vram));
                    145:   memcpy(cpuz80_ram, ssp->s_z80ram, sizeof(ssp->s_z80ram));
                    146:   memcpy(vdp_cram, ssp->s_cram, sizeof(ssp->s_cram));
                    147:   memcpy(vdp_vsram, ssp->s_vsram, sizeof(ssp->s_vsram));
                    148:   for (i = 0; i < 16; i++)
                    149:     regs.regs[i] = LOCENDIAN32(((uint32 *)ssp->s_68k_regs)[i]);
                    150:   regs.pc = LOCENDIAN32(*(uint32 *)ssp->s_68k_pc);
                    151:   regs.sp = LOCENDIAN32(*(uint32 *)ssp->s_68k_sp);
                    152:   regs.sr.sr_int = LOCENDIAN16(*(uint16 *)ssp->s_68k_sr);
                    153:   regs.stop = ssp->s_68k_stop[0];
                    154:   regs.pending = ssp->s_68k_pending[0];
                    155:   cpuz80_z80.z80af = LOCENDIAN16(*(uint16 *)ssp->s_z80_af);
                    156:   cpuz80_z80.z80bc = LOCENDIAN16(*(uint16 *)ssp->s_z80_bc);
                    157:   cpuz80_z80.z80de = LOCENDIAN16(*(uint16 *)ssp->s_z80_de);
                    158:   cpuz80_z80.z80hl = LOCENDIAN16(*(uint16 *)ssp->s_z80_hl);
                    159:   cpuz80_z80.z80afprime = LOCENDIAN16(*(uint16 *)ssp->s_z80_afprime);
                    160:   cpuz80_z80.z80bcprime = LOCENDIAN16(*(uint16 *)ssp->s_z80_bcprime);
                    161:   cpuz80_z80.z80deprime = LOCENDIAN16(*(uint16 *)ssp->s_z80_deprime);
                    162:   cpuz80_z80.z80hlprime = LOCENDIAN16(*(uint16 *)ssp->s_z80_hlprime);
                    163:   cpuz80_z80.z80ix = LOCENDIAN16(*(uint16 *)ssp->s_z80_ix);
                    164:   cpuz80_z80.z80iy = LOCENDIAN16(*(uint16 *)ssp->s_z80_iy);
                    165:   cpuz80_z80.z80sp = LOCENDIAN16(*(uint16 *)ssp->s_z80_sp);
                    166:   cpuz80_z80.z80pc = LOCENDIAN16(*(uint16 *)ssp->s_z80_pc);
                    167:   cpuz80_z80.z80i = ssp->s_z80_i[0];
                    168:   cpuz80_z80.z80r = ssp->s_z80_r[0];
                    169:   cpuz80_bank = LOCENDIAN32(*(uint32 *)ssp->s_z80_bank);
                    170:   memcpy(vdp_reg, ssp->s_vdp_regs, sizeof(ssp->s_vdp_regs));
                    171:   vdp_pal = ssp->s_vdp_pal[0];
                    172:   vdp_overseas = ssp->s_vdp_overseas[0];
                    173:   vdp_ctrlflag = ssp->s_vdp_ctrlflag[0];
                    174:   vdp_code = ssp->s_vdp_code[0];
                    175:   vdp_first = LOCENDIAN16(*(uint16 *)ssp->s_vdp_first);
                    176:   vdp_second = LOCENDIAN16(*(uint16 *)ssp->s_vdp_second);
                    177:   vdp_dmabytes = LOCENDIAN32(*(uint32 *)ssp->s_vdp_dmabytes);
                    178:   vdp_address = LOCENDIAN16(*(uint16 *)ssp->s_vdp_address);
                    179:   
                    180:   /* reset some other run-time stuff that isn't important enough to save */
                    181:   vdp_setupvideo();
                    182:   vdp_dmabusy = vdp_dmabytes > 0 ? 1 : 0;
                    183: 
                    184:   for (i = 0; i < 256; i++) {
                    185:     soundi_ym2612store(0, i);
                    186:     soundi_ym2612store(1, ssp->s_fmregs1[i]);
                    187:     soundi_ym2612store(2, i);
                    188:     soundi_ym2612store(3, ssp->s_fmregs2[i]);
                    189:   }
                    190:   soundi_ym2612store(0, ssp->s_fmaddr1[0]);
                    191:   soundi_ym2612store(1, ssp->s_fmaddr2[0]);
                    192:   cpuz80_updatecontext();
                    193:   return 0;
                    194: }
                    195: 
                    196: /*** state_save - save to the given slot ***/
                    197: 
                    198: int state_save(const int slot)
                    199: {
                    200:   char filename[256];
                    201:   struct savestate ss;
                    202:   struct savestate *ssp = &ss; /* I want a pointer like the load routines */
                    203:   struct stat statbuf;
                    204:   FILE *f, *a;
                    205:   int i;
                    206: 
                    207:   snprintf(filename, sizeof(filename), "%s.gt%d", gen_leafname, slot);
                    208:   if ((f = fopen(filename, "wb")) == NULL) {
                    209:     LOG_CRITICAL(("Failed to open '%s' for writing: %s",
                    210:                   filename, strerror(errno)));
                    211:     return -1;
                    212:   }
                    213:   memset(ssp, 0, sizeof(ss));
                    214:   ssp->s_majorver[0] = 1;
                    215:   ssp->s_minorver[0] = 1;
                    216:   memcpy(ssp->s_ram, cpu68k_ram, sizeof(ssp->s_ram));
                    217:   memcpy(ssp->s_vram, vdp_vram, sizeof(ssp->s_vram));
                    218:   memcpy(ssp->s_z80ram, cpuz80_ram, sizeof(ssp->s_z80ram));
                    219:   memcpy(ssp->s_cram, vdp_cram, sizeof(ssp->s_cram));
                    220:   memcpy(ssp->s_vsram, vdp_vsram, sizeof(ssp->s_vsram));
                    221:   for (i = 0; i < 16; i++)
                    222:     ((uint32 *)ssp->s_68k_regs)[i] = LOCENDIAN32(regs.regs[i]);
                    223:   *(uint32 *)ssp->s_68k_pc = LOCENDIAN32(regs.pc);
                    224:   *(uint32 *)ssp->s_68k_sp = LOCENDIAN32(regs.sp);
                    225:   *(uint16 *)ssp->s_68k_sr = LOCENDIAN16(regs.sr.sr_int);
                    226:   ssp->s_68k_stop[0] = regs.stop;
                    227:   ssp->s_68k_pending[0] = regs.pending;
                    228:   *(uint16 *)ssp->s_z80_af = LOCENDIAN16(cpuz80_z80.z80af);
                    229:   *(uint16 *)ssp->s_z80_bc = LOCENDIAN16(cpuz80_z80.z80bc);
                    230:   *(uint16 *)ssp->s_z80_de = LOCENDIAN16(cpuz80_z80.z80de);
                    231:   *(uint16 *)ssp->s_z80_hl = LOCENDIAN16(cpuz80_z80.z80hl);
                    232:   *(uint16 *)ssp->s_z80_afprime = LOCENDIAN16(cpuz80_z80.z80afprime);
                    233:   *(uint16 *)ssp->s_z80_bcprime = LOCENDIAN16(cpuz80_z80.z80bcprime);
                    234:   *(uint16 *)ssp->s_z80_deprime = LOCENDIAN16(cpuz80_z80.z80deprime);
                    235:   *(uint16 *)ssp->s_z80_hlprime = LOCENDIAN16(cpuz80_z80.z80hlprime);
                    236:   *(uint16 *)ssp->s_z80_ix = LOCENDIAN16(cpuz80_z80.z80ix);
                    237:   *(uint16 *)ssp->s_z80_iy = LOCENDIAN16(cpuz80_z80.z80iy);
                    238:   *(uint16 *)ssp->s_z80_sp = LOCENDIAN16(cpuz80_z80.z80sp);
                    239:   *(uint16 *)ssp->s_z80_pc = LOCENDIAN16(cpuz80_z80.z80pc);
                    240:   ssp->s_z80_i[0] = cpuz80_z80.z80i;
                    241:   ssp->s_z80_r[0] = cpuz80_z80.z80r;
                    242:   *(uint32 *)ssp->s_z80_bank = LOCENDIAN32(cpuz80_bank);
                    243:   memcpy(ssp->s_vdp_regs, vdp_reg, sizeof(ssp->s_vdp_regs));
                    244:   ssp->s_vdp_pal[0] = vdp_pal;
                    245:   ssp->s_vdp_overseas[0] = vdp_overseas;
                    246:   ssp->s_vdp_ctrlflag[0] = vdp_ctrlflag;
                    247:   ssp->s_vdp_code[0] = vdp_code;
                    248:   *(uint16 *)ssp->s_vdp_first = LOCENDIAN16(vdp_first);
                    249:   *(uint16 *)ssp->s_vdp_second = LOCENDIAN16(vdp_second);
                    250:   *(uint32 *)ssp->s_vdp_dmabytes = LOCENDIAN32(vdp_dmabytes);
                    251:   *(uint16 *)ssp->s_vdp_address = LOCENDIAN16(vdp_address);
                    252:   memcpy(ssp->s_fmregs1, soundi_regs1, sizeof(ssp->s_fmregs1));
                    253:   memcpy(ssp->s_fmregs2, soundi_regs2, sizeof(ssp->s_fmregs2));
                    254:   ssp->s_fmaddr1[0] = soundi_address1;
                    255:   ssp->s_fmaddr2[0] = soundi_address2;
                    256:   if (fwrite(ssp, sizeof(ss), 1, f) != 1) {
                    257:     LOG_CRITICAL(("Error whilst writing GTR file '%s': %s", filename,
                    258:                  strerror(errno)));
                    259:     return -1;
                    260:   }
                    261:   fclose(f);
                    262:   return 0;
                    263: }

unix.superglobalmegacorp.com

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