Annotation of generator/main/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 "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.