📄 snapshot.cpp
字号:
} return (FALSE);}bool8 S9xLoadSnapshot (const char *filename){ return (S9xUnfreezeGame (filename));}bool8 S9xUnfreezeGame (const char *filename){ if (S9xLoadOrigSnapshot (filename)) return (TRUE); if (S9xUnfreezeZSNES (filename)) return (TRUE); STREAM snapshot = NULL; if (S9xOpenSnapshotFile (filename, TRUE, &snapshot)) { int result; if ((result = Unfreeze (snapshot)) != SUCCESS) { switch (result) { case WRONG_FORMAT: S9xMessage (S9X_ERROR, S9X_WRONG_FORMAT, "File not in Snes9x freeze format"); break; case WRONG_VERSION: S9xMessage (S9X_ERROR, S9X_WRONG_VERSION, "Incompatable Snes9x freeze file format version"); break; default: case FILE_NOT_FOUND: sprintf (String, "ROM image \"%s\" for freeze file not found", ROMFilename); S9xMessage (S9X_ERROR, S9X_ROM_NOT_FOUND, String); break; } S9xCloseSnapshotFile (snapshot); return (FALSE); } S9xCloseSnapshotFile (snapshot); return (TRUE); } return (FALSE);}static void Freeze (STREAM stream){ char buffer [1024]; int i; S9xSetSoundMute (TRUE);#ifdef ZSNES_FX if (Settings.SuperFX) S9xSuperFXPreSaveState ();#endif S9xSRTCPreSaveState (); for (i = 0; i < 8; i++) { SoundData.channels [i].previous16 [0] = (int16) SoundData.channels [i].previous [0]; SoundData.channels [i].previous16 [1] = (int16) SoundData.channels [i].previous [1]; } sprintf (buffer, "%s:%04d\n", SNAPSHOT_MAGIC, SNAPSHOT_VERSION); WRITE_STREAM (buffer, strlen (buffer), stream); sprintf (buffer, "NAM:%06d:%s%c", strlen (Memory.ROMFilename) + 1, Memory.ROMFilename, 0); WRITE_STREAM (buffer, strlen (buffer) + 1, stream); FreezeStruct (stream, "CPU", &CPU, SnapCPU, COUNT (SnapCPU)); FreezeStruct (stream, "REG", &Registers, SnapRegisters, COUNT (SnapRegisters)); FreezeStruct (stream, "PPU", &PPU, SnapPPU, COUNT (SnapPPU)); FreezeStruct (stream, "DMA", DMA, SnapDMA, COUNT (SnapDMA));// RAM and VRAM FreezeBlock (stream, "VRA", Memory.VRAM, 0x10000); FreezeBlock (stream, "RAM", Memory.RAM, 0x20000); FreezeBlock (stream, "SRA", ::SRAM, 0x20000); FreezeBlock (stream, "FIL", Memory.FillRAM, 0x8000); if (Settings.APUEnabled) {// APU FreezeStruct (stream, "APU", &APU, SnapAPU, COUNT (SnapAPU)); FreezeStruct (stream, "ARE", &APURegisters, SnapAPURegisters, COUNT (SnapAPURegisters)); FreezeBlock (stream, "ARA", IAPU.RAM, 0x10000); FreezeStruct (stream, "SOU", &SoundData, SnapSoundData, COUNT (SnapSoundData)); } if (Settings.SA1) { SA1Registers.PC = SA1.PC - SA1.PCBase; S9xSA1PackStatus (); FreezeStruct (stream, "SA1", &SA1, SnapSA1, COUNT (SnapSA1)); FreezeStruct (stream, "SAR", &SA1Registers, SnapSA1Registers, COUNT (SnapSA1Registers)); } S9xSetSoundMute (FALSE);#ifdef ZSNES_FX if (Settings.SuperFX) S9xSuperFXPostSaveState ();#endif}static int Unfreeze (STREAM stream){ char buffer [_MAX_PATH + 1]; char rom_filename [_MAX_PATH + 1]; int result; int version; int len = strlen (SNAPSHOT_MAGIC) + 1 + 4 + 1; if (READ_STREAM (buffer, len, stream) != len) return (WRONG_FORMAT); if (strncmp (buffer, SNAPSHOT_MAGIC, strlen (SNAPSHOT_MAGIC)) != 0) return (WRONG_FORMAT); if ((version = atoi (&buffer [strlen (SNAPSHOT_MAGIC) + 1])) > SNAPSHOT_VERSION) return (WRONG_VERSION); if ((result = UnfreezeBlock (stream, "NAM", (uint8 *) rom_filename, _MAX_PATH)) != SUCCESS) return (result); if (strcasecmp (rom_filename, Memory.ROMFilename) != 0 && strcasecmp (S9xBasename (rom_filename), S9xBasename (Memory.ROMFilename)) != 0) { S9xMessage (S9X_WARNING, S9X_FREEZE_ROM_NAME, "Current loaded ROM image doesn't match that required by freeze-game file."); } uint32 old_flags = CPU.Flags; uint32 sa1_old_flags = SA1.Flags; S9xReset (); S9xSetSoundMute (TRUE); if ((result = UnfreezeStruct (stream, "CPU", &CPU, SnapCPU, COUNT (SnapCPU))) != SUCCESS) return (result); Memory.FixROMSpeed (); CPU.Flags |= old_flags & (DEBUG_MODE_FLAG | TRACE_FLAG | SINGLE_STEP_FLAG | FRAME_ADVANCE_FLAG); if ((result = UnfreezeStruct (stream, "REG", &Registers, SnapRegisters, COUNT (SnapRegisters))) != SUCCESS) return (result); if ((result = UnfreezeStruct (stream, "PPU", &PPU, SnapPPU, COUNT (SnapPPU))) != SUCCESS) return (result); IPPU.ColorsChanged = TRUE; IPPU.OBJChanged = TRUE; CPU.InDMA = FALSE; S9xFixColourBrightness (); IPPU.RenderThisFrame = FALSE; if ((result = UnfreezeStruct (stream, "DMA", DMA, SnapDMA, COUNT (SnapDMA))) != SUCCESS) return (result); if ((result = UnfreezeBlock (stream, "VRA", Memory.VRAM, 0x10000)) != SUCCESS) return (result); if ((result = UnfreezeBlock (stream, "RAM", Memory.RAM, 0x20000)) != SUCCESS) return (result); if ((result = UnfreezeBlock (stream, "SRA", ::SRAM, 0x20000)) != SUCCESS) return (result); if ((result = UnfreezeBlock (stream, "FIL", Memory.FillRAM, 0x8000)) != SUCCESS) return (result); if (UnfreezeStruct (stream, "APU", &APU, SnapAPU, COUNT (SnapAPU)) == SUCCESS) { if ((result = UnfreezeStruct (stream, "ARE", &APURegisters, SnapAPURegisters, COUNT (SnapAPURegisters))) != SUCCESS) return (result); if ((result = UnfreezeBlock (stream, "ARA", IAPU.RAM, 0x10000)) != SUCCESS) return (result); if ((result = UnfreezeStruct (stream, "SOU", &SoundData, SnapSoundData, COUNT (SnapSoundData))) != SUCCESS) return (result); S9xSetSoundMute (FALSE); IAPU.PC = IAPU.RAM + APURegisters.PC; S9xAPUUnpackStatus (); if (APUCheckDirectPage ()) IAPU.DirectPage = IAPU.RAM + 0x100; else IAPU.DirectPage = IAPU.RAM; Settings.APUEnabled = TRUE; IAPU.APUExecuting = TRUE; } else { Settings.APUEnabled = FALSE; IAPU.APUExecuting = FALSE; S9xSetSoundMute (TRUE); } if ((result = UnfreezeStruct (stream, "SA1", &SA1, SnapSA1, COUNT(SnapSA1))) == SUCCESS) { if ((result = UnfreezeStruct (stream, "SAR", &SA1Registers, SnapSA1Registers, COUNT (SnapSA1Registers))) != SUCCESS) return (result); S9xFixSA1AfterSnapshotLoad (); SA1.Flags |= sa1_old_flags & (TRACE_FLAG); } S9xFixSoundAfterSnapshotLoad (); ICPU.ShiftedPB = Registers.PB << 16; ICPU.ShiftedDB = Registers.DB << 16; S9xSetPCBase (ICPU.ShiftedPB + Registers.PC); S9xUnpackStatus (); S9xFixCycles (); S9xReschedule ();#ifdef ZSNES_FX if (Settings.SuperFX) S9xSuperFXPostLoadState ();#endif S9xSRTCPostLoadState (); return (SUCCESS);}int FreezeSize (int size, int type){ switch (type) { case uint16_ARRAY_V: return (size * 2); case uint32_ARRAY_V: return (size * 4); default: return (size); }}void FreezeStruct (STREAM stream, char *name, void *base, FreezeData *fields, int num_fields){ // Work out the size of the required block int len = 0; int i; int j; for (i = 0; i < num_fields; i++) { if (fields [i].offset + FreezeSize (fields [i].size, fields [i].type) > len) len = fields [i].offset + FreezeSize (fields [i].size, fields [i].type); } uint8 *block = new uint8 [len]; uint8 *ptr = block; uint16 word; uint32 dword; int64 qword; // Build the block ready to be streamed out for (i = 0; i < num_fields; i++) { switch (fields [i].type) { case INT_V: switch (fields [i].size) { case 1: *ptr++ = *((uint8 *) base + fields [i].offset); break; case 2: word = *((uint16 *) ((uint8 *) base + fields [i].offset)); *ptr++ = (uint8) (word >> 8); *ptr++ = (uint8) word; break; case 4: dword = *((uint32 *) ((uint8 *) base + fields [i].offset)); *ptr++ = (uint8) (dword >> 24); *ptr++ = (uint8) (dword >> 16); *ptr++ = (uint8) (dword >> 8); *ptr++ = (uint8) dword; break; case 8: qword = *((int64 *) ((uint8 *) base + fields [i].offset)); *ptr++ = (uint8) (qword >> 56); *ptr++ = (uint8) (qword >> 48); *ptr++ = (uint8) (qword >> 40); *ptr++ = (uint8) (qword >> 32); *ptr++ = (uint8) (qword >> 24); *ptr++ = (uint8) (qword >> 16); *ptr++ = (uint8) (qword >> 8); *ptr++ = (uint8) qword; break; } break; case uint8_ARRAY_V: memmove (ptr, (uint8 *) base + fields [i].offset, fields [i].size); ptr += fields [i].size; break; case uint16_ARRAY_V: for (j = 0; j < fields [i].size; j++) { word = *((uint16 *) ((uint8 *) base + fields [i].offset + j * 2)); *ptr++ = (uint8) (word >> 8); *ptr++ = (uint8) word; } break; case uint32_ARRAY_V: for (j = 0; j < fields [i].size; j++) { dword = *((uint32 *) ((uint8 *) base + fields [i].offset + j * 4)); *ptr++ = (uint8) (dword >> 24); *ptr++ = (uint8) (dword >> 16); *ptr++ = (uint8) (dword >> 8); *ptr++ = (uint8) dword; } break; } } FreezeBlock (stream, name, block, len); delete block;}void FreezeBlock (STREAM stream, char *name, uint8 *block, int size){ char buffer [512]; sprintf (buffer, "%s:%06d:", name, size); WRITE_STREAM (buffer, strlen (buffer), stream); WRITE_STREAM (block, size, stream); }int UnfreezeStruct (STREAM stream, char *name, void *base, FreezeData *fields, int num_fields){ // Work out the size of the required block int len = 0; int i; int j; for (i = 0; i < num_fields; i++) { if (fields [i].offset + FreezeSize (fields [i].size, fields [i].type) > len) len = fields [i].offset + FreezeSize (fields [i].size, fields [i].type); } uint8 *block = new uint8 [len]; uint8 *ptr = block; uint16 word; uint32 dword; int64 qword; int result; if ((result = UnfreezeBlock (stream, name, block, len)) != SUCCESS) { delete block; return (result); } // Unpack the block of data into a C structure for (i = 0; i < num_fields; i++) { switch (fields [i].type) { case INT_V: switch (fields [i].size) { case 1: *((uint8 *) base + fields [i].offset) = *ptr++; break; case 2: word = *ptr++ << 8; word |= *ptr++; *((uint16 *) ((uint8 *) base + fields [i].offset)) = word; break; case 4: dword = *ptr++ << 24; dword |= *ptr++ << 16; dword |= *ptr++ << 8; dword |= *ptr++; *((uint32 *) ((uint8 *) base + fields [i].offset)) = dword; break; case 8: qword = (int64) *ptr++ << 56; qword |= (int64) *ptr++ << 48; qword |= (int64) *ptr++ << 40; qword |= (int64) *ptr++ << 32; qword |= (int64) *ptr++ << 24; qword |= (int64) *ptr++ << 16; qword |= (int64) *ptr++ << 8; qword |= (int64) *ptr++; *((int64 *) ((uint8 *) base + fields [i].offset)) = qword; break; } break; case uint8_ARRAY_V: memmove ((uint8 *) base + fields [i].offset, ptr, fields [i].size); ptr += fields [i].size; break; case uint16_ARRAY_V: for (j = 0; j < fields [i].size; j++) { word = *ptr++ << 8; word |= *ptr++; *((uint16 *) ((uint8 *) base + fields [i].offset + j * 2)) = word; } break; case uint32_ARRAY_V: for (j = 0; j < fields [i].size; j++) { dword = *ptr++ << 24; dword |= *ptr++ << 16; dword |= *ptr++ << 8; dword |= *ptr++; *((uint32 *) ((uint8 *) base + fields [i].offset + j * 4)) = dword; } break; }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -