//////////////////////////////////////////////////////////////////////////////////////// // // Nestopia - NES/Famicom emulator written in C++ // // Copyright (C) 2003-2008 Martin Freij // // This file is part of Nestopia. // // Nestopia is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation; either version 2 of the License, or // (at your option) any later version. // // Nestopia is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with Nestopia; if not, write to the Free Software // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA // //////////////////////////////////////////////////////////////////////////////////////// #include #include "../NstMachine.hpp" #include "../NstImage.hpp" #include "../NstState.hpp" #include "NstApiMachine.hpp" namespace Nes { namespace Api { Machine::EventCaller Machine::eventCallback; uint Machine::Is(uint a) const throw() { return emulator.Is( a ); } bool Machine::Is(uint a,uint b) const throw() { return emulator.Is( a, b ); } bool Machine::IsLocked() const { return emulator.tracker.IsLocked(); } #ifdef NST_MSVC_OPTIMIZE #pragma optimize("s", on) #endif Result Machine::Load(std::istream& stream,FavoredSystem system,AskProfile ask,Patch* patch,uint type) { Result result; const bool on = Is(ON); try { result = emulator.Load ( stream, static_cast(system), ask == ASK_PROFILE, patch ? &patch->stream : NULL, patch ? patch->bypassChecksum : false, patch ? &patch->result : NULL, type ); } catch (Result r) { return r; } catch (const std::bad_alloc&) { return RESULT_ERR_OUT_OF_MEMORY; } catch (...) { return RESULT_ERR_GENERIC; } if (on) Power( true ); return result; } Result Machine::Load(std::istream& stream,FavoredSystem system,AskProfile ask) throw() { return Load( stream, system, ask, NULL, Core::Image::UNKNOWN ); } Result Machine::Load(std::istream& stream,FavoredSystem system,Patch& patch,AskProfile ask) throw() { return Load( stream, system, ask, &patch, Core::Image::UNKNOWN ); } Result Machine::LoadCartridge(std::istream& stream,FavoredSystem system,AskProfile ask) throw() { return Load( stream, system, ask, NULL, Core::Image::CARTRIDGE ); } Result Machine::LoadCartridge(std::istream& stream,FavoredSystem system,Patch& patch,AskProfile ask) throw() { return Load( stream, system, ask, &patch, Core::Image::CARTRIDGE ); } Result Machine::LoadDisk(std::istream& stream,FavoredSystem system) throw() { return Load( stream, system, DONT_ASK_PROFILE, NULL, Core::Image::DISK ); } Result Machine::LoadSound(std::istream& stream,FavoredSystem system) throw() { return Load( stream, system, DONT_ASK_PROFILE, NULL, Core::Image::SOUND ); } Result Machine::Unload() throw() { if (!Is(IMAGE)) return RESULT_NOP; return emulator.Unload(); } Result Machine::Power(const bool on) throw() { if (on == bool(Is(ON))) return RESULT_NOP; if (on) { try { emulator.Reset( true ); } catch (Result result) { return result; } catch (const std::bad_alloc&) { return RESULT_ERR_OUT_OF_MEMORY; } catch (...) { return RESULT_ERR_GENERIC; } return RESULT_OK; } else { return emulator.PowerOff(); } } Result Machine::Reset(const bool hard) throw() { if (!Is(ON) || IsLocked()) return RESULT_ERR_NOT_READY; try { emulator.Reset( hard ); } catch (Result result) { return result; } catch (const std::bad_alloc&) { return RESULT_ERR_OUT_OF_MEMORY; } catch (...) { return RESULT_ERR_GENERIC; } return RESULT_OK; } Result Machine::SetRamPowerState(const uint state) throw() { emulator.SetRamPowerState(state); return RESULT_OK; } Machine::Mode Machine::GetMode() const throw() { return static_cast(Is(NTSC|PAL)); } Machine::Mode Machine::GetDesiredMode() const throw() { return (!emulator.image || emulator.image->GetDesiredRegion() == Core::REGION_NTSC) ? NTSC : PAL; } Result Machine::SetMode(const Mode mode) throw() { if (mode == GetMode()) return RESULT_NOP; Result result = Power( false ); if (NES_SUCCEEDED(result)) { emulator.SwitchMode(); if (result != RESULT_NOP) result = Power( true ); } return result; } Result Machine::LoadState(std::istream& stream) throw() { if (!Is(GAME,ON) || IsLocked()) return RESULT_ERR_NOT_READY; try { emulator.tracker.Resync(); Core::State::Loader loader( &stream, true ); if (emulator.LoadState( loader, true )) return RESULT_OK; else return RESULT_ERR_INVALID_CRC; } catch (Result result) { return result; } catch (const std::bad_alloc&) { return RESULT_ERR_OUT_OF_MEMORY; } catch (...) { return RESULT_ERR_GENERIC; } } Result Machine::SaveState(std::ostream& stream,Compression compression) const throw() { if (!Is(GAME,ON)) return RESULT_ERR_NOT_READY; try { Core::State::Saver saver( &stream, compression != NO_COMPRESSION, false ); emulator.SaveState( saver ); } catch (Result result) { return result; } catch (const std::bad_alloc&) { return RESULT_ERR_OUT_OF_MEMORY; } catch (...) { return RESULT_ERR_GENERIC; } return RESULT_OK; } #ifdef NST_MSVC_OPTIMIZE #pragma optimize("", on) #endif } }