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 <new> 26 #include "../NstMachine.hpp" 27 #include "../NstImage.hpp" 28 #include "../NstState.hpp" 29 #include "NstApiMachine.hpp" 30 31 namespace Nes 32 { 33 namespace Api 34 { 35 Machine::EventCaller Machine::eventCallback; 36 Is(uint a) const37 uint Machine::Is(uint a) const throw() 38 { 39 return emulator.Is( a ); 40 } 41 Is(uint a,uint b) const42 bool Machine::Is(uint a,uint b) const throw() 43 { 44 return emulator.Is( a, b ); 45 } 46 IsLocked() const47 bool Machine::IsLocked() const 48 { 49 return emulator.tracker.IsLocked(); 50 } 51 52 #ifdef NST_MSVC_OPTIMIZE 53 #pragma optimize("s", on) 54 #endif 55 Load(std::istream & stream,FavoredSystem system,AskProfile ask,Patch * patch,uint type)56 Result Machine::Load(std::istream& stream,FavoredSystem system,AskProfile ask,Patch* patch,uint type) 57 { 58 Result result; 59 60 const bool on = Is(ON); 61 62 try 63 { 64 result = emulator.Load 65 ( 66 stream, 67 static_cast<Core::FavoredSystem>(system), 68 ask == ASK_PROFILE, 69 patch ? &patch->stream : NULL, 70 patch ? patch->bypassChecksum : false, 71 patch ? &patch->result : NULL, 72 type 73 ); 74 } 75 catch (Result r) 76 { 77 return r; 78 } 79 catch (const std::bad_alloc&) 80 { 81 return RESULT_ERR_OUT_OF_MEMORY; 82 } 83 catch (...) 84 { 85 return RESULT_ERR_GENERIC; 86 } 87 88 if (on) 89 Power( true ); 90 91 return result; 92 } 93 Load(std::istream & stream,FavoredSystem system,AskProfile ask)94 Result Machine::Load(std::istream& stream,FavoredSystem system,AskProfile ask) throw() 95 { 96 return Load( stream, system, ask, NULL, Core::Image::UNKNOWN ); 97 } 98 Load(std::istream & stream,FavoredSystem system,Patch & patch,AskProfile ask)99 Result Machine::Load(std::istream& stream,FavoredSystem system,Patch& patch,AskProfile ask) throw() 100 { 101 return Load( stream, system, ask, &patch, Core::Image::UNKNOWN ); 102 } 103 LoadCartridge(std::istream & stream,FavoredSystem system,AskProfile ask)104 Result Machine::LoadCartridge(std::istream& stream,FavoredSystem system,AskProfile ask) throw() 105 { 106 return Load( stream, system, ask, NULL, Core::Image::CARTRIDGE ); 107 } 108 LoadCartridge(std::istream & stream,FavoredSystem system,Patch & patch,AskProfile ask)109 Result Machine::LoadCartridge(std::istream& stream,FavoredSystem system,Patch& patch,AskProfile ask) throw() 110 { 111 return Load( stream, system, ask, &patch, Core::Image::CARTRIDGE ); 112 } 113 LoadDisk(std::istream & stream,FavoredSystem system)114 Result Machine::LoadDisk(std::istream& stream,FavoredSystem system) throw() 115 { 116 return Load( stream, system, DONT_ASK_PROFILE, NULL, Core::Image::DISK ); 117 } 118 LoadSound(std::istream & stream,FavoredSystem system)119 Result Machine::LoadSound(std::istream& stream,FavoredSystem system) throw() 120 { 121 return Load( stream, system, DONT_ASK_PROFILE, NULL, Core::Image::SOUND ); 122 } 123 Unload()124 Result Machine::Unload() throw() 125 { 126 if (!Is(IMAGE)) 127 return RESULT_NOP; 128 129 return emulator.Unload(); 130 } 131 Power(const bool on)132 Result Machine::Power(const bool on) throw() 133 { 134 if (on == bool(Is(ON))) 135 return RESULT_NOP; 136 137 if (on) 138 { 139 try 140 { 141 emulator.Reset( true ); 142 } 143 catch (Result result) 144 { 145 return result; 146 } 147 catch (const std::bad_alloc&) 148 { 149 return RESULT_ERR_OUT_OF_MEMORY; 150 } 151 catch (...) 152 { 153 return RESULT_ERR_GENERIC; 154 } 155 156 return RESULT_OK; 157 } 158 else 159 { 160 return emulator.PowerOff(); 161 } 162 } 163 Reset(const bool hard)164 Result Machine::Reset(const bool hard) throw() 165 { 166 if (!Is(ON) || IsLocked()) 167 return RESULT_ERR_NOT_READY; 168 169 try 170 { 171 emulator.Reset( hard ); 172 } 173 catch (Result result) 174 { 175 return result; 176 } 177 catch (const std::bad_alloc&) 178 { 179 return RESULT_ERR_OUT_OF_MEMORY; 180 } 181 catch (...) 182 { 183 return RESULT_ERR_GENERIC; 184 } 185 186 return RESULT_OK; 187 } 188 SetRamPowerState(const uint state)189 Result Machine::SetRamPowerState(const uint state) throw() 190 { 191 emulator.SetRamPowerState(state); 192 return RESULT_OK; 193 } 194 GetMode() const195 Machine::Mode Machine::GetMode() const throw() 196 { 197 return static_cast<Mode>(Is(NTSC|PAL)); 198 } 199 GetDesiredMode() const200 Machine::Mode Machine::GetDesiredMode() const throw() 201 { 202 return (!emulator.image || emulator.image->GetDesiredRegion() == Core::REGION_NTSC) ? NTSC : PAL; 203 } 204 SetMode(const Mode mode)205 Result Machine::SetMode(const Mode mode) throw() 206 { 207 if (mode == GetMode()) 208 return RESULT_NOP; 209 210 Result result = Power( false ); 211 212 if (NES_SUCCEEDED(result)) 213 { 214 emulator.SwitchMode(); 215 216 if (result != RESULT_NOP) 217 result = Power( true ); 218 } 219 220 return result; 221 } 222 LoadState(std::istream & stream)223 Result Machine::LoadState(std::istream& stream) throw() 224 { 225 if (!Is(GAME,ON) || IsLocked()) 226 return RESULT_ERR_NOT_READY; 227 228 try 229 { 230 emulator.tracker.Resync(); 231 Core::State::Loader loader( &stream, true ); 232 233 if (emulator.LoadState( loader, true )) 234 return RESULT_OK; 235 else 236 return RESULT_ERR_INVALID_CRC; 237 } 238 catch (Result result) 239 { 240 return result; 241 } 242 catch (const std::bad_alloc&) 243 { 244 return RESULT_ERR_OUT_OF_MEMORY; 245 } 246 catch (...) 247 { 248 return RESULT_ERR_GENERIC; 249 } 250 } 251 SaveState(std::ostream & stream,Compression compression) const252 Result Machine::SaveState(std::ostream& stream,Compression compression) const throw() 253 { 254 if (!Is(GAME,ON)) 255 return RESULT_ERR_NOT_READY; 256 257 try 258 { 259 Core::State::Saver saver( &stream, compression != NO_COMPRESSION, false ); 260 emulator.SaveState( saver ); 261 } 262 catch (Result result) 263 { 264 return result; 265 } 266 catch (const std::bad_alloc&) 267 { 268 return RESULT_ERR_OUT_OF_MEMORY; 269 } 270 catch (...) 271 { 272 return RESULT_ERR_GENERIC; 273 } 274 275 return RESULT_OK; 276 } 277 278 #ifdef NST_MSVC_OPTIMIZE 279 #pragma optimize("", on) 280 #endif 281 } 282 } 283