//////////////////////////////////////////////////////////////////////////////////////// // // 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 // //////////////////////////////////////////////////////////////////////////////////////// #ifndef NST_MANAGER_INPUT_H #define NST_MANAGER_INPUT_H #pragma once #include "NstDirectInput.hpp" #include "NstResourceCursor.hpp" namespace Nestopia { namespace Window { class Input; } namespace Managers { class Input : Manager { public: typedef Object::Delegate Screening; Input ( Window::Custom&, Window::Menu&, Emulator&, const Configuration&, const Screening&, const Screening& ); ~Input(); void Save(Configuration&) const; void StartEmulation(); void StopEmulation(); private: void ForcePoll(); bool SetAdapter(uint) const; void SyncControllers(uint,Nes::Input::Type,uint) const; void UpdateDevices(); void UpdateSettings(); void UpdateAdapterPort(Nes::Input::Adapter) const; void OnMenuPort1(const Window::Menu::PopupHandler::Param&); void OnMenuPort2(const Window::Menu::PopupHandler::Param&); void OnMenuPort3(const Window::Menu::PopupHandler::Param&); void OnMenuPort4(const Window::Menu::PopupHandler::Param&); void OnMenuPort5(const Window::Menu::PopupHandler::Param&); void OnEmuEvent(Emulator::Event,Emulator::Data); void OnCmdMachineAutoSelectController(uint); void OnCmdMachinePort(uint); void OnCmdMachineAdapter(uint); void OnCmdOptionsInput(uint); class Callbacks; class Cursor { public: Cursor(Window::Custom&,const Screening&,const Screening&); ~Cursor(); void Acquire(Emulator&); void Unacquire(); void AutoHide(); bool Poll(uint&,uint&,uint&,uint* = NULL) const; private: enum { TIME_OUT = 3000, NO_DEADLINE = DWORD(~0UL), WHEEL_MIN = -WHEEL_DELTA*30, WHEEL_MAX = +WHEEL_DELTA*30, WHEEL_SCALE = 56 }; ibool OnNop (Window::Param&); ibool OnSetCursor (Window::Param&); ibool OnMouseMove (Window::Param&); ibool OnLButtonDown (Window::Param&); ibool OnRButtonDown (Window::Param&); ibool OnRButtonDownNop (Window::Param&); ibool OnButtonUp (Window::Param&); ibool OnWheel (Window::Param&); HCURSOR hCursor; HCURSOR hCurrent; DWORD deadline; Window::Custom& window; int wheel; const Screening getInputRect; const Screening getOutputRect; const Resource::Cursor gun; const uint primaryButtonId; const uint secondaryButtonId; public: int GetWheel() const { return wheel / WHEEL_SCALE; } bool MustAutoHide() const { return deadline != NO_DEADLINE && deadline <= ::GetTickCount(); } }; class Commands { typedef DirectX::DirectInput::Key Key; public: Commands(Window::Custom&,DirectX::DirectInput&); ~Commands(); void BeginAdd(); void Add(const Key&,uint); void EndAdd(); void Acquire(); void Unacquire(); private: bool ForcePoll(); void Update(); uint OnTimer(); void OnFocus(Window::Param&); enum { POLL_RAPID = 50, POLL_REST = 1000, CLOCK_DEFAULT = 1, CLOCK_STOP = 0 }; struct CmdKey : Key { CmdKey(const Key&,uint); uint cmd; bool prev; }; typedef Collection::Vector Keys; bool acquired; Keys keys; uint clock; Window::Custom& window; DirectX::DirectInput& directInput; bool CanPoll() const { return !keys.Empty() && window.Focused(); } public: void Poll() { if (CanPoll()) ForcePoll(); } }; class Clipboard : Manager { public: Clipboard(Emulator&,Window::Menu&); enum Type { FAMILY, SUBOR }; uint Query(const uchar* NST_RESTRICT,Type); void Clear(); void operator ++ (); private: bool CanPaste() const; void OnCmdMachineKeyboardPaste(uint); void OnMenuKeyboard(const Window::Menu::PopupHandler::Param&); uint pos; uchar releasing; uchar hold; bool shifted; bool paste; String::Heap buffer; public: bool Shifted() const { return shifted; } void Shift() { shifted = true; } uint operator * () { return releasing ? (--releasing, UINT_MAX) : buffer[pos]; } }; class AutoFire : public ImplicitBool { public: inline AutoFire(); void operator = (uint); private: uint step; uint signal; public: bool operator ! () const { return step < signal; } void operator ++ () { step = (step < signal) ? (step + 1) : 0; } }; AutoFire autoFire; Cursor cursor; Nes::Input::Controllers nesControllers; DirectX::DirectInput directInput; Object::Heap dialog; Commands commands; Clipboard clipboard; public: void Calibrate(bool full) { directInput.Calibrate( full ); } Nes::Input::Controllers* GetOutput() { ++autoFire; return &nesControllers; } void Poll() { ForcePoll(); if (cursor.MustAutoHide()) cursor.AutoHide(); } }; } } #endif