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 "NstResourceString.hpp" 26 #include "NstWindowUser.hpp" 27 #include "NstIoScreen.hpp" 28 #include "NstManager.hpp" 29 #include "NstManagerPreferences.hpp" 30 #include "NstManagerMachine.hpp" 31 #include "../core/api/NstApiMachine.hpp" 32 33 namespace Nestopia 34 { 35 namespace Managers 36 { 37 NST_COMPILE_ASSERT 38 ( 39 IDM_MACHINE_SYSTEM_NTSC == IDM_MACHINE_SYSTEM_AUTO + 1 && 40 IDM_MACHINE_SYSTEM_PAL == IDM_MACHINE_SYSTEM_AUTO + 2 41 ); 42 Machine(Emulator & e,const Configuration & cfg,Window::Menu & m,const Preferences & p)43 Machine::Machine(Emulator& e,const Configuration& cfg,Window::Menu& m,const Preferences& p) 44 : 45 Manager ( e, m, this, &Machine::OnEmuEvent ), 46 preferences ( p ) 47 { 48 { 49 static const Window::Menu::CmdHandler::Entry<Machine> commands[] = 50 { 51 { IDM_MACHINE_POWER, &Machine::OnCmdPower }, 52 { IDM_MACHINE_RESET_SOFT, &Machine::OnCmdReset }, 53 { IDM_MACHINE_RESET_HARD, &Machine::OnCmdReset }, 54 { IDM_MACHINE_PAUSE, &Machine::OnCmdPause }, 55 { IDM_MACHINE_SYSTEM_AUTO, &Machine::OnCmdSystem }, 56 { IDM_MACHINE_SYSTEM_NTSC, &Machine::OnCmdSystem }, 57 { IDM_MACHINE_SYSTEM_PAL, &Machine::OnCmdSystem } 58 }; 59 60 menu.Commands().Add( this, commands ); 61 } 62 63 { 64 const GenericString type( cfg["machine"]["region"].Str() ); 65 66 SetRegion 67 ( 68 type == L"ntsc" ? IDM_MACHINE_SYSTEM_NTSC : 69 type == L"pal" ? IDM_MACHINE_SYSTEM_PAL : 70 IDM_MACHINE_SYSTEM_AUTO 71 ); 72 } 73 74 UpdateMenu(); 75 UpdateMenuPowerState(); 76 } 77 Save(Configuration & cfg) const78 void Machine::Save(Configuration& cfg) const 79 { 80 cfg["machine"]["region"].Str() = 81 ( 82 menu[IDM_MACHINE_SYSTEM_AUTO].Checked() ? "auto" : 83 Nes::Machine(emulator).Is(Nes::Machine::NTSC) ? "ntsc" : 84 "pal" 85 ); 86 } 87 UpdateMenu() const88 void Machine::UpdateMenu() const 89 { 90 const bool on = emulator.IsOn(); 91 const bool reset = (on && emulator.GetPlayer() == Emulator::MASTER); 92 const bool pause = (on && emulator.NetPlayers() == 0); 93 94 menu[IDM_MACHINE_POWER].Text() << Resource::String( on ? IDS_MENU_POWER_OFF : IDS_MENU_POWER_ON ); 95 menu[IDM_MACHINE_RESET_SOFT].Enable( reset ); 96 menu[IDM_MACHINE_RESET_HARD].Enable( reset ); 97 menu[IDM_POS_MACHINE][IDM_POS_MACHINE_RESET].Enable( reset ); 98 menu[IDM_MACHINE_PAUSE].Enable( pause ); 99 } 100 UpdateMenuPowerState() const101 void Machine::UpdateMenuPowerState() const 102 { 103 menu[IDM_MACHINE_POWER].Enable( emulator.IsImage() && emulator.NetPlayers() == 0 ); 104 } 105 SetRegion(const uint id) const106 bool Machine::SetRegion(const uint id) const 107 { 108 const Nes::Result result = Nes::Machine(emulator).SetMode 109 ( 110 id == IDM_MACHINE_SYSTEM_AUTO ? Nes::Machine(emulator).GetDesiredMode() : 111 id == IDM_MACHINE_SYSTEM_NTSC ? Nes::Machine::NTSC : Nes::Machine::PAL 112 ); 113 114 if (NES_SUCCEEDED(result)) 115 { 116 menu[id].Check( IDM_MACHINE_SYSTEM_AUTO, IDM_MACHINE_SYSTEM_PAL ); 117 return result != Nes::RESULT_NOP; 118 } 119 120 return false; 121 } 122 OnCmdPower(uint)123 void Machine::OnCmdPower(uint) 124 { 125 if (emulator.IsOn()) 126 { 127 if 128 ( 129 !preferences[Preferences::CONFIRM_RESET] || 130 Window::User::Confirm( IDS_ARE_YOU_SURE, IDS_MACHINE_POWER_OFF_TITLE ) 131 ) 132 { 133 if (emulator.Power( false )) 134 Io::Screen() << Resource::String(IDS_SCREEN_POWER_OFF); 135 } 136 } 137 else if (emulator.Power( true )) 138 { 139 Io::Screen() << Resource::String(IDS_SCREEN_POWER_ON); 140 } 141 } 142 OnCmdReset(uint hard)143 void Machine::OnCmdReset(uint hard) 144 { 145 if 146 ( 147 !preferences[Preferences::CONFIRM_RESET] || 148 Window::User::Confirm( IDS_ARE_YOU_SURE, IDS_MACHINE_RESET_TITLE ) 149 ) 150 emulator.SendCommand( Emulator::COMMAND_RESET, hard == IDM_MACHINE_RESET_HARD ); 151 152 Resume(); 153 } 154 OnCmdPause(uint)155 void Machine::OnCmdPause(uint) 156 { 157 const bool pause = !emulator.Paused(); 158 159 emulator.Pause( pause ); 160 Io::Screen() << Resource::String(pause ? IDS_SCREEN_PAUSE : IDS_SCREEN_RESUME); 161 162 if (!pause) 163 Resume(); 164 } 165 OnCmdSystem(uint id)166 void Machine::OnCmdSystem(uint id) 167 { 168 if (SetRegion( id )) 169 Io::Screen() << Resource::String(Nes::Machine(emulator).Is(Nes::Machine::NTSC) ? IDS_SCREEN_NTSC : IDS_SCREEN_PAL); 170 171 Resume(); 172 } 173 OnEmuEvent(const Emulator::Event event,Emulator::Data)174 void Machine::OnEmuEvent(const Emulator::Event event,Emulator::Data) 175 { 176 switch (event) 177 { 178 case Emulator::EVENT_RESET_SOFT: 179 case Emulator::EVENT_RESET_HARD: 180 181 Io::Screen() << Resource::String(event == Emulator::EVENT_RESET_HARD ? IDS_SCREEN_RESET_HARD : IDS_SCREEN_RESET_SOFT); 182 break; 183 184 case Emulator::EVENT_MODE_NTSC: 185 case Emulator::EVENT_MODE_PAL: 186 187 if (menu[IDM_MACHINE_SYSTEM_AUTO].Unchecked()) 188 menu[event == Emulator::EVENT_MODE_NTSC ? IDM_MACHINE_SYSTEM_NTSC : IDM_MACHINE_SYSTEM_PAL].Check( IDM_MACHINE_SYSTEM_AUTO, IDM_MACHINE_SYSTEM_PAL ); 189 190 break; 191 192 case Emulator::EVENT_PAUSE: 193 case Emulator::EVENT_RESUME: 194 195 menu[IDM_MACHINE_PAUSE].Check( event == Emulator::EVENT_PAUSE ); 196 break; 197 198 case Emulator::EVENT_MOVIE_PLAYING: 199 case Emulator::EVENT_MOVIE_PLAYING_STOPPED: 200 case Emulator::EVENT_MOVIE_RECORDING: 201 case Emulator::EVENT_MOVIE_RECORDING_STOPPED: 202 { 203 const bool noplay = (event != Emulator::EVENT_MOVIE_PLAYING); 204 const bool stopped = (event == Emulator::EVENT_MOVIE_PLAYING_STOPPED || event == Emulator::EVENT_MOVIE_RECORDING_STOPPED); 205 206 menu[IDM_MACHINE_RESET_SOFT].Enable( noplay ); 207 menu[IDM_MACHINE_RESET_HARD].Enable( noplay ); 208 menu[IDM_POS_MACHINE][IDM_POS_MACHINE_RESET].Enable( noplay ); 209 210 for (uint i=IDM_MACHINE_SYSTEM_AUTO; i <= IDM_MACHINE_SYSTEM_PAL; ++i) 211 menu[i].Enable( stopped ); 212 213 break; 214 } 215 216 case Emulator::EVENT_POWER_ON: 217 case Emulator::EVENT_POWER_OFF: 218 219 UpdateMenu(); 220 break; 221 222 case Emulator::EVENT_LOAD: 223 case Emulator::EVENT_UNLOAD: 224 225 UpdateMenuPowerState(); 226 227 if (emulator.NetPlayers()) 228 { 229 const bool enable = (event == Emulator::EVENT_UNLOAD); 230 231 menu[IDM_POS_MACHINE][IDM_POS_MACHINE_REGION].Enable( enable ); 232 233 for (uint i=IDM_MACHINE_SYSTEM_AUTO; i <= IDM_MACHINE_SYSTEM_PAL; ++i) 234 menu[i].Enable( enable ); 235 } 236 break; 237 } 238 } 239 } 240 } 241