1 ////////////////////////////////////////////////////////////////////////////////////////
2 //
3 // Nestopia - NES/Famicom emulator written in C++
4 //
5 // Copyright (C) 2003-2008 Martin Freij
6 //
7 // This file is part of Nestopia.
8 //
9 // Nestopia is free software; you can redistribute it and/or modify
10 // it under the terms of the GNU General Public License as published by
11 // the Free Software Foundation; either version 2 of the License, or
12 // (at your option) any later version.
13 //
14 // Nestopia is distributed in the hope that it will be useful,
15 // but WITHOUT ANY WARRANTY; without even the implied warranty of
16 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17 // GNU General Public License for more details.
18 //
19 // You should have received a copy of the GNU General Public License
20 // along with Nestopia; if not, write to the Free Software
21 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
22 //
23 ////////////////////////////////////////////////////////////////////////////////////////
24 
25 #include "NstState.hpp"
26 #include "NstMemory.hpp"
27 
28 namespace Nes
29 {
30 	namespace Core
31 	{
32 		#ifdef NST_MSVC_OPTIMIZE
33 		#pragma optimize("s", on)
34 		#endif
35 
SaveState(State::Saver & state,const dword baseChunk,const Ram * const NST_RESTRICT sources,const uint numSources,const byte * const NST_RESTRICT pages,const uint numPages) const36 		void Memory<0,0,0>::SaveState
37 		(
38 			State::Saver& state,
39 			const dword baseChunk,
40 			const Ram* const NST_RESTRICT sources,
41 			const uint numSources,
42 			const byte* const NST_RESTRICT pages,
43 			const uint numPages
44 		)   const
45 		{
46 			NST_ASSERT( numSources >= 1 && numSources <= MAX_SOURCES && numPages );
47 
48 			state.Begin( baseChunk );
49 
50 			{
51 				byte data[MAX_SOURCES];
52 
53 				for (uint i=0; i < numSources; ++i)
54 					data[i] = (sources[i].Readable() ? 0x1U : 0x0U) | (sources[i].Writable() ? 0x2U : 0x0U);
55 
56 				state.Begin( AsciiId<'A','C','C'>::V ).Write( data, numSources ).End();
57 			}
58 
59 			state.Begin( AsciiId<'B','N','K'>::V ).Write( pages, numPages * 3 ).End();
60 
61 			state.End();
62 		}
63 
LoadState(State::Loader & state,Ram * const NST_RESTRICT sources,const uint numSources,byte * const NST_RESTRICT pages,const uint numPages) const64 		bool Memory<0,0,0>::LoadState
65 		(
66 			State::Loader& state,
67 			Ram* const NST_RESTRICT sources,
68 			const uint numSources,
69 			byte* const NST_RESTRICT pages,
70 			const uint numPages
71 		)   const
72 		{
73 			NST_ASSERT( numSources >= 1 && numSources <= MAX_SOURCES && numPages );
74 
75 			bool paged = false;
76 
77 			while (const dword chunk = state.Begin())
78 			{
79 				switch (chunk)
80 				{
81 					case AsciiId<'A','C','C'>::V:
82 					{
83 						byte data[MAX_SOURCES];
84 						state.Read( data, numSources );
85 
86 						for (uint i=0; i < numSources; ++i)
87 						{
88 							sources[i].ReadEnable( data[i] & 0x1U );
89 
90 							NST_VERIFY( sources[i].GetType() != Ram::ROM || !(data[i] & 0x2U) );
91 
92 							if (sources[i].GetType() != Ram::ROM)
93 								sources[i].WriteEnable( data[i] & 0x2U );
94 						}
95 						break;
96 					}
97 
98 					case AsciiId<'B','N','K'>::V:
99 
100 						paged = true;
101 						state.Read( pages, numPages * 3 );
102 						break;
103 
104 					default:
105 
106 						// deprecated
107 
108 						for (uint i=0; i < numSources; ++i)
109 						{
110 							if (chunk == AsciiId<'R','M','0'>::R(0,0,i))
111 							{
112 								NST_DEBUG_MSG("Memory::LoadState() deprecated!");
113 								state.Uncompress( sources[i].Mem(), sources[i].Size() );
114 								break;
115 							}
116 						}
117 						break;
118 				}
119 
120 				state.End();
121 			}
122 
123 			return paged;
124 		}
125 
126 		#ifdef NST_MSVC_OPTIMIZE
127 		#pragma optimize("", on)
128 		#endif
129 	}
130 }
131