/[pcsx2_0.9.7]/trunk/pcsx2/SaveState.cpp
ViewVC logotype

Contents of /trunk/pcsx2/SaveState.cpp

Parent Directory Parent Directory | Revision Log Revision Log


Revision 283 - (show annotations) (download)
Thu Dec 23 12:39:52 2010 UTC (9 years, 5 months ago) by william
File size: 9363 byte(s)
Auto Commited Import of: pcsx2-0.9.7-DEBUG (upstream: v0.9.7.4132 local: v0.9.7.282-latest) in ./trunk
1 /* PCSX2 - PS2 Emulator for PCs
2 * Copyright (C) 2002-2010 PCSX2 Dev Team
3 *
4 * PCSX2 is free software: you can redistribute it and/or modify it under the terms
5 * of the GNU Lesser General Public License as published by the Free Software Found-
6 * ation, either version 3 of the License, or (at your option) any later version.
7 *
8 * PCSX2 is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
9 * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
10 * PURPOSE. See the GNU General Public License for more details.
11 *
12 * You should have received a copy of the GNU General Public License along with PCSX2.
13 * If not, see <http://www.gnu.org/licenses/>.
14 */
15
16
17 #include "PrecompiledHeader.h"
18 #include "IopCommon.h"
19 #include "SaveState.h"
20
21 #include "ps2/BiosTools.h"
22 #include "COP0.h"
23 #include "VUmicro.h"
24 #include "Cache.h"
25 #include "AppConfig.h"
26
27 #include "Elfheader.h"
28 #include "Counters.h"
29
30 #include "Utilities/SafeArray.inl"
31
32 using namespace R5900;
33
34
35 static void PreLoadPrep()
36 {
37 SysClearExecutionCache();
38 }
39
40 static void PostLoadPrep()
41 {
42 memzero(pCache);
43 // WriteCP0Status(cpuRegs.CP0.n.Status.val);
44 for(int i=0; i<48; i++) MapTLB(i);
45
46 UpdateVSyncRate();
47 }
48
49 // --------------------------------------------------------------------------------------
50 // SaveStateBase (implementations)
51 // --------------------------------------------------------------------------------------
52 wxString SaveStateBase::GetFilename( int slot )
53 {
54 wxString serialName( DiscSerial );
55 if (serialName.IsEmpty()) serialName = L"BIOS";
56
57 return (g_Conf->Folders.Savestates +
58 pxsFmt( L"%s (%08X).%02d.p2s", serialName.c_str(), ElfCRC, slot )).GetFullPath();
59
60 //return (g_Conf->Folders.Savestates +
61 // pxsFmt( L"%08X.%03d", ElfCRC, slot )).GetFullPath();
62 }
63
64 SaveStateBase::SaveStateBase( SafeArray<u8>& memblock )
65 {
66 Init( &memblock );
67 }
68
69 SaveStateBase::SaveStateBase( SafeArray<u8>* memblock )
70 {
71 Init( memblock );
72 }
73
74 void SaveStateBase::Init( SafeArray<u8>* memblock )
75 {
76 m_memory = memblock;
77 m_version = g_SaveVersion;
78 m_idx = 0;
79 m_DidBios = false;
80 }
81
82 void SaveStateBase::PrepBlock( int size )
83 {
84 pxAssumeDev( m_memory, "Savestate memory/buffer pointer is null!" );
85
86 const int end = m_idx+size;
87 if( IsSaving() )
88 m_memory->MakeRoomFor( end );
89 else
90 {
91 if( m_memory->GetSizeInBytes() < end )
92 throw Exception::SaveStateLoadError();
93 }
94 }
95
96 void SaveStateBase::FreezeTag( const char* src )
97 {
98 const uint allowedlen = sizeof( m_tagspace )-1;
99 pxAssertDev( strlen(src) < allowedlen, pxsFmt( L"Tag name exceeds the allowed length of %d chars.", allowedlen) );
100
101 memzero( m_tagspace );
102 strcpy( m_tagspace, src );
103 Freeze( m_tagspace );
104
105 if( strcmp( m_tagspace, src ) != 0 )
106 {
107 wxString msg( L"Savestate data corruption detected while reading tag: " + fromUTF8(src) );
108 pxFail( msg );
109 throw Exception::SaveStateLoadError().SetDiagMsg(msg);
110 }
111 }
112
113 SaveStateBase& SaveStateBase::FreezeBios()
114 {
115 FreezeTag( "BIOS" );
116
117 // Check the BIOS, and issue a warning if the bios for this state
118 // doesn't match the bios currently being used (chances are it'll still
119 // work fine, but some games are very picky).
120
121 u32 bioscheck = BiosChecksum;
122 char biosdesc[256];
123
124 pxToUTF8 utf8(BiosDescription);
125
126 memzero( biosdesc );
127 memcpy_fast( biosdesc, utf8, std::min( sizeof(biosdesc), utf8.Length() ) );
128
129 Freeze( bioscheck );
130 Freeze( biosdesc );
131
132 if (bioscheck != BiosChecksum)
133 {
134 Console.Newline();
135 Console.Indent(1).Error( "Warning: BIOS Version Mismatch, savestate may be unstable!" );
136 Console.Indent(2).Error(
137 "Current BIOS: %ls (crc=0x%08x)\n"
138 "Savestate BIOS: %s (crc=0x%08x)\n",
139 BiosDescription.c_str(), BiosChecksum,
140 biosdesc, bioscheck
141 );
142 }
143
144 return *this;
145 }
146
147 static const uint MainMemorySizeInBytes =
148 Ps2MemSize::MainRam + Ps2MemSize::Scratch + Ps2MemSize::Hardware +
149 Ps2MemSize::IopRam + Ps2MemSize::IopHardware;
150
151 SaveStateBase& SaveStateBase::FreezeMainMemory()
152 {
153 if (IsLoading())
154 PreLoadPrep();
155 else
156 m_memory->MakeRoomFor( m_idx + MainMemorySizeInBytes );
157
158 // First Block - Memory Dumps
159 // ---------------------------
160 FreezeMem(eeMem->Main, Ps2MemSize::MainRam); // 32 MB main memory
161 FreezeMem(eeMem->Scratch, Ps2MemSize::Scratch); // scratch pad
162 FreezeMem(eeHw, Ps2MemSize::Hardware); // hardware memory
163
164 FreezeMem(iopMem->Main, Ps2MemSize::IopRam); // 2 MB main memory
165 FreezeMem(iopHw, Ps2MemSize::IopHardware); // hardware memory
166
167 FreezeMem(vuRegs[0].Micro, VU0_PROGSIZE);
168 FreezeMem(vuRegs[0].Mem, VU0_MEMSIZE);
169
170 FreezeMem(vuRegs[1].Micro, VU1_PROGSIZE);
171 FreezeMem(vuRegs[1].Mem, VU1_MEMSIZE);
172
173 return *this;
174 }
175
176 SaveStateBase& SaveStateBase::FreezeInternals()
177 {
178 if( IsLoading() )
179 PreLoadPrep();
180
181 // Second Block - Various CPU Registers and States
182 // -----------------------------------------------
183 FreezeTag( "cpuRegs" );
184 Freeze(cpuRegs); // cpu regs + COP0
185 Freeze(psxRegs); // iop regs
186 Freeze(fpuRegs);
187 Freeze(tlb); // tlbs
188
189 // Third Block - Cycle Timers and Events
190 // -------------------------------------
191 FreezeTag( "Cycles" );
192 Freeze(EEsCycle);
193 Freeze(EEoCycle);
194 Freeze(g_nextEventCycle);
195 Freeze(g_iopNextEventCycle);
196 Freeze(s_iLastCOP0Cycle);
197 Freeze(s_iLastPERFCycle);
198
199 // Fourth Block - EE-related systems
200 // ---------------------------------
201 FreezeTag( "EE-Subsystems" );
202 rcntFreeze();
203 gsFreeze();
204 vuMicroFreeze();
205 vif0Freeze();
206 vif1Freeze();
207 sifFreeze();
208 ipuFreeze();
209 ipuDmaFreeze();
210 gifFreeze();
211 sprFreeze();
212
213 // Fifth Block - iop-related systems
214 // ---------------------------------
215 FreezeTag( "IOP-Subsystems" );
216 FreezeMem(iopMem->Sif, sizeof(iopMem->Sif)); // iop's sif memory (not really needed, but oh well)
217
218 #ifdef ENABLE_NEW_IOPDMA
219 iopDmacFreeze();
220 #endif
221 psxRcntFreeze();
222 sioFreeze();
223 sio2Freeze();
224 cdrFreeze();
225 cdvdFreeze();
226
227 // technically this is HLE BIOS territory, but we don't have enough such stuff
228 // to merit an HLE Bios sub-section... yet.
229 deci2Freeze();
230
231 if( IsLoading() )
232 PostLoadPrep();
233
234 return *this;
235 }
236
237 SaveStateBase& SaveStateBase::FreezePlugins()
238 {
239 for (uint i=0; i<PluginId_Count; ++i)
240 {
241 FreezeTag( FastFormatAscii().Write("Plugin:%s", tbl_PluginInfo[i].shortname) );
242 GetCorePlugins().Freeze( (PluginsEnum_t)i, *this );
243 }
244
245 return *this;
246 }
247
248 SaveStateBase& SaveStateBase::FreezeAll()
249 {
250 FreezeMainMemory();
251 FreezeBios();
252 FreezeInternals();
253 FreezePlugins();
254
255 return *this;
256 }
257
258
259 // --------------------------------------------------------------------------------------
260 // memSavingState (implementations)
261 // --------------------------------------------------------------------------------------
262 // uncompressed to/from memory state saves implementation
263
264 memSavingState::memSavingState( SafeArray<u8>& save_to )
265 : SaveStateBase( save_to )
266 {
267 }
268
269 memSavingState::memSavingState( SafeArray<u8>* save_to )
270 : SaveStateBase( save_to )
271 {
272 }
273
274 // Saving of state data
275 void memSavingState::FreezeMem( void* data, int size )
276 {
277 if (!size) return;
278
279 m_memory->MakeRoomFor( m_idx + size );
280 memcpy_fast( m_memory->GetPtr(m_idx), data, size );
281 m_idx += size;
282 }
283
284 void memSavingState::MakeRoomForData()
285 {
286 pxAssumeDev( m_memory, "Savestate memory/buffer pointer is null!" );
287
288 m_memory->ChunkSize = ReallocThreshold;
289 m_memory->MakeRoomFor( m_idx + MemoryBaseAllocSize );
290 }
291
292 // Saving of state data to a memory buffer
293 memSavingState& memSavingState::FreezeAll()
294 {
295 MakeRoomForData();
296 _parent::FreezeAll();
297 return *this;
298 }
299
300 // --------------------------------------------------------------------------------------
301 // memLoadingState (implementations)
302 // --------------------------------------------------------------------------------------
303 memLoadingState::memLoadingState( const SafeArray<u8>& load_from )
304 : SaveStateBase( const_cast<SafeArray<u8>&>(load_from) )
305 {
306 }
307
308 memLoadingState::memLoadingState( const SafeArray<u8>* load_from )
309 : SaveStateBase( const_cast<SafeArray<u8>*>(load_from) )
310 {
311 }
312
313 memLoadingState::~memLoadingState() throw() { }
314
315 // Loading of state data from a memory buffer...
316 void memLoadingState::FreezeMem( void* data, int size )
317 {
318 const u8* const src = m_memory->GetPtr(m_idx);
319 m_idx += size;
320 memcpy_fast( data, src, size );
321 }
322
323 // --------------------------------------------------------------------------------------
324 // SaveState Exception Messages
325 // --------------------------------------------------------------------------------------
326
327 wxString Exception::UnsupportedStateVersion::FormatDiagnosticMessage() const
328 {
329 // Note: no stacktrace needed for this one...
330 return pxsFmt( L"Unknown or unsupported savestate version: 0x%x", Version );
331 }
332
333 wxString Exception::UnsupportedStateVersion::FormatDisplayMessage() const
334 {
335 // m_message_user contains a recoverable savestate error which is helpful to the user.
336 return
337 m_message_user + L"\n\n" +
338 pxsFmt( _("Cannot load savestate. It is of an unknown or unsupported version."), Version );
339 }
340
341 wxString Exception::StateCrcMismatch::FormatDiagnosticMessage() const
342 {
343 // Note: no stacktrace needed for this one...
344 return pxsFmt(
345 L"Game/CDVD does not match the savestate CRC.\n"
346 L"\tCdvd CRC: 0x%X\n\tGame CRC: 0x%X\n",
347 Crc_Savestate, Crc_Cdvd
348 );
349 }
350
351 wxString Exception::StateCrcMismatch::FormatDisplayMessage() const
352 {
353 return
354 m_message_user + L"\n\n" +
355 pxsFmt(
356 L"Savestate game/crc mismatch. Cdvd CRC: 0x%X Game CRC: 0x%X\n",
357 Crc_Savestate, Crc_Cdvd
358 );
359 }

  ViewVC Help
Powered by ViewVC 1.1.22