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

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 "fm.h"
                     22: 
                     23: /*
                     24:  * NB:
                     25:  * states are only loaded/saved at the end of the frame
                     26:  * all local values are stored in network / 68k format (big endian)
                     27:  */
                     28: 
1.1.1.2 ! root       29: struct savestate
        !            30: {
1.1       root       31:   /* must ensure everything is aligned as expected */
                     32:   char s_majorver[1];
                     33:   char s_minorver[1];
1.1.1.2 ! root       34:   char reserved1[2];            /* align */
1.1       root       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];
1.1.1.2 ! root       40:   char s_68k_regs[4 * 16];
1.1       root       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];
1.1.1.2 ! root       61:   char s_z80_halted[1];         /* was reserved in 0.31 */
1.1       root       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];
1.1.1.2 ! root       68:   char s_z80_im[1];             /* was reserved in 0.31 */
1.1       root       69:   char s_vdp_pal[1];
                     70:   char s_vdp_overseas[1];
                     71:   char s_vdp_ctrlflag[1];
                     72:   char s_vdp_code[1];
1.1.1.2 ! root       73:   char s_vdp_first[2];          /* possibly only top two bits required here */
        !            74:   char s_vdp_second[2];         /* used for unterminated ctrl writes */
1.1       root       75:   char s_vdp_dmabytes[4];
                     76:   char s_vdp_address[2];
1.1.1.2 ! root       77:   char s_z80_iff1[1];           /* was reserved in 0.31 */
        !            78:   char s_z80_iff2[1];           /* was reserved in 0.31 */
1.1       root       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) {
1.1.1.2 ! root      111:     LOG_CRITICAL(("Failed to allocate memory whilst loading '%s'", filename));
1.1       root      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,
1.1.1.2 ! root      124:                   strerror(errno)));
1.1       root      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: #ifdef RAZE
1.1.1.2 ! root      156:   z80_set_reg(Z80_REG_AF, LOCENDIAN16(*(uint16 *)ssp->s_z80_af));
        !           157:   z80_set_reg(Z80_REG_BC, LOCENDIAN16(*(uint16 *)ssp->s_z80_bc));
        !           158:   z80_set_reg(Z80_REG_DE, LOCENDIAN16(*(uint16 *)ssp->s_z80_de));
        !           159:   z80_set_reg(Z80_REG_HL, LOCENDIAN16(*(uint16 *)ssp->s_z80_hl));
1.1       root      160:   z80_set_reg(Z80_REG_AF2, LOCENDIAN16(*(uint16 *)ssp->s_z80_afprime));
                    161:   z80_set_reg(Z80_REG_BC2, LOCENDIAN16(*(uint16 *)ssp->s_z80_bcprime));
                    162:   z80_set_reg(Z80_REG_DE2, LOCENDIAN16(*(uint16 *)ssp->s_z80_deprime));
                    163:   z80_set_reg(Z80_REG_HL2, LOCENDIAN16(*(uint16 *)ssp->s_z80_hlprime));
1.1.1.2 ! root      164:   z80_set_reg(Z80_REG_IX, LOCENDIAN16(*(uint16 *)ssp->s_z80_ix));
        !           165:   z80_set_reg(Z80_REG_IY, LOCENDIAN16(*(uint16 *)ssp->s_z80_iy));
        !           166:   z80_set_reg(Z80_REG_SP, LOCENDIAN16(*(uint16 *)ssp->s_z80_sp));
        !           167:   z80_set_reg(Z80_REG_PC, LOCENDIAN16(*(uint16 *)ssp->s_z80_pc));
1.1       root      168:   z80_set_reg(Z80_REG_IFF1, ssp->s_z80_iff1[0]);
                    169:   z80_set_reg(Z80_REG_IFF2, ssp->s_z80_iff2[0]);
1.1.1.2 ! root      170:   z80_set_reg(Z80_REG_IR, ssp->s_z80_i[0] << 8 | ssp->s_z80_r[0]);
1.1       root      171:   z80_set_reg(Z80_REG_IM, ssp->s_z80_im[0]);
                    172:   z80_set_reg(Z80_REG_Halted, ssp->s_z80_halted[0]);
                    173:   /* FIX:
1.1.1.2 ! root      174:      Z80_REG_IRQVector,   0x00 to 0xff
        !           175:      Z80_REG_IRQLine,     boolean - 1 or 0
        !           176:    */
