2 * Snes9x - Portable Super Nintendo Entertainment System (TM) emulator.
4 * (c) Copyright 1996 - 2001 Gary Henderson (gary.henderson@ntlworld.com) and
5 * Jerremy Koot (jkoot@snes9x.com)
7 * Super FX C emulator code
8 * (c) Copyright 1997 - 1999 Ivar (ivar@snes9x.com) and
10 * Super FX assembler emulator code (c) Copyright 1998 zsKnight and _Demo_.
12 * DSP1 emulator code (c) Copyright 1998 Ivar, _Demo_ and Gary Henderson.
13 * C4 asm and some C emulation code (c) Copyright 2000 zsKnight and _Demo_.
14 * C4 C code (c) Copyright 2001 Gary Henderson (gary.henderson@ntlworld.com).
16 * DOS port code contains the works of other authors. See headers in
19 * Snes9x homepage: http://www.snes9x.com
21 * Permission to use, copy, modify and distribute Snes9x in both binary and
22 * source form, for non-commercial purposes, is hereby granted without fee,
23 * providing that this license information and copyright notice appear with
24 * all copies and any derived work.
26 * This software is provided 'as-is', without any express or implied
27 * warranty. In no event shall the authors be held liable for any damages
28 * arising from the use of this software.
30 * Snes9x is freeware for PERSONAL USE only. Commercial users should
31 * seek permission of the copyright holders first. Commercial use includes
32 * charging money for Snes9x or software derived from Snes9x.
34 * The copyright holders request that bug fixes and improvements to the code
35 * should be forwarded to them so everyone can benefit from the modifications
38 * Super NES and Super Nintendo Entertainment System are trademarks of
39 * Nintendo Co., Limited and its subsidiary companies.
45 #if defined(__unix) || defined(__linux) || defined(__sun) || defined(__DJGPP)
47 #include <sys/types.h>
62 struct SOrigPPU OrigPPU;
63 struct SOrigDMA OrigDMA [8];
64 struct SOrigRegisters OrigRegisters;
65 struct SOrigCPUState OrigCPU;
66 struct SOrigAPU OrigAPU;
67 SOrigSoundData OrigSoundData;
68 struct SOrigAPURegisters OrigAPURegisters;
69 char ROMFilename [1025];
71 static int ReadOrigSnapshot (STREAM);
73 bool8_32 S9xLoadOrigSnapshot (const char *filename)
75 STREAM snapshot = NULL;
76 if (S9xOpenSnapshotFile (filename, TRUE, &snapshot))
79 if ((result = ReadOrigSnapshot (snapshot)) != SUCCESS)
81 S9xCloseSnapshotFile (snapshot);
84 S9xCloseSnapshotFile (snapshot);
91 #pragma warning(disable : 4018)
93 static int ReadBlock (const char *key, void *block, int max_len, STREAM snap)
99 if (READ_STREAM (buffer, 11, snap) != 11 ||
100 strncmp (buffer, key, 4) != 0 ||
101 (len = atoi (&buffer [4])) == 0)
102 return (WRONG_FORMAT);
109 if (READ_STREAM (block, len, snap) != len)
110 return (WRONG_FORMAT);
114 char *junk = new char [rem];
115 READ_STREAM (junk, rem, snap);
122 static int ReadOrigSnapshot (STREAM snap)
124 char buffer [_MAX_PATH];
125 char rom_filename [_MAX_PATH];
131 int len = strlen (ORIG_SNAPSHOT_MAGIC) + 1 + 4 + 1;
132 if (READ_STREAM (buffer, len, snap) != len)
133 return (WRONG_FORMAT);
134 if (strncmp (buffer, ORIG_SNAPSHOT_MAGIC, strlen (ORIG_SNAPSHOT_MAGIC)) != 0)
135 return (WRONG_FORMAT);
136 if ((version = atoi (&buffer [strlen (SNAPSHOT_MAGIC) + 1])) > ORIG_SNAPSHOT_VERSION)
137 return (WRONG_VERSION);
139 if ((result = ReadBlock ("NAM:", rom_filename, _MAX_PATH, snap)) != SUCCESS)
142 if ((result = ReadBlock ("HiR:", buffer, 0x41, snap)) != SUCCESS)
145 if (strcasecmp (rom_filename, Memory.ROMFilename) != 0 &&
146 strcasecmp (S9xBasename (rom_filename), S9xBasename (Memory.ROMFilename)) != 0)
148 S9xMessage (S9X_WARNING, S9X_FREEZE_ROM_NAME,
149 "Current loaded ROM image doesn't match that required by freeze-game file.");
153 S9xSetSoundMute (TRUE);
154 if ((result = ReadBlock ("CPU:", &OrigCPU, sizeof (OrigCPU), snap)) != SUCCESS)
156 OrigCPU.FastROMSpeed = OrigCPU.FastROMSpeed_old;
157 Memory.FixROMSpeed ();
160 OrigCPU.Cycles = OrigCPU.Cycles_old;
161 OrigCPU.NextEvent = OrigCPU.NextEvent_old;
162 OrigCPU.V_Counter = OrigCPU.V_Counter_old;
163 OrigCPU.MemSpeed = OrigCPU.MemSpeed_old;
164 OrigCPU.MemSpeedx2 = OrigCPU.MemSpeedx2_old;
165 OrigCPU.FastROMSpeed = OrigCPU.FastROMSpeed_old;
167 CPU.Flags = OrigCPU.Flags;
168 CPU.BranchSkip = OrigCPU.BranchSkip;
169 CPU.NMIActive = OrigCPU.NMIActive;
170 CPU.IRQActive = OrigCPU.IRQActive;
171 CPU.WaitingForInterrupt = OrigCPU.WaitingForInterrupt;
172 CPU.WhichEvent = OrigCPU.WhichEvent;
173 CPU.Cycles = OrigCPU.Cycles;
174 CPU.NextEvent = OrigCPU.NextEvent;
175 CPU.V_Counter = OrigCPU.V_Counter;
176 CPU.MemSpeed = OrigCPU.MemSpeed;
177 CPU.MemSpeedx2 = OrigCPU.MemSpeedx2;
178 CPU.FastROMSpeed = OrigCPU.FastROMSpeed;
180 if ((result = ReadBlock ("REG:", &OrigRegisters, sizeof (OrigRegisters), snap)) != SUCCESS)
183 Registers = *(struct SRegisters *) &OrigRegisters;
185 if ((result = ReadBlock ("PPU:", &OrigPPU, sizeof (OrigPPU), snap)) != SUCCESS)
190 OrigPPU.OBJNameSelect = OrigPPU.OBJNameSelect_old << 13;
191 OrigPPU.OBJNameBase <<= 1;
192 OrigPPU.OBJNameSelect <<= 13;
194 PPU.BGMode = OrigPPU.BGMode;
195 PPU.BG3Priority = OrigPPU.BG3Priority;
196 PPU.Brightness = OrigPPU.Brightness;
198 PPU.VMA.High = OrigPPU.VMA.High;
199 PPU.VMA.Increment = OrigPPU.VMA.Increment;
200 PPU.VMA.Address = OrigPPU.VMA.Address;
201 PPU.VMA.Mask1 = OrigPPU.VMA.Mask1;
202 PPU.VMA.FullGraphicCount = OrigPPU.VMA.FullGraphicCount;
203 PPU.VMA.Shift = OrigPPU.VMA.Shift;
205 for (i = 0; i < 4; i++)
207 PPU.BG[i].SCBase = OrigPPU.BG[i].SCBase;
208 PPU.BG[i].VOffset = OrigPPU.BG[i].VOffset;
209 PPU.BG[i].HOffset = OrigPPU.BG[i].HOffset;
210 PPU.BG[i].BGSize = OrigPPU.BG[i].BGSize;
211 PPU.BG[i].NameBase = OrigPPU.BG[i].NameBase;
212 PPU.BG[i].SCSize = OrigPPU.BG[i].SCSize;
215 PPU.CGFLIP = OrigPPU.CGFLIP;
216 for (i = 0; i < 256; i++)
217 PPU.CGDATA [i] = OrigPPU.CGDATA [i];
218 PPU.FirstSprite = OrigPPU.FirstSprite;
219 for (i = 0; i < 128; i++)
221 PPU.OBJ[i].HPos = OrigPPU.OBJ [i].HPos;
222 PPU.OBJ[i].VPos = OrigPPU.OBJ [i].VPos;
223 PPU.OBJ[i].Name = OrigPPU.OBJ [i].Name;
224 PPU.OBJ[i].VFlip = OrigPPU.OBJ [i].VFlip;
225 PPU.OBJ[i].HFlip = OrigPPU.OBJ [i].HFlip;
226 PPU.OBJ[i].Priority = OrigPPU.OBJ [i].Priority;
227 PPU.OBJ[i].Palette = OrigPPU.OBJ [i].Palette;
228 PPU.OBJ[i].Size = OrigPPU.OBJ [i].Size;
230 PPU.OAMPriorityRotation = OrigPPU.OAMPriorityRotation;
231 PPU.OAMAddr = OrigPPU.OAMAddr;
233 PPU.OAMFlip = OrigPPU.OAMFlip;
234 PPU.OAMTileAddress = OrigPPU.OAMTileAddress;
235 PPU.IRQVBeamPos = OrigPPU.IRQVBeamPos;
236 PPU.IRQHBeamPos = OrigPPU.IRQHBeamPos;
237 PPU.VBeamPosLatched = OrigPPU.VBeamPosLatched;
238 PPU.HBeamPosLatched = OrigPPU.HBeamPosLatched;
240 PPU.HBeamFlip = OrigPPU.HBeamFlip;
241 PPU.VBeamFlip = OrigPPU.VBeamFlip;
242 PPU.HVBeamCounterLatched = OrigPPU.HVBeamCounterLatched;
244 PPU.MatrixA = OrigPPU.MatrixA;
245 PPU.MatrixB = OrigPPU.MatrixB;
246 PPU.MatrixC = OrigPPU.MatrixC;
247 PPU.MatrixD = OrigPPU.MatrixD;
248 PPU.CentreX = OrigPPU.CentreX;
249 PPU.CentreY = OrigPPU.CentreY;
250 PPU.Joypad1ButtonReadPos = OrigPPU.Joypad1ButtonReadPos;
251 PPU.Joypad2ButtonReadPos = OrigPPU.Joypad2ButtonReadPos;
252 PPU.Joypad3ButtonReadPos = OrigPPU.Joypad3ButtonReadPos;
254 PPU.CGADD = OrigPPU.CGADD;
255 PPU.FixedColourRed = OrigPPU.FixedColourRed;
256 PPU.FixedColourGreen = OrigPPU.FixedColourGreen;
257 PPU.FixedColourBlue = OrigPPU.FixedColourBlue;
258 PPU.SavedOAMAddr = OrigPPU.SavedOAMAddr;
259 PPU.ScreenHeight = OrigPPU.ScreenHeight;
260 PPU.WRAM = OrigPPU.WRAM;
261 PPU.ForcedBlanking = OrigPPU.ForcedBlanking;
262 PPU.OBJNameSelect = OrigPPU.OBJNameSelect;
263 PPU.OBJSizeSelect = OrigPPU.OBJSizeSelect;
264 PPU.OBJNameBase = OrigPPU.OBJNameBase;
265 PPU.OAMReadFlip = OrigPPU.OAMReadFlip;
266 memmove (PPU.OAMData, OrigPPU.OAMData, sizeof (PPU.OAMData));
267 PPU.VTimerEnabled = OrigPPU.VTimerEnabled;
268 PPU.HTimerEnabled = OrigPPU.HTimerEnabled;
269 PPU.HTimerPosition = OrigPPU.HTimerPosition;
270 PPU.Mosaic = OrigPPU.Mosaic;
271 memmove (PPU.BGMosaic, OrigPPU.BGMosaic, sizeof (PPU.BGMosaic));
272 PPU.Mode7HFlip = OrigPPU.Mode7HFlip;
273 PPU.Mode7VFlip = OrigPPU.Mode7VFlip;
274 PPU.Mode7Repeat = OrigPPU.Mode7Repeat;
275 PPU.Window1Left = OrigPPU.Window1Left;
276 PPU.Window1Right = OrigPPU.Window1Right;
277 PPU.Window2Left = OrigPPU.Window2Left;
278 PPU.Window2Right = OrigPPU.Window2Right;
279 for (i = 0; i < 6; i++)
281 PPU.ClipWindowOverlapLogic [i] = OrigPPU.ClipWindowOverlapLogic [i];
282 PPU.ClipWindow1Enable [i] = OrigPPU.ClipWindow1Enable [i];
283 PPU.ClipWindow2Enable [i] = OrigPPU.ClipWindow2Enable [i];
284 PPU.ClipWindow1Inside [i] = OrigPPU.ClipWindow1Inside [i];
285 PPU.ClipWindow2Inside [i] = OrigPPU.ClipWindow2Inside [i];
287 PPU.CGFLIPRead = OrigPPU.CGFLIPRead;
288 PPU.Need16x8Mulitply = OrigPPU.Need16x8Mulitply;
290 IPPU.ColorsChanged = TRUE;
291 IPPU.OBJChanged = TRUE;
292 S9xFixColourBrightness ();
293 IPPU.RenderThisFrame = FALSE;
295 if ((result = ReadBlock ("DMA:", OrigDMA, sizeof (OrigDMA), snap)) != SUCCESS)
298 for (i = 0; i < 8; i++)
300 DMA[i].TransferDirection = OrigDMA[i].TransferDirection;
301 DMA[i].AAddressFixed = OrigDMA[i].AAddressFixed;
302 DMA[i].AAddressDecrement = OrigDMA[i].AAddressDecrement;
303 DMA[i].TransferMode = OrigDMA[i].TransferMode;
304 DMA[i].ABank = OrigDMA[i].ABank;
305 DMA[i].AAddress = OrigDMA[i].AAddress;
306 DMA[i].Address = OrigDMA[i].Address;
307 DMA[i].BAddress = OrigDMA[i].BAddress;
308 DMA[i].TransferBytes = OrigDMA[i].TransferBytes;
309 DMA[i].HDMAIndirectAddressing = OrigDMA[i].HDMAIndirectAddressing;
310 DMA[i].IndirectAddress = OrigDMA[i].IndirectAddress;
311 DMA[i].IndirectBank = OrigDMA[i].IndirectBank;
312 DMA[i].Repeat = OrigDMA[i].Repeat;
313 DMA[i].LineCount = OrigDMA[i].LineCount;
314 DMA[i].FirstLine = OrigDMA[i].FirstLine;
317 if ((result = ReadBlock ("VRA:", Memory.VRAM, 0x10000, snap)) != SUCCESS)
319 if ((result = ReadBlock ("RAM:", Memory.RAM, 0x20000, snap)) != SUCCESS)
321 if ((result = ReadBlock ("SRA:", ::SRAM, 0x10000, snap)) != SUCCESS)
323 if ((result = ReadBlock ("FIL:", Memory.FillRAM, 0x8000, snap)) != SUCCESS)
325 if (ReadBlock ("APU:", &OrigAPU, sizeof (OrigAPU), snap) == SUCCESS)
327 APU = *(struct SAPU *) &OrigAPU;
329 if ((result = ReadBlock ("ARE:", &OrigAPURegisters,
330 sizeof (OrigAPURegisters), snap)) != SUCCESS)
332 APURegisters = *(struct SAPURegisters *) &OrigAPURegisters;
333 if ((result = ReadBlock ("ARA:", IAPU.RAM, 0x10000, snap)) != SUCCESS)
335 if ((result = ReadBlock ("SOU:", &OrigSoundData,
336 sizeof (SOrigSoundData), snap)) != SUCCESS)
339 SoundData.master_volume_left = OrigSoundData.master_volume_left;
340 SoundData.master_volume_right = OrigSoundData.master_volume_right;
341 SoundData.echo_volume_left = OrigSoundData.echo_volume_left;
342 SoundData.echo_volume_right = OrigSoundData.echo_volume_right;
343 SoundData.echo_enable = OrigSoundData.echo_enable;
344 SoundData.echo_feedback = OrigSoundData.echo_feedback;
345 SoundData.echo_ptr = OrigSoundData.echo_ptr;
346 SoundData.echo_buffer_size = OrigSoundData.echo_buffer_size;
347 SoundData.echo_write_enabled = OrigSoundData.echo_write_enabled;
348 SoundData.echo_channel_enable = OrigSoundData.echo_channel_enable;
349 SoundData.pitch_mod = OrigSoundData.pitch_mod;
351 for (i = 0; i < 3; i++)
352 SoundData.dummy [i] = OrigSoundData.dummy [i];
353 for (i = 0; i < NUM_CHANNELS; i++)
355 SoundData.channels [i].state = OrigSoundData.channels [i].state;
356 SoundData.channels [i].type = OrigSoundData.channels [i].type;
357 SoundData.channels [i].volume_left = OrigSoundData.channels [i].volume_left;
358 SoundData.channels [i].volume_right = OrigSoundData.channels [i].volume_right;
359 SoundData.channels [i].hertz = OrigSoundData.channels [i].frequency;
360 SoundData.channels [i].count = OrigSoundData.channels [i].count;
361 SoundData.channels [i].loop = OrigSoundData.channels [i].loop;
362 SoundData.channels [i].envx = OrigSoundData.channels [i].envx;
363 SoundData.channels [i].left_vol_level = OrigSoundData.channels [i].left_vol_level;
364 SoundData.channels [i].right_vol_level = OrigSoundData.channels [i].right_vol_level;
365 SoundData.channels [i].envx_target = OrigSoundData.channels [i].envx_target;
366 SoundData.channels [i].env_error = OrigSoundData.channels [i].env_error;
367 SoundData.channels [i].erate = OrigSoundData.channels [i].erate;
368 SoundData.channels [i].direction = OrigSoundData.channels [i].direction;
369 SoundData.channels [i].attack_rate = OrigSoundData.channels [i].attack_rate;
370 SoundData.channels [i].decay_rate = OrigSoundData.channels [i].decay_rate;
371 SoundData.channels [i].sustain_rate = OrigSoundData.channels [i].sustain_rate;
372 SoundData.channels [i].release_rate = OrigSoundData.channels [i].release_rate;
373 SoundData.channels [i].sustain_level = OrigSoundData.channels [i].sustain_level;
374 SoundData.channels [i].sample = OrigSoundData.channels [i].sample;
375 for (j = 0; j < 16; j++)
376 SoundData.channels [i].decoded [j] = OrigSoundData.channels [i].decoded [j];
378 for (j = 0; j < 2; j++)
379 SoundData.channels [i].previous [j] = OrigSoundData.channels [i].previous [j];
381 SoundData.channels [i].sample_number = OrigSoundData.channels [i].sample_number;
382 SoundData.channels [i].last_block = OrigSoundData.channels [i].last_block;
383 SoundData.channels [i].needs_decode = OrigSoundData.channels [i].needs_decode;
384 SoundData.channels [i].block_pointer = OrigSoundData.channels [i].block_pointer;
385 SoundData.channels [i].sample_pointer = OrigSoundData.channels [i].sample_pointer;
386 SoundData.channels [i].mode = OrigSoundData.channels [i].mode;
389 S9xSetSoundMute (FALSE);
390 IAPU.PC = IAPU.RAM + IAPU.PC;
391 S9xAPUUnpackStatus ();
392 if (APUCheckDirectPage ())
393 IAPU.DirectPage = IAPU.RAM + 0x100;
395 IAPU.DirectPage = IAPU.RAM;
396 Settings.APUEnabled = TRUE;
397 CPU.APU_APUExecuting = TRUE;
401 Settings.APUEnabled = FALSE;
402 CPU.APU_APUExecuting = FALSE;
403 S9xSetSoundMute (TRUE);
405 S9xFixSoundAfterSnapshotLoad ();
406 ICPU.ShiftedPB = Registers.PB << 16;
407 ICPU.ShiftedDB = Registers.DB << 16;
408 S9xSetPCBase (ICPU.ShiftedPB + Registers.PC, &CPU);
410 S9xFixCycles (&Registers, &ICPU);