nestopia/source/win32/NstManagerInput.cpp

1874 lines
72 KiB
C++

////////////////////////////////////////////////////////////////////////////////////////
//
// 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<Input> 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<Input> popups[] =
{
{ Window::Menu::PopupHandler::Pos<IDM_POS_MACHINE,IDM_POS_MACHINE_INPUT,IDM_POS_MACHINE_INPUT_PORT1>::ID, &Input::OnMenuPort1 },
{ Window::Menu::PopupHandler::Pos<IDM_POS_MACHINE,IDM_POS_MACHINE_INPUT,IDM_POS_MACHINE_INPUT_PORT2>::ID, &Input::OnMenuPort2 },
{ Window::Menu::PopupHandler::Pos<IDM_POS_MACHINE,IDM_POS_MACHINE_INPUT,IDM_POS_MACHINE_INPUT_PORT3>::ID, &Input::OnMenuPort3 },
{ Window::Menu::PopupHandler::Pos<IDM_POS_MACHINE,IDM_POS_MACHINE_INPUT,IDM_POS_MACHINE_INPUT_PORT4>::ID, &Input::OnMenuPort4 },
{ Window::Menu::PopupHandler::Pos<IDM_POS_MACHINE,IDM_POS_MACHINE_INPUT,IDM_POS_MACHINE_INPUT_EXP>::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::Type>(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<Nes::Input::Type>(data), players );
}
}
case Emulator::EVENT_PORT5_CONTROLLER:
UpdateDevices();
break;
case Emulator::EVENT_PORT_ADAPTER:
UpdateAdapterPort( static_cast<Nes::Input::Adapter>(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::Type>(Nes::Input::PAD1 + pad) );
SyncControllers( port, static_cast<Nes::Input::Type>(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<Nes::Input::Type>(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<Input*>(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<Cursor*>(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<Input*>(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<Input*>(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<Cursor*>(data)->Poll( paddle.x, y, paddle.button );
return true;
}
bool NST_CALLBACK Input::Callbacks::PollPowerPad(UserData data,PowerPad& powerPad)
{
Input& input = *static_cast<Input*>(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<Input*>(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<Cursor*>(data)->Poll( mouse.x, mouse.y, mouse.button );
return true;
}
bool NST_CALLBACK Input::Callbacks::PollOekaKidsTablet(UserData data,OekaKidsTablet& tablet)
{
static_cast<Cursor*>(data)->Poll( tablet.x, tablet.y, tablet.button );
return true;
}
bool NST_CALLBACK Input::Callbacks::PollHoriTrack(UserData data,HoriTrack& horiTrack)
{
Input& input = *static_cast<Input*>(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<Input*>(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<Input*>(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<Input*>(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<Input*>(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<Input*>(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<Input*>(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<Input*>(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<Input*>(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<Input*>(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<Input*>(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<Input*>(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<Input*>(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<Input*>(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<Input*>(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
}
}