1.1       root      177: #else
                    178:   cpuz80_z80.z80af = LOCENDIAN16(*(uint16 *)ssp->s_z80_af);
                    179:   cpuz80_z80.z80bc = LOCENDIAN16(*(uint16 *)ssp->s_z80_bc);
                    180:   cpuz80_z80.z80de = LOCENDIAN16(*(uint16 *)ssp->s_z80_de);
                    181:   cpuz80_z80.z80hl = LOCENDIAN16(*(uint16 *)ssp->s_z80_hl);
                    182:   cpuz80_z80.z80afprime = LOCENDIAN16(*(uint16 *)ssp->s_z80_afprime);
                    183:   cpuz80_z80.z80bcprime = LOCENDIAN16(*(uint16 *)ssp->s_z80_bcprime);
                    184:   cpuz80_z80.z80deprime = LOCENDIAN16(*(uint16 *)ssp->s_z80_deprime);
                    185:   cpuz80_z80.z80hlprime = LOCENDIAN16(*(uint16 *)ssp->s_z80_hlprime);
                    186:   cpuz80_z80.z80ix = LOCENDIAN16(*(uint16 *)ssp->s_z80_ix);
                    187:   cpuz80_z80.z80iy = LOCENDIAN16(*(uint16 *)ssp->s_z80_iy);
                    188:   cpuz80_z80.z80sp = LOCENDIAN16(*(uint16 *)ssp->s_z80_sp);
                    189:   cpuz80_z80.z80pc = LOCENDIAN16(*(uint16 *)ssp->s_z80_pc);
                    190:   cpuz80_z80.z80i = ssp->s_z80_i[0];
                    191:   cpuz80_z80.z80r = ssp->s_z80_r[0];
                    192:   cpuz80_z80.z80inInterrupt = ssp->s_z80_iff1[0];
                    193:   cpuz80_z80.z80interruptState = ssp->s_z80_iff2[0];
                    194:   cpuz80_z80.z80interruptMode = ssp->s_z80_im[0];
                    195:   cpuz80_z80.z80halted = ssp->s_z80_halted[0];
                    196:   /* FIX:
1.1.1.2 ! root      197:      c -> z80intAddr = z80intAddr;
        !           198:      c -> z80nmiAddr = z80nmiAddr;
        !           199:    */
1.1       root      200: #endif
                    201:   cpuz80_bank = LOCENDIAN32(*(uint32 *)ssp->s_z80_bank);
                    202: 
                    203: 
                    204:   memcpy(vdp_reg, ssp->s_vdp_regs, sizeof(ssp->s_vdp_regs));
                    205:   vdp_pal = ssp->s_vdp_pal[0];
                    206:   vdp_overseas = ssp->s_vdp_overseas[0];
                    207:   vdp_ctrlflag = ssp->s_vdp_ctrlflag[0];
                    208:   vdp_code = ssp->s_vdp_code[0];
                    209:   vdp_first = LOCENDIAN16(*(uint16 *)ssp->s_vdp_first);
                    210:   vdp_second = LOCENDIAN16(*(uint16 *)ssp->s_vdp_second);
                    211:   vdp_dmabytes = LOCENDIAN32(*(uint32 *)ssp->s_vdp_dmabytes);
                    212:   vdp_address = LOCENDIAN16(*(uint16 *)ssp->s_vdp_address);
1.1.1.2 ! root      213: 
1.1       root      214:   /* reset some other run-time stuff that isn't important enough to save */
                    215:   vdp_setupvideo();
                    216:   vdp_dmabusy = vdp_dmabytes > 0 ? 1 : 0;
                    217: 
                    218:   for (i = 0; i < 256; i++) {
1.1.1.2 ! root      219:     sound_ym2612store(0, i);
        !           220:     sound_ym2612store(1, ssp->s_fmregs1[i]);
        !           221:     sound_ym2612store(2, i);
        !           222:     sound_ym2612store(3, ssp->s_fmregs2[i]);
1.1       root      223:   }
1.1.1.2 ! root      224:   sound_ym2612store(0, ssp->s_fmaddr1[0]);
        !           225:   sound_ym2612store(1, ssp->s_fmaddr2[0]);
