Annotation of generator/src/state.c, revision 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.