static int ReadOrigSnapshot(STREAM snap) { char buffer [_MAX_PATH]; char rom_filename [_MAX_PATH]; int result; int i; int j; int version; int len = strlen(ORIG_SNAPSHOT_MAGIC) + 1 + 4 + 1; if (READ_STREAM(buffer, len, snap) != len) return (WRONG_FORMAT); if (strncmp(buffer, ORIG_SNAPSHOT_MAGIC, strlen(ORIG_SNAPSHOT_MAGIC)) != 0) return (WRONG_FORMAT); if ((version = atoi(&buffer [strlen(SNAPSHOT_MAGIC) + 1])) > ORIG_SNAPSHOT_VERSION) return (WRONG_VERSION); if ((result = ReadBlock("NAM:", rom_filename, _MAX_PATH, snap)) != SUCCESS) return (result); if ((result = ReadBlock("HiR:", buffer, 0x41, snap)) != 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."); } S9xReset(); S9xSetSoundMute(TRUE); if ((result = ReadBlock("CPU:", &OrigCPU, sizeof(OrigCPU), snap)) != SUCCESS) return (result); OrigCPU.FastROMSpeed = OrigCPU.FastROMSpeed_old; Memory.FixROMSpeed(); if (version == 3) { OrigCPU.Cycles = OrigCPU.Cycles_old; OrigCPU.NextEvent = OrigCPU.NextEvent_old; OrigCPU.V_Counter = OrigCPU.V_Counter_old; OrigCPU.MemSpeed = OrigCPU.MemSpeed_old; OrigCPU.MemSpeedx2 = OrigCPU.MemSpeedx2_old; OrigCPU.FastROMSpeed = OrigCPU.FastROMSpeed_old; } CPU.Flags = OrigCPU.Flags; CPU.BranchSkip = OrigCPU.BranchSkip; CPU.NMIActive = OrigCPU.NMIActive; CPU.IRQActive = OrigCPU.IRQActive; CPU.WaitingForInterrupt = OrigCPU.WaitingForInterrupt; CPU.WhichEvent = OrigCPU.WhichEvent; CPU.Cycles = OrigCPU.Cycles; CPU.NextEvent = OrigCPU.NextEvent; CPU.V_Counter = OrigCPU.V_Counter; CPU.MemSpeed = OrigCPU.MemSpeed; CPU.MemSpeedx2 = OrigCPU.MemSpeedx2; CPU.FastROMSpeed = OrigCPU.FastROMSpeed; if ((result = ReadBlock("REG:", &OrigRegisters, sizeof(OrigRegisters), snap)) != SUCCESS) return (result); Registers = *(struct SRegisters*) &OrigRegisters; if ((result = ReadBlock("PPU:", &OrigPPU, sizeof(OrigPPU), snap)) != SUCCESS) return (result); if (version == 2) { OrigPPU.OBJNameSelect = OrigPPU.OBJNameSelect_old << 13; OrigPPU.OBJNameBase <<= 1; OrigPPU.OBJNameSelect <<= 13; } PPU.BGMode = OrigPPU.BGMode; PPU.BG3Priority = OrigPPU.BG3Priority; PPU.Brightness = OrigPPU.Brightness; PPU.VMA.High = OrigPPU.VMA.High; PPU.VMA.Increment = OrigPPU.VMA.Increment; PPU.VMA.Address = OrigPPU.VMA.Address; PPU.VMA.Mask1 = OrigPPU.VMA.Mask1; PPU.VMA.FullGraphicCount = OrigPPU.VMA.FullGraphicCount; PPU.VMA.Shift = OrigPPU.VMA.Shift; for (i = 0; i < 4; i++) { PPU.BG[i].SCBase = OrigPPU.BG[i].SCBase; PPU.BG[i].VOffset = OrigPPU.BG[i].VOffset; PPU.BG[i].HOffset = OrigPPU.BG[i].HOffset; PPU.BG[i].BGSize = OrigPPU.BG[i].BGSize; PPU.BG[i].NameBase = OrigPPU.BG[i].NameBase; PPU.BG[i].SCSize = OrigPPU.BG[i].SCSize; } PPU.CGFLIP = OrigPPU.CGFLIP; for (i = 0; i < 256; i++) PPU.CGDATA [i] = OrigPPU.CGDATA [i]; PPU.FirstSprite = OrigPPU.FirstSprite; for (i = 0; i < 128; i++) { PPU.OBJ[i].HPos = OrigPPU.OBJ [i].HPos; PPU.OBJ[i].VPos = OrigPPU.OBJ [i].VPos; PPU.OBJ[i].Name = OrigPPU.OBJ [i].Name; PPU.OBJ[i].VFlip = OrigPPU.OBJ [i].VFlip; PPU.OBJ[i].HFlip = OrigPPU.OBJ [i].HFlip; PPU.OBJ[i].Priority = OrigPPU.OBJ [i].Priority; PPU.OBJ[i].Palette = OrigPPU.OBJ [i].Palette; PPU.OBJ[i].Size = OrigPPU.OBJ [i].Size; } PPU.OAMPriorityRotation = OrigPPU.OAMPriorityRotation; PPU.OAMAddr = OrigPPU.OAMAddr; PPU.OAMFlip = OrigPPU.OAMFlip; PPU.OAMTileAddress = OrigPPU.OAMTileAddress; PPU.IRQVBeamPos = OrigPPU.IRQVBeamPos; PPU.IRQHBeamPos = OrigPPU.IRQHBeamPos; PPU.VBeamPosLatched = OrigPPU.VBeamPosLatched; PPU.HBeamPosLatched = OrigPPU.HBeamPosLatched; PPU.HBeamFlip = OrigPPU.HBeamFlip; PPU.VBeamFlip = OrigPPU.VBeamFlip; PPU.HVBeamCounterLatched = OrigPPU.HVBeamCounterLatched; PPU.MatrixA = OrigPPU.MatrixA; PPU.MatrixB = OrigPPU.MatrixB; PPU.MatrixC = OrigPPU.MatrixC; PPU.MatrixD = OrigPPU.MatrixD; PPU.CentreX = OrigPPU.CentreX; PPU.CentreY = OrigPPU.CentreY; PPU.Joypad1ButtonReadPos = OrigPPU.Joypad1ButtonReadPos; PPU.Joypad2ButtonReadPos = OrigPPU.Joypad2ButtonReadPos; PPU.Joypad3ButtonReadPos = OrigPPU.Joypad3ButtonReadPos; PPU.CGADD = OrigPPU.CGADD; PPU.FixedColourRed = OrigPPU.FixedColourRed; PPU.FixedColourGreen = OrigPPU.FixedColourGreen; PPU.FixedColourBlue = OrigPPU.FixedColourBlue; PPU.SavedOAMAddr = OrigPPU.SavedOAMAddr; PPU.ScreenHeight = OrigPPU.ScreenHeight; PPU.WRAM = OrigPPU.WRAM; PPU.ForcedBlanking = OrigPPU.ForcedBlanking; PPU.OBJNameSelect = OrigPPU.OBJNameSelect; PPU.OBJSizeSelect = OrigPPU.OBJSizeSelect; PPU.OBJNameBase = OrigPPU.OBJNameBase; PPU.OAMReadFlip = OrigPPU.OAMReadFlip; memmove(PPU.OAMData, OrigPPU.OAMData, sizeof(PPU.OAMData)); PPU.VTimerEnabled = OrigPPU.VTimerEnabled; PPU.HTimerEnabled = OrigPPU.HTimerEnabled; PPU.HTimerPosition = OrigPPU.HTimerPosition; PPU.Mosaic = OrigPPU.Mosaic; memmove(PPU.BGMosaic, OrigPPU.BGMosaic, sizeof(PPU.BGMosaic)); PPU.Mode7HFlip = OrigPPU.Mode7HFlip; PPU.Mode7VFlip = OrigPPU.Mode7VFlip; PPU.Mode7Repeat = OrigPPU.Mode7Repeat; PPU.Window1Left = OrigPPU.Window1Left; PPU.Window1Right = OrigPPU.Window1Right; PPU.Window2Left = OrigPPU.Window2Left; PPU.Window2Right = OrigPPU.Window2Right; for (i = 0; i < 6; i++) { PPU.ClipWindowOverlapLogic [i] = OrigPPU.ClipWindowOverlapLogic [i]; PPU.ClipWindow1Enable [i] = OrigPPU.ClipWindow1Enable [i]; PPU.ClipWindow2Enable [i] = OrigPPU.ClipWindow2Enable [i]; PPU.ClipWindow1Inside [i] = OrigPPU.ClipWindow1Inside [i]; PPU.ClipWindow2Inside [i] = OrigPPU.ClipWindow2Inside [i]; } PPU.CGFLIPRead = OrigPPU.CGFLIPRead; PPU.Need16x8Mulitply = OrigPPU.Need16x8Mulitply; IPPU.ColorsChanged = TRUE; IPPU.OBJChanged = TRUE; S9xFixColourBrightness(); IPPU.RenderThisFrame = FALSE; if ((result = ReadBlock("DMA:", OrigDMA, sizeof(OrigDMA), snap)) != SUCCESS) return (result); for (i = 0; i < 8; i++) { DMA[i].TransferDirection = OrigDMA[i].TransferDirection; DMA[i].AAddressFixed = OrigDMA[i].AAddressFixed; DMA[i].AAddressDecrement = OrigDMA[i].AAddressDecrement; DMA[i].TransferMode = OrigDMA[i].TransferMode; DMA[i].ABank = OrigDMA[i].ABank; DMA[i].AAddress = OrigDMA[i].AAddress; DMA[i].Address = OrigDMA[i].Address; DMA[i].BAddress = OrigDMA[i].BAddress; DMA[i].TransferBytes = OrigDMA[i].TransferBytes; DMA[i].HDMAIndirectAddressing = OrigDMA[i].HDMAIndirectAddressing; DMA[i].IndirectAddress = OrigDMA[i].IndirectAddress; DMA[i].IndirectBank = OrigDMA[i].IndirectBank; DMA[i].Repeat = OrigDMA[i].Repeat; DMA[i].LineCount = OrigDMA[i].LineCount; DMA[i].FirstLine = OrigDMA[i].FirstLine; } if ((result = ReadBlock("VRA:", Memory.VRAM, 0x10000, snap)) != SUCCESS) return (result); if ((result = ReadBlock("RAM:", Memory.RAM, 0x20000, snap)) != SUCCESS) return (result); if ((result = ReadBlock("SRA:", SRAM, 0x10000, snap)) != SUCCESS) return (result); if ((result = ReadBlock("FIL:", Memory.FillRAM, 0x8000, snap)) != SUCCESS) return (result); if (ReadBlock("APU:", &OrigAPU, sizeof(OrigAPU), snap) == SUCCESS) { APU = *(struct SAPU*) &OrigAPU; if ((result = ReadBlock("ARE:", &OrigAPURegisters, sizeof(OrigAPURegisters), snap)) != SUCCESS) return (result); APURegisters = *(struct SAPURegisters*) &OrigAPURegisters; if ((result = ReadBlock("ARA:", IAPU.RAM, 0x10000, snap)) != SUCCESS) return (result); if ((result = ReadBlock("SOU:", &OrigSoundData, sizeof(SOrigSoundData), snap)) != SUCCESS) return (result); SoundData.master_volume_left = OrigSoundData.master_volume_left; SoundData.master_volume_right = OrigSoundData.master_volume_right; SoundData.echo_volume_left = OrigSoundData.echo_volume_left; SoundData.echo_volume_right = OrigSoundData.echo_volume_right; SoundData.echo_enable = OrigSoundData.echo_enable; SoundData.echo_feedback = OrigSoundData.echo_feedback; SoundData.echo_ptr = OrigSoundData.echo_ptr; SoundData.echo_buffer_size = OrigSoundData.echo_buffer_size; SoundData.echo_write_enabled = OrigSoundData.echo_write_enabled; SoundData.echo_channel_enable = OrigSoundData.echo_channel_enable; SoundData.pitch_mod = OrigSoundData.pitch_mod; for (i = 0; i < 3; i++) SoundData.dummy [i] = OrigSoundData.dummy [i]; for (i = 0; i < NUM_CHANNELS; i++) { SoundData.channels [i].state = OrigSoundData.channels [i].state; SoundData.channels [i].type = OrigSoundData.channels [i].type; SoundData.channels [i].volume_left = OrigSoundData.channels [i].volume_left; SoundData.channels [i].volume_right = OrigSoundData.channels [i].volume_right; SoundData.channels [i].hertz = OrigSoundData.channels [i].frequency; SoundData.channels [i].count = OrigSoundData.channels [i].count; SoundData.channels [i].loop = OrigSoundData.channels [i].loop; SoundData.channels [i].envx = OrigSoundData.channels [i].envx; SoundData.channels [i].left_vol_level = OrigSoundData.channels [i].left_vol_level; SoundData.channels [i].right_vol_level = OrigSoundData.channels [i].right_vol_level; SoundData.channels [i].envx_target = OrigSoundData.channels [i].envx_target; SoundData.channels [i].env_error = OrigSoundData.channels [i].env_error; SoundData.channels [i].erate = OrigSoundData.channels [i].erate; SoundData.channels [i].direction = OrigSoundData.channels [i].direction; SoundData.channels [i].attack_rate = OrigSoundData.channels [i].attack_rate; SoundData.channels [i].decay_rate = OrigSoundData.channels [i].decay_rate; SoundData.channels [i].sustain_rate = OrigSoundData.channels [i].sustain_rate; SoundData.channels [i].release_rate = OrigSoundData.channels [i].release_rate; SoundData.channels [i].sustain_level = OrigSoundData.channels [i].sustain_level; SoundData.channels [i].sample = OrigSoundData.channels [i].sample; for (j = 0; j < 16; j++) SoundData.channels [i].decoded [j] = OrigSoundData.channels [i].decoded [j]; for (j = 0; j < 2; j++) SoundData.channels [i].previous [j] = OrigSoundData.channels [i].previous [j]; SoundData.channels [i].sample_number = OrigSoundData.channels [i].sample_number; SoundData.channels [i].last_block = OrigSoundData.channels [i].last_block; SoundData.channels [i].needs_decode = OrigSoundData.channels [i].needs_decode; SoundData.channels [i].block_pointer = OrigSoundData.channels [i].block_pointer; SoundData.channels [i].sample_pointer = OrigSoundData.channels [i].sample_pointer; SoundData.channels [i].mode = OrigSoundData.channels [i].mode; } S9xSetSoundMute(FALSE); IAPU.PC = IAPU.RAM + IAPU.PC; S9xAPUUnpackStatus(); if (APUCheckDirectPage()) IAPU.DirectPage = IAPU.RAM + 0x100; else IAPU.DirectPage = IAPU.RAM; Settings.APUEnabled = TRUE; CPU.APU_APUExecuting = TRUE; } else { Settings.APUEnabled = FALSE; CPU.APU_APUExecuting = FALSE; S9xSetSoundMute(TRUE); } S9xFixSoundAfterSnapshotLoad(); ICPU.ShiftedPB = Registers.PB << 16; ICPU.ShiftedDB = Registers.DB << 16; S9xSetPCBase(ICPU.ShiftedPB + Registers.PC, &CPU); S9xUnpackStatus(); S9xFixCycles(&Registers, &ICPU); S9xReschedule(); return (SUCCESS); }
/* Restore SPC state ---------------------------------------------------------------- */ static void RestoreSPC() { int i; APURegisters.PC = BackupAPURegisters.PC; APURegisters.YA.B.A = BackupAPURegisters.YA.B.A; APURegisters.X = BackupAPURegisters.X; APURegisters.YA.B.Y = BackupAPURegisters.YA.B.Y; APURegisters.P = BackupAPURegisters.P; APURegisters.S = BackupAPURegisters.S; memcpy (IAPU.RAM, BackupAPURAM, 65536); memcpy (APU.ExtraRAM, BackupAPUExtraRAM, 64); memcpy (APU.DSP, BackupDSPRAM, 128); for (i = 0; i < 4; i ++) { APU.OutPorts[i] = IAPU.RAM[0xf4 + i]; } IAPU.TimerErrorCounter = 0; for (i = 0; i < 3; i ++) { if (IAPU.RAM[0xfa + i] == 0) APU.TimerTarget[i] = 0x100; else APU.TimerTarget[i] = IAPU.RAM[0xfa + i]; } S9xSetAPUControl (IAPU.RAM[0xf1]); /* from snaporig.cpp (ReadOrigSnapshot) */ 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; S9xFixSoundAfterSnapshotLoad (); S9xSetFrequencyModulationEnable (APU.DSP[APU_PMON]); S9xSetMasterVolume (APU.DSP[APU_MVOL_LEFT], APU.DSP[APU_MVOL_RIGHT]); S9xSetEchoVolume (APU.DSP[APU_EVOL_LEFT], APU.DSP[APU_EVOL_RIGHT]); uint8 mask = 1; int type; for (i = 0; i < 8; i++, mask <<= 1) { Channel *ch = &SoundData.channels[i]; S9xFixEnvelope (i, APU.DSP[APU_GAIN + (i << 4)], APU.DSP[APU_ADSR1 + (i << 4)], APU.DSP[APU_ADSR2 + (i << 4)]); S9xSetSoundVolume (i, APU.DSP[APU_VOL_LEFT + (i << 4)], APU.DSP[APU_VOL_RIGHT + (i << 4)]); S9xSetSoundFrequency (i, ((APU.DSP[APU_P_LOW + (i << 4)] + (APU.DSP[APU_P_HIGH + (i << 4)] << 8)) & FREQUENCY_MASK) * 8); if (APU.DSP [APU_NON] & mask) type = SOUND_NOISE; else type = SOUND_SAMPLE; S9xSetSoundType (i, type); if ((APU.DSP[APU_KON] & mask) != 0) { APU.KeyedChannels |= mask; S9xPlaySample (i); } } #if 0 unsigned char temp=IAPU.RAM[0xf2]; for(i=0; i<128; i++) { IAPU.RAM[0xf2]=i; S9xSetAPUDSP(APU.DSP[i]); } IAPU.RAM[0xf2]=temp; #endif }