1.1       root      226:   cpuz80_updatecontext();
                    227:   return 0;
                    228: }
                    229: 
                    230: /*** state_save - save to the given slot ***/
                    231: 
                    232: int state_save(const int slot)
                    233: {
                    234:   char filename[256];
                    235:   struct savestate ss;
1.1.1.2 ! root      236:   struct savestate *ssp = &ss;  /* I want a pointer like the load routines */
1.1       root      237:   struct stat statbuf;
                    238:   FILE *f, *a;
                    239:   int i;
                    240: 
                    241:   snprintf(filename, sizeof(filename), "%s.gt%d", gen_leafname, slot);
                    242:   if ((f = fopen(filename, "wb")) == NULL) {
                    243:     LOG_CRITICAL(("Failed to open '%s' for writing: %s",
                    244:                   filename, strerror(errno)));
                    245:     return -1;
                    246:   }
                    247:   memset(ssp, 0, sizeof(ss));
                    248:   ssp->s_majorver[0] = 1;
                    249:   ssp->s_minorver[0] = 2;
                    250:   memcpy(ssp->s_ram, cpu68k_ram, sizeof(ssp->s_ram));
                    251:   memcpy(ssp->s_vram, vdp_vram, sizeof(ssp->s_vram));
                    252:   memcpy(ssp->s_z80ram, cpuz80_ram, sizeof(ssp->s_z80ram));
                    253:   memcpy(ssp->s_cram, vdp_cram, sizeof(ssp->s_cram));
                    254:   memcpy(ssp->s_vsram, vdp_vsram, sizeof(ssp->s_vsram));
                    255:   for (i = 0; i < 16; i++)
                    256:     ((uint32 *)ssp->s_68k_regs)[i] = LOCENDIAN32(regs.regs[i]);
                    257:   *(uint32 *)ssp->s_68k_pc = LOCENDIAN32(regs.pc);
                    258:   *(uint32 *)ssp->s_68k_sp = LOCENDIAN32(regs.sp);
                    259:   *(uint16 *)ssp->s_68k_sr = LOCENDIAN16(regs.sr.sr_int);
                    260:   ssp->s_68k_stop[0] = regs.stop;
                    261:   ssp->s_68k_pending[0] = regs.pending;
                    262: #ifdef RAZE
                    263:   *(uint16 *)ssp->s_z80_af = LOCENDIAN16(z80_get_reg(Z80_REG_AF));
                    264:   *(uint16 *)ssp->s_z80_bc = LOCENDIAN16(z80_get_reg(Z80_REG_BC));
                    265:   *(uint16 *)ssp->s_z80_de = LOCENDIAN16(z80_get_reg(Z80_REG_DE));
                    266:   *(uint16 *)ssp->s_z80_hl = LOCENDIAN16(z80_get_reg(Z80_REG_HL));
                    267:   *(uint16 *)ssp->s_z80_afprime = LOCENDIAN16(z80_get_reg(Z80_REG_AF2));
                    268:   *(uint16 *)ssp->s_z80_bcprime = LOCENDIAN16(z80_get_reg(Z80_REG_BC2));
                    269:   *(uint16 *)ssp->s_z80_deprime = LOCENDIAN16(z80_get_reg(Z80_REG_DE2));
                    270:   *(uint16 *)ssp->s_z80_hlprime = LOCENDIAN16(z80_get_reg(Z80_REG_HL2));
                    271:   *(uint16 *)ssp->s_z80_ix = LOCENDIAN16(z80_get_reg(Z80_REG_IX));
                    272:   *(uint16 *)ssp->s_z80_iy = LOCENDIAN16(z80_get_reg(Z80_REG_IY));
                    273:   *(uint16 *)ssp->s_z80_sp = LOCENDIAN16(z80_get_reg(Z80_REG_SP));
                    274:   *(uint16 *)ssp->s_z80_pc = LOCENDIAN16(z80_get_reg(Z80_REG_PC));
                    275:   ssp->s_z80_i[0] = (z80_get_reg(Z80_REG_IR) >> 8) & 0xff;
                    276:   ssp->s_z80_r[0] = z80_get_reg(Z80_REG_IR) & 0xff;
                    277:   ssp->s_z80_iff1[0] = z80_get_reg(Z80_REG_IFF1);
                    278:   ssp->s_z80_iff2[0] = z80_get_reg(Z80_REG_IFF2);
                    279:   ssp->s_z80_im[0] = z80_get_reg(Z80_REG_IM);
                    280: #else
                    281:   *(uint16 *)ssp->s_z80_af = LOCENDIAN16(cpuz80_z80.z80af);
                    282:   *(uint16 *)ssp->s_z80_bc = LOCENDIAN16(cpuz80_z80.z80bc);
                    283:   *(uint16 *)ssp->s_z80_de = LOCENDIAN16(cpuz80_z80.z80de);
                    284:   *(uint16 *)ssp->s_z80_hl = LOCENDIAN16(cpuz80_z80.z80hl);
                    285:   *(uint16 *)ssp->s_z80_afprime = LOCENDIAN16(cpuz80_z80.z80afprime);
                    286:   *(uint16 *)ssp->s_z80_bcprime = LOCENDIAN16(cpuz80_z80.z80bcprime);
                    287:   *(uint16 *)ssp->s_z80_deprime = LOCENDIAN16(cpuz80_z80.z80deprime);
                    288:   *(uint16 *)ssp->s_z80_hlprime = LOCENDIAN16(cpuz80_z80.z80hlprime);
                    289:   *(uint16 *)ssp->s_z80_ix = LOCENDIAN16(cpuz80_z80.z80ix);
                    290:   *(uint16 *)ssp->s_z80_iy = LOCENDIAN16(cpuz80_z80.z80iy);
                    291:   *(uint16 *)ssp->s_z80_sp = LOCENDIAN16(cpuz80_z80.z80sp);
                    292:   *(uint16 *)ssp->s_z80_pc = LOCENDIAN16(cpuz80_z80.z80pc);
                    293:   ssp->s_z80_i[0] = cpuz80_z80.z80i;
                    294:   ssp->s_z80_r[0] = cpuz80_z80.z80r;
                    295:   ssp->s_z80_iff1[0] = cpuz80_z80.z80inInterrupt;
                    296:   ssp->s_z80_iff2[0] = cpuz80_z80.z80interruptState;
                    297:   ssp->s_z80_im[0] = cpuz80_z80.z80interruptMode;
                    298:   ssp->s_z80_halted[0] = cpuz80_z80.z80halted;
                    299: #endif
                    300:   *(uint32 *)ssp->s_z80_bank = LOCENDIAN32(cpuz80_bank);
                    301:   memcpy(ssp->s_vdp_regs, vdp_reg, sizeof(ssp->s_vdp_regs));
                    302:   ssp->s_vdp_pal[0] = vdp_pal;
                    303:   ssp->s_vdp_overseas[0] = vdp_overseas;
                    304:   ssp->s_vdp_ctrlflag[0] = vdp_ctrlflag;
                    305:   ssp->s_vdp_code[0] = vdp_code;
                    306:   *(uint16 *)ssp->s_vdp_first = LOCENDIAN16(vdp_first);
                    307:   *(uint16 *)ssp->s_vdp_second = LOCENDIAN16(vdp_second);
                    308:   *(uint32 *)ssp->s_vdp_dmabytes = LOCENDIAN32(vdp_dmabytes);
                    309:   *(uint16 *)ssp->s_vdp_address = LOCENDIAN16(vdp_address);
1.1.1.2 ! root      310:   memcpy(ssp->s_fmregs1, sound_regs1, sizeof(ssp->s_fmregs1));
        !           311:   memcpy(ssp->s_fmregs2, sound_regs2, sizeof(ssp->s_fmregs2));
        !           312:   ssp->s_fmaddr1[0] = sound_address1;
        !           313:   ssp->s_fmaddr2[0] = sound_address2;
1.1       root      314:   if (fwrite(ssp, sizeof(ss), 1, f) != 1) {
                    315:     LOG_CRITICAL(("Error whilst writing GTR file '%s': %s", filename,
1.1.1.2 ! root      316:                   strerror(errno)));
1.1       root      317:     return -1;
                    318:   }
                    319:   fclose(f);
                    320:   return 0;
                    321: }

unix.superglobalmegacorp.com

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