//////////////////////////////////////////////////////////////////////////////////////// // // 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 "NstIoScreen.hpp" #include "NstResourceString.hpp" #include "NstManager.hpp" #include "NstDialogInput.hpp" #include "NstManagerInput.hpp" namespace Nestopia { namespace Managers { class Input::Callbacks { public: typedef Nes::Input::UserData UserData; typedef Window::Input::Settings Settings; typedef Settings::Key Key; typedef Nes::Input::Controllers::Pad Pad; typedef Nes::Input::Controllers::Zapper Zapper; typedef Nes::Input::Controllers::Paddle Paddle; typedef Nes::Input::Controllers::PowerPad PowerPad; typedef Nes::Input::Controllers::PowerGlove PowerGlove; typedef Nes::Input::Controllers::Mouse Mouse; typedef Nes::Input::Controllers::OekaKidsTablet OekaKidsTablet; typedef Nes::Input::Controllers::KonamiHyperShot KonamiHyperShot; typedef Nes::Input::Controllers::BandaiHyperShot BandaiHyperShot; typedef Nes::Input::Controllers::CrazyClimber CrazyClimber; typedef Nes::Input::Controllers::FamilyTrainer FamilyTrainer; typedef Nes::Input::Controllers::FamilyKeyboard FamilyKeyboard; typedef Nes::Input::Controllers::SuborKeyboard SuborKeyboard; typedef Nes::Input::Controllers::DoremikkoKeyboard DoremikkoKeyboard; typedef Nes::Input::Controllers::HoriTrack HoriTrack; typedef Nes::Input::Controllers::Pachinko Pachinko; typedef Nes::Input::Controllers::Mahjong Mahjong; typedef Nes::Input::Controllers::ExcitingBoxing ExcitingBoxing; typedef Nes::Input::Controllers::TopRider TopRider; typedef Nes::Input::Controllers::PokkunMoguraa PokkunMoguraa; typedef Nes::Input::Controllers::PartyTap PartyTap; typedef Nes::Input::Controllers::VsSystem VsSystem; typedef Nes::Input::Controllers::KaraokeStudio KaraokeStudio; static bool NST_CALLBACK PollPad (UserData,Pad&,uint); static bool NST_CALLBACK PollZapper (UserData,Zapper&); static bool NST_CALLBACK PollPaddle (UserData,Paddle&); static bool NST_CALLBACK PollPowerPad (UserData,PowerPad&); static bool NST_CALLBACK PollPowerGlove (UserData,PowerGlove&); static bool NST_CALLBACK PollMouse (UserData,Mouse&); static bool NST_CALLBACK PollOekaKidsTablet (UserData,OekaKidsTablet&); static bool NST_CALLBACK PollKonamiHyperShot (UserData,KonamiHyperShot&); static bool NST_CALLBACK PollBandaiHyperShot (UserData,BandaiHyperShot&); static bool NST_CALLBACK PollCrazyClimber (UserData,CrazyClimber&); static bool NST_CALLBACK PollFamilyTrainer (UserData,FamilyTrainer&); static bool NST_CALLBACK PollFamilyKeyboard (UserData,FamilyKeyboard&,uint,uint); static bool NST_CALLBACK PollSuborKeyboard (UserData,SuborKeyboard&,uint,uint); static bool NST_CALLBACK PollDoremikkoKeyboard (UserData,DoremikkoKeyboard&,uint,uint); static bool NST_CALLBACK PollHoriTrack (UserData,HoriTrack&); static bool NST_CALLBACK PollPachinko (UserData,Pachinko&); static bool NST_CALLBACK PollMahjong (UserData,Mahjong&,uint); static bool NST_CALLBACK PollExcitingBoxing (UserData,ExcitingBoxing&,uint); static bool NST_CALLBACK PollTopRider (UserData,TopRider&); static bool NST_CALLBACK PollPokkunMoguraa (UserData,PokkunMoguraa&,uint); static bool NST_CALLBACK PollPartyTap (UserData,PartyTap&); static bool NST_CALLBACK PollVsSystem (UserData,VsSystem&); static bool NST_CALLBACK PollKaraokeStudio (UserData,KaraokeStudio&); }; inline Input::AutoFire::AutoFire() : step(0), signal(3) {} void Input::AutoFire::operator = (uint speed) { static const uchar speeds[Window::Input::Settings::AUTOFIRE_NUM_SPEEDS] = { 7,6,5,4,3,2,1 }; signal = speeds[speed]; } Input::Input ( Window::Custom& w, Window::Menu& m, Emulator& e, const Configuration& cfg, const Screening& si, const Screening& so ) : Manager ( e, m, this, &Input::OnEmuEvent ), cursor ( w, si, so ), directInput ( w ), dialog ( new Window::Input(directInput,e,cfg) ), commands ( w, directInput ), clipboard ( e, m ) { static const Window::Menu::CmdHandler::Entry commands[] = { { IDM_MACHINE_INPUT_AUTOSELECT, &Input::OnCmdMachineAutoSelectController }, { IDM_MACHINE_INPUT_PORT1_UNCONNECTED, &Input::OnCmdMachinePort }, { IDM_MACHINE_INPUT_PORT1_PAD1, &Input::OnCmdMachinePort }, { IDM_MACHINE_INPUT_PORT1_PAD2, &Input::OnCmdMachinePort }, { IDM_MACHINE_INPUT_PORT1_PAD3, &Input::OnCmdMachinePort }, { IDM_MACHINE_INPUT_PORT1_PAD4, &Input::OnCmdMachinePort }, { IDM_MACHINE_INPUT_PORT1_ZAPPER, &Input::OnCmdMachinePort }, { IDM_MACHINE_INPUT_PORT1_PADDLE, &Input::OnCmdMachinePort }, { IDM_MACHINE_INPUT_PORT1_POWERPAD, &Input::OnCmdMachinePort }, { IDM_MACHINE_INPUT_PORT1_POWERGLOVE, &Input::OnCmdMachinePort }, { IDM_MACHINE_INPUT_PORT1_MOUSE, &Input::OnCmdMachinePort }, { IDM_MACHINE_INPUT_PORT1_ROB, &Input::OnCmdMachinePort }, { IDM_MACHINE_INPUT_PORT2_UNCONNECTED, &Input::OnCmdMachinePort }, { IDM_MACHINE_INPUT_PORT2_PAD1, &Input::OnCmdMachinePort }, { IDM_MACHINE_INPUT_PORT2_PAD2, &Input::OnCmdMachinePort }, { IDM_MACHINE_INPUT_PORT2_PAD3, &Input::OnCmdMachinePort }, { IDM_MACHINE_INPUT_PORT2_PAD4, &Input::OnCmdMachinePort }, { IDM_MACHINE_INPUT_PORT2_ZAPPER, &Input::OnCmdMachinePort }, { IDM_MACHINE_INPUT_PORT2_PADDLE, &Input::OnCmdMachinePort }, { IDM_MACHINE_INPUT_PORT2_POWERPAD, &Input::OnCmdMachinePort }, { IDM_MACHINE_INPUT_PORT2_POWERGLOVE, &Input::OnCmdMachinePort }, { IDM_MACHINE_INPUT_PORT2_MOUSE, &Input::OnCmdMachinePort }, { IDM_MACHINE_INPUT_PORT2_ROB, &Input::OnCmdMachinePort }, { IDM_MACHINE_INPUT_PORT3_UNCONNECTED, &Input::OnCmdMachinePort }, { IDM_MACHINE_INPUT_PORT3_PAD1, &Input::OnCmdMachinePort }, { IDM_MACHINE_INPUT_PORT3_PAD2, &Input::OnCmdMachinePort }, { IDM_MACHINE_INPUT_PORT3_PAD3, &Input::OnCmdMachinePort }, { IDM_MACHINE_INPUT_PORT3_PAD4, &Input::OnCmdMachinePort }, { IDM_MACHINE_INPUT_PORT4_UNCONNECTED, &Input::OnCmdMachinePort }, { IDM_MACHINE_INPUT_PORT4_PAD1, &Input::OnCmdMachinePort }, { IDM_MACHINE_INPUT_PORT4_PAD2, &Input::OnCmdMachinePort }, { IDM_MACHINE_INPUT_PORT4_PAD3, &Input::OnCmdMachinePort }, { IDM_MACHINE_INPUT_PORT4_PAD4, &Input::OnCmdMachinePort }, { IDM_MACHINE_INPUT_EXP_UNCONNECTED, &Input::OnCmdMachinePort }, { IDM_MACHINE_INPUT_EXP_FAMILYTRAINER, &Input::OnCmdMachinePort }, { IDM_MACHINE_INPUT_EXP_FAMILYBASICKEYBOARD, &Input::OnCmdMachinePort }, { IDM_MACHINE_INPUT_EXP_SUBORKEYBOARD, &Input::OnCmdMachinePort }, { IDM_MACHINE_INPUT_EXP_DOREMIKKOKEYBOARD, &Input::OnCmdMachinePort }, { IDM_MACHINE_INPUT_EXP_HORITRACK, &Input::OnCmdMachinePort }, { IDM_MACHINE_INPUT_EXP_PACHINKO, &Input::OnCmdMachinePort }, { IDM_MACHINE_INPUT_EXP_PADDLE, &Input::OnCmdMachinePort }, { IDM_MACHINE_INPUT_EXP_OEKAKIDSTABLET, &Input::OnCmdMachinePort }, { IDM_MACHINE_INPUT_EXP_KONAMIHYPERSHOT, &Input::OnCmdMachinePort }, { IDM_MACHINE_INPUT_EXP_BANDAIHYPERSHOT, &Input::OnCmdMachinePort }, { IDM_MACHINE_INPUT_EXP_CRAZYCLIMBER, &Input::OnCmdMachinePort }, { IDM_MACHINE_INPUT_EXP_MAHJONG, &Input::OnCmdMachinePort }, { IDM_MACHINE_INPUT_EXP_EXCITINGBOXING, &Input::OnCmdMachinePort }, { IDM_MACHINE_INPUT_EXP_TOPRIDER, &Input::OnCmdMachinePort }, { IDM_MACHINE_INPUT_EXP_POKKUNMOGURAA, &Input::OnCmdMachinePort }, { IDM_MACHINE_INPUT_EXP_PARTYTAP, &Input::OnCmdMachinePort }, { IDM_MACHINE_INPUT_EXP_TURBOFILE, &Input::OnCmdMachinePort }, { IDM_MACHINE_INPUT_EXP_BARCODEWORLD, &Input::OnCmdMachinePort }, { IDM_MACHINE_INPUT_ADAPTER_AUTO, &Input::OnCmdMachineAdapter }, { IDM_MACHINE_INPUT_ADAPTER_NES, &Input::OnCmdMachineAdapter }, { IDM_MACHINE_INPUT_ADAPTER_FAMICOM, &Input::OnCmdMachineAdapter }, { IDM_OPTIONS_INPUT, &Input::OnCmdOptionsInput } }; menu.Commands().Add( this, commands ); static const Window::Menu::PopupHandler::Entry popups[] = { { Window::Menu::PopupHandler::Pos::ID, &Input::OnMenuPort1 }, { Window::Menu::PopupHandler::Pos::ID, &Input::OnMenuPort2 }, { Window::Menu::PopupHandler::Pos::ID, &Input::OnMenuPort3 }, { Window::Menu::PopupHandler::Pos::ID, &Input::OnMenuPort4 }, { Window::Menu::PopupHandler::Pos::ID, &Input::OnMenuPort5 } }; menu.Popups().Add( this, popups ); typedef Nes::Input::Controllers Controllers; Controllers::Pad::callback.Set ( &Callbacks::PollPad, this ); Controllers::Zapper::callback.Set ( &Callbacks::PollZapper, &cursor ); Controllers::Paddle::callback.Set ( &Callbacks::PollPaddle, &cursor ); Controllers::PowerPad::callback.Set ( &Callbacks::PollPowerPad, this ); Controllers::PowerGlove::callback.Set ( &Callbacks::PollPowerGlove, this ); Controllers::Mouse::callback.Set ( &Callbacks::PollMouse, &cursor ); Controllers::OekaKidsTablet::callback.Set ( &Callbacks::PollOekaKidsTablet, &cursor ); Controllers::KonamiHyperShot::callback.Set ( &Callbacks::PollKonamiHyperShot, this ); Controllers::BandaiHyperShot::callback.Set ( &Callbacks::PollBandaiHyperShot, this ); Controllers::FamilyTrainer::callback.Set ( &Callbacks::PollFamilyTrainer, this ); Controllers::FamilyKeyboard::callback.Set ( &Callbacks::PollFamilyKeyboard, this ); Controllers::SuborKeyboard::callback.Set ( &Callbacks::PollSuborKeyboard, this ); Controllers::DoremikkoKeyboard::callback.Set ( &Callbacks::PollDoremikkoKeyboard, this ); Controllers::HoriTrack::callback.Set ( &Callbacks::PollHoriTrack, this ); Controllers::Pachinko::callback.Set ( &Callbacks::PollPachinko, this ); Controllers::CrazyClimber::callback.Set ( &Callbacks::PollCrazyClimber, this ); Controllers::Mahjong::callback.Set ( &Callbacks::PollMahjong, this ); Controllers::ExcitingBoxing::callback.Set ( &Callbacks::PollExcitingBoxing, this ); Controllers::TopRider::callback.Set ( &Callbacks::PollTopRider, this ); Controllers::PokkunMoguraa::callback.Set ( &Callbacks::PollPokkunMoguraa, this ); Controllers::PartyTap::callback.Set ( &Callbacks::PollPartyTap, this ); Controllers::VsSystem::callback.Set ( &Callbacks::PollVsSystem, this ); Controllers::KaraokeStudio::callback.Set ( &Callbacks::PollKaraokeStudio, this ); Configuration::ConstSection machine( cfg["machine"] ); { const GenericString type( machine["adapter"].Str() ); SetAdapter ( type == L"nes" ? IDM_MACHINE_INPUT_ADAPTER_NES : type == L"famicom" ? IDM_MACHINE_INPUT_ADAPTER_FAMICOM : IDM_MACHINE_INPUT_ADAPTER_AUTO ); } menu[IDM_MACHINE_INPUT_AUTOSELECT].Check( !machine["auto-select-controllers"].No() ); { NST_COMPILE_ASSERT ( Emulator::EVENT_PORT2_CONTROLLER - Emulator::EVENT_PORT1_CONTROLLER == 1 && Emulator::EVENT_PORT3_CONTROLLER - Emulator::EVENT_PORT1_CONTROLLER == 2 && Emulator::EVENT_PORT4_CONTROLLER - Emulator::EVENT_PORT1_CONTROLLER == 3 ); String::Stack<16,char> string("port-#"); for (uint i=0; i < 5; ++i) { string[5] = '1' + i; const GenericString type( machine[string.Ptr()].Str() ); Nes::Input::Type controller = Nes::Input::UNCONNECTED; switch (i) { case 0: case 1: if (type == L"zapper" ) { controller = Nes::Input::ZAPPER; break; } else if (type == L"paddle" ) { controller = Nes::Input::PADDLE; break; } else if (type == L"powerpad" ) { controller = Nes::Input::POWERPAD; break; } else if (type == L"powerglove" ) { controller = Nes::Input::POWERGLOVE; break; } else if (type == L"mouse" ) { controller = Nes::Input::MOUSE; break; } else if (type == L"rob" ) { controller = Nes::Input::ROB; break; } case 2: case 3: if (type == L"pad1" ) controller = Nes::Input::PAD1; else if (type == L"pad2" ) controller = Nes::Input::PAD2; else if (type == L"pad3" ) controller = Nes::Input::PAD3; else if (type == L"pad4" ) controller = Nes::Input::PAD4; else if (type == L"unconnected" ) controller = Nes::Input::UNCONNECTED; else if (i == 0 ) controller = Nes::Input::PAD1; else if (i == 1 ) controller = Nes::Input::PAD2; break; case 4: if (type == L"paddle" ) controller = Nes::Input::PADDLE; else if (type == L"familytrainer" ) controller = Nes::Input::FAMILYTRAINER; else if (type == L"familykeyboard" ) controller = Nes::Input::FAMILYKEYBOARD; else if (type == L"suborkeyboard" ) controller = Nes::Input::SUBORKEYBOARD; else if (type == L"doremikkokeyboard" ) controller = Nes::Input::DOREMIKKOKEYBOARD; else if (type == L"horitrack" ) controller = Nes::Input::HORITRACK; else if (type == L"pachinko" ) controller = Nes::Input::PACHINKO; else if (type == L"oekakidstablet" ) controller = Nes::Input::OEKAKIDSTABLET; else if (type == L"konamihypershot" ) controller = Nes::Input::KONAMIHYPERSHOT; else if (type == L"bandaihypershot" ) controller = Nes::Input::BANDAIHYPERSHOT; else if (type == L"crazyclimber" ) controller = Nes::Input::CRAZYCLIMBER; else if (type == L"mahjong" ) controller = Nes::Input::MAHJONG; else if (type == L"excitingboxing" ) controller = Nes::Input::EXCITINGBOXING; else if (type == L"toprider" ) controller = Nes::Input::TOPRIDER; else if (type == L"pokkunmoguraa" ) controller = Nes::Input::POKKUNMOGURAA; else if (type == L"partytap" ) controller = Nes::Input::PARTYTAP; else if (type == L"turbofile" ) controller = Nes::Input::TURBOFILE; else if (type == L"barcodeworld" ) controller = Nes::Input::BARCODEWORLD; break; } Nes::Input(emulator).ConnectController( i, controller ); } } UpdateSettings(); } Input::~Input() { typedef Nes::Input::Controllers Controllers; Controllers::Pad::callback.Unset(); Controllers::Zapper::callback.Unset(); Controllers::Paddle::callback.Unset(); Controllers::PowerPad::callback.Unset(); Controllers::PowerGlove::callback.Unset(); Controllers::Mouse::callback.Unset(); Controllers::OekaKidsTablet::callback.Unset(); Controllers::KonamiHyperShot::callback.Unset(); Controllers::BandaiHyperShot::callback.Unset(); Controllers::FamilyTrainer::callback.Unset(); Controllers::FamilyKeyboard::callback.Unset(); Controllers::SuborKeyboard::callback.Unset(); Controllers::DoremikkoKeyboard::callback.Unset(); Controllers::HoriTrack::callback.Unset(); Controllers::Pachinko::callback.Unset(); Controllers::CrazyClimber::callback.Unset(); Controllers::Mahjong::callback.Unset(); Controllers::ExcitingBoxing::callback.Unset(); Controllers::TopRider::callback.Unset(); Controllers::PokkunMoguraa::callback.Unset(); Controllers::PartyTap::callback.Unset(); Controllers::VsSystem::callback.Unset(); Controllers::KaraokeStudio::callback.Unset(); } void Input::Save(Configuration& cfg) const { Configuration::Section machine( cfg["machine"] ); machine["auto-select-controllers"].YesNo() = menu[IDM_MACHINE_INPUT_AUTOSELECT].Checked(); machine["adapter"].Str() = ( menu[ IDM_MACHINE_INPUT_ADAPTER_NES ].Checked() ? "nes" : menu[ IDM_MACHINE_INPUT_ADAPTER_FAMICOM ].Checked() ? "famicom" : "auto" ); { String::Stack<16,char> string("port-x"); for (uint i=0; i < 5; ++i) { cstring type; switch (Nes::Input(emulator).GetConnectedController( i )) { case Nes::Input::PAD1: type = "pad1"; break; case Nes::Input::PAD2: type = "pad2"; break; case Nes::Input::PAD3: type = "pad3"; break; case Nes::Input::PAD4: type = "pad4"; break; case Nes::Input::ZAPPER: type = "zapper"; break; case Nes::Input::PADDLE: type = "paddle"; break; case Nes::Input::POWERPAD: type = "powerpad"; break; case Nes::Input::POWERGLOVE: type = "powerglove"; break; case Nes::Input::MOUSE: type = "mouse"; break; case Nes::Input::ROB: type = "rob"; break; case Nes::Input::FAMILYTRAINER: type = "familytrainer"; break; case Nes::Input::FAMILYKEYBOARD: type = "familykeyboard"; break; case Nes::Input::SUBORKEYBOARD: type = "suborkeyboard"; break; case Nes::Input::DOREMIKKOKEYBOARD: type = "doremikkokeyboard"; break; case Nes::Input::HORITRACK: type = "horitrack"; break; case Nes::Input::PACHINKO: type = "pachinko"; break; case Nes::Input::OEKAKIDSTABLET: type = "oekakidstablet"; break; case Nes::Input::KONAMIHYPERSHOT: type = "konamihypershot"; break; case Nes::Input::BANDAIHYPERSHOT: type = "bandaihypershot"; break; case Nes::Input::CRAZYCLIMBER: type = "crazyclimber"; break; case Nes::Input::MAHJONG: type = "mahjong"; break; case Nes::Input::EXCITINGBOXING: type = "excitingboxing"; break; case Nes::Input::TOPRIDER: type = "toprider"; break; case Nes::Input::POKKUNMOGURAA: type = "pokkunmoguraa"; break; case Nes::Input::PARTYTAP: type = "partytap"; break; case Nes::Input::TURBOFILE: type = "turbofile"; break; case Nes::Input::BARCODEWORLD: type = "barcodeworld"; break; default: type = "unconnected"; break; } string[5] = '1' + i; machine[string.Ptr()].Str() = type; } } dialog->Save( cfg ); } void Input::StartEmulation() { if (emulator.IsGame()) { directInput.Acquire(); commands.Acquire(); UpdateDevices(); } } void Input::StopEmulation() { clipboard.Clear(); commands.Unacquire(); directInput.Unacquire(); cursor.Unacquire(); Window::Menu::EnableAccelerators( true ); } void Input::UpdateDevices() { if (emulator.IsGameOn()) { cursor.Acquire( emulator ); Window::Menu::EnableAccelerators ( !Nes::Input(emulator).IsControllerConnected( Nes::Input::FAMILYKEYBOARD ) && !Nes::Input(emulator).IsControllerConnected( Nes::Input::SUBORKEYBOARD ) && !Nes::Input(emulator).IsControllerConnected( Nes::Input::DOREMIKKOKEYBOARD ) ); } } void Input::UpdateSettings() { autoFire = dialog->GetSettings().AutoFireSpeed(); for (uint i=0; i < 4; ++i) nesControllers.pad[i].allowSimulAxes = dialog->GetSettings().AllowSimulAxes(); typedef Window::Input::Settings Settings; directInput.Build( dialog->GetSettings().GetKeys(), Settings::NUM_KEYS ); static const ushort lut[Settings::NUM_COMMAND_KEYS][2] = { { Settings::FILE_KEYS + Settings::FILE_KEY_OPEN, IDM_FILE_OPEN }, { Settings::FILE_KEYS + Settings::FILE_KEY_LOAD_STATE, IDM_FILE_LOAD_NST }, { Settings::FILE_KEYS + Settings::FILE_KEY_SAVE_STATE, IDM_FILE_SAVE_NST }, { Settings::FILE_KEYS + Settings::FILE_KEY_QUICK_LOAD_STATE_1, IDM_FILE_QUICK_LOAD_STATE_SLOT_1 }, { Settings::FILE_KEYS + Settings::FILE_KEY_QUICK_LOAD_STATE_2, IDM_FILE_QUICK_LOAD_STATE_SLOT_2 }, { Settings::FILE_KEYS + Settings::FILE_KEY_QUICK_LOAD_STATE_3, IDM_FILE_QUICK_LOAD_STATE_SLOT_3 }, { Settings::FILE_KEYS + Settings::FILE_KEY_QUICK_LOAD_STATE_4, IDM_FILE_QUICK_LOAD_STATE_SLOT_4 }, { Settings::FILE_KEYS + Settings::FILE_KEY_QUICK_LOAD_STATE_5, IDM_FILE_QUICK_LOAD_STATE_SLOT_5 }, { Settings::FILE_KEYS + Settings::FILE_KEY_QUICK_LOAD_STATE_6, IDM_FILE_QUICK_LOAD_STATE_SLOT_6 }, { Settings::FILE_KEYS + Settings::FILE_KEY_QUICK_LOAD_STATE_7, IDM_FILE_QUICK_LOAD_STATE_SLOT_7 }, { Settings::FILE_KEYS + Settings::FILE_KEY_QUICK_LOAD_STATE_8, IDM_FILE_QUICK_LOAD_STATE_SLOT_8 }, { Settings::FILE_KEYS + Settings::FILE_KEY_QUICK_LOAD_STATE_9, IDM_FILE_QUICK_LOAD_STATE_SLOT_9 }, { Settings::FILE_KEYS + Settings::FILE_KEY_QUICK_LOAD_LAST_STATE, IDM_FILE_QUICK_LOAD_STATE_SLOT_NEWEST }, { Settings::FILE_KEYS + Settings::FILE_KEY_QUICK_SAVE_STATE_1, IDM_FILE_QUICK_SAVE_STATE_SLOT_1 }, { Settings::FILE_KEYS + Settings::FILE_KEY_QUICK_SAVE_STATE_2, IDM_FILE_QUICK_SAVE_STATE_SLOT_2 }, { Settings::FILE_KEYS + Settings::FILE_KEY_QUICK_SAVE_STATE_3, IDM_FILE_QUICK_SAVE_STATE_SLOT_3 }, { Settings::FILE_KEYS + Settings::FILE_KEY_QUICK_SAVE_STATE_4, IDM_FILE_QUICK_SAVE_STATE_SLOT_4 }, { Settings::FILE_KEYS + Settings::FILE_KEY_QUICK_SAVE_STATE_5, IDM_FILE_QUICK_SAVE_STATE_SLOT_5 }, { Settings::FILE_KEYS + Settings::FILE_KEY_QUICK_SAVE_STATE_6, IDM_FILE_QUICK_SAVE_STATE_SLOT_6 }, { Settings::FILE_KEYS + Settings::FILE_KEY_QUICK_SAVE_STATE_7, IDM_FILE_QUICK_SAVE_STATE_SLOT_7 }, { Settings::FILE_KEYS + Settings::FILE_KEY_QUICK_SAVE_STATE_8, IDM_FILE_QUICK_SAVE_STATE_SLOT_8 }, { Settings::FILE_KEYS + Settings::FILE_KEY_QUICK_SAVE_STATE_9, IDM_FILE_QUICK_SAVE_STATE_SLOT_9 }, { Settings::FILE_KEYS + Settings::FILE_KEY_QUICK_SAVE_NEXT_STATE, IDM_FILE_QUICK_SAVE_STATE_SLOT_OLDEST }, { Settings::FILE_KEYS + Settings::FILE_KEY_SAVE_SCREENSHOT, IDM_FILE_SAVE_SCREENSHOT }, { Settings::FILE_KEYS + Settings::FILE_KEY_LAUNCHER, IDM_FILE_LAUNCHER }, { Settings::FILE_KEYS + Settings::FILE_KEY_EXIT, IDM_FILE_QUIT }, { Settings::MACHINE_KEYS + Settings::MACHINE_KEY_POWER, IDM_MACHINE_POWER }, { Settings::MACHINE_KEYS + Settings::MACHINE_KEY_RESET_SOFT, IDM_MACHINE_RESET_SOFT }, { Settings::MACHINE_KEYS + Settings::MACHINE_KEY_RESET_HARD, IDM_MACHINE_RESET_HARD }, { Settings::MACHINE_KEYS + Settings::MACHINE_KEY_PAUSE, IDM_MACHINE_PAUSE }, { Settings::MACHINE_KEYS + Settings::MACHINE_KEY_UNLIMITED_SPRITES, IDM_MACHINE_OPTIONS_UNLIMITEDSPRITES }, { Settings::MACHINE_KEYS + Settings::MACHINE_KEY_CHANGE_DISK_SIDE, IDM_MACHINE_EXT_FDS_CHANGE_SIDE }, { Settings::NSF_KEYS + Settings::NSF_KEY_PLAY, IDM_MACHINE_NSF_PLAY }, { Settings::NSF_KEYS + Settings::NSF_KEY_STOP, IDM_MACHINE_NSF_STOP }, { Settings::NSF_KEYS + Settings::NSF_KEY_NEXT, IDM_MACHINE_NSF_NEXT }, { Settings::NSF_KEYS + Settings::NSF_KEY_PREV, IDM_MACHINE_NSF_PREV }, { Settings::VIEW_KEYS + Settings::VIEW_KEY_SCREENSIZE_1X, IDM_VIEW_WINDOWSIZE_1X }, { Settings::VIEW_KEYS + Settings::VIEW_KEY_SCREENSIZE_2X, IDM_VIEW_WINDOWSIZE_2X }, { Settings::VIEW_KEYS + Settings::VIEW_KEY_SCREENSIZE_3X, IDM_VIEW_WINDOWSIZE_3X }, { Settings::VIEW_KEYS + Settings::VIEW_KEY_SCREENSIZE_4X, IDM_VIEW_WINDOWSIZE_4X }, { Settings::VIEW_KEYS + Settings::VIEW_KEY_SCREENSIZE_5X, IDM_VIEW_WINDOWSIZE_5X }, { Settings::VIEW_KEYS + Settings::VIEW_KEY_SCREENSIZE_6X, IDM_VIEW_WINDOWSIZE_6X }, { Settings::VIEW_KEYS + Settings::VIEW_KEY_SCREENSIZE_7X, IDM_VIEW_WINDOWSIZE_7X }, { Settings::VIEW_KEYS + Settings::VIEW_KEY_SCREENSIZE_8X, IDM_VIEW_WINDOWSIZE_8X }, { Settings::VIEW_KEYS + Settings::VIEW_KEY_SCREENSIZE_9X, IDM_VIEW_WINDOWSIZE_9X }, { Settings::VIEW_KEYS + Settings::VIEW_KEY_SCREENSIZE_MAX, IDM_VIEW_WINDOWSIZE_MAX }, { Settings::VIEW_KEYS + Settings::VIEW_KEY_SHOW_MENU, IDM_VIEW_MENU }, { Settings::VIEW_KEYS + Settings::VIEW_KEY_SHOW_STATUSBAR, IDM_VIEW_STATUSBAR }, { Settings::VIEW_KEYS + Settings::VIEW_KEY_SHOW_ONTOP, IDM_VIEW_ON_TOP }, { Settings::VIEW_KEYS + Settings::VIEW_KEY_SHOW_FPS, IDM_VIEW_FPS }, { Settings::VIEW_KEYS + Settings::VIEW_KEY_FULLSCREEN, IDM_VIEW_SWITCH_SCREEN }, { Settings::HELP_KEYS + Settings::HELP_KEY_HELP, IDM_HELP_HELP } }; commands.BeginAdd(); ACCEL accel[Settings::NUM_COMMAND_KEYS]; for (uint i=0; i < Settings::NUM_COMMAND_KEYS; ++i) { const DirectX::DirectInput::Key& key = dialog->GetSettings().GetKey( lut[i][0] ); commands.Add( key, lut[i][1] ); key.GetVirtualKey( accel[i] ); accel[i].cmd = lut[i][1]; } commands.EndAdd(); menu.SetKeys( accel, Settings::NUM_COMMAND_KEYS ); } void Input::SyncControllers(const uint master,const Nes::Input::Type type,const uint slaves) const { uint pad = type - uint(Nes::Input::PAD1); if (pad < 4) { for (uint i=1; i < 4; ++i) { Nes::Input(emulator).ConnectController ( (master+i) % 4, (master+i) % 4 < slaves ? static_cast(Nes::Input::PAD1 + (++pad % 4)) : Nes::Input::UNCONNECTED ); } } } void Input::UpdateAdapterPort(const Nes::Input::Adapter adapter) const { if (menu[IDM_MACHINE_INPUT_ADAPTER_AUTO].Unchecked()) menu[adapter == Nes::Input::ADAPTER_NES ? IDM_MACHINE_INPUT_ADAPTER_NES : IDM_MACHINE_INPUT_ADAPTER_FAMICOM].Check( IDM_MACHINE_INPUT_ADAPTER_AUTO, IDM_MACHINE_INPUT_ADAPTER_FAMICOM ); } void Input::OnMenuPort1(const Window::Menu::PopupHandler::Param& param) { uint id; switch (Nes::Input(emulator).GetConnectedController( 0 )) { case Nes::Input::PAD1: id = IDM_MACHINE_INPUT_PORT1_PAD1; break; case Nes::Input::PAD2: id = IDM_MACHINE_INPUT_PORT1_PAD2; break; case Nes::Input::PAD3: id = IDM_MACHINE_INPUT_PORT1_PAD3; break; case Nes::Input::PAD4: id = IDM_MACHINE_INPUT_PORT1_PAD4; break; case Nes::Input::ZAPPER: id = IDM_MACHINE_INPUT_PORT1_ZAPPER; break; case Nes::Input::PADDLE: id = IDM_MACHINE_INPUT_PORT1_PADDLE; break; case Nes::Input::POWERPAD: id = IDM_MACHINE_INPUT_PORT1_POWERPAD; break; case Nes::Input::POWERGLOVE: id = IDM_MACHINE_INPUT_PORT1_POWERGLOVE; break; case Nes::Input::MOUSE: id = IDM_MACHINE_INPUT_PORT1_MOUSE; break; case Nes::Input::ROB: id = IDM_MACHINE_INPUT_PORT1_ROB; break; default: id = IDM_MACHINE_INPUT_PORT1_UNCONNECTED; break; } param.menu[id].Check( IDM_MACHINE_INPUT_PORT1_UNCONNECTED, IDM_MACHINE_INPUT_PORT1_ROB, param.show ); } void Input::OnMenuPort2(const Window::Menu::PopupHandler::Param& param) { uint id; switch (Nes::Input(emulator).GetConnectedController( 1 )) { case Nes::Input::PAD1: id = IDM_MACHINE_INPUT_PORT2_PAD1; break; case Nes::Input::PAD2: id = IDM_MACHINE_INPUT_PORT2_PAD2; break; case Nes::Input::PAD3: id = IDM_MACHINE_INPUT_PORT2_PAD3; break; case Nes::Input::PAD4: id = IDM_MACHINE_INPUT_PORT2_PAD4; break; case Nes::Input::ZAPPER: id = IDM_MACHINE_INPUT_PORT2_ZAPPER; break; case Nes::Input::PADDLE: id = IDM_MACHINE_INPUT_PORT2_PADDLE; break; case Nes::Input::POWERPAD: id = IDM_MACHINE_INPUT_PORT2_POWERPAD; break; case Nes::Input::POWERGLOVE: id = IDM_MACHINE_INPUT_PORT2_POWERGLOVE; break; case Nes::Input::MOUSE: id = IDM_MACHINE_INPUT_PORT2_MOUSE; break; case Nes::Input::ROB: id = IDM_MACHINE_INPUT_PORT2_ROB; break; default: id = IDM_MACHINE_INPUT_PORT2_UNCONNECTED; break; } param.menu[id].Check( IDM_MACHINE_INPUT_PORT2_UNCONNECTED, IDM_MACHINE_INPUT_PORT2_ROB, param.show ); } void Input::OnMenuPort3(const Window::Menu::PopupHandler::Param& param) { uint id; switch (Nes::Input(emulator).GetConnectedController( 2 )) { case Nes::Input::PAD1: id = IDM_MACHINE_INPUT_PORT3_PAD1; break; case Nes::Input::PAD2: id = IDM_MACHINE_INPUT_PORT3_PAD2; break; case Nes::Input::PAD3: id = IDM_MACHINE_INPUT_PORT3_PAD3; break; case Nes::Input::PAD4: id = IDM_MACHINE_INPUT_PORT3_PAD4; break; default: id = IDM_MACHINE_INPUT_PORT3_UNCONNECTED; break; } param.menu[id].Check( IDM_MACHINE_INPUT_PORT3_UNCONNECTED, IDM_MACHINE_INPUT_PORT3_PAD4, param.show ); } void Input::OnMenuPort4(const Window::Menu::PopupHandler::Param& param) { uint id; switch (Nes::Input(emulator).GetConnectedController( 3 )) { case Nes::Input::PAD1: id = IDM_MACHINE_INPUT_PORT4_PAD1; break; case Nes::Input::PAD2: id = IDM_MACHINE_INPUT_PORT4_PAD2; break; case Nes::Input::PAD3: id = IDM_MACHINE_INPUT_PORT4_PAD3; break; case Nes::Input::PAD4: id = IDM_MACHINE_INPUT_PORT4_PAD4; break; default: id = IDM_MACHINE_INPUT_PORT4_UNCONNECTED; break; } param.menu[id].Check( IDM_MACHINE_INPUT_PORT4_UNCONNECTED, IDM_MACHINE_INPUT_PORT4_PAD4, param.show ); } void Input::OnMenuPort5(const Window::Menu::PopupHandler::Param& param) { uint id; switch (Nes::Input(emulator).GetConnectedController( 4 )) { case Nes::Input::FAMILYTRAINER: id = IDM_MACHINE_INPUT_EXP_FAMILYTRAINER; break; case Nes::Input::FAMILYKEYBOARD: id = IDM_MACHINE_INPUT_EXP_FAMILYBASICKEYBOARD; break; case Nes::Input::SUBORKEYBOARD: id = IDM_MACHINE_INPUT_EXP_SUBORKEYBOARD; break; case Nes::Input::DOREMIKKOKEYBOARD: id = IDM_MACHINE_INPUT_EXP_DOREMIKKOKEYBOARD; break; case Nes::Input::HORITRACK: id = IDM_MACHINE_INPUT_EXP_HORITRACK; break; case Nes::Input::PACHINKO: id = IDM_MACHINE_INPUT_EXP_PACHINKO; break; case Nes::Input::PADDLE: id = IDM_MACHINE_INPUT_EXP_PADDLE; break; case Nes::Input::OEKAKIDSTABLET: id = IDM_MACHINE_INPUT_EXP_OEKAKIDSTABLET; break; case Nes::Input::KONAMIHYPERSHOT: id = IDM_MACHINE_INPUT_EXP_KONAMIHYPERSHOT; break; case Nes::Input::BANDAIHYPERSHOT: id = IDM_MACHINE_INPUT_EXP_BANDAIHYPERSHOT; break; case Nes::Input::CRAZYCLIMBER: id = IDM_MACHINE_INPUT_EXP_CRAZYCLIMBER; break; case Nes::Input::MAHJONG: id = IDM_MACHINE_INPUT_EXP_MAHJONG; break; case Nes::Input::EXCITINGBOXING: id = IDM_MACHINE_INPUT_EXP_EXCITINGBOXING; break; case Nes::Input::TOPRIDER: id = IDM_MACHINE_INPUT_EXP_TOPRIDER; break; case Nes::Input::POKKUNMOGURAA: id = IDM_MACHINE_INPUT_EXP_POKKUNMOGURAA; break; case Nes::Input::PARTYTAP: id = IDM_MACHINE_INPUT_EXP_PARTYTAP; break; case Nes::Input::TURBOFILE: id = IDM_MACHINE_INPUT_EXP_TURBOFILE; break; case Nes::Input::BARCODEWORLD: id = IDM_MACHINE_INPUT_EXP_BARCODEWORLD; break; default: id = IDM_MACHINE_INPUT_EXP_UNCONNECTED; break; } param.menu[id].Check( IDM_MACHINE_INPUT_EXP_UNCONNECTED, IDM_MACHINE_INPUT_EXP_BARCODEWORLD, param.show ); } bool Input::SetAdapter(const uint id) const { Nes::Result result; if (id == IDM_MACHINE_INPUT_ADAPTER_AUTO) { result = Nes::Input(emulator).AutoSelectAdapter(); } else { result = Nes::Input(emulator).ConnectAdapter ( id == IDM_MACHINE_INPUT_ADAPTER_NES ? Nes::Input::ADAPTER_NES : Nes::Input::ADAPTER_FAMICOM ); } if (NES_SUCCEEDED(result)) { menu[id].Check( IDM_MACHINE_INPUT_ADAPTER_AUTO, IDM_MACHINE_INPUT_ADAPTER_FAMICOM ); return result != Nes::RESULT_NOP; } return false; } void Input::OnEmuEvent(const Emulator::Event event,Emulator::Data data) { NST_COMPILE_ASSERT ( Emulator::EVENT_PORT2_CONTROLLER == Emulator::EVENT_PORT1_CONTROLLER + 1 && Emulator::EVENT_PORT3_CONTROLLER == Emulator::EVENT_PORT1_CONTROLLER + 2 && Emulator::EVENT_PORT4_CONTROLLER == Emulator::EVENT_PORT1_CONTROLLER + 3 && Emulator::EVENT_PORT5_CONTROLLER == Emulator::EVENT_PORT1_CONTROLLER + 4 ); switch (event) { case Emulator::EVENT_PORT1_CONTROLLER: case Emulator::EVENT_PORT2_CONTROLLER: case Emulator::EVENT_PORT3_CONTROLLER: case Emulator::EVENT_PORT4_CONTROLLER: if (emulator.IsOn()) { if (const uint players = emulator.NetPlayers()) { const uint port = event - Emulator::EVENT_PORT1_CONTROLLER; if (port == emulator.GetPlayer()) SyncControllers( port, static_cast(data), players ); } } case Emulator::EVENT_PORT5_CONTROLLER: UpdateDevices(); break; case Emulator::EVENT_PORT_ADAPTER: UpdateAdapterPort( static_cast(data) ); break; case Emulator::EVENT_NETPLAY_MODE: data = !data; menu[IDM_MACHINE_INPUT_AUTOSELECT].Enable( data ); menu[IDM_POS_MACHINE][IDM_POS_MACHINE_INPUT][IDM_POS_MACHINE_INPUT_EXP].Enable( data ); for (uint i=IDM_MACHINE_INPUT_EXP_UNCONNECTED; i <= IDM_MACHINE_INPUT_EXP_BARCODEWORLD; ++i) menu[i].Enable( data ); for (uint i=IDM_MACHINE_INPUT_ADAPTER_AUTO; i <= IDM_MACHINE_INPUT_ADAPTER_FAMICOM; ++i) menu[i].Enable( data ); menu[IDM_POS_MACHINE][IDM_POS_MACHINE_EXT][IDM_POS_MACHINE_EXT_KEYBOARD].Enable( data ); menu[IDM_OPTIONS_INPUT].Enable( data ); if (data) { for (uint i=IDM_MACHINE_INPUT_PORT1_UNCONNECTED; i < IDM_MACHINE_INPUT_EXP_UNCONNECTED; ++i) menu[i].Enable(); for (uint i=0; i < 4; ++i) menu[IDM_POS_MACHINE][IDM_POS_MACHINE_INPUT][IDM_POS_MACHINE_INPUT_PORT1+i].Enable(); break; } case Emulator::EVENT_POWER_ON: case Emulator::EVENT_POWER_OFF: if (uint players = emulator.NetPlayers()) { uint player = emulator.GetPlayer(); if (event != Emulator::EVENT_POWER_ON) { player = 0; players = 1; } static const ushort offsets[] = { IDM_MACHINE_INPUT_PORT1_PAD1, IDM_MACHINE_INPUT_PORT2_PAD1, IDM_MACHINE_INPUT_PORT3_PAD1, IDM_MACHINE_INPUT_PORT4_PAD1 }; for (uint j = (player < 4 ? offsets[player] : IDM_MACHINE_INPUT_EXP_UNCONNECTED), i=IDM_MACHINE_INPUT_PORT1_UNCONNECTED; i < IDM_MACHINE_INPUT_EXP_UNCONNECTED; ++i) menu[i].Enable( i - j < 4 ); for (uint i=0; i < 4; ++i) menu[IDM_POS_MACHINE][IDM_POS_MACHINE_INPUT][IDM_POS_MACHINE_INPUT_PORT1+i].Enable( i == player ); uint port = (event == Emulator::EVENT_POWER_ON ? 0 : player); uint pad = Nes::Input(emulator).GetConnectedController( port ) - uint(Nes::Input::PAD1); if (pad > 3) pad = 0; port = (event == Emulator::EVENT_POWER_ON ? player : 0); Nes::Input(emulator).ConnectController( port, static_cast(Nes::Input::PAD1 + pad) ); SyncControllers( port, static_cast(Nes::Input::PAD1 + pad), players ); Nes::Input(emulator).ConnectController( 4, Nes::Input::UNCONNECTED ); } break; case Emulator::EVENT_LOAD: case Emulator::EVENT_UNLOAD: if (menu[IDM_MACHINE_INPUT_ADAPTER_AUTO].Checked()) Nes::Input(emulator).AutoSelectAdapter(); if (menu[IDM_MACHINE_INPUT_AUTOSELECT].Checked() && emulator.NetPlayers() == 0) Nes::Input(emulator).AutoSelectControllers(); break; } } void Input::OnCmdOptionsInput(uint) { dialog->Open(); UpdateSettings(); } void Input::OnCmdMachineAutoSelectController(uint) { if (menu[IDM_MACHINE_INPUT_AUTOSELECT].ToggleCheck()) Nes::Input(emulator).AutoSelectControllers(); } void Input::OnCmdMachinePort(uint id) { static const uchar table[][2] = { { 0, Nes::Input::UNCONNECTED }, { 0, Nes::Input::PAD1 }, { 0, Nes::Input::PAD2 }, { 0, Nes::Input::PAD3 }, { 0, Nes::Input::PAD4 }, { 0, Nes::Input::ZAPPER }, { 0, Nes::Input::PADDLE }, { 0, Nes::Input::POWERPAD }, { 0, Nes::Input::POWERGLOVE }, { 0, Nes::Input::MOUSE }, { 0, Nes::Input::ROB }, { 1, Nes::Input::UNCONNECTED }, { 1, Nes::Input::PAD1 }, { 1, Nes::Input::PAD2 }, { 1, Nes::Input::PAD3 }, { 1, Nes::Input::PAD4 }, { 1, Nes::Input::ZAPPER }, { 1, Nes::Input::PADDLE }, { 1, Nes::Input::POWERPAD }, { 1, Nes::Input::POWERGLOVE }, { 1, Nes::Input::MOUSE }, { 1, Nes::Input::ROB }, { 2, Nes::Input::UNCONNECTED }, { 2, Nes::Input::PAD1 }, { 2, Nes::Input::PAD2 }, { 2, Nes::Input::PAD3 }, { 2, Nes::Input::PAD4 }, { 3, Nes::Input::UNCONNECTED }, { 3, Nes::Input::PAD1 }, { 3, Nes::Input::PAD2 }, { 3, Nes::Input::PAD3 }, { 3, Nes::Input::PAD4 }, { 4, Nes::Input::UNCONNECTED }, { 4, Nes::Input::FAMILYTRAINER }, { 4, Nes::Input::FAMILYKEYBOARD }, { 4, Nes::Input::SUBORKEYBOARD }, { 4, Nes::Input::DOREMIKKOKEYBOARD }, { 4, Nes::Input::HORITRACK }, { 4, Nes::Input::PACHINKO }, { 4, Nes::Input::PADDLE }, { 4, Nes::Input::OEKAKIDSTABLET }, { 4, Nes::Input::KONAMIHYPERSHOT }, { 4, Nes::Input::BANDAIHYPERSHOT }, { 4, Nes::Input::CRAZYCLIMBER }, { 4, Nes::Input::MAHJONG }, { 4, Nes::Input::EXCITINGBOXING }, { 4, Nes::Input::TOPRIDER }, { 4, Nes::Input::POKKUNMOGURAA }, { 4, Nes::Input::PARTYTAP }, { 4, Nes::Input::TURBOFILE }, { 4, Nes::Input::BARCODEWORLD } }; const uchar* const offset = table[id - IDM_MACHINE_INPUT_PORT1_UNCONNECTED]; Nes::Input(emulator).ConnectController( offset[0], static_cast(offset[1]) ); Resume(); } void Input::OnCmdMachineAdapter(uint id) { SetAdapter( id ); Resume(); } #ifdef NST_MSVC_OPTIMIZE #pragma optimize("t", on) #endif void Input::ForcePoll() { directInput.Poll(); typedef Window::Input::Settings Settings; const Settings::Key* const NST_RESTRICT keys = dialog->GetSettings().GetKeys(Settings::EMULATION_KEYS); emulator.ToggleSpeed( keys[Settings::EMULATION_KEY_ALT_SPEED].GetState() ); emulator.ToggleRewind( keys[Settings::EMULATION_KEY_REWIND].GetState() ); commands.Poll(); } bool NST_CALLBACK Input::Callbacks::PollPad(UserData data,Pad& pad,uint index) { NST_COMPILE_ASSERT ( Settings::TYPE_PAD1 == 0 && Settings::TYPE_PAD2 == 1 && Settings::TYPE_PAD3 == 2 && Settings::TYPE_PAD4 == 3 ); NST_ASSERT(index < 4); Input& input = *static_cast(data); input.ForcePoll(); const Key* const NST_RESTRICT keys = input.dialog->GetSettings().GetKeys(index,0); uint buttons = 0; keys[ Settings::PAD_KEY_A ].GetState( buttons, Pad::A ); keys[ Settings::PAD_KEY_B ].GetState( buttons, Pad::B ); keys[ Settings::PAD_KEY_SELECT ].GetState( buttons, Pad::SELECT ); keys[ Settings::PAD_KEY_START ].GetState( buttons, Pad::START ); keys[ Settings::PAD_KEY_UP ].GetState( buttons, Pad::UP ); keys[ Settings::PAD_KEY_DOWN ].GetState( buttons, Pad::DOWN ); keys[ Settings::PAD_KEY_LEFT ].GetState( buttons, Pad::LEFT ); keys[ Settings::PAD_KEY_RIGHT ].GetState( buttons, Pad::RIGHT ); if (input.autoFire) { keys[ Settings::PAD_KEY_AUTOFIRE_A ].GetState( buttons, Pad::A ); keys[ Settings::PAD_KEY_AUTOFIRE_B ].GetState( buttons, Pad::B ); } pad.buttons = buttons; buttons = 0; keys[ Settings::PAD_KEY_MIC ].GetState( buttons, Pad::MIC ); pad.mic = buttons; return true; } bool NST_CALLBACK Input::Callbacks::PollZapper(UserData data,Zapper& zapper) { uint x, y, offscreen; if (static_cast(data)->Poll( x, y, zapper.fire, &offscreen )) { if (offscreen) { zapper.fire = true; zapper.x = ~0U; zapper.y = ~0U; } else if (zapper.x != ~0U) { zapper.x = x; zapper.y = y; } else if (zapper.fire) { zapper.x = ~1U; } } return true; } bool NST_CALLBACK Input::Callbacks::PollBandaiHyperShot(UserData data,BandaiHyperShot& bandaiHyperShot) { uint x, y, offscreen; if (static_cast(data)->cursor.Poll( x, y, bandaiHyperShot.fire, &offscreen )) { if (offscreen) { bandaiHyperShot.fire = true; bandaiHyperShot.x = ~0U; bandaiHyperShot.y = ~0U; } else if (bandaiHyperShot.x != ~0U) { bandaiHyperShot.x = x; bandaiHyperShot.y = y; } else if (bandaiHyperShot.fire) { bandaiHyperShot.x = ~1U; } } const Key* const NST_RESTRICT keys = static_cast(data)->dialog->GetSettings().GetKeys(Settings::PAD1_KEYS); bandaiHyperShot.move = keys[Settings::PAD_KEY_UP].GetState(); return true; } bool NST_CALLBACK Input::Callbacks::PollPaddle(UserData data,Paddle& paddle) { uint y; static_cast(data)->Poll( paddle.x, y, paddle.button ); return true; } bool NST_CALLBACK Input::Callbacks::PollPowerPad(UserData data,PowerPad& powerPad) { Input& input = *static_cast(data); input.ForcePoll(); const Key* NST_RESTRICT keys = input.dialog->GetSettings().GetKeys(Settings::POWERPAD_KEYS); for (uint i=0; i < Settings::POWERPAD_NUM_SIDE_A_KEYS; ++i) powerPad.sideA[i] = keys[i].GetState(); keys += Settings::POWERPAD_NUM_SIDE_A_KEYS; for (uint i=0; i < Settings::POWERPAD_NUM_SIDE_B_KEYS; ++i) powerPad.sideB[i] = keys[i].GetState(); return true; } bool NST_CALLBACK Input::Callbacks::PollPowerGlove(UserData data,PowerGlove& glove) { Input& input = *static_cast(data); input.ForcePoll(); const Key* const NST_RESTRICT keys = input.dialog->GetSettings().GetKeys(Settings::POWERGLOVE_KEYS); uint pad = 0; keys[ Settings::POWERGLOVE_KEY_SELECT ].GetState( pad, PowerGlove::SELECT ); keys[ Settings::POWERGLOVE_KEY_START ].GetState( pad, PowerGlove::START ); glove.buttons = pad; if (keys[Settings::POWERGLOVE_KEY_MOVE_IN].GetState()) { glove.distance = PowerGlove::DISTANCE_IN; } else if (keys[Settings::POWERGLOVE_KEY_MOVE_OUT].GetState()) { glove.distance = PowerGlove::DISTANCE_OUT; } else { glove.distance = 0; } if (keys[Settings::POWERGLOVE_KEY_ROLL_LEFT].GetState()) { glove.wrist = PowerGlove::ROLL_LEFT; } else if (keys[Settings::POWERGLOVE_KEY_ROLL_RIGHT].GetState()) { glove.wrist = PowerGlove::ROLL_RIGHT; } else { glove.wrist = 0; } uint buttons[2], x=0, y=0; input.cursor.Poll( x, y, buttons[0], buttons+1 ); glove.x = x; glove.y = y; if (buttons[0]) { glove.gesture = PowerGlove::GESTURE_FIST; } else if (buttons[1]) { glove.gesture = PowerGlove::GESTURE_FINGER; } else { glove.gesture = PowerGlove::GESTURE_OPEN; } return true; } bool NST_CALLBACK Input::Callbacks::PollMouse(UserData data,Mouse& mouse) { static_cast(data)->Poll( mouse.x, mouse.y, mouse.button ); return true; } bool NST_CALLBACK Input::Callbacks::PollOekaKidsTablet(UserData data,OekaKidsTablet& tablet) { static_cast(data)->Poll( tablet.x, tablet.y, tablet.button ); return true; } bool NST_CALLBACK Input::Callbacks::PollHoriTrack(UserData data,HoriTrack& horiTrack) { Input& input = *static_cast(data); input.ForcePoll(); const Key* const NST_RESTRICT keys = input.dialog->GetSettings().GetKeys(Settings::HORITRACK_KEYS); uint buttons = 0; keys[ Settings::HORITRACK_KEY_A ].GetState( buttons, HoriTrack::BUTTON_A ); keys[ Settings::HORITRACK_KEY_B ].GetState( buttons, HoriTrack::BUTTON_B ); keys[ Settings::HORITRACK_KEY_SELECT ].GetState( buttons, HoriTrack::BUTTON_SELECT ); keys[ Settings::HORITRACK_KEY_START ].GetState( buttons, HoriTrack::BUTTON_START ); keys[ Settings::HORITRACK_KEY_UP ].GetState( buttons, HoriTrack::BUTTON_UP ); keys[ Settings::HORITRACK_KEY_DOWN ].GetState( buttons, HoriTrack::BUTTON_DOWN ); keys[ Settings::HORITRACK_KEY_LEFT ].GetState( buttons, HoriTrack::BUTTON_LEFT ); keys[ Settings::HORITRACK_KEY_RIGHT ].GetState( buttons, HoriTrack::BUTTON_RIGHT ); static bool speed = false; if (keys[Settings::HORITRACK_KEY_SPEED].GetToggle( speed )) { horiTrack.mode ^= HoriTrack::MODE_LOWSPEED; Io::Screen() << Resource::String((horiTrack.mode & HoriTrack::MODE_LOWSPEED) ? IDS_SCREEN_HORITRACK_SPEED_LOW : IDS_SCREEN_HORITRACK_SPEED_HIGH); } static bool orientation = false; if (keys[Settings::HORITRACK_KEY_ORIENTATION].GetToggle( orientation )) { horiTrack.mode ^= HoriTrack::MODE_REVERSED; Io::Screen() << Resource::String((horiTrack.mode & HoriTrack::MODE_REVERSED) ? IDS_SCREEN_HORITRACK_ORIENTATION_RIGHT : IDS_SCREEN_HORITRACK_ORIENTATION_LEFT); } horiTrack.buttons = buttons; uint mouseButton; input.cursor.Poll( horiTrack.x, horiTrack.y, mouseButton ); horiTrack.buttons = (horiTrack.buttons & (HoriTrack::BUTTON_A^0xFFU)) | (mouseButton ? HoriTrack::BUTTON_A : 0); return true; } bool NST_CALLBACK Input::Callbacks::PollPachinko(UserData data,Pachinko& pachinko) { Input& input = *static_cast(data); input.ForcePoll(); const Key* const NST_RESTRICT keys = input.dialog->GetSettings().GetKeys(Settings::PACHINKO_KEYS); uint buttons = 0; keys[ Settings::PACHINKO_KEY_A ].GetState( buttons, Pachinko::BUTTON_A ); keys[ Settings::PACHINKO_KEY_B ].GetState( buttons, Pachinko::BUTTON_B ); keys[ Settings::PACHINKO_KEY_SELECT ].GetState( buttons, Pachinko::BUTTON_SELECT ); keys[ Settings::PACHINKO_KEY_START ].GetState( buttons, Pachinko::BUTTON_START ); keys[ Settings::PACHINKO_KEY_UP ].GetState( buttons, Pachinko::BUTTON_UP ); keys[ Settings::PACHINKO_KEY_DOWN ].GetState( buttons, Pachinko::BUTTON_DOWN ); keys[ Settings::PACHINKO_KEY_LEFT ].GetState( buttons, Pachinko::BUTTON_LEFT ); keys[ Settings::PACHINKO_KEY_RIGHT ].GetState( buttons, Pachinko::BUTTON_RIGHT ); pachinko.buttons = buttons; pachinko.throttle = input.cursor.GetWheel(); return true; } bool NST_CALLBACK Input::Callbacks::PollKonamiHyperShot(UserData data,KonamiHyperShot& konamiHyperShot) { Input& input = *static_cast(data); input.ForcePoll(); const Key* const NST_RESTRICT keys[2] = { input.dialog->GetSettings().GetKeys(Settings::PAD1_KEYS), input.dialog->GetSettings().GetKeys(Settings::PAD2_KEYS) }; uint buttons = 0; keys[0][ Settings::PAD_KEY_A ].GetState( buttons, KonamiHyperShot::PLAYER1_BUTTON_1 ); keys[0][ Settings::PAD_KEY_B ].GetState( buttons, KonamiHyperShot::PLAYER1_BUTTON_2 ); keys[1][ Settings::PAD_KEY_A ].GetState( buttons, KonamiHyperShot::PLAYER2_BUTTON_1 ); keys[1][ Settings::PAD_KEY_B ].GetState( buttons, KonamiHyperShot::PLAYER2_BUTTON_2 ); if (input.autoFire) { keys[0][ Settings::PAD_KEY_AUTOFIRE_A ].GetState( buttons, KonamiHyperShot::PLAYER1_BUTTON_1 ); keys[0][ Settings::PAD_KEY_AUTOFIRE_B ].GetState( buttons, KonamiHyperShot::PLAYER1_BUTTON_2 ); keys[1][ Settings::PAD_KEY_AUTOFIRE_A ].GetState( buttons, KonamiHyperShot::PLAYER2_BUTTON_1 ); keys[1][ Settings::PAD_KEY_AUTOFIRE_B ].GetState( buttons, KonamiHyperShot::PLAYER2_BUTTON_2 ); } konamiHyperShot.buttons = buttons; return true; } bool NST_CALLBACK Input::Callbacks::PollCrazyClimber(UserData data,CrazyClimber& crazyClimber) { Input& input = *static_cast(data); input.ForcePoll(); const Key* const NST_RESTRICT keys = input.dialog->GetSettings().GetKeys(Settings::CRAZYCLIMBER_KEYS); uint buttons = 0; keys[ Settings::CRAZYCLIMBER_KEY_LEFT_UP ].GetState( buttons, CrazyClimber::UP ); keys[ Settings::CRAZYCLIMBER_KEY_LEFT_RIGHT ].GetState( buttons, CrazyClimber::RIGHT ); keys[ Settings::CRAZYCLIMBER_KEY_LEFT_DOWN ].GetState( buttons, CrazyClimber::DOWN ); keys[ Settings::CRAZYCLIMBER_KEY_LEFT_LEFT ].GetState( buttons, CrazyClimber::LEFT ); crazyClimber.left = buttons; buttons = 0; keys[ Settings::CRAZYCLIMBER_KEY_RIGHT_UP ].GetState( buttons, CrazyClimber::UP ); keys[ Settings::CRAZYCLIMBER_KEY_RIGHT_RIGHT ].GetState( buttons, CrazyClimber::RIGHT ); keys[ Settings::CRAZYCLIMBER_KEY_RIGHT_DOWN ].GetState( buttons, CrazyClimber::DOWN ); keys[ Settings::CRAZYCLIMBER_KEY_RIGHT_LEFT ].GetState( buttons, CrazyClimber::LEFT ); crazyClimber.right = buttons; return true; } bool NST_CALLBACK Input::Callbacks::PollFamilyTrainer(UserData data,FamilyTrainer& familyTrainer) { Input& input = *static_cast(data); input.ForcePoll(); const Key* NST_RESTRICT keys = input.dialog->GetSettings().GetKeys(Settings::POWERPAD_KEYS); for (uint i=0; i < Settings::POWERPAD_NUM_SIDE_A_KEYS; ++i) familyTrainer.sideA[i] = keys[i].GetState(); keys += Settings::POWERPAD_NUM_SIDE_A_KEYS; for (uint i=0; i < Settings::POWERPAD_NUM_SIDE_B_KEYS; ++i) familyTrainer.sideB[i] = keys[i].GetState(); return true; } bool NST_CALLBACK Input::Callbacks::PollFamilyKeyboard(UserData data,FamilyKeyboard& keyboard,uint part,uint mode) { Input& input = *static_cast(data); input.ForcePoll(); const uchar* const NST_RESTRICT buffer = input.directInput.GetKeyboardBuffer(); uint key = 0; #define NST_2(a_,b_) ((a_) | (b_) << 8) if (input.clipboard.Query( buffer, Clipboard::FAMILY )) { static const ushort asciiMap[FamilyKeyboard::NUM_PARTS][FamilyKeyboard::NUM_MODES][4] = { { { 0, '\r', NST_2('[','['|0x80), NST_2(']',']'|0x80) }, { 0xFF, 0, '\\', 0 } }, { { 0, '@', NST_2(':','*'), NST_2(';','+') }, { NST_2('\t','_'), NST_2('/','?'), NST_2('-','='), '^' } }, { { 0, NST_2('o','o'|0x80), 'l', 'k' }, { NST_2('.','>'), NST_2(',','<'), NST_2('p','p'|0x80), '0' } }, { { 0, NST_2('i','i'|0x80), NST_2('u','u'|0x80), 'j' }, { NST_2('m','m'|0x80), NST_2('n','n'|0x80), NST_2('9',')'), NST_2('8','(') } }, { { 0, NST_2('y','y'|0x80), 'g', 'h' }, { 'b', 'v', NST_2('7','\''), NST_2('6','&') } }, { { 0, 't', 'r', 'd' }, { 'f', NST_2('c','c'|0x80), NST_2('5','%'), NST_2('4','$') } }, { { 0, 'w', 's', 'a' }, { 'x', 'z', 'e', NST_2('3','#') } }, { { 0, 0, 'q', 0 }, { 0, 0xFE, NST_2('1','!'), NST_2('2','\"') } }, { { 0, 0, 0, 0 }, { 0, ' ', 0, 0 } }, }; if (input.clipboard.Shifted() && part == 7 && mode == 1) key = 0x02; uint next = *input.clipboard; if (next != UINT_MAX && (next & 0x100)) { next &= 0xFF; if (part == 7 && mode == 1) key |= 0x04; } for (uint i=0; i < 4; ++i) { if ((asciiMap[part][mode][i] & 0xFFU) == next) { key |= 1U << (i+1); ++input.clipboard; break; } else if ((asciiMap[part][mode][i] >> 8) == next) { if (input.clipboard.Shifted()) { key |= 1U << (i+1); ++input.clipboard; } else { input.clipboard.Shift(); } break; } } } else { static const ushort dikMap[FamilyKeyboard::NUM_PARTS][FamilyKeyboard::NUM_MODES][4] = { { { DIK_F8, NST_2(DIK_RETURN,DIK_NUMPADENTER), DIK_LBRACKET, DIK_RBRACKET }, { NST_2(DIK_KANA,DIK_F9), DIK_RSHIFT, NST_2(DIK_YEN,DIK_BACKSLASH), DIK_END } }, { { DIK_F7, NST_2(DIK_GRAVE,DIK_AT), NST_2(DIK_APOSTROPHE,DIK_COLON), DIK_SEMICOLON }, { NST_2(DIK_UNDERLINE,DIK_TAB), NST_2(DIK_SLASH,DIK_NUMPADSLASH), NST_2(DIK_MINUS,DIK_NUMPADMINUS), NST_2(DIK_EQUALS,DIK_CIRCUMFLEX) } }, { { DIK_F6, DIK_O, DIK_L, DIK_K }, { DIK_PERIOD, NST_2(DIK_COMMA,DIK_NUMPADCOMMA), DIK_P, NST_2(DIK_0,DIK_NUMPAD0) } }, { { DIK_F5, DIK_I, DIK_U, DIK_J }, { DIK_M, DIK_N, NST_2(DIK_9,DIK_NUMPAD9), NST_2(DIK_8,DIK_NUMPAD8) } }, { { DIK_F4, DIK_Y, DIK_G, DIK_H }, { DIK_B, DIK_V, NST_2(DIK_7,DIK_NUMPAD7), NST_2(DIK_6,DIK_NUMPAD6) } }, { { DIK_F3, DIK_T, DIK_R, DIK_D }, { DIK_F, DIK_C, NST_2(DIK_5,DIK_NUMPAD5), NST_2(DIK_4,DIK_NUMPAD4) } }, { { DIK_F2, DIK_W, DIK_S, DIK_A }, { DIK_X, DIK_Z, DIK_E, NST_2(DIK_3,DIK_NUMPAD3) } }, { { DIK_F1, DIK_ESCAPE, DIK_Q, NST_2(DIK_LCONTROL,DIK_RCONTROL) }, { DIK_LSHIFT, 0, NST_2(DIK_1,DIK_NUMPAD1), NST_2(DIK_2,DIK_NUMPAD2) } }, { { DIK_HOME, DIK_UP, DIK_RIGHT, DIK_LEFT }, { DIK_DOWN, DIK_SPACE, NST_2(DIK_BACK,DIK_DELETE), DIK_INSERT } }, }; if (part == 7 && mode == 1) key |= (::GetKeyState(VK_CAPITAL) & 0x0001U) << 2; for (uint i=0; i < 4; ++i) { const uint pushed = 0x80 & ( buffer[dikMap[part][mode][i] & 0xFFU] | buffer[dikMap[part][mode][i] >> 8] ); key |= pushed >> ( 7 - ( i + 1 ) ); } } #undef NST_2 keyboard.parts[part] = key; return true; } bool NST_CALLBACK Input::Callbacks::PollSuborKeyboard(UserData data,SuborKeyboard& keyboard,uint part,uint mode) { Input& input = *static_cast(data); input.ForcePoll(); const uchar* const NST_RESTRICT buffer = input.directInput.GetKeyboardBuffer(); uint key = 0; #define NST_2(a_,b_) ((a_) | (b_) << 8) if (input.clipboard.Query( buffer, Clipboard::SUBOR )) { static const ushort asciiMap[SuborKeyboard::NUM_PARTS][SuborKeyboard::NUM_MODES][4] = { { { NST_2('4','$'), 'g', 'f', 'c' }, { 0, 'e', NST_2('5','%'), 'v' } }, { { NST_2('2','@'), 'd', 's', 0 }, { 0, 'w', NST_2('3','#'), 'x' } }, { { 0, 0, 0, 0 }, { 0, 0, 0, 0 } }, { { NST_2('9','('), 'i', 'l', NST_2(',','<') }, { 0, 'o', NST_2('0',')'), NST_2('.','>') } }, { { NST_2(']','}'), '\r', 0, 0 }, { 0, NST_2('[','{'), NST_2('\\','|'), 0 } }, { { 'q', 0, 'z', 0 }, { 0, 'a', NST_2('1','!'), 0 } }, { { NST_2('7','&'), 'y', 'k', 'm' }, { 0, 'u', NST_2('8','*'), 'j' } }, { { NST_2('-','_'), NST_2(';',':'), NST_2('\'','\"'), NST_2('/','?') }, { 0, 'p', NST_2('=','+'), 0 } }, { { 't', 'h', 'n', ' ' }, { 0, 'r', NST_2('6','^'), 'b' } }, { { 0, 0, 0, 0 }, { 0, 0, 0, 0 } } }; if (input.clipboard.Shifted() && part == 7 && mode == 1) key = 0x10; const uint next = *input.clipboard; for (uint i=0; i < 4; ++i) { if ((asciiMap[part][mode][i] & 0xFFU) == next) { key |= 1U << (i+1); ++input.clipboard; break; } else if ((asciiMap[part][mode][i] >> 8) == next) { if (input.clipboard.Shifted()) { key |= 1U << (i+1); ++input.clipboard; } else { input.clipboard.Shift(); } break; } } } else { static const ushort dikMap[SuborKeyboard::NUM_PARTS][SuborKeyboard::NUM_MODES][4] = { { { NST_2(DIK_4,DIK_NUMPAD4), DIK_G, DIK_F, DIK_C }, { DIK_F2, DIK_E, NST_2(DIK_5,DIK_NUMPAD5), DIK_V } }, { { NST_2(DIK_2,DIK_NUMPAD2), DIK_D, DIK_S, DIK_END }, { DIK_F1, DIK_W, NST_2(DIK_3,DIK_NUMPAD3), DIK_X } }, { { DIK_INSERT, DIK_BACK, DIK_NEXT, DIK_RIGHT }, { DIK_F8, DIK_PRIOR, DIK_DELETE, DIK_HOME } }, { { NST_2(DIK_9,DIK_NUMPAD9), DIK_I, DIK_L, NST_2(DIK_COMMA,DIK_NUMPADCOMMA) }, { DIK_F5, DIK_O, NST_2(DIK_0,DIK_NUMPAD0), DIK_PERIOD } }, { { DIK_RBRACKET, NST_2(DIK_RETURN,DIK_NUMPADENTER), DIK_UP, DIK_LEFT }, { DIK_F7, DIK_LBRACKET, NST_2(DIK_BACKSLASH,DIK_YEN), DIK_DOWN } }, { { DIK_Q, DIK_CAPITAL, DIK_Z, DIK_TAB }, { DIK_ESCAPE, DIK_A, NST_2(DIK_1,DIK_NUMPAD1), NST_2(DIK_LCONTROL,DIK_RCONTROL) } }, { { NST_2(DIK_7,DIK_NUMPAD7), DIK_Y, DIK_K, DIK_M }, { DIK_F4, DIK_U, NST_2(DIK_8,DIK_NUMPAD8), DIK_J } }, { { NST_2(DIK_MINUS,DIK_NUMPADMINUS), DIK_SEMICOLON, NST_2(DIK_APOSTROPHE,DIK_COLON), NST_2(DIK_SLASH,DIK_NUMPADSLASH) }, { DIK_F6, DIK_P, NST_2(DIK_EQUALS,DIK_CIRCUMFLEX), NST_2(DIK_LSHIFT,DIK_RSHIFT) } }, { { DIK_T, DIK_H, DIK_N, DIK_SPACE }, { DIK_F3, DIK_R, NST_2(DIK_6,DIK_NUMPAD6), DIK_B } }, { { NST_2(DIK_GRAVE,DIK_AT), 0, 0, 0 }, { 0, 0, 0, 0 } } }; for (uint i=0; i < 4; ++i) { const uint pushed = 0x80U & ( buffer[dikMap[part][mode][i] & 0xFFU] | buffer[dikMap[part][mode][i] >> 8] ); key |= pushed >> ( 7 - ( i + 1 ) ); } } #undef NST_2 keyboard.parts[part] = key; return true; } bool NST_CALLBACK Input::Callbacks::PollDoremikkoKeyboard(UserData data,DoremikkoKeyboard& doremikko,const uint part,const uint mode) { Input& input = *static_cast(data); input.ForcePoll(); const uchar* const NST_RESTRICT keyboard = input.directInput.GetKeyboardBuffer(); uint keys = 0; switch (part) { case DoremikkoKeyboard::PART_1: if (mode == DoremikkoKeyboard::MODE_B) { if (keyboard[ DIK_Z ] & 0x80U) keys |= DoremikkoKeyboard::MODE_B_0; if (keyboard[ DIK_S ] & 0x80U) keys |= DoremikkoKeyboard::MODE_B_1; } break; case DoremikkoKeyboard::PART_2: if (mode == DoremikkoKeyboard::MODE_A) { if (keyboard[ DIK_X ] & 0x80U) keys |= DoremikkoKeyboard::MODE_A_0; if (keyboard[ DIK_D ] & 0x80U) keys |= DoremikkoKeyboard::MODE_A_1; if (keyboard[ DIK_C ] & 0x80U) keys |= DoremikkoKeyboard::MODE_A_2; if (keyboard[ DIK_V ] & 0x80U) keys |= DoremikkoKeyboard::MODE_A_3; } else { if (keyboard[ DIK_G ] & 0x80U) keys |= DoremikkoKeyboard::MODE_B_0; if (keyboard[ DIK_B ] & 0x80U) keys |= DoremikkoKeyboard::MODE_B_1; } break; case DoremikkoKeyboard::PART_3: if (mode == DoremikkoKeyboard::MODE_A) { if (keyboard[ DIK_H ] & 0x80U) keys |= DoremikkoKeyboard::MODE_A_0; if (keyboard[ DIK_N ] & 0x80U) keys |= DoremikkoKeyboard::MODE_A_1; if (keyboard[ DIK_J ] & 0x80U) keys |= DoremikkoKeyboard::MODE_A_2; if (keyboard[ DIK_M ] & 0x80U) keys |= DoremikkoKeyboard::MODE_A_3; } else { if (keyboard[ DIK_COMMA ] & 0x80U) keys |= DoremikkoKeyboard::MODE_B_0; if (keyboard[ DIK_L ] & 0x80U) keys |= DoremikkoKeyboard::MODE_B_1; } break; case DoremikkoKeyboard::PART_4: if (mode == DoremikkoKeyboard::MODE_A) { if (keyboard[ DIK_PERIOD ] & 0x80U) keys |= DoremikkoKeyboard::MODE_A_0; if (keyboard[ DIK_SEMICOLON ] & 0x80U) keys |= DoremikkoKeyboard::MODE_A_1; if (keyboard[ DIK_SLASH ] & 0x80U) keys |= DoremikkoKeyboard::MODE_A_2; if (keyboard[ DIK_Q ] & 0x80U) keys |= DoremikkoKeyboard::MODE_A_3; } else { if (keyboard[ DIK_2 ] & 0x80U) keys |= DoremikkoKeyboard::MODE_B_0; if (keyboard[ DIK_W ] & 0x80U) keys |= DoremikkoKeyboard::MODE_B_1; } break; case DoremikkoKeyboard::PART_5: if (mode == DoremikkoKeyboard::MODE_A) { if (keyboard[ DIK_3 ] & 0x80U) keys |= DoremikkoKeyboard::MODE_A_0; if (keyboard[ DIK_E ] & 0x80U) keys |= DoremikkoKeyboard::MODE_A_1; if (keyboard[ DIK_4 ] & 0x80U) keys |= DoremikkoKeyboard::MODE_A_2; if (keyboard[ DIK_R ] & 0x80U) keys |= DoremikkoKeyboard::MODE_A_3; } else { if (keyboard[ DIK_T ] & 0x80U) keys |= DoremikkoKeyboard::MODE_B_0; if (keyboard[ DIK_6 ] & 0x80U) keys |= DoremikkoKeyboard::MODE_B_1; } break; case DoremikkoKeyboard::PART_6: if (mode == DoremikkoKeyboard::MODE_A) { if (keyboard[ DIK_Y ] & 0x80U) keys |= DoremikkoKeyboard::MODE_A_0; if (keyboard[ DIK_7 ] & 0x80U) keys |= DoremikkoKeyboard::MODE_A_1; if (keyboard[ DIK_U ] & 0x80U) keys |= DoremikkoKeyboard::MODE_A_2; if (keyboard[ DIK_I ] & 0x80U) keys |= DoremikkoKeyboard::MODE_A_3; } else { if (keyboard[ DIK_9 ] & 0x80U) keys |= DoremikkoKeyboard::MODE_B_0; if (keyboard[ DIK_O ] & 0x80U) keys |= DoremikkoKeyboard::MODE_B_1; } break; case DoremikkoKeyboard::PART_7: if (mode == DoremikkoKeyboard::MODE_A) { if (keyboard[ DIK_0 ] & 0x80U) keys |= DoremikkoKeyboard::MODE_A_0; if (keyboard[ DIK_P ] & 0x80U) keys |= DoremikkoKeyboard::MODE_A_1; if (keyboard[ DIK_MINUS ] & 0x80U) keys |= DoremikkoKeyboard::MODE_A_2; if (keyboard[ DIK_AT ] & 0x80U) keys |= DoremikkoKeyboard::MODE_A_3; } break; } doremikko.keys = keys; return true; } bool NST_CALLBACK Input::Callbacks::PollMahjong(UserData data,Mahjong& mahjong,uint part) { Input& input = *static_cast(data); input.ForcePoll(); const Key* const NST_RESTRICT keys = input.dialog->GetSettings().GetKeys(Settings::MAHJONG_KEYS); uint buttons = 0; switch (part) { case Mahjong::PART_1: keys[ Settings::MAHJONG_KEY_I ].GetState( buttons, Mahjong::PART_1_I ); keys[ Settings::MAHJONG_KEY_J ].GetState( buttons, Mahjong::PART_1_J ); keys[ Settings::MAHJONG_KEY_K ].GetState( buttons, Mahjong::PART_1_K ); keys[ Settings::MAHJONG_KEY_L ].GetState( buttons, Mahjong::PART_1_L ); keys[ Settings::MAHJONG_KEY_M ].GetState( buttons, Mahjong::PART_1_M ); keys[ Settings::MAHJONG_KEY_N ].GetState( buttons, Mahjong::PART_1_N ); break; case Mahjong::PART_2: keys[ Settings::MAHJONG_KEY_A ].GetState( buttons, Mahjong::PART_2_A ); keys[ Settings::MAHJONG_KEY_B ].GetState( buttons, Mahjong::PART_2_B ); keys[ Settings::MAHJONG_KEY_C ].GetState( buttons, Mahjong::PART_2_C ); keys[ Settings::MAHJONG_KEY_D ].GetState( buttons, Mahjong::PART_2_D ); keys[ Settings::MAHJONG_KEY_E ].GetState( buttons, Mahjong::PART_2_E ); keys[ Settings::MAHJONG_KEY_F ].GetState( buttons, Mahjong::PART_2_F ); keys[ Settings::MAHJONG_KEY_G ].GetState( buttons, Mahjong::PART_2_G ); keys[ Settings::MAHJONG_KEY_H ].GetState( buttons, Mahjong::PART_2_H ); break; case Mahjong::PART_3: keys[ Settings::MAHJONG_KEY_SELECT ].GetState( buttons, Mahjong::PART_3_SELECT ); keys[ Settings::MAHJONG_KEY_START ].GetState( buttons, Mahjong::PART_3_START ); keys[ Settings::MAHJONG_KEY_KAN ].GetState( buttons, Mahjong::PART_3_KAN ); keys[ Settings::MAHJONG_KEY_PON ].GetState( buttons, Mahjong::PART_3_PON ); keys[ Settings::MAHJONG_KEY_CHI ].GetState( buttons, Mahjong::PART_3_CHI ); keys[ Settings::MAHJONG_KEY_REACH ].GetState( buttons, Mahjong::PART_3_REACH ); keys[ Settings::MAHJONG_KEY_RON ].GetState( buttons, Mahjong::PART_3_RON ); break; } mahjong.buttons = buttons; return true; } bool NST_CALLBACK Input::Callbacks::PollExcitingBoxing(UserData data,ExcitingBoxing& excitingBoxing,uint part) { Input& input = *static_cast(data); input.ForcePoll(); const Key* const NST_RESTRICT keys = input.dialog->GetSettings().GetKeys(Settings::EXCITINGBOXING_KEYS); uint buttons = 0; switch (part) { case ExcitingBoxing::PART_1: keys[ Settings::EXCITINGBOXING_KEY_RIGHT_HOOK ].GetState( buttons, ExcitingBoxing::PART_1_RIGHT_HOOK ); keys[ Settings::EXCITINGBOXING_KEY_RIGHT_MOVE ].GetState( buttons, ExcitingBoxing::PART_1_RIGHT_MOVE ); keys[ Settings::EXCITINGBOXING_KEY_LEFT_MOVE ].GetState( buttons, ExcitingBoxing::PART_1_LEFT_MOVE ); keys[ Settings::EXCITINGBOXING_KEY_LEFT_HOOK ].GetState( buttons, ExcitingBoxing::PART_1_LEFT_HOOK ); break; case ExcitingBoxing::PART_2: keys[ Settings::EXCITINGBOXING_KEY_STRAIGHT ].GetState( buttons, ExcitingBoxing::PART_2_STRAIGHT ); keys[ Settings::EXCITINGBOXING_KEY_RIGHT_JAB ].GetState( buttons, ExcitingBoxing::PART_2_RIGHT_JAB ); keys[ Settings::EXCITINGBOXING_KEY_BODY ].GetState( buttons, ExcitingBoxing::PART_2_BODY ); keys[ Settings::EXCITINGBOXING_KEY_LEFT_JAB ].GetState( buttons, ExcitingBoxing::PART_2_LEFT_JAB ); break; } excitingBoxing.buttons = buttons; return true; } bool NST_CALLBACK Input::Callbacks::PollTopRider(UserData data,TopRider& topRider) { Input& input = *static_cast(data); input.ForcePoll(); const Key* const NST_RESTRICT keys = input.dialog->GetSettings().GetKeys(Settings::PAD1_KEYS); uint buttons = 0; keys[ Settings::PAD_KEY_UP ].GetState( buttons, TopRider::SHIFT_GEAR ); keys[ Settings::PAD_KEY_RIGHT ].GetState( buttons, TopRider::STEER_RIGHT ); keys[ Settings::PAD_KEY_DOWN ].GetState( buttons, TopRider::REAR ); keys[ Settings::PAD_KEY_LEFT ].GetState( buttons, TopRider::STEER_LEFT ); keys[ Settings::PAD_KEY_SELECT ].GetState( buttons, TopRider::SELECT ); keys[ Settings::PAD_KEY_START ].GetState( buttons, TopRider::START ); keys[ Settings::PAD_KEY_A ].GetState( buttons, TopRider::ACCEL ); keys[ Settings::PAD_KEY_B ].GetState( buttons, TopRider::BRAKE ); topRider.buttons = buttons; return true; } bool NST_CALLBACK Input::Callbacks::PollPokkunMoguraa(UserData data,PokkunMoguraa& pokkunMoguraa,uint row) { Input& input = *static_cast(data); input.ForcePoll(); const Key* const NST_RESTRICT keys = input.dialog->GetSettings().GetKeys(Settings::POKKUNMOGURAA_KEYS); uint buttons = 0; if (row & PokkunMoguraa::ROW_1) { keys[ Settings::POKKUNMOGURAA_KEY_ROW_1_1 ].GetState( buttons, PokkunMoguraa::BUTTON_1 ); keys[ Settings::POKKUNMOGURAA_KEY_ROW_1_2 ].GetState( buttons, PokkunMoguraa::BUTTON_2 ); keys[ Settings::POKKUNMOGURAA_KEY_ROW_1_3 ].GetState( buttons, PokkunMoguraa::BUTTON_3 ); keys[ Settings::POKKUNMOGURAA_KEY_ROW_1_4 ].GetState( buttons, PokkunMoguraa::BUTTON_4 ); } if (row & PokkunMoguraa::ROW_2) { keys[ Settings::POKKUNMOGURAA_KEY_ROW_2_1 ].GetState( buttons, PokkunMoguraa::BUTTON_1 ); keys[ Settings::POKKUNMOGURAA_KEY_ROW_2_2 ].GetState( buttons, PokkunMoguraa::BUTTON_2 ); keys[ Settings::POKKUNMOGURAA_KEY_ROW_2_3 ].GetState( buttons, PokkunMoguraa::BUTTON_3 ); keys[ Settings::POKKUNMOGURAA_KEY_ROW_2_4 ].GetState( buttons, PokkunMoguraa::BUTTON_4 ); } if (row & PokkunMoguraa::ROW_3) { keys[ Settings::POKKUNMOGURAA_KEY_ROW_3_1 ].GetState( buttons, PokkunMoguraa::BUTTON_1 ); keys[ Settings::POKKUNMOGURAA_KEY_ROW_3_2 ].GetState( buttons, PokkunMoguraa::BUTTON_2 ); keys[ Settings::POKKUNMOGURAA_KEY_ROW_3_3 ].GetState( buttons, PokkunMoguraa::BUTTON_3 ); keys[ Settings::POKKUNMOGURAA_KEY_ROW_3_4 ].GetState( buttons, PokkunMoguraa::BUTTON_4 ); } pokkunMoguraa.buttons = buttons; return true; } bool NST_CALLBACK Input::Callbacks::PollPartyTap(UserData data,PartyTap& partyTap) { Input& input = *static_cast(data); input.ForcePoll(); const Key* const NST_RESTRICT keys = input.dialog->GetSettings().GetKeys(Settings::PARTYTAP_KEYS); uint units = 0; keys[ Settings::PARTYTAP_UNIT_1 ].GetState( units, PartyTap::UNIT_1 ); keys[ Settings::PARTYTAP_UNIT_2 ].GetState( units, PartyTap::UNIT_2 ); keys[ Settings::PARTYTAP_UNIT_3 ].GetState( units, PartyTap::UNIT_3 ); keys[ Settings::PARTYTAP_UNIT_4 ].GetState( units, PartyTap::UNIT_4 ); keys[ Settings::PARTYTAP_UNIT_5 ].GetState( units, PartyTap::UNIT_5 ); keys[ Settings::PARTYTAP_UNIT_6 ].GetState( units, PartyTap::UNIT_6 ); partyTap.units = units; return true; } bool NST_CALLBACK Input::Callbacks::PollVsSystem(UserData data,VsSystem& vsSystem) { Input& input = *static_cast(data); input.ForcePoll(); const Key* const NST_RESTRICT keys = input.dialog->GetSettings().GetKeys(Settings::EMULATION_KEYS); uint buttons = 0; keys[ Settings::EMULATION_KEY_INSERT_COIN_1 ].GetState( buttons, VsSystem::COIN_1 ); keys[ Settings::EMULATION_KEY_INSERT_COIN_2 ].GetState( buttons, VsSystem::COIN_2 ); vsSystem.insertCoin = buttons; return true; } bool NST_CALLBACK Input::Callbacks::PollKaraokeStudio(UserData data,KaraokeStudio& karaokeStudio) { Input& input = *static_cast(data); input.ForcePoll(); const Key* const NST_RESTRICT keys = input.dialog->GetSettings().GetKeys(Settings::KARAOKESTUDIO_KEYS); uint buttons = 0; keys[ Settings::KARAOKESTUDIO_MIC ].GetState( buttons, KaraokeStudio::MIC ); keys[ Settings::KARAOKESTUDIO_A ].GetState( buttons, KaraokeStudio::A ); keys[ Settings::KARAOKESTUDIO_B ].GetState( buttons, KaraokeStudio::B ); karaokeStudio.buttons = buttons; return true; } #ifdef NST_MSVC_OPTIMIZE #pragma optimize("", on) #endif } }