removing now unneeded dir from package
[drnoksnes] / snaporig.cpp
1 /*
2  * Snes9x - Portable Super Nintendo Entertainment System (TM) emulator.
3  *
4  * (c) Copyright 1996 - 2001 Gary Henderson (gary.henderson@ntlworld.com) and
5  *                           Jerremy Koot (jkoot@snes9x.com)
6  *
7  * Super FX C emulator code 
8  * (c) Copyright 1997 - 1999 Ivar (ivar@snes9x.com) and
9  *                           Gary Henderson.
10  * Super FX assembler emulator code (c) Copyright 1998 zsKnight and _Demo_.
11  *
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).
15  *
16  * DOS port code contains the works of other authors. See headers in
17  * individual files.
18  *
19  * Snes9x homepage: http://www.snes9x.com
20  *
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.
25  *
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.
29  *
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.
33  *
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
36  * in future versions.
37  *
38  * Super NES and Super Nintendo Entertainment System are trademarks of
39  * Nintendo Co., Limited and its subsidiary companies.
40  */
41 #include <string.h>
42 #include <ctype.h>
43 #include <stdlib.h>
44
45 #if defined(__unix) || defined(__linux) || defined(__sun) || defined(__DJGPP)
46 //#include <unistd.h>
47 #include <sys/types.h>
48 #include <sys/stat.h>
49 #endif
50
51 #include "snapshot.h"
52 #include "snaporig.h"
53 #include "memmap.h"
54 #include "snes9x.h"
55 #include "65c816.h"
56 #include "ppu.h"
57 #include "cpuexec.h"
58 #include "display.h"
59 #include "apu.h"
60 #include "soundux.h"
61
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];
70
71 static int ReadOrigSnapshot (STREAM);
72
73 bool8_32 S9xLoadOrigSnapshot (const char *filename)
74 {
75     STREAM snapshot = NULL;
76     if (S9xOpenSnapshotFile (filename, TRUE, &snapshot))
77     {
78         int result;
79         if ((result = ReadOrigSnapshot (snapshot)) != SUCCESS)
80         {
81             S9xCloseSnapshotFile (snapshot);
82             return (FALSE);
83         }
84         S9xCloseSnapshotFile (snapshot);
85         return (TRUE);
86     }
87     return (FALSE);
88 }
89
90 #ifdef _SNESPPC
91 #pragma warning(disable : 4018)
92 #endif
93 static int ReadBlock (const char *key, void *block, int max_len, STREAM snap)
94 {
95     char buffer [20];
96     int len = 0;
97     int rem = 0;
98     
99     if (READ_STREAM (buffer, 11, snap) != 11 ||
100         strncmp (buffer, key, 4) != 0 ||
101         (len = atoi (&buffer [4])) == 0)
102         return (WRONG_FORMAT);
103
104     if (len > max_len)
105     {
106         rem = len - max_len;
107         len = max_len;
108     }
109     if (READ_STREAM (block, len, snap) != len)
110         return (WRONG_FORMAT);
111
112     if (rem)
113     {
114         char *junk = new char [rem];
115         READ_STREAM (junk, rem, snap);
116         delete junk;
117     }
118         
119     return (SUCCESS);
120 }
121
122 static int ReadOrigSnapshot (STREAM snap)
123 {
124     char buffer [_MAX_PATH];
125     char rom_filename [_MAX_PATH];
126     int result;
127     int i;
128     int j;
129
130     int version;
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);
138
139     if ((result = ReadBlock ("NAM:", rom_filename, _MAX_PATH, snap)) != SUCCESS)
140         return (result);
141
142     if ((result = ReadBlock ("HiR:", buffer, 0x41, snap)) != SUCCESS)
143         return (result);
144
145     if (strcasecmp (rom_filename, Memory.ROMFilename) != 0 &&
146         strcasecmp (S9xBasename (rom_filename), S9xBasename (Memory.ROMFilename)) != 0)
147     {
148         S9xMessage (S9X_WARNING, S9X_FREEZE_ROM_NAME,
149                     "Current loaded ROM image doesn't match that required by freeze-game file.");
150     }
151
152     S9xReset ();
153     S9xSetSoundMute (TRUE);
154     if ((result = ReadBlock ("CPU:", &OrigCPU, sizeof (OrigCPU), snap)) != SUCCESS)
155         return (result);
156     OrigCPU.FastROMSpeed = OrigCPU.FastROMSpeed_old;
157     Memory.FixROMSpeed ();
158     if (version == 3)
159     {
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;
166     }
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;
179
180     if ((result = ReadBlock ("REG:", &OrigRegisters, sizeof (OrigRegisters), snap)) != SUCCESS)
181         return (result);
182
183     Registers = *(struct SRegisters *) &OrigRegisters;
184
185     if ((result = ReadBlock ("PPU:", &OrigPPU, sizeof (OrigPPU), snap)) != SUCCESS)
186         return (result);
187
188     if (version == 2)
189     {
190         OrigPPU.OBJNameSelect = OrigPPU.OBJNameSelect_old << 13;
191         OrigPPU.OBJNameBase <<= 1;
192         OrigPPU.OBJNameSelect <<= 13;
193     }
194     PPU.BGMode = OrigPPU.BGMode;
195     PPU.BG3Priority = OrigPPU.BG3Priority;
196     PPU.Brightness = OrigPPU.Brightness;
197
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;
204
205     for (i = 0; i < 4; i++)
206     {
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;
213     }
214
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++)
220     {
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;
229     }
230     PPU.OAMPriorityRotation = OrigPPU.OAMPriorityRotation;
231     PPU.OAMAddr = OrigPPU.OAMAddr;
232
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;
239
240     PPU.HBeamFlip = OrigPPU.HBeamFlip;
241     PPU.VBeamFlip = OrigPPU.VBeamFlip;
242     PPU.HVBeamCounterLatched = OrigPPU.HVBeamCounterLatched;
243
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;
253
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++)
280     {
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];
286     }
287     PPU.CGFLIPRead = OrigPPU.CGFLIPRead;
288     PPU.Need16x8Mulitply = OrigPPU.Need16x8Mulitply;
289
290     IPPU.ColorsChanged = TRUE;
291     IPPU.OBJChanged = TRUE;
292     S9xFixColourBrightness ();
293     IPPU.RenderThisFrame = FALSE;
294
295     if ((result = ReadBlock ("DMA:", OrigDMA, sizeof (OrigDMA), snap)) != SUCCESS)
296         return (result);
297
298     for (i = 0; i < 8; i++)
299     {
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;
315     }
316
317     if ((result = ReadBlock ("VRA:", Memory.VRAM, 0x10000, snap)) != SUCCESS)
318         return (result);
319     if ((result = ReadBlock ("RAM:", Memory.RAM, 0x20000, snap)) != SUCCESS)
320         return (result);
321     if ((result = ReadBlock ("SRA:", ::SRAM, 0x10000, snap)) != SUCCESS)
322         return (result);
323     if ((result = ReadBlock ("FIL:", Memory.FillRAM, 0x8000, snap)) != SUCCESS)
324         return (result);
325     if (ReadBlock ("APU:", &OrigAPU, sizeof (OrigAPU), snap) == SUCCESS)
326     {
327         APU = *(struct SAPU *) &OrigAPU;
328
329         if ((result = ReadBlock ("ARE:", &OrigAPURegisters,
330                                  sizeof (OrigAPURegisters), snap)) != SUCCESS)
331             return (result);
332         APURegisters = *(struct SAPURegisters *) &OrigAPURegisters;
333         if ((result = ReadBlock ("ARA:", IAPU.RAM, 0x10000, snap)) != SUCCESS)
334             return (result);
335         if ((result = ReadBlock ("SOU:", &OrigSoundData,
336                                  sizeof (SOrigSoundData), snap)) != SUCCESS)
337             return (result);
338
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;
350
351         for (i = 0; i < 3; i++)
352             SoundData.dummy [i] = OrigSoundData.dummy [i];
353         for (i = 0; i < NUM_CHANNELS; i++)
354         {
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];
377
378             for (j = 0; j < 2; j++)
379                 SoundData.channels [i].previous [j] = OrigSoundData.channels [i].previous [j];
380
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;
387         }
388
389         S9xSetSoundMute (FALSE);
390         IAPU.PC = IAPU.RAM + IAPU.PC;
391         S9xAPUUnpackStatus ();
392         if (APUCheckDirectPage ())
393             IAPU.DirectPage = IAPU.RAM + 0x100;
394         else
395             IAPU.DirectPage = IAPU.RAM;
396         Settings.APUEnabled = TRUE;
397         CPU.APU_APUExecuting = TRUE;
398     }
399     else
400     {
401         Settings.APUEnabled = FALSE;
402         CPU.APU_APUExecuting = FALSE;
403         S9xSetSoundMute (TRUE);
404     }
405     S9xFixSoundAfterSnapshotLoad ();
406     ICPU.ShiftedPB = Registers.PB << 16;
407     ICPU.ShiftedDB = Registers.DB << 16;
408     S9xSetPCBase (ICPU.ShiftedPB + Registers.PC, &CPU);
409     S9xUnpackStatus ();
410     S9xFixCycles (&Registers, &ICPU);
411     S9xReschedule ();
412
413     return (SUCCESS);
414 }