├── Pokopom ├── Background.bmp ├── ConfigDialog.h ├── psemupro.h ├── FileIO.h ├── Stuff_Shared.cpp ├── DebugStuff.h ├── Exports.def ├── Stuff.h ├── DebugStuff.cpp ├── Settings.cpp ├── General.h ├── TypeDefs.h ├── Settings.h ├── Input.h ├── demul.h ├── Chankast.h ├── playstation_codes.h ├── playstation_guitar.cpp ├── playstation_mtap.cpp ├── Zilmar_Devices.h ├── Input_Shared.h ├── Stuff_Linux.cpp ├── resource.h ├── Chankast.cpp ├── Zilmar_Controller_Interface.h ├── regini.h ├── Stuff_Windows.cpp ├── playstation_devices.h ├── regini.cpp ├── playstation_dualshock2.cpp ├── demul.cpp ├── PSemuPro_Interface.h ├── Pokopom.vcxproj.filters ├── Zilmar_Devices.cpp ├── Pokopom.vcxproj ├── Pokopom.rc ├── Zilmar.cpp ├── playstation_dualshock.cpp ├── FileIO.cpp ├── Input_Linux.cpp ├── psemupro.cpp ├── Input_XInput.cpp ├── ConfigDialog.cpp └── Input_Shared.cpp ├── .gitattributes ├── SCP ├── SCPExtensions.h └── SCPExtensions.cpp ├── Pokopom.sln ├── LICENSE ├── Makefile ├── CMakeLists.txt ├── README └── .gitignore /Pokopom/Background.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KrossX/Pokopom/HEAD/Pokopom/Background.bmp -------------------------------------------------------------------------------- /Pokopom/ConfigDialog.h: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2012 KrossX 2 | * License: http://www.opensource.org/licenses/mit-license.html MIT License 3 | */ 4 | 5 | #pragma once 6 | 7 | 8 | void CreateConfigDialog(); -------------------------------------------------------------------------------- /Pokopom/psemupro.h: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2012 KrossX 2 | * License: http://www.opensource.org/licenses/mit-license.html MIT License 3 | */ 4 | 5 | #include "General.h" 6 | 7 | #include "playstation_devices.h" 8 | #include "PSemuPro_Interface.h" 9 | #include "FileIO.h" 10 | -------------------------------------------------------------------------------- /Pokopom/FileIO.h: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2012 KrossX 2 | * License: http://www.opensource.org/licenses/mit-license.html MIT License 3 | */ 4 | 5 | #pragma once 6 | 7 | namespace FileIO 8 | { 9 | void INI_LoadSettings(); 10 | void INI_SaveSettings(); 11 | 12 | bool FASTCALL LoadMempak(u8 *data, u8 port); 13 | void FASTCALL SaveMempak(u8 *data, u8 port); 14 | 15 | bool FASTCALL LoadEEPROM(u8 *data); 16 | void FASTCALL SaveEEPROM(u8 *data); 17 | } 18 | -------------------------------------------------------------------------------- /Pokopom/Stuff_Shared.cpp: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2012 KrossX 2 | * License: http://www.opensource.org/licenses/mit-license.html MIT License 3 | */ 4 | 5 | #include "General.h" 6 | 7 | std::list keyEventList; 8 | 9 | bool disableLED = false; 10 | bool SwapPortsEnabled = false; 11 | bool bPriority = false; 12 | bool isPs2Emulator = false; 13 | bool isPSemulator = false; 14 | bool bKeepAwake = false; // Screensaver and stuff 15 | s32 INIversion = 5; // INI version 16 | _Settings settings[4]; 17 | 18 | 19 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | # Auto detect text files and perform LF normalization 2 | * text=auto 3 | 4 | # Custom for Visual Studio 5 | *.cs diff=csharp 6 | *.sln merge=union 7 | *.csproj merge=union 8 | *.vbproj merge=union 9 | *.fsproj merge=union 10 | *.dbproj merge=union 11 | 12 | # Standard to msysgit 13 | *.doc diff=astextplain 14 | *.DOC diff=astextplain 15 | *.docx diff=astextplain 16 | *.DOCX diff=astextplain 17 | *.dot diff=astextplain 18 | *.DOT diff=astextplain 19 | *.pdf diff=astextplain 20 | *.PDF diff=astextplain 21 | *.rtf diff=astextplain 22 | *.RTF diff=astextplain 23 | -------------------------------------------------------------------------------- /Pokopom/DebugStuff.h: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2012 KrossX 2 | * License: http://www.opensource.org/licenses/mit-license.html MIT License 3 | */ 4 | 5 | #pragma once 6 | 7 | 8 | #if 0 9 | 10 | bool _DebugOpen(); 11 | void _DebugClose(); 12 | void _DebugFunc(const char* func); 13 | void _DebugPrint(const char* func, const char* fmt, ...); 14 | 15 | #define DebugOpen() _DebugOpen() 16 | #define DebugClose() _DebugClose() 17 | #define DebugPrint(...) _DebugPrint(__FUNCTION__, __VA_ARGS__) 18 | #define DebugFunc() _DebugFunc(__FUNCTION__) 19 | 20 | #else 21 | 22 | #define DebugOpen() 23 | #define DebugClose() 24 | #define DebugPrint(...) 25 | #define DebugFunc() 26 | 27 | #endif -------------------------------------------------------------------------------- /Pokopom/Exports.def: -------------------------------------------------------------------------------- 1 | EXPORTS 2 | PS2EgetLibType 3 | PS2EgetLibName 4 | PS2EgetLibVersion2 5 | 6 | PSEgetLibType 7 | PSEgetLibName 8 | PSEgetLibVersion 9 | PADreadPort1 10 | PADreadPort2 11 | PADinit 12 | PADshutdown 13 | PADopen 14 | PADclose 15 | PADkeyEvent 16 | PADstartPoll 17 | PADpoll 18 | PADquery 19 | PADconfigure 20 | PADtest 21 | PADabout 22 | PADupdate 23 | PADfreeze 24 | PADsetSlot 25 | PADsetSettingsDir 26 | PADqueryMtap 27 | 28 | ;dcGetInterface 29 | ;GetInputInterface 30 | 31 | GetDllInfo 32 | CloseDLL 33 | DllConfig 34 | DllAbout 35 | DllTest 36 | RomOpen 37 | RomClosed 38 | InitiateControllers 39 | GetKeys 40 | ControllerCommand 41 | ReadController 42 | WM_KeyDown 43 | WM_KeyUp 44 | 45 | ;DEMUL 46 | getType 47 | getName 48 | getInterface -------------------------------------------------------------------------------- /Pokopom/Stuff.h: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2012 KrossX 2 | * License: http://www.opensource.org/licenses/mit-license.html MIT License 3 | */ 4 | 5 | #pragma once 6 | 7 | enum 8 | { 9 | KEEPAWAKE_INIT = 0, 10 | KEEPAWAKE_CLOSE 11 | }; 12 | 13 | void GetDisplay(void* pDisplay); 14 | void ShowDialog(const wchar_t* message, const wchar_t* title); 15 | void KeepAwake(u8 mode); 16 | 17 | u8 SwapPorts(); 18 | void SetPriority(); 19 | 20 | void KeyboardOpen(); 21 | void KeyboardClose(); 22 | void KeyboardCheck(); 23 | 24 | struct keyEvent 25 | { 26 | u32 key; 27 | u32 evt; 28 | }; 29 | 30 | extern std::list keyEventList; 31 | 32 | extern bool SwapPortsEnabled; 33 | extern bool isPs2Emulator; 34 | extern bool isPSemulator; 35 | extern bool bPriority; 36 | extern bool bKeepAwake; 37 | extern s32 INIversion; 38 | -------------------------------------------------------------------------------- /SCP/SCPExtensions.h: -------------------------------------------------------------------------------- 1 | /* Scarlet.Crush's 2 | * XInput Wrapper for DS3 and Play.com USB Dual DS2 Controller 3 | * http://forums.pcsx2.net/Thread-XInput-Wrapper-for-DS3-and-Play-com-USB-Dual-DS2-Controller 4 | */ 5 | 6 | #pragma once 7 | #ifdef _WIN32 8 | typedef struct 9 | { 10 | float SCP_UP; 11 | float SCP_RIGHT; 12 | float SCP_DOWN; 13 | float SCP_LEFT; 14 | 15 | float SCP_LX; 16 | float SCP_LY; 17 | 18 | float SCP_L1; 19 | float SCP_L2; 20 | float SCP_L3; 21 | 22 | float SCP_RX; 23 | float SCP_RY; 24 | 25 | float SCP_R1; 26 | float SCP_R2; 27 | float SCP_R3; 28 | 29 | float SCP_T; 30 | float SCP_C; 31 | float SCP_X; 32 | float SCP_S; 33 | 34 | float SCP_SELECT; 35 | float SCP_START; 36 | 37 | } SCP_EXTN; 38 | 39 | typedef DWORD (WINAPI *XInputGetExtendedFunction)(DWORD dwUserIndex, SCP_EXTN* pPressure); 40 | 41 | extern DWORD WINAPI XInputGetExtended(DWORD dwUserIndex, SCP_EXTN* pPressure); 42 | #endif 43 | -------------------------------------------------------------------------------- /SCP/SCPExtensions.cpp: -------------------------------------------------------------------------------- 1 | /* Scarlet.Crush's 2 | * XInput Wrapper for DS3 and Play.com USB Dual DS2 Controller 3 | * http://forums.pcsx2.net/Thread-XInput-Wrapper-for-DS3-and-Play-com-USB-Dual-DS2-Controller 4 | */ 5 | #ifdef _WIN32 6 | #include "SCPExtensions.h" 7 | 8 | DWORD WINAPI XInputGetExtended(DWORD dwUserIndex, SCP_EXTN* pPressure) 9 | { 10 | static BOOL l_Loaded = false, l_Available = false; 11 | static HMODULE l_hXInputDll = NULL; 12 | static FARPROC l_hXInputFunc[] = { NULL }; 13 | 14 | DWORD RetVal = ERROR_NOT_SUPPORTED; 15 | 16 | if (!l_Loaded) 17 | { 18 | if ((l_hXInputDll = LoadLibrary(L"XInput1_3.dll")) != NULL) 19 | { 20 | if ((l_hXInputFunc[0] = GetProcAddress(l_hXInputDll, "XInputGetExtended")) != NULL) 21 | { 22 | l_Available = true; 23 | } 24 | } 25 | 26 | l_Loaded = true; 27 | } 28 | 29 | if (l_Available) 30 | { 31 | RetVal = ((XInputGetExtendedFunction)(l_hXInputFunc[0]))(dwUserIndex, pPressure); 32 | } 33 | 34 | return RetVal; 35 | } 36 | #endif 37 | -------------------------------------------------------------------------------- /Pokopom.sln: -------------------------------------------------------------------------------- 1 | 2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio Express 2013 for Windows Desktop 4 | VisualStudioVersion = 12.0.21005.1 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Pokopom", "Pokopom\Pokopom.vcxproj", "{25BE40B9-3ADC-4163-B055-AC71B856A9C3}" 7 | EndProject 8 | Global 9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 10 | Debug|Win32 = Debug|Win32 11 | Release|Win32 = Release|Win32 12 | EndGlobalSection 13 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 14 | {25BE40B9-3ADC-4163-B055-AC71B856A9C3}.Debug|Win32.ActiveCfg = Debug|Win32 15 | {25BE40B9-3ADC-4163-B055-AC71B856A9C3}.Debug|Win32.Build.0 = Debug|Win32 16 | {25BE40B9-3ADC-4163-B055-AC71B856A9C3}.Release|Win32.ActiveCfg = Release|Win32 17 | {25BE40B9-3ADC-4163-B055-AC71B856A9C3}.Release|Win32.Build.0 = Release|Win32 18 | EndGlobalSection 19 | GlobalSection(SolutionProperties) = preSolution 20 | HideSolutionNode = FALSE 21 | EndGlobalSection 22 | EndGlobal 23 | -------------------------------------------------------------------------------- /Pokopom/DebugStuff.cpp: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2012 KrossX 2 | * License: http://www.opensource.org/licenses/mit-license.html MIT License 3 | */ 4 | 5 | #include "General.h" 6 | #include 7 | 8 | FILE *logfile = NULL; 9 | 10 | bool _DebugOpen() 11 | { 12 | logfile = fopen("pokopom.log", "w"); 13 | if(logfile) fprintf(logfile, "DebugOpen\n"); 14 | return !!logfile; 15 | } 16 | 17 | void _DebugClose() 18 | { 19 | if(logfile) fprintf(logfile, "DebugClose\n"); 20 | if(logfile) fclose(logfile); 21 | logfile = NULL; 22 | } 23 | 24 | void _DebugFunc(const char* func) 25 | { 26 | if(!logfile && !_DebugOpen()) return; 27 | 28 | fprintf(logfile, "%s\n", func); 29 | fflush(logfile); 30 | } 31 | 32 | void _DebugPrint(const char* func, const char* fmt, ...) 33 | { 34 | if(!logfile && !_DebugOpen()) return; 35 | 36 | va_list args; 37 | 38 | fprintf(logfile, "%s : ", func); 39 | 40 | va_start(args,fmt); 41 | vfprintf(logfile, fmt, args); 42 | va_end(args); 43 | 44 | fprintf(logfile, "\n"); 45 | fflush(logfile); 46 | } 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | -------------------------------------------------------------------------------- /Pokopom/Settings.cpp: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2012 KrossX 2 | * License: http://www.opensource.org/licenses/mit-license.html MIT License 3 | */ 4 | 5 | #include "General.h" 6 | 7 | _Settings::_Settings() 8 | { 9 | SetDefaults(); 10 | } 11 | 12 | void _Settings::SetDefaults() 13 | { 14 | SwapXO = false; 15 | SwapSticksEnabled = false; 16 | greenAnalog = false; 17 | defaultAnalog = false; 18 | isGuitar = false; 19 | disabled = false; 20 | sticksLocked = true; 21 | xinputPort = 0; 22 | 23 | stickL.SetDefaults(); 24 | stickR.SetDefaults(); 25 | 26 | rumble = 1.0; 27 | pressureRate = 10; 28 | triggerDeadzone = 0; 29 | 30 | for(u8 i = 0; i < 4; i++) 31 | { 32 | axisInverted[i] = false; 33 | axisRemap[i] = i; 34 | axisValue[i] = 0; 35 | } 36 | } 37 | 38 | void StickSettings::SetDefaults() 39 | { 40 | b4wayDAC = false; 41 | DACenabled = true; 42 | DACthreshold = 28000; 43 | 44 | extThreshold = 32767.0; // 40201 real max radius 45 | extMult = 1.4142135623730950488016887242097; // sqrt(2) 46 | 47 | deadzone = 0.0; 48 | antiDeadzone = 0.0; 49 | linearity = 0.0; 50 | } 51 | -------------------------------------------------------------------------------- /Pokopom/General.h: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2012 KrossX 2 | * License: http://www.opensource.org/licenses/mit-license.html MIT License 3 | */ 4 | 5 | 6 | #pragma once 7 | 8 | #ifdef _WIN32 9 | #include 10 | 11 | #define EXPORT_CALL __stdcall 12 | #define FASTCALL __fastcall 13 | #define CALL __cdecl 14 | 15 | #ifdef __cplusplus 16 | #define DllExport extern "C" __declspec(dllexport) 17 | #else 18 | #define DllExport __declspec(dllexport) 19 | #endif 20 | #elif defined __linux__ 21 | #define EXPORT_CALL __stdcall 22 | #define FASTCALL 23 | #define CALLBACK 24 | #define HANDLE void* 25 | #define HWND void* 26 | #define WNDPROC void* 27 | #define WORD short 28 | 29 | #include 30 | #include 31 | 32 | #ifdef __cplusplus 33 | #define DllExport extern "C" __attribute__((stdcall, visibility ("default"))) 34 | #else 35 | #define DllExport __attribute__((stdcall)) 36 | #endif 37 | #endif 38 | 39 | #include 40 | #include 41 | 42 | #include "TypeDefs.h" 43 | #include "Stuff.h" 44 | #include "Settings.h" 45 | 46 | #include "DebugStuff.h" 47 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2012 KrossX 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy 4 | of this software and associated documentation files (the "Software"), to deal 5 | in the Software without restriction, including without limitation the rights 6 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | copies of the Software, and to permit persons to whom the Software is 8 | furnished to do so, subject to the following conditions: 9 | 10 | The above copyright notice and this permission notice shall be included in 11 | all copies or substantial portions of the Software. 12 | 13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | THE SOFTWARE. -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | CC = gcc 2 | CFLAGS = -Wall -O2 -flto -std=c++11 -march=i686 -m32 -s 3 | LDLIBS = -lstdc++ -luxtheme 4 | 5 | OBJ = ConfigDialog.o \ 6 | DebugStuff.o \ 7 | demul.o \ 8 | FileIO.o \ 9 | Input_Linux.o \ 10 | Input_Shared.o \ 11 | Input_XInput.o \ 12 | playstation_dualshock.o \ 13 | playstation_dualshock2.o \ 14 | playstation_guitar.o \ 15 | playstation_mtap.o \ 16 | psemupro.o \ 17 | regini.o \ 18 | Settings.o \ 19 | Stuff_Linux.o \ 20 | Stuff_Shared.o \ 21 | Stuff_Windows.o \ 22 | Zilmar.o \ 23 | Zilmar_Devices.o 24 | 25 | 26 | %.o : pokopom/%.cpp 27 | @$(CC) -o $@ -c $< -DUNICODE $(CFLAGS) 28 | 29 | default: $(OBJ) 30 | @windres pokopom/pokopom.rc pokopom_res.o --target=pe-i386 31 | @$(CC) -shared -static-libgcc -static-libstdc++ $^ pokopom_res.o pokopom/exports.def $(CFLAGS) $(LDLIBS) -o padPokopom.dll 32 | -------------------------------------------------------------------------------- /Pokopom/TypeDefs.h: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2012 KrossX 2 | * License: http://www.opensource.org/licenses/mit-license.html MIT License 3 | */ 4 | 5 | #pragma once 6 | 7 | #ifndef KROSSX_TYPEDEFS 8 | #define KROSSX_TYPEDEFS 9 | 10 | #include 11 | 12 | typedef int8_t s8; 13 | typedef uint8_t u8; 14 | typedef int16_t s16; 15 | typedef uint16_t u16; 16 | typedef int32_t s32; 17 | typedef uint32_t u32; 18 | typedef int64_t s64; 19 | typedef uint64_t u64; 20 | 21 | typedef intptr_t sPointer; 22 | typedef uintptr_t uPointer; 23 | 24 | typedef float f32; 25 | typedef double f64; 26 | 27 | union Word 28 | { 29 | f32 float32; 30 | u32 bits32; 31 | u16 bits16[2]; 32 | u8 bits8[4]; 33 | }; 34 | 35 | union DWord 36 | { 37 | u64 bits64; 38 | f64 float64; 39 | f32 float32[2]; 40 | u32 bits32[2]; 41 | u16 bits16[4]; 42 | u8 bits8[8]; 43 | 44 | Word word[2]; 45 | }; 46 | 47 | union QWord 48 | { 49 | u64 bits64[2]; 50 | f64 float64[2]; 51 | f32 float32[4]; 52 | u32 bits32[4]; 53 | u16 bits16[8]; 54 | u8 bits8[16]; 55 | 56 | Word word[4]; 57 | DWord dword[2]; 58 | }; 59 | #endif // KROSSX_TYPEDEFS 60 | -------------------------------------------------------------------------------- /Pokopom/Settings.h: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2012 KrossX 2 | * License: http://www.opensource.org/licenses/mit-license.html MIT License 3 | */ 4 | 5 | #pragma once 6 | 7 | enum GAMEPAD_AXES 8 | { 9 | GP_AXIS_LX, 10 | GP_AXIS_LY, 11 | GP_AXIS_RX, 12 | GP_AXIS_RY 13 | }; 14 | 15 | struct StickSettings 16 | { 17 | bool b4wayDAC; 18 | bool DACenabled; 19 | f64 DACthreshold; 20 | 21 | f64 extThreshold, extMult; 22 | f32 deadzone, antiDeadzone; 23 | f64 linearity; 24 | 25 | void SetDefaults(); 26 | }; 27 | 28 | struct _Settings 29 | { 30 | void SetDefaults(); 31 | 32 | bool greenAnalog; 33 | bool defaultAnalog; 34 | bool sticksLocked; 35 | 36 | u8 xinputPort; 37 | f32 rumble; 38 | 39 | StickSettings stickL, stickR; 40 | 41 | u8 axisInverted[4]; 42 | u8 axisRemap[4]; 43 | s32 axisValue[4]; 44 | 45 | u16 pressureRate; 46 | u8 triggerDeadzone; 47 | 48 | bool SwapDCBumpers; 49 | bool SwapXO; 50 | bool SwapSticksEnabled; 51 | bool isGuitar; 52 | bool disabled; 53 | 54 | _Settings(); 55 | _Settings(const _Settings &); 56 | _Settings& operator=(const _Settings &); 57 | }; 58 | 59 | extern _Settings settings[4]; 60 | -------------------------------------------------------------------------------- /Pokopom/Input.h: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2012 KrossX 2 | * License: http://www.opensource.org/licenses/mit-license.html MIT License 3 | */ 4 | 5 | #pragma once 6 | 7 | namespace Input 8 | { 9 | bool FASTCALL Recheck(u8 port); 10 | void FASTCALL Pause(bool pewpew); 11 | void FASTCALL StopRumble(u8 port); 12 | void StopRumbleAll(); 13 | 14 | bool FASTCALL CheckAnalogToggle(u8 port); 15 | void FASTCALL SetAnalogLed(u8 port, bool digital); 16 | 17 | void FASTCALL DualshockPoll(u16 * bufferOut, _Settings &set, bool &gamepadPlugged, const bool digital); 18 | void FASTCALL DualshockRumble(u8 smalldata, u8 bigdata, _Settings &set, bool &gamepadPlugged); 19 | bool FASTCALL DualshockPressure(u8 * bufferOut, u32 mask, _Settings &set, bool &gamepadPlugged); 20 | 21 | void FASTCALL DreamcastPoll(u32* buffer_out, _Settings &set, bool &gamepadPlugged); 22 | void FASTCALL DreamcastRumble(s16 intensity, bool freqH, bool freqL, u16 wait, _Settings &set, bool &gamepadPlugged, HANDLE &thread); 23 | 24 | void FASTCALL NaomiPoll(u32* buffer_out, _Settings &set, bool &gamepadPlugged); 25 | 26 | void FASTCALL N64rumbleSwitch(u8 port, bool &rumble, bool &gamepadPlugged); 27 | void FASTCALL N64controllerPoll(u8 *outBuffer, _Settings &set, bool &gamepadPlugged); 28 | void FASTCALL N64rumble(bool on, _Settings &set, bool &gamepadPlugged); 29 | 30 | void FASTCALL demul_read1(u32* buffer_out, _Settings &set, bool &gamepadPlugged); 31 | } 32 | -------------------------------------------------------------------------------- /Pokopom/demul.h: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2015 KrossX 2 | * License: http://www.opensource.org/licenses/mit-license.html MIT License 3 | */ 4 | 5 | #pragma once 6 | 7 | #include "General.h" 8 | 9 | #ifdef _WIN32 10 | 11 | struct demul_interface 12 | { 13 | u8(*func13)(); // 552 14 | int(*func12)(); // 556 15 | void(*func11)(); // 560 16 | int(*func10)(); // 564 17 | void(*func07)(); // 576 18 | int(*func05)(); // 584 19 | void(*func04)(); // 588 20 | int(*func02)(); // 596 21 | int(*func01)(); // 600 22 | 23 | int(__fastcall *func09)(int); // 568 24 | void(__fastcall *func08)(int, int); // 572 25 | int(__fastcall *func06)(u8); // 580 26 | int(__fastcall *func03)(int, int, int, int); // 592 27 | }; 28 | 29 | // old nullDC stuff 30 | 31 | union RumbleSettings 32 | { 33 | u32 RAW; 34 | 35 | struct 36 | { 37 | u8 VSET0; 38 | u8 VSET1; 39 | u8 FM0; 40 | u8 FM1; 41 | }; 42 | 43 | struct 44 | { 45 | unsigned VD : 2; 46 | unsigned VP : 2; 47 | unsigned VN : 4; 48 | 49 | unsigned VA : 4; 50 | unsigned OWF : 1; 51 | unsigned PD : 1; 52 | unsigned CV : 1; 53 | unsigned PF : 1; 54 | }; 55 | }; 56 | 57 | union RumbleConfig 58 | { 59 | u32 RAW; 60 | 61 | struct 62 | { 63 | u8 CTRL; 64 | u8 POW; 65 | u8 FREQ; // Frequency 66 | u8 INQ; // Inclination 67 | }; 68 | 69 | struct 70 | { 71 | unsigned CNT : 1; // Continuous mode 72 | unsigned Res : 3; // ... 73 | unsigned VN : 4; // Number of sources [1..F] 74 | 75 | unsigned Mpow : 3; // Backward intensity 76 | unsigned EXH : 1; // Divergency 77 | unsigned Ppow : 3; // Forward intensity 78 | unsigned INH : 1; // Convergency 79 | }; 80 | }; 81 | 82 | #endif 83 | -------------------------------------------------------------------------------- /Pokopom/Chankast.h: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2012 KrossX 2 | * License: http://www.opensource.org/licenses/mit-license.html MIT License 3 | */ 4 | 5 | #pragma once 6 | //#include "nullDC_Devices.h" 7 | 8 | #if 0 9 | //#ifdef _WIN32 10 | 11 | //////////////////////////////////////////////////////////////////////// 12 | // Interface stuff 13 | //////////////////////////////////////////////////////////////////////// 14 | 15 | struct ChankastInputInterface 16 | { 17 | s32 Version; 18 | char *Description; 19 | s32 (__cdecl *Init)(void* hWnd); 20 | s32 (__cdecl *GetNumControllers)(); 21 | void (__cdecl *End)(); 22 | s32 (__cdecl *Configure)(void* hWnd); 23 | void (__cdecl *Update)(); 24 | void (__cdecl *GetStatus)(s32 iNumPad, void* _pContCond); 25 | }; 26 | 27 | 28 | //////////////////////////////////////////////////////////////////////// 29 | // Device structure 30 | //////////////////////////////////////////////////////////////////////// 31 | 32 | #pragma pack(1) 33 | struct ChankastPadData 34 | { 35 | WORD buttons; /* buttons bitfield */ 36 | BYTE rtrig; /* right trigger */ 37 | BYTE ltrig; /* left trigger */ 38 | BYTE joyx; /* joystick X */ 39 | BYTE joyy; /* joystick Y */ 40 | BYTE joy2x; /* second joystick X */ 41 | BYTE joy2y; /* second joystick Y */ 42 | }; 43 | 44 | //////////////////////////////////////////////////////////////////////// 45 | // Device.. stuff 46 | //////////////////////////////////////////////////////////////////////// 47 | 48 | class ChankastController : public DreamcastController 49 | { 50 | ChankastController & operator = (const ChankastController & other) {} 51 | 52 | public: 53 | void PollData(ChankastPadData &Data); 54 | 55 | ChankastController(u32 _port, _Settings &config) : 56 | DreamcastController(_port, config) {} 57 | }; 58 | 59 | #endif // Win32 60 | -------------------------------------------------------------------------------- /Pokopom/playstation_codes.h: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2012 KrossX 2 | * License: http://www.opensource.org/licenses/mit-license.html MIT License 3 | */ 4 | 5 | #pragma once 6 | 7 | const u8 DUALSHOCK_ID[5][5] = { 8 | {0x00, 0x00, 0x02, 0x00, 0x0A}, 9 | {0x00, 0x00, 0x00, 0x00, 0x14}, 10 | {0x00, 0x02, 0x00, 0x00, 0x00}, 11 | {0x00, 0x00, 0x04, 0x00, 0x00}, 12 | {0x00, 0x00, 0x06, 0x00, 0x00}}; 13 | 14 | const u8 DUALSHOCK_MODEL[6] = {0x02, 0x02, 0x00, 0x02, 0x00, 0x00}; 15 | 16 | 17 | //Wireless DualShock2 controller 18 | const u8 DUALSHOCK2_ID[5][5] = { 19 | {0x00, 0x01, 0x02, 0x00, 0x0A}, 20 | {0x00, 0x01, 0x01, 0x01, 0x14}, 21 | {0x00, 0x02, 0x00, 0x01, 0x00}, 22 | {0x00, 0x00, 0x04, 0x00, 0x00}, 23 | {0x00, 0x00, 0x07, 0x00, 0x00}}; 24 | 25 | const u8 DUALSHOCK2_MODEL[6] = {0x03, 0x02, 0x00, 0x02, 0x01, 0x00}; 26 | 27 | 28 | const u8 GUITARHERO_ID[5][5] = { 29 | {0x00, 0x01, 0x02, 0x00, 0x0A}, 30 | {0x00, 0x01, 0x01, 0x01, 0x14}, 31 | {0x00, 0x02, 0x00, 0x01, 0x00}, 32 | {0x00, 0x00, 0x04, 0x00, 0x00}, 33 | {0x00, 0x00, 0x07, 0x00, 0x00} }; 34 | 35 | const u8 GUITARHERO_MODEL[6] = {0x01, 0x02, 0x00, 0x02, 0x01, 0x00}; 36 | 37 | 38 | const u8 POLL_MASK_FULL[6] = {0xFF, 0xFF, 0x03, 0x00, 0x00, 0x5A}; 39 | const u8 WTF[6] = {0x00, 0x00, 0x02, 0x00, 0x00, 0x5A}; 40 | 41 | // Pad modes 42 | enum ID : u8 43 | { 44 | ID_DIGITAL = 0x41, 45 | ID_ANALOG_GREEN = 0x53, //Dual stick fight mode on the DualAnalog controller 46 | ID_ANALOG_RED = 0x73, 47 | ID_ANALOG_REDP = 0x79, // Dualshock 2 analog mode + pressure 48 | ID_MULTITAP = 0x80, 49 | ID_CONFIG = 0xF3, 50 | }; 51 | 52 | /* 53 | enum ID 54 | { 55 | ID_DIGITAL = 0x41, 56 | ID_ANALOG = 0x73, 57 | ID_ANALOGJOYSTICK = 0x53, 58 | ID_MOUSE = 0x12, 59 | ID_NEGCON = 0x23, 60 | ID_NASKA = 0x23, 61 | ID_VOLUME = 0x23, 62 | ID_JOGCON = 0xE3, 63 | ID_MULTITAP = 0x80, 64 | ID_CONFIG = 0xF3, 65 | */ -------------------------------------------------------------------------------- /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.5) 2 | project(Pokopom) 3 | 4 | set(CMAKE_CXX_STANDARD 11) 5 | set(CMAKE_BUILD_TYPE Release) 6 | ADD_DEFINITIONS(-DUNICODE) 7 | ADD_DEFINITIONS(-D_UNICODE) 8 | set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -m32 -D_UNICODE -DUNICODE") 9 | if (UNIX) 10 | set(CMAKE_CXX_VISIBILITY_PRESET hidden) 11 | endif(UNIX) 12 | 13 | set(SOURCE_FILES 14 | Pokopom/Chankast.cpp 15 | Pokopom/Chankast.h 16 | Pokopom/ConfigDialog.cpp 17 | Pokopom/ConfigDialog.h 18 | Pokopom/DebugStuff.cpp 19 | Pokopom/DebugStuff.h 20 | Pokopom/demul.cpp 21 | Pokopom/demul.h 22 | Pokopom/Exports.def 23 | Pokopom/FileIO.cpp 24 | Pokopom/FileIO.h 25 | Pokopom/General.h 26 | Pokopom/Input.h 27 | Pokopom/Input_Linux.cpp 28 | Pokopom/Input_Shared.cpp 29 | Pokopom/Input_Shared.h 30 | Pokopom/Input_XInput.cpp 31 | Pokopom/playstation_codes.h 32 | Pokopom/playstation_devices.h 33 | Pokopom/playstation_dualshock.cpp 34 | Pokopom/playstation_dualshock2.cpp 35 | Pokopom/playstation_guitar.cpp 36 | Pokopom/playstation_mtap.cpp 37 | Pokopom/Pokopom.rc 38 | Pokopom/psemupro.cpp 39 | Pokopom/psemupro.h 40 | Pokopom/PSemuPro_Interface.h 41 | Pokopom/regini.cpp 42 | Pokopom/regini.h 43 | Pokopom/resource.h 44 | Pokopom/Settings.cpp 45 | Pokopom/Settings.h 46 | Pokopom/Stuff.h 47 | Pokopom/Stuff_Linux.cpp 48 | Pokopom/Stuff_Shared.cpp 49 | Pokopom/Stuff_Windows.cpp 50 | Pokopom/TypeDefs.h 51 | Pokopom/Zilmar.cpp 52 | Pokopom/Zilmar_Controller_Interface.h 53 | Pokopom/Zilmar_Devices.cpp 54 | Pokopom/Zilmar_Devices.h) 55 | 56 | add_library(padPokopom SHARED ${SOURCE_FILES}) 57 | set(CMAKE_EXE_LINKER_FLAGS " -static") 58 | if(WIN32) 59 | target_link_libraries(padPokopom UxTheme.lib) 60 | endif(WIN32) 61 | -------------------------------------------------------------------------------- /Pokopom/playstation_guitar.cpp: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2012 KrossX 2 | * License: http://www.opensource.org/licenses/mit-license.html MIT License 3 | */ 4 | 5 | #include "General.h" 6 | #include "playstation_devices.h" 7 | #include "playstation_codes.h" 8 | 9 | PS2_Guitar::PS2_Guitar(_Settings &config): 10 | DualShock2(config) {} 11 | 12 | void PS2_Guitar::ReadInputGuitar(const bool config, u8 *buffer) 13 | { 14 | if(config) ReadInput(buffer); 15 | else ReadInputPressure(buffer); 16 | 17 | buffer[3] &= 0x7F; // Switch off LEFT DPAD for some reason. 18 | // 9 - A // A - F // E - 9 // F - E 19 | u8 bitswap[4] = {0}; 20 | 21 | bitswap[0] = (buffer[4] & 0x2)? 0: 1 << 2; // 9 - A 22 | bitswap[1] = (buffer[4] & 0x4)? 0: 1 << 7; // A - F 23 | bitswap[2] = (buffer[4] & 0x40)? 0: 1 << 1; // E - 9 24 | bitswap[3] = (buffer[4] & 0x80)? 0: 1 << 6; // F - E 25 | 26 | buffer[4] |= 0xC6; 27 | buffer[4] &= ~(bitswap[0] + bitswap[1] + bitswap[2] + bitswap[3]); 28 | } 29 | 30 | 31 | void PS2_Guitar::Cmd1(u8 data) 32 | { 33 | switch(data) 34 | { 35 | case 0x42: // Polls common input and handles vibration 36 | if(bConfig) ReadInputGuitar(true, dataBuffer); 37 | else ReadInputGuitar(false, dataBuffer); 38 | break; 39 | 40 | case 0x43: // Toggle config mode, poll input and pressures. 41 | if(bConfig) memset(&dataBuffer[3], 0x00, 6); 42 | else ReadInputGuitar(false, dataBuffer); 43 | break; 44 | 45 | case 0x45: if(bConfig) { // Query model, 5th means LED status 46 | memcpy(&dataBuffer[3], GUITARHERO_MODEL, 6); 47 | dataBuffer[5] = padID == ID_DIGITAL? 0x00 : 0x01; } 48 | break; 49 | 50 | default: DualShock2::Cmd1(data); 51 | } 52 | } 53 | 54 | void PS2_Guitar::Cmd4(u8 data) 55 | { 56 | switch(data) 57 | { 58 | case 0x46: if(bConfig) {// Unknown constant part 1 and 2 59 | if(cmdBuffer[3] == 0x00) memcpy(&dataBuffer[4], GUITARHERO_ID[0], 5); 60 | else memcpy(&dataBuffer[4], GUITARHERO_ID[1], 5);} 61 | break; 62 | 63 | case 0x47: if(bConfig) {//Unknown constant part 3 64 | memcpy(&dataBuffer[4], GUITARHERO_ID[2], 5); } 65 | break; 66 | 67 | case 0x4C: if(bConfig) {// Unknown constant part 4 and 5 68 | if(cmdBuffer[3] == 0x00) memcpy(&dataBuffer[4], GUITARHERO_ID[3], 5); 69 | else memcpy(&dataBuffer[4], GUITARHERO_ID[4], 5);} 70 | break; 71 | 72 | default: DualShock2::Cmd4(data); 73 | } 74 | } 75 | 76 | -------------------------------------------------------------------------------- /Pokopom/playstation_mtap.cpp: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2012 KrossX 2 | * License: http://www.opensource.org/licenses/mit-license.html MIT License 3 | */ 4 | 5 | #include "General.h" 6 | #include "playstation_devices.h" 7 | #include "playstation_codes.h" 8 | 9 | 10 | extern u8 multitap; 11 | 12 | MultiTap::MultiTap(_Settings *config) : PlayStationDevice(config[0], 1) 13 | { 14 | for(slot = 0; slot < 4; slot++) 15 | { 16 | u8 dev = multitap == 2 ? (slot + 1) % 4 : slot; 17 | 18 | Device[slot] = isPs2Emulator? new DualShock2(config[dev]) : new DualShock(config[dev]); 19 | Device[slot]->SetPortX(dev); 20 | } 21 | 22 | if(multitap == 2) Device[3] = new PlayStationDevice(config[0], 1); 23 | } 24 | 25 | MultiTap::~MultiTap() 26 | { 27 | for(int i = 0; i < 4; i++) delete Device[i]; 28 | } 29 | 30 | u8 MultiTap::command(const u32 _counter, const u8 data) 31 | { 32 | const u8 counter = _counter & 0xFF; 33 | //slot = 0; 34 | u8 output = 0xFF; 35 | 36 | if(counter < 3) switch(counter) 37 | { 38 | case 1: output = 0x80; break; 39 | case 2: output = 0x5A; break; 40 | } 41 | else if(counter < 11) 42 | { 43 | //slot = 1; 44 | if(counter == 3) output = Device[0]->command(0, data); 45 | output = Device[0]->command(counter - 2, data); 46 | } 47 | else if(counter < 19) 48 | { 49 | //slot = 2; 50 | if(counter == 11) output = Device[1]->command(0, data); 51 | output = Device[1]->command(counter - 10, data); 52 | } 53 | else if(counter < 27) 54 | { 55 | //slot = 3; 56 | if(counter == 19) output = Device[2]->command(0, data); 57 | output = Device[2]->command(counter - 18, data); 58 | } 59 | else 60 | { 61 | //slot = 4; 62 | if(counter == 27) output = Device[3]->command(0, data); 63 | output = Device[3]->command(counter - 26, data); 64 | } 65 | 66 | //if(counter == 0) printf("\n"); 67 | //Debug("[%02d|%d] %02X:%02X\n", counter, slot, data, output); 68 | 69 | return output; 70 | } 71 | 72 | void MultiTap::LoadState(PlayStationDeviceState state) 73 | { 74 | } 75 | 76 | void MultiTap::SaveState(PlayStationDeviceState &state) 77 | { 78 | } 79 | 80 | //////////////////////////////////////////////////////////////////////// 81 | // PCSX2 Multitap 82 | //////////////////////////////////////////////////////////////////////// 83 | 84 | MultiTap2::MultiTap2(_Settings *config) : MultiTap(config) 85 | {} 86 | 87 | u8 MultiTap2::command(const u32 counter, const u8 data) 88 | { 89 | if(counter == 0) slot = data - 1; 90 | 91 | return Device[slot]->command(counter, data); 92 | } -------------------------------------------------------------------------------- /Pokopom/Zilmar_Devices.h: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2012 KrossX 2 | * License: http://www.opensource.org/licenses/mit-license.html MIT License 3 | */ 4 | 5 | #pragma once 6 | 7 | #include "Zilmar_Controller_Interface.h" 8 | 9 | #ifdef _WIN32 10 | 11 | class Zilmar_Device 12 | { 13 | Zilmar_Device(); 14 | Zilmar_Device(const Zilmar_Device&); 15 | Zilmar_Device& operator=(const Zilmar_Device&); 16 | 17 | protected: 18 | const u8 zPort; 19 | Zilmar::CONTROL &zControl; 20 | _Settings &set; 21 | 22 | bool gamepadPlugged; 23 | void Recheck(); 24 | 25 | public: 26 | virtual void FASTCALL Read(u8 *cmd) = 0; 27 | virtual void FASTCALL Command(u8 *cmd) = 0; 28 | 29 | Zilmar_Device(_Settings &settings, Zilmar::CONTROL &control, u8 port); 30 | }; 31 | 32 | //////////////////////////////////////////////////////////////////////// 33 | 34 | class N64mempak 35 | { 36 | N64mempak(); 37 | N64mempak(const N64mempak&); 38 | N64mempak& operator=(const N64mempak&); 39 | 40 | const u8 zPort; 41 | 42 | union 43 | { // 0x0000 - 0x7FFF 44 | u8 RAW8[0x8000]; 45 | u8 BLOCK[0x400][0x20]; 46 | } MEMPAK; 47 | 48 | bool Load(); 49 | void Save(); 50 | 51 | public: 52 | u8 CRC(u8 *data, s32 iLenght); 53 | 54 | void FASTCALL ReadBlock(u8 *data, u16 address, bool rumble); 55 | void FASTCALL WriteBlock(u8 *data, u16 address, bool rumble); 56 | 57 | N64mempak(u8 port); 58 | }; 59 | 60 | class N64controller : public Zilmar_Device 61 | { 62 | N64controller(); 63 | N64controller(const N64controller&); 64 | N64controller& operator=(const N64controller&); 65 | 66 | N64mempak mempak; 67 | 68 | bool bPolled; 69 | bool bRumble; 70 | 71 | struct _status { u8 Mode, EEPROM, Plugin; } status; 72 | union _poll { u8 RAW8[4]; s16 RAW16[2]; } poll; 73 | 74 | void Poll(); 75 | void GetStatus(); 76 | void RumbleIt(bool on); 77 | 78 | public: 79 | void FASTCALL Read(u8 *cmd); 80 | void FASTCALL Command(u8 *cmd); 81 | 82 | N64controller(_Settings &settings, Zilmar::CONTROL &control, u8 port); 83 | }; 84 | 85 | //////////////////////////////////////////////////////////////////////// 86 | 87 | enum RAW_COMMAND 88 | { 89 | RAW_GET_STATUS = 0x00, 90 | RAW_READ_KEYS = 0x01, 91 | RAW_READ_PACK = 0x02, 92 | RAW_WRITE_PACK = 0x03, 93 | RAW_READ_ROM = 0x04, 94 | RAW_WRITE_ROM = 0x05, 95 | RAW_RESET = 0xFF 96 | }; 97 | 98 | enum RAW_RETURN 99 | { 100 | RAW_RET_OK = 0x00, 101 | RAW_RET_WRONG_SIZE = 0x40, 102 | RAW_RET_ERROR = 0x80 103 | }; 104 | 105 | #endif 106 | -------------------------------------------------------------------------------- /Pokopom/Input_Shared.h: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2012 KrossX 2 | * License: http://www.opensource.org/licenses/mit-license.html MIT License 3 | */ 4 | 5 | #pragma once 6 | 7 | #include 8 | 9 | namespace Input 10 | { 11 | enum 12 | { 13 | DS_SELECT = 0, 14 | DS_L3, 15 | DS_R3, 16 | DS_START, 17 | DS_UP, 18 | DS_RIGHT, 19 | DS_DOWN, 20 | DS_LEFT, 21 | DS_L2, 22 | DS_R2, 23 | DS_L1, 24 | DS_R1, 25 | DS_TRIANGLE, 26 | DS_CIRCLE, 27 | DS_CROSS, 28 | DS_SQUARE 29 | }; 30 | 31 | enum 32 | { 33 | DC_B = 1, 34 | DC_A, 35 | DC_START, 36 | DC_UP, 37 | DC_DOWN, 38 | DC_LEFT, 39 | DC_RIGHT, 40 | DC_Y = 9, 41 | DC_X 42 | }; 43 | 44 | enum 45 | { 46 | NAOMI_BUTTON2 = 0, 47 | NAOMI_BUTTON1, 48 | 49 | NAOMI_DRIGHT, 50 | NAOMI_DLEFT, 51 | NAOMI_DDOWN, 52 | NAOMI_DUP, 53 | 54 | NAOMI_TEST, 55 | NAOMI_START, 56 | 57 | NAOMI_BUTTON6 = 12, 58 | NAOMI_BUTTON5, 59 | NAOMI_BUTTON4, 60 | NAOMI_BUTTON3, 61 | }; 62 | 63 | enum 64 | { 65 | N64_RIGHT = 0, 66 | N64_LEFT, 67 | N64_DOWN, 68 | N64_UP, 69 | N64_START, 70 | N64_TRIGGERZ, 71 | N64_B, 72 | N64_A, 73 | N64_CRIGHT, 74 | N64_CLEFT, 75 | N64_CDOWN, 76 | N64_CUP, 77 | N64_TRIGGERR, 78 | N64_TRIGGERL 79 | }; 80 | 81 | enum 82 | { 83 | ANALOGD_XP = 0x01, 84 | ANALOGD_XN = 0x02, 85 | ANALOGD_YP = 0x04, 86 | ANALOGD_YN = 0x08 87 | }; 88 | 89 | enum 90 | { 91 | X360_DUP = 0, 92 | X360_DDOWN, 93 | X360_DLEFT, 94 | X360_DRIGHT, 95 | X360_START, 96 | X360_BACK, 97 | X360_LS, 98 | X360_RS, 99 | X360_LB, 100 | X360_RB, 101 | X360_A, 102 | X360_B, 103 | X360_X, 104 | X360_Y, 105 | X360_BIGX, 106 | X360_BUTTONS 107 | }; 108 | 109 | enum 110 | { 111 | X360_STICKLX = 0, 112 | X360_STICKLY, 113 | X360_STICKRX, 114 | X360_STICKRY, 115 | X360_TRIGGERL, 116 | X360_TRIGGERR, 117 | X360_ANALOGS 118 | }; 119 | 120 | struct _Stick 121 | { 122 | s32 X, Y; 123 | f64 radius; 124 | f64 angle; 125 | 126 | _Stick() 127 | { 128 | X = Y = 0; 129 | radius = 0; 130 | angle = 0; 131 | } 132 | }; 133 | 134 | struct _Pad 135 | { 136 | u8 buttons[X360_BUTTONS]; 137 | s32 analog[X360_ANALOGS]; 138 | 139 | _Stick stickL, stickR; 140 | _Stick modL, modR; 141 | }; 142 | 143 | void FASTCALL TriggerDeadzone(_Pad& pad, _Settings &set); 144 | bool FASTCALL InputGetState(_Pad& pad, _Settings &set); 145 | void FASTCALL GetRadius(_Stick& stick); 146 | 147 | inline WORD Clamp(f64 input) { return input > 0xFFFF ? 0xFFFF : (WORD)input; } 148 | inline s32 ClampAnalog(f64 input) { return (s32)(input < -32768? -32768 : input > 32767 ? 32767 : input); } 149 | } 150 | 151 | -------------------------------------------------------------------------------- /Pokopom/Stuff_Linux.cpp: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2012 KrossX 2 | * License: http://www.opensource.org/licenses/mit-license.html MIT License 3 | */ 4 | 5 | #include "General.h" 6 | #include "Stuff.h" 7 | 8 | #ifdef __linux__ 9 | 10 | #include 11 | #include 12 | 13 | Display *hDisplay = NULL; 14 | Window hWindow = 0; 15 | Atom aProtocols = 0, aDeleteWindow = 0; 16 | 17 | void KeyboardOpen() 18 | { 19 | //Debug("Pokopom -> Keyboard Open\n"); 20 | aProtocols = XInternAtom(hDisplay, "WM_PROTOCOLS", 0); 21 | aDeleteWindow = XInternAtom(hDisplay, "WM_DELETE_WINDOW", 0); 22 | 23 | XkbSetDetectableAutoRepeat(hDisplay, true, NULL); 24 | } 25 | 26 | void KeyboardClose() 27 | { 28 | //Debug("Pokopom -> Keyboard Close\n"); 29 | XkbSetDetectableAutoRepeat(hDisplay, false, NULL); 30 | } 31 | 32 | void KeyboardCheck() 33 | { 34 | XEvent xEvent; 35 | keyEvent newEvent; 36 | 37 | while (XPending(hDisplay)) 38 | { 39 | XNextEvent(hDisplay, &xEvent); 40 | switch (xEvent.type) 41 | { 42 | case KeyPress: 43 | { 44 | newEvent.evt = 1; 45 | newEvent.key = XLookupKeysym((XKeyEvent *)&xEvent, 0); 46 | keyEventList.push_back(newEvent); 47 | } 48 | break; 49 | 50 | case KeyRelease: 51 | { 52 | newEvent.evt = 2; 53 | newEvent.key = XLookupKeysym((XKeyEvent *)&xEvent, 0) | 0x40000000; 54 | keyEventList.push_back(newEvent); 55 | } 56 | break; 57 | 58 | case ClientMessage: 59 | { 60 | XClientMessageEvent *xce = (XClientMessageEvent *)&xEvent; 61 | if (xce->message_type == aProtocols && (Atom)xce->data.l[0] == aDeleteWindow) 62 | { 63 | // Fake an ESC key if user clicked the close button on window 64 | newEvent.evt = 1; 65 | newEvent.key = XK_Escape; 66 | keyEventList.push_back(newEvent); 67 | return; 68 | } 69 | } 70 | break; 71 | } 72 | } 73 | } 74 | 75 | void GetDisplay(void* pDisplay) 76 | { 77 | //Debug("Pokopom -> GetDisplay\n"); 78 | hDisplay = (Display*)*(uPointer*)pDisplay; 79 | } 80 | 81 | void ShowDialog(const wchar_t* message, const wchar_t* title) 82 | { 83 | } 84 | 85 | void SetPriority() 86 | { 87 | } 88 | 89 | u8 SwapPorts() 90 | { 91 | static u8 swapIt = 0; /* 92 | static bool pressed = false; 93 | const bool currPress = !!(GetAsyncKeyState(0x30) >> 1); 94 | 95 | if(!pressed && currPress) 96 | { 97 | swapIt ^= 1; 98 | pressed = true; 99 | } 100 | else if(pressed && !currPress) 101 | { 102 | pressed = false; 103 | } 104 | */ 105 | return swapIt; 106 | } 107 | 108 | void KeepAwake(u8 mode) 109 | { 110 | switch(mode) 111 | { 112 | case KEEPAWAKE_INIT: 113 | { 114 | } 115 | break; 116 | 117 | case KEEPAWAKE_CLOSE: 118 | { 119 | } 120 | break; 121 | } 122 | } 123 | 124 | #endif //Linux 125 | -------------------------------------------------------------------------------- /Pokopom/resource.h: -------------------------------------------------------------------------------- 1 | #ifndef IDC_STATIC 2 | #define IDC_STATIC (-1) 3 | #endif 4 | 5 | #define ID_OK 2 6 | #define ID_CANCEL 3 7 | #define IDRESET 4 8 | #define IDD_CONFIG 110 9 | #define IDD_INTAB 111 10 | #define IDB_BITMAP1 115 11 | #define IDC_TAB1 1015 12 | #define IDC_SLIDER_RUMBLE 1017 13 | #define IDC_SLIDER_LINEARITY 1018 14 | #define IDC_SLIDER_DEADZONE 1019 15 | #define IDC_SLIDER_ANTIDEADZONE 1020 16 | #define IDC_TEXT_DEADZONE 1021 17 | #define IDC_TEXT_ANTIDEADZONE 1022 18 | #define IDC_TEXT_RUMBLE 1023 19 | #define IDC_TEXT_LINEARITY 1024 20 | #define IDC_SLIDER_DEADZONE2 1025 21 | #define IDC_TEXT_DEADZONE2 1026 22 | #define IDC_COMBO_LX 1027 23 | #define IDC_COMBO_LY 1028 24 | #define IDC_COMBO_RX 1029 25 | #define IDC_COMBO_RY 1030 26 | #define IDC_INVERT_LX 1031 27 | #define IDC_INVERT_LY 1032 28 | #define IDC_INVERT_RX 1033 29 | #define IDC_INVERT_RY 1034 30 | #define IDC_SCREENSAVER 1035 31 | #define IDC_SLIDER_ANTIDEADZONE2 1036 32 | #define IDC_COMBO_PROFILES 1037 33 | #define IDC_TEXT_ANTIDEADZONE2 1038 34 | #define IDC_PROFILE_SAVE 1039 35 | #define IDC_SLIDER_LINEARITY2 1040 36 | #define IDC_PROFILE_DELETE 1041 37 | #define IDC_TEXT_LINEARITY2 1042 38 | #define IDC_XINPUT1 1043 39 | #define IDC_XINPUT2 1044 40 | #define IDC_XINPUT3 1045 41 | #define IDC_XINPUT4 1046 42 | #define IDC_MODE_DIGITAL 1047 43 | #define IDC_MODE_ANALOG 1048 44 | #define IDC_GUITAR 1049 45 | #define IDC_MULTITAP 1050 46 | #define IDC_DISABLED 1051 47 | #define IDC_SWAPPORTS 1052 48 | #define IDC_PROCPRIORITY 1053 49 | #define IDC_ANALOG_GREEN 1054 50 | #define IDC_SWAPSTICKS 1055 51 | #define IDC_LOCKSLIDERS 1056 52 | #define IDC_4WAYSTICK 1057 53 | #define IDC_SWAPXO 1058 54 | -------------------------------------------------------------------------------- /README: -------------------------------------------------------------------------------- 1 | Pokopom - Input plugin for emulators 2 | =============================================================================== 3 | 4 | Main repo: https://github.com/KrossX/Pokopom 5 | Wiki: https://github.com/KrossX/Pokopom/wiki 6 | Download: https://github.com/KrossX/Pokopom/releases 7 | 8 | 9 | Description and information 10 | ------------------------------------------------------------------------------- 11 | 12 | Pokopom is an imput plugin that supports many emulators like PCSX, PCSX2, PJ64, 13 | nullDC, Chankast, etc. Started as a XInput only plugin for X360 controllers, but 14 | now it supports linux too (also for X360 controllers) though GUI less. Supports 15 | rumble, though it depends on emulator/device. 16 | 17 | DualShock3 are supported on Windows by using Scarlet.Crush's driver: 18 | http://forums.pcsx2.net/Thread-XInput-Wrapper-for-DS3-and-Play-com-USB-Dual-DS2-Controller 19 | 20 | Also for ePSXe, Shark would be needed: 21 | Shark: http://ngemu.com/threads/epsxe-shark.142361/ 22 | Shark Enhanced: http://ngemu.com/threads/epsxe-shark-enhanced-by-tapeq.154634/ 23 | 24 | For more information, check the Wiki. 25 | 26 | 27 | Thanks / Contact 28 | ------------------------------------------------------------------------------- 29 | 30 | Lots of thanks to gunshin (Harakiri), for his source and information helped 31 | lots. Site: http://www.geocities.co.jp/Playtown-Rook/2087/ 32 | 33 | Tons of thanks to Curious Inventor too, for this great source of information: 34 | http://store.curiousinventor.com/guides/ps2/ 35 | 36 | Thanks to H.Kashima, fundamental information to get multitap working 37 | http://kaele.com/~kashima/games/ps_jpn.txt 38 | 39 | = Contact = 40 | KrossX, krossx@live.com 41 | 42 | 43 | License / Disclaimer 44 | ------------------------------------------------------------------------------- 45 | 46 | Copyright (c) 2012 KrossX 47 | 48 | Permission is hereby granted, free of charge, to any person obtaining a copy 49 | of this software and associated documentation files (the "Software"), to deal 50 | in the Software without restriction, including without limitation the rights 51 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 52 | copies of the Software, and to permit persons to whom the Software is 53 | furnished to do so, subject to the following conditions: 54 | 55 | The above copyright notice and this permission notice shall be included in 56 | all copies or substantial portions of the Software. 57 | 58 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 59 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 60 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 61 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 62 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 63 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 64 | THE SOFTWARE. 65 | -------------------------------------------------------------------------------- /Pokopom/Chankast.cpp: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2012 KrossX 2 | * License: http://www.opensource.org/licenses/mit-license.html MIT License 3 | */ 4 | 5 | #include "General.h" 6 | #include "FileIO.h" 7 | #include "ConfigDialog.h" 8 | #include "Chankast.h" 9 | #include "Input.h" 10 | 11 | #if 0 12 | //#ifdef _WIN32 13 | 14 | ChankastController * chankastPad[2] = {NULL, NULL}; 15 | ChankastPadData chankastData[2]; 16 | 17 | //////////////////////////////////////////////////////////////////////// 18 | // On start? 19 | //////////////////////////////////////////////////////////////////////// 20 | 21 | s32 InitPads(void* hWnd) 22 | { 23 | FileIO::INI_LoadSettings(); 24 | FileIO::INI_SaveSettings(); 25 | 26 | chankastPad[0] = new ChankastController(0, settings[0]); 27 | chankastPad[1] = new ChankastController(1, settings[1]); 28 | 29 | memset(chankastData, 0, sizeof(chankastData)); 30 | 31 | Input::Pause(false); 32 | KeepAwake(KEEPAWAKE_INIT); 33 | 34 | return 0; 35 | } 36 | 37 | //////////////////////////////////////////////////////////////////////// 38 | // ??? 39 | //////////////////////////////////////////////////////////////////////// 40 | 41 | s32 GetNumControllers() 42 | { 43 | return 2; 44 | } 45 | 46 | //////////////////////////////////////////////////////////////////////// 47 | // On close? 48 | //////////////////////////////////////////////////////////////////////// 49 | 50 | void EndPads() 51 | { 52 | delete chankastPad[0]; 53 | delete chankastPad[1]; 54 | 55 | chankastPad[0] = NULL; 56 | chankastPad[1] = NULL; 57 | 58 | Input::Pause(true); 59 | KeepAwake(KEEPAWAKE_CLOSE); 60 | } 61 | 62 | //////////////////////////////////////////////////////////////////////// 63 | // Config! 64 | //////////////////////////////////////////////////////////////////////// 65 | 66 | s32 ConfigurePads(void* hWnd) 67 | { 68 | FileIO::INI_LoadSettings(); 69 | CreateConfigDialog(); 70 | return 0; 71 | } 72 | 73 | //////////////////////////////////////////////////////////////////////// 74 | // Poll 75 | //////////////////////////////////////////////////////////////////////// 76 | 77 | void ChankastController::PollData(ChankastPadData &Data) 78 | { 79 | u16 buffer[6]; 80 | Input::DreamcastPoll((u32*)buffer, set, gamepadPlugged); 81 | memcpy(&Data, &buffer[2], 8); 82 | } 83 | 84 | void UpdateInput() 85 | { 86 | chankastPad[0]->PollData(chankastData[0]); 87 | chankastPad[1]->PollData(chankastData[1]); 88 | } 89 | 90 | void GetStatusPads(s32 iNumPad, void* _pContCond) 91 | { 92 | memcpy(_pContCond,&chankastData[iNumPad],sizeof(ChankastPadData)); 93 | } 94 | 95 | //////////////////////////////////////////////////////////////////////// 96 | // Interface stuff 97 | //////////////////////////////////////////////////////////////////////// 98 | 99 | static ChankastInputInterface ChankastInterface = 100 | { 101 | MAKEWORD(1,0), 102 | "Pokopom Interface", 103 | InitPads, 104 | GetNumControllers, 105 | EndPads, 106 | ConfigurePads, 107 | UpdateInput, 108 | GetStatusPads, 109 | }; 110 | 111 | DllExport ChankastInputInterface *GetInputInterface() 112 | { 113 | return &ChankastInterface; 114 | } 115 | 116 | #endif // Win32 117 | -------------------------------------------------------------------------------- /Pokopom/Zilmar_Controller_Interface.h: -------------------------------------------------------------------------------- 1 | /********************************************************************************** 2 | Common Controller plugin spec, version #1.1 maintained by 3 | zilmar (zilmar@emulation64.com) 4 | 5 | All questions or suggestions should go through the emutalk plugin forum. 6 | http://www.emutalk.net/cgi-bin/ikonboard/ikonboard.cgi?s=3bd272222f66ffff;act=SF;f=20 7 | **********************************************************************************/ 8 | 9 | // 2012 - Messed up by KrossX, sorry~ 10 | 11 | #pragma once 12 | #ifdef _WIN32 13 | 14 | namespace Zilmar 15 | { 16 | const u16 INTERFACE_VERSION = 0x0100; // 0x01000 for 1.0, x0101 for 1.1 17 | const u8 PLUGIN_TYPE_CONTROLLER = 4; 18 | 19 | /*** Conteroller plugin's ****/ 20 | const u8 PLUGIN_NONE = 1; 21 | const u8 PLUGIN_MEMPAK = 2; 22 | const u8 PLUGIN_RUMBLE_PAK = 3; // not implemeted for non raw data 23 | const u8 PLUGIN_TANSFER_PAK = 4; // not implemeted for non raw data 24 | const u8 PLUGIN_RAW = 5; // the controller plugin is passed in raw data 25 | 26 | /********************************************************************************* 27 | Note about Conteroller plugin's: 28 | the rumble pak needs a function for the force feed back joystick and tranfer pak 29 | probaly needs a function for the plugin to be able to select the GB rom and 30 | eeprom... maybe this should be done by the emu instead of the plugin, but I think 31 | it probaly should be done by the plugin. I will see about adding these functions 32 | in the next spec 33 | **********************************************************************************/ 34 | 35 | /***** Structures *****/ 36 | typedef struct { 37 | WORD Version; /* Should be set to 0x0101 */ 38 | WORD Type; /* Set to PLUGIN_TYPE_CONTROLLER */ 39 | char Name[100]; /* Name of the DLL */ 40 | BOOL Reserved1; 41 | BOOL Reserved2; 42 | } PLUGIN_INFO; 43 | 44 | typedef struct { 45 | BOOL Present; 46 | BOOL RawData; 47 | int Plugin; 48 | } CONTROL; 49 | 50 | typedef union { 51 | DWORD Value; 52 | struct { 53 | unsigned R_DPAD : 1; 54 | unsigned L_DPAD : 1; 55 | unsigned D_DPAD : 1; 56 | unsigned U_DPAD : 1; 57 | unsigned START_BUTTON : 1; 58 | unsigned Z_TRIG : 1; 59 | unsigned B_BUTTON : 1; 60 | unsigned A_BUTTON : 1; 61 | 62 | unsigned R_CBUTTON : 1; 63 | unsigned L_CBUTTON : 1; 64 | unsigned D_CBUTTON : 1; 65 | unsigned U_CBUTTON : 1; 66 | unsigned R_TRIG : 1; 67 | unsigned L_TRIG : 1; 68 | unsigned Reserved1 : 1; 69 | unsigned Reserved2 : 1; 70 | 71 | signed Y_AXIS : 8; 72 | 73 | signed X_AXIS : 8; 74 | }; 75 | } BUTTONS; 76 | 77 | typedef struct { 78 | HWND hMainWindow; 79 | HINSTANCE hinst; 80 | 81 | BOOL MemoryBswaped; // If this is set to TRUE, then the memory has been pre 82 | // bswap on a dword (32 bits) boundry, only effects header. 83 | // eg. the first 8 bytes are stored like this: 84 | // 4 3 2 1 8 7 6 5 85 | BYTE * HEADER; // This is the rom header (first 40h bytes of the rom) 86 | CONTROL *Controls; // A pointer to an array of 4 controllers .. eg: 87 | // CONTROL Controls[4]; 88 | } CONTROL_INFO; 89 | 90 | } // End namespace 91 | #endif //WIN32 92 | 93 | -------------------------------------------------------------------------------- /Pokopom/regini.h: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2014 KrossX 2 | * License: http://www.opensource.org/licenses/mit-license.html MIT License 3 | */ 4 | 5 | #ifndef REGINI_H 6 | #define REGINI_H 7 | 8 | namespace regini 9 | { 10 | using std::string; 11 | using std::vector; 12 | 13 | struct entry_type 14 | { 15 | string key; 16 | string value; 17 | }; 18 | 19 | struct section_type 20 | { 21 | string name; 22 | vector entry; 23 | }; 24 | 25 | class regini_file 26 | { 27 | string filename; 28 | 29 | section_type* current_section; 30 | vector vsection; 31 | 32 | void add_section(string in); 33 | void add_entry(string in); 34 | 35 | section_type* get_section(string section_name); 36 | entry_type* get_entry(string section_name, string key_name); 37 | 38 | bool read_string(string section, string key, string &out); 39 | void write_string(string section, string key, string value); 40 | 41 | public: 42 | // template 43 | // T read(string section, string key, T default_value) 44 | // { 45 | // string value; 46 | // if (read_string(section, key, value)) default_value = std::stoi(value); 47 | // return static_cast(default_value); 48 | // } 49 | 50 | int readi(string section, string key, int default_value) 51 | { 52 | string value; 53 | if (read_string(section, key, value)) default_value = std::stoi(value); 54 | return default_value; 55 | } 56 | 57 | long readl(string section, string key, long default_value) 58 | { 59 | string value; 60 | if (read_string(section, key, value)) default_value = std::stol(value); 61 | return default_value; 62 | } 63 | 64 | long long readll(string section, string key, long long default_value) 65 | { 66 | string value; 67 | if (read_string(section, key, value)) default_value = std::stoll(value); 68 | return default_value; 69 | } 70 | 71 | unsigned long readul(string section, string key, unsigned long default_value) 72 | { 73 | string value; 74 | if (read_string(section, key, value)) default_value = std::stoul(value); 75 | return default_value; 76 | } 77 | 78 | unsigned long long readull(string section, string key, unsigned long long default_value) 79 | { 80 | string value; 81 | if (read_string(section, key, value)) default_value = std::stoull(value); 82 | return default_value; 83 | } 84 | 85 | float readf(string section, string key, float default_value) 86 | { 87 | string value; 88 | if (read_string(section, key, value)) default_value = std::stof(value); 89 | return default_value; 90 | } 91 | 92 | double readd(string section, string key, double default_value) 93 | { 94 | string value; 95 | if (read_string(section, key, value)) default_value = std::stod(value); 96 | return default_value; 97 | } 98 | 99 | long double readld(string section, string key, long double default_value) 100 | { 101 | string value; 102 | if (read_string(section, key, value)) default_value = std::stold(value); 103 | return default_value; 104 | } 105 | 106 | // template 107 | // void write(string section, string key, T value) 108 | // { 109 | // string string_value = std::to_string(value); 110 | // write_string(section, key, string_value); 111 | // } 112 | 113 | void write(string section, string key, string value) 114 | { 115 | write_string(section, key, value); 116 | } 117 | 118 | bool open(string filename); 119 | void save(); 120 | }; 121 | } 122 | 123 | #endif -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | ################# 2 | ## Eclipse 3 | ################# 4 | 5 | *.pydevproject 6 | .project 7 | .metadata 8 | bin/ 9 | tmp/ 10 | *.tmp 11 | *.bak 12 | *.swp 13 | *~.nib 14 | local.properties 15 | .classpath 16 | .settings/ 17 | .loadpath 18 | 19 | # External tool builders 20 | .externalToolBuilders/ 21 | 22 | # Locally stored "Eclipse launch configurations" 23 | *.launch 24 | 25 | # CDT-specific 26 | .cproject 27 | 28 | # PDT-specific 29 | .buildpath 30 | 31 | 32 | ################# 33 | ## Visual Studio 34 | ################# 35 | 36 | ## Ignore Visual Studio temporary files, build results, and 37 | ## files generated by popular Visual Studio add-ons. 38 | 39 | # User-specific files 40 | *.suo 41 | *.user 42 | *.sln.docstates 43 | 44 | # Build results 45 | 46 | [Dd]ebug/ 47 | [Rr]elease/ 48 | x64/ 49 | build/ 50 | [Bb]in/ 51 | [Oo]bj/ 52 | 53 | # MSTest test Results 54 | [Tt]est[Rr]esult*/ 55 | [Bb]uild[Ll]og.* 56 | 57 | *_i.c 58 | *_p.c 59 | *.ilk 60 | *.meta 61 | *.obj 62 | *.pch 63 | *.pdb 64 | *.pgc 65 | *.pgd 66 | *.rsp 67 | *.sbr 68 | *.tlb 69 | *.tli 70 | *.tlh 71 | *.tmp 72 | *.tmp_proj 73 | *.log 74 | *.vspscc 75 | *.vssscc 76 | .builds 77 | *.pidb 78 | *.log 79 | *.scc 80 | 81 | # Visual C++ cache files 82 | ipch/ 83 | *.aps 84 | *.ncb 85 | *.opensdf 86 | *.sdf 87 | *.cachefile 88 | 89 | # Visual Studio profiler 90 | *.psess 91 | *.vsp 92 | *.vspx 93 | 94 | # Guidance Automation Toolkit 95 | *.gpState 96 | 97 | # ReSharper is a .NET coding add-in 98 | _ReSharper*/ 99 | *.[Rr]e[Ss]harper 100 | 101 | # TeamCity is a build add-in 102 | _TeamCity* 103 | 104 | # DotCover is a Code Coverage Tool 105 | *.dotCover 106 | 107 | # NCrunch 108 | *.ncrunch* 109 | .*crunch*.local.xml 110 | 111 | # Installshield output folder 112 | [Ee]xpress/ 113 | 114 | # DocProject is a documentation generator add-in 115 | DocProject/buildhelp/ 116 | DocProject/Help/*.HxT 117 | DocProject/Help/*.HxC 118 | DocProject/Help/*.hhc 119 | DocProject/Help/*.hhk 120 | DocProject/Help/*.hhp 121 | DocProject/Help/Html2 122 | DocProject/Help/html 123 | 124 | # Click-Once directory 125 | publish/ 126 | 127 | # Publish Web Output 128 | *.Publish.xml 129 | *.pubxml 130 | 131 | # NuGet Packages Directory 132 | ## TODO: If you have NuGet Package Restore enabled, uncomment the next line 133 | #packages/ 134 | 135 | # Windows Azure Build Output 136 | csx 137 | *.build.csdef 138 | 139 | # Windows Store app package directory 140 | AppPackages/ 141 | 142 | # Others 143 | sql/ 144 | *.Cache 145 | ClientBin/ 146 | [Ss]tyle[Cc]op.* 147 | ~$* 148 | *~ 149 | *.dbmdl 150 | *.[Pp]ublish.xml 151 | *.pfx 152 | *.publishsettings 153 | 154 | # RIA/Silverlight projects 155 | Generated_Code/ 156 | 157 | # Backup & report files from converting an old project file to a newer 158 | # Visual Studio version. Backup files are not needed, because we have git ;-) 159 | _UpgradeReport_Files/ 160 | Backup*/ 161 | UpgradeLog*.XML 162 | UpgradeLog*.htm 163 | 164 | # SQL Server files 165 | App_Data/*.mdf 166 | App_Data/*.ldf 167 | 168 | ############# 169 | ## Windows detritus 170 | ############# 171 | 172 | # Windows image file caches 173 | Thumbs.db 174 | ehthumbs.db 175 | 176 | # Folder config file 177 | Desktop.ini 178 | 179 | # Recycle Bin used on file shares 180 | $RECYCLE.BIN/ 181 | 182 | # Mac crap 183 | .DS_Store 184 | 185 | 186 | ############# 187 | ## Python 188 | ############# 189 | 190 | *.py[co] 191 | 192 | # Packages 193 | *.egg 194 | *.egg-info 195 | dist/ 196 | build/ 197 | eggs/ 198 | parts/ 199 | var/ 200 | sdist/ 201 | develop-eggs/ 202 | .installed.cfg 203 | 204 | # Installer logs 205 | pip-log.txt 206 | 207 | # Unit test / coverage reports 208 | .coverage 209 | .tox 210 | 211 | #Translations 212 | *.mo 213 | 214 | #Mr Developer 215 | .mr.developer.cfg 216 | -------------------------------------------------------------------------------- /Pokopom/Stuff_Windows.cpp: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2012 KrossX 2 | * License: http://www.opensource.org/licenses/mit-license.html MIT License 3 | */ 4 | 5 | //#include "general.h" 6 | #include "psemupro.h" 7 | #include "Input.h" 8 | #include "Stuff.h" 9 | 10 | #ifdef _WIN32 11 | 12 | HWND h_display = NULL; 13 | HINSTANCE h_instance = NULL; 14 | WNDPROC h_winproc = NULL; 15 | 16 | void ShowDialog(const wchar_t* message, const wchar_t* title) 17 | { 18 | MessageBox(NULL, message,title, MB_OK); 19 | } 20 | 21 | void MouseThread() 22 | { 23 | while(true) 24 | { 25 | mouse_event( MOUSEEVENTF_MOVE, 0, 0, 0, NULL); 26 | Sleep(50000); 27 | } 28 | } 29 | 30 | void SetPriority() 31 | { 32 | if(bPriority) 33 | { 34 | const HANDLE currProc = GetCurrentProcess(); 35 | SetPriorityClass(currProc, ABOVE_NORMAL_PRIORITY_CLASS); 36 | } 37 | } 38 | 39 | void KeepAwake(u8 mode) 40 | { 41 | static HANDLE hMouseThread = NULL; 42 | 43 | if(bKeepAwake) 44 | switch(mode) 45 | { 46 | case KEEPAWAKE_INIT: 47 | { 48 | if(hMouseThread == NULL) 49 | hMouseThread = CreateThread(0, 0, (LPTHREAD_START_ROUTINE)MouseThread, 0, 0, NULL); 50 | } 51 | break; 52 | 53 | case KEEPAWAKE_CLOSE: 54 | { 55 | if(hMouseThread) 56 | { 57 | TerminateThread(hMouseThread,0); 58 | hMouseThread = NULL; 59 | } 60 | } 61 | break; 62 | } 63 | } 64 | 65 | void GetDisplay(void* pDisplay) 66 | { 67 | if(IsWindow((HWND)pDisplay)) 68 | h_display = (HWND)pDisplay; 69 | else if(IsWindow(*(HWND*)pDisplay)) // And hopefully doesn't crash... 70 | h_display = *(HWND*)pDisplay; 71 | else 72 | h_display = NULL; 73 | } 74 | 75 | LRESULT CALLBACK KeyboardProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) 76 | { 77 | keyEvent newEvent; 78 | 79 | switch(msg) 80 | { 81 | case WM_KEYDOWN: 82 | case WM_SYSKEYDOWN: 83 | newEvent.evt = 1; 84 | newEvent.key = wParam; 85 | keyEventList.push_back(newEvent); 86 | break; 87 | 88 | case WM_KEYUP: 89 | case WM_SYSKEYUP: 90 | newEvent.evt = 2; 91 | newEvent.key = wParam; 92 | keyEventList.push_back(newEvent); 93 | break; 94 | 95 | case WM_DESTROY: 96 | case WM_QUIT: 97 | newEvent.evt = 1; 98 | newEvent.key = VK_ESCAPE; 99 | keyEventList.push_back(newEvent); 100 | break; 101 | } 102 | 103 | return CallWindowProcW(h_winproc, hWnd, msg, wParam, lParam); 104 | } 105 | 106 | u8 SwapPorts() 107 | { 108 | static u8 swapIt = 0; 109 | static bool pressed = false; 110 | const bool currPress = !!(GetAsyncKeyState(0x30) >> 1); 111 | 112 | if(!pressed && currPress) 113 | { 114 | swapIt ^= 1; 115 | pressed = true; 116 | } 117 | else if(pressed && !currPress) 118 | { 119 | pressed = false; 120 | } 121 | 122 | return swapIt; 123 | } 124 | 125 | void KeyboardOpen() 126 | { 127 | if(isPs2Emulator) 128 | h_winproc = (WNDPROC)SetWindowLongPtr(h_display, GWLP_WNDPROC, (LPARAM)KeyboardProc); 129 | } 130 | 131 | void KeyboardClose() 132 | { 133 | if(isPs2Emulator) 134 | SetWindowLongPtr(h_display, GWLP_WNDPROC, (LPARAM)h_winproc); 135 | } 136 | 137 | void KeyboardCheck() {} 138 | 139 | void ScrollLockStuff(bool init) 140 | { 141 | static bool scrollLock = false; 142 | static bool scrollLockSaved = false; 143 | 144 | if (!scrollLockSaved && init) 145 | { 146 | scrollLock = GetKeyState(VK_SCROLL) & 0x1; 147 | scrollLockSaved = true; 148 | } 149 | else if (scrollLockSaved && !init) 150 | { 151 | if (scrollLock != (GetKeyState(VK_SCROLL) & 0x1)) 152 | { 153 | keybd_event(VK_SCROLL, 0x45, KEYEVENTF_EXTENDEDKEY, 0); 154 | keybd_event(VK_SCROLL, 0x45, KEYEVENTF_EXTENDEDKEY | KEYEVENTF_KEYUP, 0); 155 | } 156 | } 157 | } 158 | 159 | struct scroll_auto 160 | { 161 | scroll_auto() { ScrollLockStuff(true); } 162 | ~scroll_auto() { ScrollLockStuff(false); } 163 | } scrolly; 164 | 165 | BOOL APIENTRY DllMain(HMODULE hInst, DWORD dwReason, LPVOID lpReserved) 166 | { 167 | h_instance = hInst; 168 | 169 | switch(dwReason) 170 | { 171 | case DLL_PROCESS_ATTACH: 172 | break; 173 | 174 | case DLL_PROCESS_DETACH: 175 | break; 176 | } 177 | 178 | return TRUE; 179 | } 180 | 181 | #endif //WIN32 182 | -------------------------------------------------------------------------------- /Pokopom/playstation_devices.h: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2012 KrossX 2 | * License: http://www.opensource.org/licenses/mit-license.html MIT License 3 | */ 4 | 5 | #pragma once 6 | 7 | struct PlayStationDeviceState 8 | { 9 | char libraryName[25]; 10 | u16 version; 11 | 12 | u16 buttons, buttonsStick, analogL, analogR; 13 | u8 padID; 14 | bool bConfig, bModeLock; 15 | u8 motorMapS, motorMapL; 16 | u8 triggerL, triggerR; 17 | 18 | u8 pollMask[6]; 19 | u16 pressureButton[12]; 20 | }; 21 | 22 | class PlayStationDevice 23 | { 24 | PlayStationDevice(); 25 | PlayStationDevice(const PlayStationDevice &); 26 | PlayStationDevice& operator=(const PlayStationDevice &); 27 | 28 | protected: 29 | _Settings &settings; 30 | 31 | u8 port; 32 | u8 *dataBuffer, *cmdBuffer; 33 | const u16 sizeBuffer; 34 | 35 | bool gamepadPlugged; 36 | void Recheck(); 37 | 38 | public: 39 | void Enable() { settings.disabled = false; } 40 | void Disable() { settings.disabled = true; } 41 | void SetPortX(u8 p); 42 | 43 | virtual void LoadState(PlayStationDeviceState state) {}; 44 | virtual void SaveState(PlayStationDeviceState &state) {}; 45 | 46 | virtual u8 command(const u32 counter, const u8 data) { return 0x00; }; 47 | 48 | PlayStationDevice(_Settings &config, u16 bufferSize); // 9 PS1, 21 PS2 49 | ~PlayStationDevice(); 50 | }; 51 | 52 | 53 | class DualShock : public PlayStationDevice 54 | { 55 | DualShock(); 56 | DualShock(const DualShock &); 57 | DualShock& operator=(const DualShock &); 58 | 59 | protected: 60 | virtual void Cmd0(); // To use the analog toggle or whatever before command 61 | virtual void Cmd1(const u8 data); // Requires only main command byte to be known 62 | virtual void Cmd4(const u8 data); // Requires bytes 3 and 4 to be known 63 | virtual void Cmd8(const u8 data); // Requires 8 bytes from the command to be known 64 | 65 | void poll(); 66 | void vibration(u8 smalldata, u8 bigdata); 67 | void ReadInput(u8 *buffer); 68 | void SetVibration(); 69 | void Reset(); 70 | 71 | u16 buttons, buttonsStick, analogL, analogR; 72 | u8 padID, padDefault; 73 | bool bConfig, bModeLock; 74 | u8 motorMapS, motorMapL; 75 | u8 triggerL, triggerR; 76 | 77 | public: 78 | u8 command(const u32 counter, const u8 data); 79 | 80 | void LoadState(PlayStationDeviceState state); 81 | void SaveState(PlayStationDeviceState &state); 82 | 83 | DualShock(_Settings &config, u16 bsize = 9); 84 | }; 85 | 86 | class DualShock2 : public DualShock 87 | { 88 | DualShock2(); 89 | DualShock2(const DualShock2 &); 90 | DualShock2& operator=(const DualShock2 &); 91 | 92 | protected: 93 | void Cmd1(const u8 data); 94 | void Cmd4(const u8 data); 95 | void Cmd8(const u8 data); 96 | 97 | void ReadInputPressure(u8 *buffer); 98 | u8 pollMask[6]; 99 | u16 pressureButton[12]; 100 | 101 | public: 102 | void LoadState(PlayStationDeviceState state); 103 | void SaveState(PlayStationDeviceState &state); 104 | 105 | DualShock2(_Settings &config); 106 | }; 107 | 108 | class PS2_Guitar : public DualShock2 109 | { 110 | PS2_Guitar(); 111 | PS2_Guitar(const PS2_Guitar &); 112 | PS2_Guitar& operator=(const PS2_Guitar &); 113 | 114 | void Cmd1(const u8 data); 115 | void Cmd4(const u8 data); 116 | 117 | void ReadInputGuitar(const bool bConfig, u8 *buffer); 118 | 119 | public: 120 | PS2_Guitar(_Settings &config); 121 | }; 122 | 123 | class MultiTap : public PlayStationDevice 124 | { 125 | MultiTap(); 126 | MultiTap(const MultiTap &); 127 | MultiTap& operator=(const MultiTap &); 128 | 129 | protected: 130 | u8 slot; 131 | PlayStationDevice * Device[4]; 132 | 133 | public: 134 | void LoadState(PlayStationDeviceState state); 135 | void SaveState(PlayStationDeviceState &state); 136 | 137 | u8 command(const u32 counter, const u8 data); 138 | 139 | MultiTap(_Settings *config); 140 | ~MultiTap(); 141 | }; 142 | 143 | class MultiTap2 : public MultiTap 144 | { 145 | MultiTap2(); 146 | MultiTap2(const MultiTap2 &); 147 | MultiTap2& operator=(const MultiTap2 &); 148 | 149 | public: 150 | u8 command(const u32 counter, const u8 data); 151 | 152 | MultiTap2(_Settings *config); 153 | }; 154 | 155 | -------------------------------------------------------------------------------- /Pokopom/regini.cpp: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2014 KrossX 2 | * License: http://www.opensource.org/licenses/mit-license.html MIT License 3 | */ 4 | 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | #include "regini.h" 11 | 12 | namespace regini 13 | { 14 | const string winreg = "Windows Registry Editor Version 5.00"; 15 | 16 | static inline string string_tolower(string in) 17 | { 18 | string out = in; 19 | std::transform(out.begin(), out.end(), out.begin(), ::tolower); 20 | return out; 21 | } 22 | 23 | void regini_file::add_section(string in) 24 | { 25 | in = in.substr(1, in.size() - 2); 26 | 27 | for (size_t i = 0; i < vsection.size(); i++) 28 | { 29 | if (vsection[i].name.compare(in) == 0) 30 | { 31 | current_section = &vsection[i]; 32 | return; 33 | } 34 | } 35 | 36 | section_type newsection; 37 | newsection.name = in; 38 | vsection.push_back(newsection); 39 | current_section= &vsection.back(); 40 | } 41 | 42 | void regini_file::add_entry(string in) 43 | { 44 | size_t pos = in.find('='); 45 | 46 | entry_type newentry; 47 | newentry.key = in.substr(1, pos - 2); 48 | 49 | for (entry_type et : current_section->entry) 50 | { 51 | if (et.key.compare(newentry.key) == 0) 52 | { 53 | et.value = in.substr(pos + 2, in.size() - pos - 3); 54 | return; 55 | } 56 | } 57 | 58 | newentry.value = in.substr(pos + 2, in.size() - pos - 3); 59 | current_section->entry.push_back(newentry); 60 | } 61 | 62 | 63 | bool regini_file::open(string fname) 64 | { 65 | filename = fname; 66 | std::ifstream file(fname); 67 | vector line; 68 | 69 | vsection.clear(); 70 | 71 | if (file.is_open()) 72 | { 73 | while (!file.eof()) 74 | { 75 | string newline; 76 | std::getline(file, newline); 77 | line.push_back(newline); 78 | } 79 | 80 | file.close(); 81 | 82 | if (!line.empty()) 83 | { 84 | current_section = nullptr; 85 | 86 | for (string str : line) 87 | { 88 | if (str.empty()) continue; 89 | 90 | size_t size = str.size(); 91 | 92 | if (str[0] == '[' && str[size - 1] == ']') 93 | { 94 | add_section(str); 95 | } 96 | else if (str[0] == '"' && str.find('=') != string::npos && current_section != 0) 97 | { 98 | add_entry(str); 99 | } 100 | } 101 | } 102 | } 103 | 104 | return !vsection.empty(); 105 | } 106 | 107 | void regini_file::save() 108 | { 109 | if (vsection.empty()) return; 110 | 111 | std::ofstream file(filename, std::ios::out | std::ios::trunc); 112 | 113 | if (file.is_open()) 114 | { 115 | //file << winreg << "\n\n"; 116 | 117 | for (section_type sec : vsection) 118 | { 119 | file << "[" << sec.name << "]\n"; 120 | 121 | for (entry_type entry : sec.entry) 122 | { 123 | file << "\"" << entry.key << "\"" << "=\"" << entry.value << "\"\n"; 124 | } 125 | 126 | file << "\n"; 127 | } 128 | 129 | file.close(); 130 | } 131 | } 132 | 133 | section_type* regini_file::get_section(string section_name) 134 | { 135 | section_name = string_tolower(section_name); 136 | 137 | for (size_t i = 0; i < vsection.size(); i++) 138 | { 139 | string sname = string_tolower(vsection[i].name); 140 | 141 | if (sname.compare(section_name) == 0) 142 | return &vsection[i]; 143 | } 144 | 145 | return nullptr; 146 | } 147 | 148 | entry_type* regini_file::get_entry(string section_name, string key_name) 149 | { 150 | section_type* sec = get_section(section_name); 151 | 152 | if (sec != nullptr) 153 | { 154 | key_name = string_tolower(key_name); 155 | 156 | for (size_t i = 0; i < sec->entry.size(); i++) 157 | { 158 | string ekeyname = string_tolower(sec->entry[i].key); 159 | 160 | if (ekeyname.compare(key_name) == 0) 161 | return &sec->entry[i]; 162 | } 163 | } 164 | 165 | return nullptr; 166 | } 167 | 168 | bool regini_file::read_string(string section, string key, string &out) 169 | { 170 | entry_type *entry = get_entry(section, key); 171 | 172 | if (entry != nullptr) 173 | { 174 | out = entry->value; 175 | return true; 176 | } 177 | else 178 | { 179 | return false; 180 | } 181 | } 182 | 183 | void regini_file::write_string(string section, string key, string value) 184 | { 185 | section_type *sec = get_section(section); 186 | 187 | entry_type newentry; 188 | newentry.key = key; 189 | newentry.value = value; 190 | 191 | if (sec == nullptr) 192 | { 193 | section_type newsection; 194 | newsection.name = section; 195 | newsection.entry.push_back(newentry); 196 | this->vsection.push_back(newsection); 197 | } 198 | else 199 | { 200 | entry_type *entry = get_entry(section, key); 201 | 202 | if (entry == nullptr) 203 | { 204 | sec->entry.push_back(newentry); 205 | } 206 | else 207 | { 208 | entry->value = newentry.value; 209 | } 210 | } 211 | } 212 | 213 | 214 | } // end regini namespace 215 | 216 | 217 | 218 | -------------------------------------------------------------------------------- /Pokopom/playstation_dualshock2.cpp: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2012 KrossX 2 | * License: http://www.opensource.org/licenses/mit-license.html MIT License 3 | */ 4 | 5 | #include "General.h" 6 | #include "playstation_codes.h" 7 | #include "playstation_devices.h" 8 | #include "Input.h" 9 | 10 | DualShock2::DualShock2(_Settings &config) : DualShock(config, 21) 11 | { 12 | memset(pressureButton, 0x00, sizeof(pressureButton)); 13 | memcpy(pollMask, POLL_MASK_FULL, 6); 14 | } 15 | 16 | void DualShock2::ReadInputPressure(u8 *buffer) 17 | { 18 | u8 pressure[12] = {0}; 19 | u32 mask = ((pollMask[2] << 16) | (pollMask[1] << 8) | (pollMask[0])) >> 6; 20 | 21 | ReadInput(buffer); 22 | 23 | if(mask) 24 | { 25 | static bool hasPressure = true; 26 | hasPressure = hasPressure? Input::DualshockPressure(pressure, mask, settings, gamepadPlugged) : false; 27 | 28 | if(!hasPressure) 29 | { 30 | //Right, left, up, down 31 | pressureButton[0x00] = (mask & 0x01) && (buttons & 0x20) ? 0x00 : pressureButton[0x00] + settings.pressureRate; 32 | pressureButton[0x01] = (mask & 0x02) && (buttons & 0x80) ? 0x00 : pressureButton[0x01] + settings.pressureRate; 33 | pressureButton[0x02] = (mask & 0x04) && (buttons & 0x10) ? 0x00 : pressureButton[0x02] + settings.pressureRate; 34 | pressureButton[0x03] = (mask & 0x08) && (buttons & 0x40) ? 0x00 : pressureButton[0x03] + settings.pressureRate; 35 | 36 | //triangle, circle, cross, square 37 | pressureButton[0x04] = (mask & 0x10) && (buttons & 0x1000) ? 0x00 : pressureButton[0x04] + settings.pressureRate; 38 | pressureButton[0x05] = (mask & 0x20) && (buttons & 0x2000) ? 0x00 : pressureButton[0x05] + settings.pressureRate; 39 | pressureButton[0x06] = (mask & 0x40) && (buttons & 0x4000) ? 0x00 : pressureButton[0x06] + settings.pressureRate; 40 | pressureButton[0x07] = (mask & 0x80) && (buttons & 0x8000) ? 0x00 : pressureButton[0x07] + settings.pressureRate; 41 | 42 | //l1, r1, l2, r2 43 | pressureButton[0x08] = (mask & 0x100) && (buttons & 0x400) ? 0x00 : pressureButton[0x08] + settings.pressureRate; 44 | pressureButton[0x09] = (mask & 0x200) && (buttons & 0x800) ? 0x00 : pressureButton[0x09] + settings.pressureRate; 45 | pressureButton[0x0A] = (mask & 0x400) && (buttons & 0x100) ? 0x00 : triggerL; 46 | pressureButton[0x0B] = (mask & 0x800) && (buttons & 0x200) ? 0x00 : triggerR; 47 | 48 | for(s32 i = 0; i < 0x0C; i++) 49 | pressureButton[i] = buffer[i+9] = pressureButton[i] > 0xFF ? 0xFF : pressureButton[i] & 0xFF; 50 | } 51 | else 52 | { 53 | for(s32 i = 0; i < 0x0C; i++) 54 | pressureButton[i] = buffer[i+9] = pressure[i]; 55 | } 56 | } 57 | else 58 | memset(&buffer[9], 0x00, 12); 59 | } 60 | 61 | void DualShock2::Cmd1(const u8 data) 62 | { 63 | switch(data) 64 | { 65 | case 0x41: if(bConfig) { 66 | if(padID == ID_DIGITAL) memset(&dataBuffer[3], 0x00, 6); 67 | else memcpy(&dataBuffer[3], pollMask, 6);} 68 | break; 69 | 70 | case 0x42: // Polls common input and handles vibration 71 | if(bConfig) ReadInput(dataBuffer); 72 | else ReadInputPressure(dataBuffer); 73 | break; 74 | 75 | case 0x43: // Toggle config mode, poll input and pressures. 76 | if(bConfig) memset(&dataBuffer[3], 0x00, 6); 77 | else ReadInputPressure(dataBuffer); 78 | break; 79 | 80 | case 0x45: if(bConfig) { // Query model, 5th means LED status 81 | memcpy(&dataBuffer[3], DUALSHOCK2_MODEL, 6); 82 | dataBuffer[5] = padID == ID_DIGITAL? 0x00 : 0x01; } 83 | break; 84 | 85 | case 0x4F: if(bConfig) { // Poll mask 86 | memset(&dataBuffer[3], 0x00, 5); 87 | dataBuffer[8] = 0x5A;} 88 | break; 89 | 90 | default: DualShock::Cmd1(data); 91 | } 92 | } 93 | 94 | void DualShock2::Cmd4(const u8 data) 95 | { 96 | switch(data) 97 | { 98 | case 0x46: if(bConfig) {// Unknown constant part 1 and 2 99 | if(cmdBuffer[3] == 0x00) memcpy(&dataBuffer[4], DUALSHOCK2_ID[0], 5); 100 | else memcpy(&dataBuffer[4], DUALSHOCK2_ID[1], 5);} 101 | break; 102 | 103 | case 0x47: if(bConfig) {//Unknown constant part 3 104 | memcpy(&dataBuffer[4], DUALSHOCK2_ID[2], 5); } 105 | break; 106 | 107 | case 0x4C: if(bConfig) {// Unknown constant part 4 and 5 108 | if(cmdBuffer[3] == 0x00) memcpy(&dataBuffer[4], DUALSHOCK2_ID[3], 5); 109 | else memcpy(&dataBuffer[4], DUALSHOCK2_ID[4], 5);} 110 | break; 111 | 112 | default: DualShock::Cmd4(data); 113 | } 114 | } 115 | 116 | void DualShock2::Cmd8(const u8 data) 117 | { 118 | switch(data) 119 | { 120 | case 0x4F: if(bConfig) { 121 | padID = ID_ANALOG_REDP; 122 | pollMask[0] = cmdBuffer[3]; 123 | pollMask[1] = cmdBuffer[4]; 124 | pollMask[2] = cmdBuffer[5]; } 125 | break; 126 | 127 | default: DualShock::Cmd8(data); 128 | } 129 | } 130 | 131 | void DualShock2::SaveState(PlayStationDeviceState &state) 132 | { 133 | DualShock::SaveState(state); 134 | 135 | memcpy(state.pollMask, pollMask, 6); 136 | memcpy(state.pressureButton, pressureButton, sizeof(pressureButton)); 137 | } 138 | 139 | void DualShock2::LoadState(PlayStationDeviceState state) 140 | { 141 | DualShock::LoadState(state); 142 | 143 | memcpy(pollMask, state.pollMask, 6); 144 | memcpy(pressureButton, state.pressureButton, sizeof(pressureButton)); 145 | } -------------------------------------------------------------------------------- /Pokopom/demul.cpp: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2015 KrossX 2 | * License: http://www.opensource.org/licenses/mit-license.html MIT License 3 | */ 4 | 5 | #include "demul.h" 6 | #include "Input.h" 7 | #include "FileIO.h" 8 | #include "ConfigDialog.h" 9 | 10 | #include 11 | #include 12 | #include 13 | 14 | #ifdef _WIN32 15 | 16 | const wchar_t demul_name[] = L"Pokopom Xinput Pad Plugin"; 17 | 18 | std::ofstream demul_logfile; 19 | 20 | void printfn(std::string fname, int a = 0, int b = 0, int c = 0, int d = 0) 21 | { 22 | if (demul_logfile.is_open()) 23 | { 24 | std::string message = fname; 25 | message.append(" (" + std::to_string(a) + ")"); 26 | message.append(" (" + std::to_string(b) + ")"); 27 | message.append(" (" + std::to_string(c) + ")"); 28 | message.append(" (" + std::to_string(d) + ")\n"); 29 | demul_logfile << message; 30 | } 31 | } 32 | 33 | void stoplog() 34 | { 35 | if (demul_logfile.is_open()) 36 | { 37 | printfn(__FUNCTION__); 38 | demul_logfile.close(); 39 | } 40 | } 41 | 42 | void startlog() 43 | { 44 | return; 45 | 46 | static bool started = false; 47 | 48 | if (!started) 49 | { 50 | started = true; 51 | std::atexit(stoplog); 52 | demul_logfile.open("pokpomlog.txt", std::ios::trunc | std::ios::out); 53 | printfn(__FUNCTION__); 54 | } 55 | } 56 | 57 | DllExport int getType(int number) 58 | { 59 | startlog(); 60 | printfn(__FUNCTION__, number); 61 | return (!number) ? 3 : 0; 62 | } 63 | 64 | DllExport const wchar_t* getName() 65 | { 66 | startlog(); 67 | printfn(__FUNCTION__); 68 | return demul_name; 69 | } 70 | 71 | int func1() { printfn(__FUNCTION__); return 0xFFFFFFFF; } 72 | int func2() { printfn(__FUNCTION__); return 0; } 73 | 74 | RumbleSettings rSettings; 75 | RumbleConfig rConfig; 76 | 77 | u8 AST = 0x13; 78 | u16 AST_ms = 0x13 * 250 + 250; 79 | u8 FreqM, FreqL, FreqH; 80 | 81 | u16 Watchdog_ms = 150; 82 | HANDLE hVibrationThread; 83 | 84 | void StopVibration() 85 | { 86 | Input::StopRumble(settings[0].xinputPort); 87 | } 88 | 89 | void UpdateVibration() 90 | { 91 | bool plugged = true; 92 | s16 intensity = (s16)(rConfig.Mpow - rConfig.Ppow); 93 | 94 | if (intensity == 0) 95 | StopVibration(); 96 | else 97 | { 98 | Input::DreamcastRumble(intensity, rConfig.FREQ > FreqH, rConfig.FREQ < FreqL, 99 | Watchdog_ms, settings[0], plugged, hVibrationThread); 100 | } 101 | } 102 | 103 | #ifdef __linux__ 104 | int __attribute__((fastcall)) func3(int a, int b, int c, int d)// ... rumble? 105 | #endif 106 | #ifdef _WIN32 107 | int __fastcall func3(int a, int b, int c, int d)// ... rumble? 108 | #endif 109 | { 110 | u32 *buffer = (u32*)b; 111 | 112 | if (a == 0x0E) 113 | { 114 | rConfig.RAW = buffer[0]; 115 | UpdateVibration(); 116 | } 117 | 118 | return 0; 119 | } 120 | 121 | 122 | 123 | void func4() { printfn(__FUNCTION__); } 124 | 125 | int func5() { printfn(__FUNCTION__); return 0x7601; } // ???? 126 | #ifdef __linux__ 127 | int __attribute__((fastcall)) func6(u8 a) { printfn(__FUNCTION__, a); return 0; } 128 | #endif 129 | #ifdef _WIN32 130 | int __fastcall func6(u8 a) { printfn(__FUNCTION__, a); return 0; } 131 | #endif 132 | void func7() { printfn(__FUNCTION__); } 133 | #ifdef __linux__ 134 | void __attribute__((fastcall)) func8(int a, int b) 135 | #endif 136 | #ifdef _WIN32 137 | void __fastcall func8(int a, int b) 138 | #endif 139 | { 140 | //printfn(__FUNCTION__, a, b); 141 | bool plugged = true; 142 | Input::DreamcastPoll((u32*)a, settings[0], plugged); 143 | } // READ JOY 144 | 145 | #ifdef __linux__ 146 | void __attribute__((fastcall)) func8b(int a, int b) { printfn(__FUNCTION__, a, b); } // READ JOY 147 | 148 | int __attribute__((fastcall)) func9(int a) { printfn(__FUNCTION__, a); return 0xFFFFFFFF; } // JOYCAPS ? 149 | #endif 150 | #ifdef _WIN32 151 | void __fastcall func8b(int a, int b) { printfn(__FUNCTION__, a, b); } // READ JOY 152 | 153 | int __fastcall func9(int a) { printfn(__FUNCTION__, a); return 0xFFFFFFFF; } // JOYCAPS ? 154 | #endif 155 | 156 | int func10() 157 | { 158 | printfn(__FUNCTION__); 159 | 160 | FileIO::INI_LoadSettings(); 161 | CreateConfigDialog(); 162 | 163 | return 0; 164 | } 165 | 166 | void func11() { printfn(__FUNCTION__); } 167 | int func12() { printfn(__FUNCTION__); return 0; } // Close ? 168 | u8 func13() { printfn(__FUNCTION__); return 1; } 169 | 170 | DllExport char getInterface(u32* demul) 171 | { 172 | startlog(); 173 | printfn(__FUNCTION__, demul[0], demul[4]); 174 | FileIO::INI_LoadSettings(); 175 | 176 | rSettings.RAW = 0x3B07E010; 177 | rConfig.RAW = 0; 178 | 179 | hVibrationThread = nullptr; 180 | StopVibration(); 181 | 182 | FreqM = (rSettings.FM1 + rSettings.FM0) >> 1; 183 | FreqL = (u8)(FreqM * 2.0f / 3.0f); 184 | FreqH = (u8)(FreqM * 1.5f); 185 | 186 | u32 some_var = demul[4]; 187 | 188 | //+2 (8 bytes) diff 230915 -> 221215 189 | demul_interface *di = (demul_interface*)&demul[138 + 2]; 190 | di->func01 = &func1; // 600 191 | 192 | switch (some_var) 193 | { 194 | case 0: 195 | di->func02 = &func2; // 596 196 | di->func03 = &func3; // 592 197 | di->func04 = &func4; // 588 198 | di->func05 = &func5; // 584 199 | di->func08 = &func8; // 572 200 | di->func09 = &func9; // 568 201 | di->func10 = &func10; // 564 202 | di->func11 = &func11; // 560 203 | di->func12 = &func12; // 556 204 | di->func13 = &func13; // 552, CONFIG ? 205 | return 1; 206 | 207 | case 1: 208 | di->func03 = &func3; // 592 209 | di->func04 = &func4; // 588 210 | di->func05 = &func5; // 584 211 | di->func08 = &func8; // 572 212 | di->func09 = &func9; // 568 213 | 214 | case 2: 215 | di->func02 = &func2; // 596 216 | 217 | case 3: 218 | case 4: 219 | case 5: 220 | case 6: 221 | case 7: 222 | case 9: 223 | case 10: 224 | case 11: 225 | di->func06 = &func6; // 580 226 | 227 | case 12: 228 | di->func07 = &func7; // 576 229 | 230 | case 8: 231 | if(some_var == 8) 232 | di->func08 = &func8b; // 572 233 | 234 | di->func10 = &func10; // 564 235 | di->func11 = &func11; // 560 236 | di->func12 = &func12; // 556 237 | di->func13 = &func13; // 552 238 | return 1; 239 | } 240 | 241 | return 0; 242 | } 243 | 244 | #endif 245 | -------------------------------------------------------------------------------- /Pokopom/PSemuPro_Interface.h: -------------------------------------------------------------------------------- 1 | /* 2 | PSEmu Plugin Developer Kit Header definition 3 | 4 | (C)1998 Vision Thing 5 | 6 | This file can be used only to develop PSEmu Plugins 7 | Other usage is highly prohibited. 8 | */ 9 | 10 | 11 | // IMPORTANT!!! 12 | // This file will be used by PSEmu version >= 1.0.3 13 | // so, please, develop Plugins w/o using this header file now 14 | // if you want to add return codes (any) just drop mail to 15 | // duddie@psemu.com 16 | 17 | // 2011 - Messed up by KrossX. 18 | 19 | #pragma once 20 | 21 | namespace emupro 22 | { 23 | // header version 24 | const s32 _PPDK_HEADER_VERSION = 1; 25 | const s32 PLUGIN_VERSION = 1; 26 | 27 | // plugin type returned by PSEgetLibType (types can be merged if plugin is multi type!) 28 | const s32 LT_CDR = 1; 29 | const s32 LT_GPU = 2; 30 | const s32 LT_SPU = 4; 31 | const s32 LT_PAD = 8; 32 | 33 | // every function in DLL if completed sucessfully should return this value 34 | const s32 ERR_SUCCESS = 0; 35 | // undefined error but fatal one, that kills all functionality 36 | const s32 ERR_FATAL = -1; 37 | 38 | 39 | // XXX_Init return values 40 | // Those return values apply to all libraries 41 | 42 | // initialization went OK 43 | const s32 INIT_ERR_SUCCESS = 0; 44 | 45 | // this driver is not configured 46 | const s32 INIT_ERR_NOTCONFIGURED = -2; 47 | 48 | // this driver can not operate properly on this hardware or hardware is not detected 49 | const s32 INIT_ERR_NOHARDWARE = -3; 50 | 51 | 52 | /* GPU PlugIn */ 53 | namespace gpu 54 | { 55 | 56 | // Test return values 57 | 58 | // sucess, everything configured, and went OK. 59 | const s32 ERR_SUCCESS = 0; 60 | 61 | // this driver is not configured 62 | const s32 ERR_NOTCONFIGURED = 1; 63 | 64 | // Query - will be implemented in v2 65 | 66 | typedef struct 67 | { 68 | u32 flags; 69 | u32 status; 70 | HWND window; 71 | u8 reserved[100]; 72 | } QueryS; 73 | 74 | // gpuQueryS.flags 75 | // this driver requests windowed mode, 76 | const s32 FLAGS_WINDOWED = 1; 77 | 78 | // gpuQueryS.status 79 | // this driver cannot operate in this windowed mode 80 | const s32 STATUS_WINDOWWRONG = 1; 81 | 82 | // Query End - will be implemented in v2 83 | } 84 | 85 | 86 | /* CDR PlugIn */ 87 | namespace cdr 88 | { 89 | // Test return values 90 | 91 | // success, everything configured, and went OK. 92 | const s32 ERR_SUCCESS = 0; 93 | 94 | // ERRORS 95 | const s32 ERR = -40; 96 | // this driver is not configured 97 | const s32 ERR_NOTCONFIGURED = ERR - 0; 98 | // if this driver is unable to read data from medium 99 | const s32 ERR_NOREAD = ERR - 1; 100 | 101 | // WARNINGS 102 | const s32 WARN = 40; 103 | // if this driver emulates lame mode ie. can read only 2048 tracks and sector header is emulated 104 | // this might happen to CDROMS that do not support RAW mode reading - surely it will kill many games 105 | const s32 WARN_LAMECD = WARN + 0; 106 | } 107 | 108 | /* SPU PlugIn */ 109 | namespace spu 110 | { 111 | // some info restricted (now!) 112 | 113 | // success, everything configured, and went OK. 114 | const s32 ERR_SUCCESS = 0; 115 | 116 | // ERRORS 117 | // this error might be returned as critical error but none of below 118 | const s32 ERR = -60; 119 | 120 | // this driver is not configured 121 | const s32 ERR_NOTCONFIGURED = ERR - 1; 122 | // this driver failed Init 123 | const s32 ERR_INIT = ERR - 2; 124 | 125 | 126 | // WARNINGS 127 | // this warning might be returned as undefined warning but allowing driver to continue 128 | const s32 WARN = 60; 129 | } 130 | 131 | /* PAD PlugIn */ 132 | namespace pad 133 | { 134 | // PADquery responses (notice - values ORed) 135 | // PSEmu will use them also in PADinit to tell Plugin which Ports will use 136 | // notice that PSEmu will call PADinit and PADopen only once when they are from 137 | // same plugin 138 | 139 | // might be used in port 1 (must support PADreadPort1() function) 140 | const s32 USE_PORT1 = 1; 141 | // might be used in port 2 (must support PADreadPort2() function) 142 | const s32 USE_PORT2 = 2; 143 | 144 | 145 | 146 | // MOUSE SCPH-1030 147 | const s32 TYPE_MOUSE = 1; 148 | // NEGCON - 16 button analog controller SLPH-00001 149 | const s32 TYPE_NEGCON = 2; 150 | // GUN CONTROLLER - gun controller SLPH-00014 from Konami 151 | const s32 TYPE_GUN = 3; 152 | // STANDARD PAD SCPH-1080, SCPH-1150 153 | const s32 TYPE_STANDARD = 4; 154 | // ANALOG JOYSTICK SCPH-1110 155 | const s32 TYPE_ANALOGJOY = 5; 156 | // GUNCON - gun controller SLPH-00034 from Namco 157 | const s32 TYPE_GUNCON = 6; 158 | // ANALOG CONTROLLER SCPH-1150 159 | const s32 TYPE_ANALOGPAD = 7; 160 | 161 | 162 | // success, everything configured, and went OK. 163 | const s32 ERR_SUCCESS = 0; 164 | // general plugin failure (undefined error) 165 | const s32 ERR_FAILURE = -1; 166 | 167 | 168 | // ERRORS 169 | // this error might be returned as critical error but none of below 170 | const s32 ERR = -80; 171 | // this driver is not configured 172 | const s32 ERR_NOTCONFIGURED = ERR - 1; 173 | // this driver failed Init 174 | const s32 ERR_INIT = ERR - 2; 175 | 176 | 177 | // WARNINGS 178 | // this warning might be returned as undefined warning but allowing driver to continue 179 | const s32 WARN = 80; 180 | 181 | 182 | typedef struct 183 | { 184 | // controller type - fill it withe predefined values above 185 | u8 controllerType; 186 | 187 | // status of buttons - every controller fills this field 188 | u16 buttonStatus; 189 | 190 | // for analog pad fill those next 4 bytes 191 | // values are analog in range 0-255 where 128 is center position 192 | u8 rightJoyX, rightJoyY, leftJoyX, leftJoyY; 193 | 194 | // for mouse fill those next 2 bytes 195 | // values are in range -128 - 127 196 | u8 moveX, moveY; 197 | 198 | u8 reserved[91]; 199 | 200 | } DataS; 201 | } 202 | 203 | //Savestates stuff 204 | namespace Savestate 205 | { 206 | const s32 LOAD = 0; 207 | const s32 SAVE = 1; 208 | const s32 QUERY_SIZE = 2; 209 | } 210 | 211 | } -------------------------------------------------------------------------------- /Pokopom/Pokopom.vcxproj.filters: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | {4c20094a-04fd-4df1-a7cd-e472e3475890} 6 | 7 | 8 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF} 9 | cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx 10 | 11 | 12 | {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} 13 | rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms 14 | 15 | 16 | {93995380-89BD-4b04-88EB-625FBE52EBFB} 17 | h;hpp;hxx;hm;inl;inc;xsd 18 | 19 | 20 | {d1dab64c-56a1-4a70-8ee2-7103d24dd2d1} 21 | 22 | 23 | {932760f6-c7ff-4ff5-83b0-0b1b09adda6f} 24 | 25 | 26 | {11bb5839-4261-44c1-a36e-72c509d3e422} 27 | 28 | 29 | {84f30087-addb-4003-8e34-61012555c6b9} 30 | 31 | 32 | {dfaccc45-c85a-4055-abcd-ddacdc88594f} 33 | 34 | 35 | {20d05d85-002f-4b06-9feb-fdb5cd3c0b22} 36 | 37 | 38 | 39 | 40 | General\Headers 41 | 42 | 43 | General\Headers 44 | 45 | 46 | Misc 47 | 48 | 49 | General\Headers 50 | 51 | 52 | General\Headers 53 | 54 | 55 | Misc 56 | 57 | 58 | Systems\Nintendo64 59 | 60 | 61 | Systems\Dreamcast\Headers 62 | 63 | 64 | Systems\Dreamcast\Headers 65 | 66 | 67 | Systems\Dreamcast\Headers 68 | 69 | 70 | Systems\Dreamcast\Headers 71 | 72 | 73 | Resources 74 | 75 | 76 | General\Headers 77 | 78 | 79 | General\Headers 80 | 81 | 82 | General\Headers 83 | 84 | 85 | Systems\Dreamcast\Headers 86 | 87 | 88 | General\Headers 89 | 90 | 91 | Systems\PlayStation\Headers 92 | 93 | 94 | Systems\PlayStation\Headers 95 | 96 | 97 | Systems\PlayStation\Headers 98 | 99 | 100 | General\Headers 101 | 102 | 103 | Systems\Dreamcast\Headers 104 | 105 | 106 | 107 | 108 | General 109 | 110 | 111 | General 112 | 113 | 114 | Systems\Dreamcast 115 | 116 | 117 | Systems\Nintendo64 118 | 119 | 120 | Systems\Nintendo64 121 | 122 | 123 | General 124 | 125 | 126 | General 127 | 128 | 129 | General 130 | 131 | 132 | General 133 | 134 | 135 | General 136 | 137 | 138 | General 139 | 140 | 141 | General 142 | 143 | 144 | General 145 | 146 | 147 | Systems\PlayStation 148 | 149 | 150 | Systems\PlayStation 151 | 152 | 153 | Systems\PlayStation 154 | 155 | 156 | Systems\PlayStation 157 | 158 | 159 | General 160 | 161 | 162 | Systems\Dreamcast 163 | 164 | 165 | Systems\PlayStation 166 | 167 | 168 | 169 | 170 | Resources 171 | 172 | 173 | Misc 174 | 175 | 176 | Misc 177 | 178 | 179 | 180 | 181 | Resources 182 | 183 | 184 | -------------------------------------------------------------------------------- /Pokopom/Zilmar_Devices.cpp: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2012 KrossX 2 | * License: http://www.opensource.org/licenses/mit-license.html MIT License 3 | */ 4 | 5 | #include "General.h" 6 | #include "Zilmar_Devices.h" 7 | #include "Input.h" 8 | #include "FileIO.h" 9 | 10 | #ifdef _WIN32 11 | 12 | //////////////////////////////////////////////////////////////////////// 13 | // General and constructors, etc... 14 | //////////////////////////////////////////////////////////////////////// 15 | 16 | Zilmar_Device::Zilmar_Device(_Settings &settings, Zilmar::CONTROL &control, u8 port) : 17 | set(settings), zControl(control), zPort(port) 18 | { 19 | gamepadPlugged = false; 20 | }; 21 | 22 | N64mempak::N64mempak(u8 port) : zPort(port) 23 | { 24 | if(!Load()) 25 | memset(MEMPAK.RAW8, 0xFF, 0x8000); 26 | }; 27 | 28 | N64controller::N64controller(_Settings &settings, Zilmar::CONTROL &control, u8 port) : 29 | Zilmar_Device(settings, control, port), mempak(port) 30 | { 31 | // 0x00 : No plugin 32 | // 0x01 : Plugin ... plugged 33 | // 0x02 : Plugin uninitialized 34 | // 0x04 : Invalid last Pack I/O address 35 | // 0x80 : EEPROM busy 36 | status.Plugin = 0x01; 37 | 38 | // 0x80 : EEPROM present 39 | // 0x00 : No EEPROM 40 | status.EEPROM = 0x00; 41 | 42 | // 0x01 : Absolute 43 | // 0x02 : Relative 44 | // 0x04 : Gamepad 45 | status.Mode = 0x04 | 0x01; 46 | 47 | bPolled = false; 48 | bRumble = true; 49 | }; 50 | 51 | //////////////////////////////////////////////////////////////////////// 52 | // Generic 53 | //////////////////////////////////////////////////////////////////////// 54 | 55 | void Zilmar_Device::Recheck() 56 | { 57 | gamepadPlugged = Input::Recheck(set.xinputPort); 58 | } 59 | 60 | //////////////////////////////////////////////////////////////////////// 61 | // N64 Controller 62 | //////////////////////////////////////////////////////////////////////// 63 | 64 | 65 | // DataCRC and basis for READ/WRITE_PACK stuff from Mupen64Plus 66 | // http://code.google.com/p/mupen64plus/ 67 | // -. I was getting mad trying to make it work, and I already had 68 | // the CRC wrong. So yay Mupen and OpenSource-ness! =D 69 | 70 | 71 | u8 N64mempak::CRC(u8 *data, s32 iLenght) 72 | { 73 | u8 remainder = data[0]; 74 | 75 | s32 iByte = 1; 76 | u8 bBit = 0; 77 | 78 | while( iByte <= iLenght ) 79 | { 80 | s32 hBit = ((remainder & 0x80) != 0); 81 | remainder = remainder << 1; 82 | 83 | remainder += ( iByte < iLenght && data[iByte] & (0x80 >> bBit )) ? 1 : 0; 84 | 85 | remainder ^= (hBit) ? 0x85 : 0; 86 | 87 | bBit++; 88 | iByte += bBit/8; 89 | bBit %= 8; 90 | } 91 | 92 | return remainder; 93 | } 94 | 95 | void FASTCALL N64mempak::ReadBlock(u8 *data, u16 address, bool rumble) 96 | { 97 | u32 *dest = (u32*)data; 98 | 99 | if(rumble) 100 | { 101 | dest[0] = dest[1] = dest[2] = dest[3] = // 102 | dest[4] = dest[5] = dest[6] = dest[7] = address < 0x400 ? 0 : 0x80808080; 103 | } 104 | else if(address < 0x400) 105 | { 106 | u32 *src = (u32*)MEMPAK.BLOCK[address]; 107 | 108 | dest[0] = src[0]; dest[1] = src[1]; 109 | dest[2] = src[2]; dest[3] = src[3]; 110 | dest[4] = src[4]; dest[5] = src[5]; 111 | dest[6] = src[6]; dest[7] = src[7]; 112 | } 113 | else 114 | { 115 | dest[0] = dest[1] = dest[2] = dest[3] = // 116 | dest[4] = dest[5] = dest[6] = dest[7] = 0; 117 | } 118 | 119 | data[32] = CRC(data, 32); 120 | } 121 | 122 | void FASTCALL N64mempak::WriteBlock(u8 *data, u16 address, bool rumble) 123 | { 124 | u32 *src = (u32*)data; 125 | 126 | if(rumble) 127 | { 128 | // Nothing here! 129 | } 130 | else if(address < 0x400) 131 | { 132 | u32 *dest = (u32*)MEMPAK.BLOCK[address]; 133 | 134 | dest[0] = src[0]; dest[1] = src[1]; 135 | dest[2] = src[2]; dest[3] = src[3]; 136 | dest[4] = src[4]; dest[5] = src[5]; 137 | dest[6] = src[6]; dest[7] = src[7]; 138 | 139 | Save(); 140 | } 141 | 142 | data[32] = CRC(data, 32); 143 | } 144 | 145 | bool N64mempak::Load() { return FileIO::LoadMempak(MEMPAK.RAW8, zPort); } 146 | void N64mempak::Save() { FileIO::SaveMempak(MEMPAK.RAW8, zPort); } 147 | 148 | //////////////////////////////////////////////////////////////////////// 149 | 150 | void FASTCALL N64controller::Command(u8 *cmd) // Input ? 151 | { 152 | // cmd[0] - input length in bytes 153 | // cmd[1] - output length in bytes | also return errors here? 154 | // cmd[2] - actual command 155 | 156 | if(!gamepadPlugged) 157 | { 158 | Recheck(); 159 | 160 | if(!gamepadPlugged) 161 | { 162 | zControl.Present = FALSE; 163 | return; 164 | } 165 | else 166 | zControl.Present = TRUE; 167 | } 168 | 169 | switch(cmd[2]) // in / out, expected length 170 | { 171 | case RAW_GET_STATUS: // 1 / 3 172 | if(cmd[1] != 3) return; 173 | GetStatus(); 174 | break; 175 | 176 | case RAW_READ_KEYS: // 1 / 4 177 | if(cmd[1] != 4) return; 178 | Poll(); 179 | bPolled = true; // for PJ64 180 | break; 181 | 182 | case RAW_READ_PACK: break; // 3 / 33 ? // Handled on Read 183 | 184 | case RAW_WRITE_PACK: // 35 / 1 ? 185 | { 186 | u16 blockAddress = (cmd[3] << 3) | (cmd[4] >> 5); 187 | //u16 crcAddress = cmd[4] & 0x1F; // Wut for? 188 | 189 | //Debug("Pokopom -> WP\t%4X %4X\n", blockAddress, crcAddress); 190 | if (bRumble && blockAddress == 0x600) RumbleIt(cmd[5] != 0); 191 | mempak.WriteBlock(&cmd[5], blockAddress, bRumble); 192 | } 193 | break; 194 | 195 | case RAW_READ_ROM: break; // Handled by the emu? 196 | case RAW_WRITE_ROM: break;// Handled by the emu? 197 | 198 | case RAW_RESET: break; 199 | 200 | default: 201 | //Debug("Pokopom(%d) -> Command\t%2d %2d %02X\n", zPort, cmd[0], cmd[1], cmd[2]); 202 | break; 203 | } 204 | 205 | } 206 | 207 | void FASTCALL N64controller::Read(u8 *cmd) // Output ? 208 | { 209 | // cmd[0] - input length in bytes 210 | // cmd[1] - output length in bytes | also return errors here? 211 | // cmd[2] - actual command 212 | 213 | if(!gamepadPlugged) 214 | { 215 | Recheck(); 216 | if(!gamepadPlugged) 217 | { 218 | zControl.Present = FALSE; 219 | cmd[1] |= RAW_RET_ERROR; 220 | return; 221 | } 222 | else 223 | zControl.Present = TRUE; 224 | } 225 | 226 | switch(cmd[2]) 227 | { 228 | case RAW_GET_STATUS: 229 | if(cmd[1] != 3) { cmd[1] |= RAW_RET_WRONG_SIZE; return; } 230 | cmd[3] = status.Mode; 231 | cmd[4] = status.EEPROM; 232 | cmd[5] = status.Plugin; 233 | break; 234 | 235 | case RAW_READ_KEYS: 236 | if(cmd[1] != 4) { cmd[1] |= RAW_RET_WRONG_SIZE; return; } 237 | 238 | Input::N64rumbleSwitch(set.xinputPort, bRumble, gamepadPlugged); 239 | 240 | if(!bPolled) Poll(); // Let's do a Poll here if there wasn't a command() before. 241 | bPolled = false; // For PJ64 that doesn't seem to use command() much. 242 | 243 | cmd[3] = poll.RAW8[0]; 244 | cmd[4] = poll.RAW8[1]; 245 | cmd[5] = poll.RAW8[2]; 246 | cmd[6] = poll.RAW8[3]; 247 | break; 248 | 249 | case RAW_READ_PACK: 250 | { 251 | u16 blockAddress = (cmd[3] << 3) | (cmd[4] >> 5); 252 | //u16 crcAddress = cmd[4] & 0x1F; // Wut for? 253 | 254 | //Debug("Pokopom -> RP\t%4X %4X\n", blockAddress, crcAddress); 255 | mempak.ReadBlock(&cmd[5], blockAddress, bRumble); 256 | }break; 257 | 258 | case RAW_WRITE_PACK: break; // Handled on Command 259 | 260 | case RAW_READ_ROM: break; // Handled by the emu? 261 | case RAW_WRITE_ROM: break;// Handled by the emu? 262 | 263 | case RAW_RESET: 264 | cmd[3] = status.Mode; 265 | cmd[4] = status.EEPROM; 266 | cmd[5] = status.Plugin; 267 | break; 268 | 269 | default: 270 | //Debug("Pokopom(%d) -> Read\t%2d %2d %02X\n", zPort, cmd[0], cmd[1], cmd[2]); 271 | cmd[1] |= RAW_RET_WRONG_SIZE; 272 | } 273 | } 274 | 275 | extern void FASTCALL N64controllerPoll(u8 *outBuffer, _Settings &set, bool &gamepadPlugged); 276 | 277 | void N64controller::Poll() 278 | { 279 | Input::N64controllerPoll(poll.RAW8, set, gamepadPlugged); 280 | } 281 | 282 | void N64controller::GetStatus() 283 | { 284 | } 285 | 286 | void N64controller::RumbleIt(bool on) 287 | { 288 | Input::N64rumble(on, set, gamepadPlugged); 289 | } 290 | 291 | #endif //WIN32 292 | -------------------------------------------------------------------------------- /Pokopom/Pokopom.vcxproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Debug 6 | Win32 7 | 8 | 9 | Release 10 | Win32 11 | 12 | 13 | 14 | {25BE40B9-3ADC-4163-B055-AC71B856A9C3} 15 | Pokopom 16 | 8.1 17 | 18 | 19 | 20 | DynamicLibrary 21 | true 22 | Unicode 23 | v140_xp 24 | 25 | 26 | DynamicLibrary 27 | false 28 | true 29 | Unicode 30 | v140_xp 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | padPokopom 44 | 45 | 46 | padPokopom 47 | 48 | 49 | 50 | Level4 51 | Disabled 52 | true 53 | 54 | 55 | true 56 | Exports.def 57 | UxTheme.lib;%(AdditionalDependencies) 58 | 59 | 60 | copy "$(SolutionDir)README" "$(TargetDir)Readme.txt" /Y 61 | 62 | 63 | 64 | 65 | Level4 66 | Full 67 | true 68 | true 69 | AnySuitable 70 | Speed 71 | StreamingSIMDExtensions2 72 | Fast 73 | 4100;4201;4996 74 | true 75 | 76 | 77 | true 78 | true 79 | true 80 | Exports.def 81 | UxTheme.lib;%(AdditionalDependencies) 82 | Windows 83 | 84 | 85 | copy "$(SolutionDir)README" "$(TargetDir)Readme.txt" /Y 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | true 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | true 107 | 108 | 109 | 110 | true 111 | 112 | 113 | true 114 | 115 | 116 | true 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | true 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | 141 | 142 | 143 | 144 | 145 | 146 | 147 | 148 | 149 | 150 | 151 | 152 | 153 | 154 | 155 | 156 | 157 | 158 | 159 | 160 | 161 | -------------------------------------------------------------------------------- /Pokopom/Pokopom.rc: -------------------------------------------------------------------------------- 1 | // Generated by ResEdit 1.6.2 2 | // Copyright (C) 2006-2014 3 | // http://www.resedit.net 4 | 5 | #include 6 | #include 7 | #include 8 | #include "resource.h" 9 | 10 | 11 | 12 | 13 | // 14 | // Bitmap resources 15 | // 16 | LANGUAGE LANG_NEUTRAL, SUBLANG_NEUTRAL 17 | IDB_BITMAP1 BITMAP "Background.bmp" 18 | 19 | 20 | 21 | // 22 | // Dialog resources 23 | // 24 | LANGUAGE LANG_NEUTRAL, SUBLANG_NEUTRAL 25 | IDD_CONFIG DIALOGEX 0, 0, 607, 220 26 | STYLE DS_MODALFRAME | DS_SHELLFONT | WS_CAPTION | WS_POPUP | WS_SYSMENU 27 | CAPTION "Pokopom Settings" 28 | FONT 8, "MS Shell Dlg", 400, 0, 1 29 | { 30 | DEFPUSHBUTTON "Restore Defaults", IDRESET, 54, 203, 66, 14, 0, WS_EX_LEFT 31 | PUSHBUTTON "Cancel", ID_CANCEL, 550, 203, 50, 14, 0, WS_EX_LEFT 32 | CONTROL "", IDC_TAB1, WC_TABCONTROL, 0, 54, 7, 423, 191, WS_EX_LEFT 33 | CONTROL IDB_BITMAP1, IDC_STATIC, WC_STATIC, SS_BITMAP, 0, 0, 45, 220, WS_EX_LEFT 34 | PUSHBUTTON "OK", ID_OK, 500, 203, 50, 14, 0, WS_EX_LEFT 35 | LTEXT "KrossX's Magical Tools", IDC_STATIC, 502, 80, 71, 8, WS_DISABLED | SS_LEFT, WS_EX_LEFT 36 | GROUPBOX "Profiles", IDC_STATIC, 478, 15, 122, 47, 0, WS_EX_LEFT 37 | COMBOBOX IDC_COMBO_PROFILES, 482, 27, 115, 30, WS_TABSTOP | WS_VSCROLL | WS_DISABLED | CBS_DROPDOWN | CBS_SORT, WS_EX_LEFT 38 | PUSHBUTTON "Save", IDC_PROFILE_SAVE, 482, 43, 50, 14, WS_DISABLED, WS_EX_LEFT 39 | PUSHBUTTON "Delete", IDC_PROFILE_DELETE, 548, 43, 50, 14, WS_DISABLED, WS_EX_LEFT 40 | GROUPBOX "General", IDC_STATIC, 478, 119, 122, 79, 0, WS_EX_LEFT 41 | AUTOCHECKBOX "Prevent Screensaver", IDC_SCREENSAVER, 484, 149, 83, 10, 0, WS_EX_LEFT 42 | AUTO3STATE "Multitap (requires restart)", IDC_MULTITAP, 484, 165, 99, 10, 0, WS_EX_LEFT 43 | LTEXT "(krossx@live.com)", IDC_STATIC, 508, 90, 60, 8, WS_DISABLED | SS_LEFT, WS_EX_LEFT 44 | AUTOCHECKBOX "Above normal process priority", IDC_PROCPRIORITY, 484, 133, 111, 10, 0, WS_EX_LEFT 45 | AUTOCHECKBOX "Swap Ports Enabled (Key 0)", IDC_SWAPPORTS, 484, 181, 105, 10, 0, WS_EX_LEFT 46 | } 47 | 48 | 49 | 50 | LANGUAGE LANG_NEUTRAL, SUBLANG_NEUTRAL 51 | IDD_INTAB DIALOGEX 55, 20, 420, 175 52 | STYLE DS_CONTROL | DS_SHELLFONT | WS_CHILDWINDOW | WS_SYSMENU 53 | EXSTYLE WS_EX_TRANSPARENT 54 | FONT 8, "MS Shell Dlg", 400, 0, 1 55 | { 56 | GROUPBOX "Left Stick", IDC_STATIC, 7, 64, 134, 52, 0, WS_EX_LEFT 57 | LTEXT "Axis X", IDC_STATIC, 15, 80, 20, 8, SS_LEFT, WS_EX_LEFT 58 | LTEXT "Axis Y", IDC_STATIC, 15, 96, 20, 8, SS_LEFT, WS_EX_LEFT 59 | COMBOBOX IDC_COMBO_LX, 40, 77, 64, 33, WS_VSCROLL | CBS_DROPDOWNLIST, WS_EX_LEFT 60 | COMBOBOX IDC_COMBO_LY, 40, 93, 64, 33, WS_VSCROLL | CBS_DROPDOWNLIST, WS_EX_LEFT 61 | AUTOCHECKBOX "Flip", IDC_INVERT_LX, 110, 80, 27, 10, NOT WS_TABSTOP, WS_EX_LEFT 62 | AUTOCHECKBOX "Flip", IDC_INVERT_LY, 110, 96, 27, 10, NOT WS_TABSTOP, WS_EX_LEFT 63 | GROUPBOX "Right Stick", IDC_STATIC, 7, 117, 134, 52, 0, WS_EX_LEFT 64 | LTEXT "Axis X", IDC_STATIC, 15, 134, 20, 8, SS_LEFT, WS_EX_LEFT 65 | LTEXT "Axis Y", IDC_STATIC, 15, 150, 20, 8, SS_LEFT, WS_EX_LEFT 66 | COMBOBOX IDC_COMBO_RX, 41, 131, 64, 37, WS_VSCROLL | CBS_DROPDOWNLIST, WS_EX_LEFT 67 | COMBOBOX IDC_COMBO_RY, 41, 147, 64, 36, WS_VSCROLL | CBS_DROPDOWNLIST, WS_EX_LEFT 68 | AUTOCHECKBOX "Flip", IDC_INVERT_RX, 111, 134, 27, 10, NOT WS_TABSTOP, WS_EX_LEFT 69 | AUTOCHECKBOX "Flip", IDC_INVERT_RY, 111, 150, 27, 10, NOT WS_TABSTOP, WS_EX_LEFT 70 | GROUPBOX "XInput Controller", IDC_STATIC, 7, 7, 67, 39, 0, WS_EX_LEFT 71 | AUTORADIOBUTTON "#1", IDC_XINPUT1, 15, 18, 25, 10, WS_GROUP, WS_EX_LEFT 72 | AUTORADIOBUTTON "#2", IDC_XINPUT2, 43, 18, 25, 10, 0, WS_EX_LEFT 73 | AUTORADIOBUTTON "#3", IDC_XINPUT3, 15, 32, 25, 10, 0, WS_EX_LEFT 74 | AUTORADIOBUTTON "#4", IDC_XINPUT4, 43, 32, 25, 10, 0, WS_EX_LEFT 75 | GROUPBOX "Default Mode", IDC_STATIC, 75, 7, 57, 39, 0, WS_EX_LEFT 76 | AUTORADIOBUTTON "Digital", IDC_MODE_DIGITAL, 82, 18, 32, 10, WS_GROUP, WS_EX_LEFT 77 | AUTORADIOBUTTON "Analog", IDC_MODE_ANALOG, 82, 32, 38, 10, 0, WS_EX_LEFT 78 | GROUPBOX "Misc", IDC_STATIC, 133, 7, 280, 39, 0, WS_EX_LEFT 79 | AUTOCHECKBOX "Guitar", IDC_GUITAR, 139, 18, 34, 10, NOT WS_TABSTOP, WS_EX_LEFT 80 | LTEXT "Rumble", IDC_STATIC, 17, 50, 24, 8, SS_LEFT, WS_EX_LEFT 81 | CONTROL "", IDC_SLIDER_RUMBLE, TRACKBAR_CLASS, TBS_BOTH | TBS_NOTICKS, 47, 47, 334, 15, WS_EX_LEFT 82 | LTEXT "100%", IDC_TEXT_RUMBLE, 383, 50, 20, 8, SS_LEFT, WS_EX_RIGHT 83 | LTEXT "Deadzone", IDC_STATIC, 147, 72, 33, 8, SS_LEFT, WS_EX_LEFT 84 | CONTROL "", IDC_SLIDER_DEADZONE, TRACKBAR_CLASS, TBS_BOTH | TBS_NOTICKS, 195, 69, 185, 15, WS_EX_LEFT 85 | LTEXT "100%", IDC_TEXT_DEADZONE, 383, 72, 20, 8, SS_LEFT, WS_EX_RIGHT 86 | LTEXT "Anti Deadzone", IDC_STATIC, 147, 88, 48, 8, SS_LEFT, WS_EX_LEFT 87 | CONTROL "", IDC_SLIDER_ANTIDEADZONE, TRACKBAR_CLASS, TBS_BOTH | TBS_NOTICKS, 195, 84, 185, 15, WS_EX_LEFT 88 | LTEXT "100%", IDC_TEXT_ANTIDEADZONE, 383, 88, 20, 8, SS_LEFT, WS_EX_RIGHT 89 | LTEXT "Linearity", IDC_STATIC, 147, 104, 28, 8, SS_LEFT, WS_EX_LEFT 90 | CONTROL "", IDC_SLIDER_LINEARITY, TRACKBAR_CLASS, TBS_BOTH | TBS_NOTICKS, 195, 99, 185, 15, WS_EX_LEFT 91 | LTEXT "100%", IDC_TEXT_LINEARITY, 383, 104, 20, 8, SS_LEFT, WS_EX_RIGHT 92 | AUTOCHECKBOX "Green Analog", IDC_ANALOG_GREEN, 182, 18, 56, 10, NOT WS_TABSTOP, WS_EX_LEFT 93 | AUTOCHECKBOX "Disabled", IDC_DISABLED, 139, 32, 38, 10, NOT WS_TABSTOP, WS_EX_LEFT 94 | GROUPBOX "", IDC_STATIC, 142, 64, 271, 52, 0, WS_EX_LEFT 95 | GROUPBOX "", IDC_STATIC, 142, 117, 271, 52, 0, WS_EX_LEFT 96 | LTEXT "Deadzone", IDC_STATIC, 147, 125, 33, 8, SS_LEFT, WS_EX_LEFT 97 | CONTROL "", IDC_SLIDER_DEADZONE2, TRACKBAR_CLASS, TBS_BOTH | TBS_NOTICKS, 195, 122, 185, 15, WS_EX_LEFT 98 | LTEXT "100%", IDC_TEXT_DEADZONE2, 383, 125, 20, 8, SS_LEFT, WS_EX_RIGHT 99 | LTEXT "Anti Deadzone", IDC_STATIC, 147, 140, 48, 8, SS_LEFT, WS_EX_LEFT 100 | CONTROL "", IDC_SLIDER_ANTIDEADZONE2, TRACKBAR_CLASS, TBS_BOTH | TBS_NOTICKS, 195, 137, 185, 15, WS_EX_LEFT 101 | LTEXT "100%", IDC_TEXT_ANTIDEADZONE2, 383, 140, 20, 8, SS_LEFT, WS_EX_RIGHT 102 | LTEXT "Linearity", IDC_STATIC, 147, 156, 28, 8, SS_LEFT, WS_EX_LEFT 103 | CONTROL "", IDC_SLIDER_LINEARITY2, TRACKBAR_CLASS, TBS_BOTH | TBS_NOTICKS, 195, 152, 185, 15, WS_EX_LEFT 104 | LTEXT "100%", IDC_TEXT_LINEARITY2, 383, 156, 20, 8, SS_LEFT, WS_EX_RIGHT 105 | GROUPBOX "", IDC_STATIC, 7, 42, 406, 22, 0, WS_EX_LEFT 106 | AUTOCHECKBOX "Lock Sliders", IDC_LOCKSLIDERS, 182, 32, 50, 10, 0, WS_EX_LEFT 107 | AUTOCHECKBOX "4-way Buttons > Stick", IDC_4WAYSTICK, 243, 18, 83, 10, 0, WS_EX_LEFT 108 | AUTOCHECKBOX "Swap [X] [O] Buttons", IDC_SWAPXO, 243, 32, 80, 10, 0, WS_EX_LEFT 109 | AUTOCHECKBOX "Stick Swap Enabled", IDC_SWAPSTICKS, 332, 18, 77, 10, 0, WS_EX_LEFT 110 | } 111 | 112 | 113 | 114 | // 115 | // Version Information resources 116 | // 117 | LANGUAGE LANG_NEUTRAL, SUBLANG_NEUTRAL 118 | VS_VERSION_INFO VERSIONINFO 119 | FILEVERSION 2,1,0,0 120 | PRODUCTVERSION 2,1,0,0 121 | FILEOS VOS_NT_WINDOWS32 122 | FILETYPE VFT_DLL 123 | FILESUBTYPE VFT2_UNKNOWN 124 | FILEFLAGSMASK 0x0000003F 125 | FILEFLAGS 0x00000000 126 | { 127 | BLOCK "StringFileInfo" 128 | { 129 | BLOCK "040001B5" 130 | { 131 | VALUE "CompanyName", "KrossX's Magical Tools" 132 | VALUE "FileDescription", "Pokopom XInput Pad Plugin" 133 | VALUE "FileVersion", "2.1.0.0" 134 | VALUE "InternalName", "padPokopom.dll" 135 | VALUE "LegalCopyright", "Copyright (C) 2012" 136 | VALUE "OriginalFilename", "padPokopom.dll" 137 | VALUE "ProductName", "Pokopom XInput Pad Plugin" 138 | VALUE "ProductVersion", "2.1.0.0" 139 | } 140 | } 141 | BLOCK "VarFileInfo" 142 | { 143 | VALUE "Translation", 0x0400, 0x01B5 144 | } 145 | } 146 | -------------------------------------------------------------------------------- /Pokopom/Zilmar.cpp: -------------------------------------------------------------------------------- 1 | /********************************************************************************** 2 | Based on... 3 | 4 | Common Controller plugin spec, version #1.1 maintained by 5 | zilmar (zilmar@emulation64.com) 6 | 7 | All questions or suggestions should go through the emutalk plugin forum. 8 | http://www.emutalk.net/cgi-bin/ikonboard/ikonboard.cgi?s=3bd272222f66ffff;act=SF;f=20 9 | **********************************************************************************/ 10 | 11 | #include "General.h" 12 | #include "Zilmar_Devices.h" 13 | #include "FileIO.h" 14 | #include "ConfigDialog.h" 15 | //#include "ConsoleOutput.h" 16 | #include "Input.h" 17 | 18 | #ifdef _WIN32 19 | 20 | Zilmar::CONTROL_INFO * zilmarInfo = NULL; 21 | Zilmar_Device * zController[4] = {NULL, NULL, NULL, NULL}; 22 | 23 | /************************************************************************************ 24 | Function: GetDllInfo 25 | 26 | Purpose: This function allows the emulator to gather information about the dll by 27 | filling in the PluginInfo structure. 28 | 29 | input: A pointer to a PLUGIN_INFO stucture that needs to be filled by the function. 30 | *************************************************************************************/ 31 | DllExport void CALL GetDllInfo(Zilmar::PLUGIN_INFO *PluginInfo) 32 | { 33 | //Debug("Pokopom -> GetDLLInfo\n"); 34 | 35 | strcpy(PluginInfo->Name, "Pokopom XInput Plugin v2.1"); 36 | PluginInfo->Type = Zilmar::PLUGIN_TYPE_CONTROLLER; 37 | PluginInfo->Version = Zilmar::INTERFACE_VERSION; 38 | 39 | //GimmeConsole(); 40 | } 41 | 42 | /************************************************************************************ 43 | Function: InitiateControllers 44 | 45 | Purpose: This function initialises how each of the controllers should be handled. 46 | 47 | input: - The handle to the main window. (wut? oh 1.0 stuff) 48 | - A controller structure that needs to be filled for the emulator to know 49 | how to handle each controller. 50 | *************************************************************************************/ 51 | DllExport void CALL InitiateControllers(HWND hMain, Zilmar::CONTROL Controls[4]) 52 | { 53 | // 1.0 seems to be the supported version around. 54 | 55 | //Debug("Pokopom -> InitControllers\n"); 56 | 57 | zilmarInfo = new Zilmar::CONTROL_INFO; 58 | zilmarInfo->hMainWindow = hMain; 59 | zilmarInfo->Controls = Controls; 60 | 61 | FileIO::INI_LoadSettings(); 62 | 63 | for(u8 i = 0; i < 4; i++) 64 | { 65 | zilmarInfo->Controls[i].Plugin = Zilmar::PLUGIN_RAW; 66 | zilmarInfo->Controls[i].Present = TRUE; 67 | zilmarInfo->Controls[i].RawData = TRUE; 68 | 69 | zController[i] = new N64controller(settings[i], zilmarInfo->Controls[i], i); 70 | } 71 | 72 | } 73 | 74 | /************************************************************************************ 75 | Function: CloseDLL 76 | 77 | Purpose: This function is called when the emulator is closing down allowing the dll 78 | to de-initialise. 79 | *************************************************************************************/ 80 | 81 | DllExport void CALL CloseDLL() 82 | { 83 | //Debug("Pokopom -> CloseDLL\n"); 84 | 85 | if(zilmarInfo) 86 | { 87 | delete zilmarInfo; 88 | zilmarInfo = NULL; 89 | } 90 | 91 | for(u8 i = 0; i < 4; i++) if(zController[i]) 92 | { 93 | delete zController[i]; 94 | zController[i] = NULL; 95 | } 96 | } 97 | 98 | /************************************************************************************ 99 | Function: DllConfig 100 | 101 | Purpose: This function is optional function that is provided to allow the user to 102 | configure the dll. 103 | 104 | input: A handle to the window that calls this function. 105 | *************************************************************************************/ 106 | DllExport void CALL DllConfig(HWND hParent) 107 | { 108 | //Debug("Pokopom -> DLLConfig\n"); 109 | 110 | FileIO::INI_LoadSettings(); 111 | CreateConfigDialog(); 112 | } 113 | 114 | /************************************************************************************ 115 | Function: DllAbout 116 | 117 | Purpose: This function is optional function that is provided to give further 118 | information about the DLL. 119 | 120 | input: A handle to the window that calls this function. 121 | *************************************************************************************/ 122 | DllExport void CALL DllAbout(HWND hParent) 123 | { 124 | MessageBox(hParent, L"Pokopom XInput Plugin - KrossX © 2012", L"About...", MB_OK); 125 | } 126 | 127 | /************************************************************************************ 128 | Function: DllTest 129 | 130 | Purpose: This function is optional function that is provided to allow the user to 131 | test the dll. 132 | 133 | input: A handle to the window that calls this function. 134 | *************************************************************************************/ 135 | DllExport void CALL DllTest(HWND hParent) 136 | { 137 | MessageBox(hParent, L"Message box test successful!", L"Test...", MB_OK); 138 | } 139 | 140 | /************************************************************************************ 141 | Function: RomOpen 142 | 143 | Purpose: This function is called when a rom is open. (from the emulation thread) 144 | *************************************************************************************/ 145 | DllExport void CALL RomOpen() 146 | { 147 | //Debug("Pokopom -> RomOpen\n"); 148 | //GimmeConsole(); 149 | Input::Pause(false); 150 | KeepAwake(KEEPAWAKE_INIT); 151 | } 152 | 153 | /************************************************************************************ 154 | Function: RomClosed 155 | 156 | Purpose: This function is called when a rom is closed. 157 | *************************************************************************************/ 158 | DllExport void CALL RomClosed() 159 | { 160 | //Debug("Pokopom -> RomClosed\n"); 161 | Input::Pause(true); 162 | KeepAwake(KEEPAWAKE_CLOSE); 163 | } 164 | 165 | 166 | /************************************************************************************ 167 | Function: GetKeys 168 | 169 | Purpose: To get the current state of the controllers buttons. 170 | 171 | input: - Controller Number (0 to 3). 172 | - A pointer to a BUTTONS structure to be filled with the controller state. 173 | *************************************************************************************/ 174 | DllExport void CALL GetKeys(s32 port, Zilmar::BUTTONS *keys) 175 | { 176 | // Only raw here... 177 | //Debug("Pokopom -> GetKeys\n"); 178 | } 179 | 180 | /************************************************************************************ 181 | Function: ControllerCommand 182 | 183 | Purpose: To process the raw data that has just been sent to a specific controller. 184 | 185 | input: - Controller Number (0 to 3) and -1 signalling end of processing the pif ram. 186 | - Pointer of data to be processed. 187 | 188 | note: This function is only needed if the DLL is allowing raw data, or the plugin 189 | is set to raw. The data that is being processed looks like this: 190 | 191 | initilize controller: 01 03 00 FF FF FF 192 | read controller: 01 04 01 FF FF FF FF 193 | *************************************************************************************/ 194 | 195 | DllExport void CALL ControllerCommand(s32 port, u8 *cmd) 196 | { 197 | if(port < 0 || cmd == NULL) return; 198 | //Debug("Pokopom -> ControllerCommand\t(%2d) | %02X\n", port, cmd[2]); 199 | zController[port]->Command(cmd); 200 | } 201 | 202 | /************************************************************************************ 203 | Function: ReadController 204 | 205 | Purpose: To process the raw data in the pif ram that is about to be read. 206 | 207 | input: - Controller Number (0 to 3) and -1 signalling end of processing the pif ram. 208 | - Pointer of data to be processed. 209 | 210 | note: This function is only needed if the DLL is allowing raw data. 211 | *************************************************************************************/ 212 | DllExport void CALL ReadController(s32 port, u8 *cmd) 213 | { 214 | if(port < 0 || cmd == NULL) return; 215 | //Debug("Pokopom -> ReadController\t(%2d) | %02X\n", port, cmd[2]); 216 | zController[port]->Read(cmd); 217 | } 218 | 219 | /************************************************************************************ 220 | Function: WM_KeyDown 221 | 222 | Purpose: To pass the WM_KeyDown message from the emulator to the plugin. 223 | 224 | input: wParam and lParam of the WM_KEYDOWN message. 225 | *************************************************************************************/ 226 | DllExport void CALL WM_KeyDown(WPARAM wParam, LPARAM lParam) 227 | { 228 | } 229 | 230 | /************************************************************************************ 231 | Function: WM_KeyUp 232 | 233 | Purpose: To pass the WM_KEYUP message from the emulator to the plugin. 234 | 235 | input: wParam and lParam of the WM_KEYDOWN message. 236 | *************************************************************************************/ 237 | DllExport void CALL WM_KeyUp(WPARAM wParam, LPARAM lParam) 238 | { 239 | } 240 | 241 | #endif //WIN32 242 | -------------------------------------------------------------------------------- /Pokopom/playstation_dualshock.cpp: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2012 KrossX 2 | * License: http://www.opensource.org/licenses/mit-license.html MIT License 3 | */ 4 | 5 | #include "General.h" 6 | #include "playstation_codes.h" 7 | #include "playstation_devices.h" 8 | #include "Input.h" 9 | 10 | #include "FileIO.h" 11 | 12 | //////////////////////////////////////////////////////////////////////// 13 | // PlayStation Device 14 | //////////////////////////////////////////////////////////////////////// 15 | 16 | PlayStationDevice::PlayStationDevice(_Settings &config, u16 bufferSize) : 17 | settings(config), sizeBuffer(bufferSize) 18 | { 19 | gamepadPlugged = false; 20 | 21 | cmdBuffer = new u8[sizeBuffer]; 22 | dataBuffer = new u8[sizeBuffer]; 23 | } 24 | 25 | PlayStationDevice::~PlayStationDevice() 26 | { 27 | delete cmdBuffer; 28 | delete dataBuffer; 29 | 30 | cmdBuffer = dataBuffer = NULL; 31 | } 32 | 33 | void PlayStationDevice::Recheck() 34 | { 35 | gamepadPlugged = Input::Recheck(settings.xinputPort); 36 | } 37 | 38 | void PlayStationDevice::SetPortX(u8 p) 39 | { 40 | port = p; 41 | DebugPrint("[%d] -> XInputPort [%d]", port, settings.xinputPort); 42 | } 43 | 44 | //////////////////////////////////////////////////////////////////////// 45 | // DualShock 46 | //////////////////////////////////////////////////////////////////////// 47 | 48 | void DualShock::Reset() 49 | { 50 | memset(dataBuffer, 0xFF, sizeBuffer); 51 | memset(cmdBuffer, 0x00, sizeBuffer); 52 | 53 | dataBuffer[2] = 0x5A; 54 | 55 | padDefault = settings.defaultAnalog ? (settings.greenAnalog ? ID_ANALOG_GREEN : ID_ANALOG_RED) : ID_DIGITAL; 56 | padID = padDefault; 57 | 58 | buttons = buttonsStick = 0xFFFF; 59 | analogL = analogR = 0x7F7F; 60 | triggerL = triggerR = 0x00; 61 | 62 | motorMapS = 0xFF; 63 | motorMapL = 0xFF; 64 | 65 | gamepadPlugged = false; 66 | bConfig = bModeLock = false; 67 | } 68 | 69 | DualShock::DualShock(_Settings &config, u16 bsize): PlayStationDevice(config, bsize) 70 | { 71 | Reset(); 72 | DebugPrint("XInputPort [%d]", settings.xinputPort); 73 | } 74 | 75 | u8 DualShock::command(const u32 counter, const u8 data) 76 | { 77 | static bool loop = false; 78 | 79 | if(!gamepadPlugged) 80 | { 81 | if (counter == 0) 82 | { 83 | Recheck(); 84 | loop = true; 85 | } 86 | 87 | if (!gamepadPlugged) 88 | { 89 | return loop? 0x00 : 0xFF; 90 | } 91 | else 92 | { 93 | padID = padDefault; 94 | } 95 | } 96 | 97 | loop = false; 98 | 99 | if (counter >= sizeBuffer) 100 | { 101 | printf("Pokopom: Out of Bound Buffer ERROR! [%02d:%02d]\n", sizeBuffer, counter); 102 | return 0x00; 103 | } 104 | 105 | cmdBuffer[counter] = data; 106 | 107 | switch(counter) 108 | { 109 | case 0x00: Cmd0(); break; 110 | 111 | case 0x01: 112 | dataBuffer[1] = bConfig? ID_CONFIG : padID; 113 | Cmd1(cmdBuffer[1]); 114 | break; 115 | 116 | case 0x02: dataBuffer[2] = 0x5A; break; 117 | 118 | case 0x04:Cmd4(cmdBuffer[1]); break; 119 | case 0x08:Cmd8(cmdBuffer[1]); break; 120 | } 121 | 122 | return dataBuffer[counter]; 123 | } 124 | 125 | void DualShock::ReadInput(u8 *buffer) 126 | { 127 | poll(); 128 | 129 | if(padID == ID_DIGITAL) 130 | { 131 | buffer[3] = buttonsStick & 0xFF; 132 | buffer[4] = buttonsStick >> 8; 133 | memset(&buffer[5], 0xFF, 4); 134 | } 135 | else 136 | { 137 | buffer[3] = buttons & 0xFF; 138 | buffer[4] = buttons >> 8; 139 | 140 | buffer[5] = analogR & 0xFF; 141 | buffer[6] = analogR >> 8; 142 | buffer[7] = analogL & 0xFF; 143 | buffer[8] = analogL >> 8; 144 | } 145 | } 146 | 147 | void DualShock::SetVibration() 148 | { 149 | motorMapS = motorMapL = 0xFF; 150 | 151 | for(u8 i = 3; i<9; i++) 152 | { 153 | if(cmdBuffer[i] == 0x00) motorMapS = i - 3; 154 | if(cmdBuffer[i] == 0x01) motorMapL = i - 3; 155 | } 156 | } 157 | 158 | extern u8 multitap; 159 | bool bPressed[4] = {false}; 160 | 161 | void DualShock::Cmd0() 162 | { 163 | if (!gamepadPlugged) 164 | { 165 | Input::SetAnalogLed(port, true); 166 | } 167 | else 168 | { 169 | if (!bModeLock) 170 | { 171 | bool analogPressed = Input::CheckAnalogToggle(settings.xinputPort); 172 | 173 | if (!bPressed[port] && analogPressed) 174 | { 175 | if (padID == ID_DIGITAL) 176 | { 177 | padID = settings.greenAnalog ? ID_ANALOG_GREEN : ID_ANALOG_RED; 178 | //Debug("Pokopom -> [%d] Switched to analog mode (%X).\n", port, padID); 179 | } 180 | else 181 | { 182 | padID = (u8)ID_DIGITAL; 183 | //Debug("Pokopom -> [%d] Switched to digital mode (%X).\n", port, padID); 184 | } 185 | 186 | bPressed[port] = true; 187 | } 188 | else if (bPressed[port] && !analogPressed) 189 | { 190 | bPressed[port] = false; 191 | } 192 | } 193 | 194 | Input::SetAnalogLed(port, padID == ID_DIGITAL); 195 | } 196 | } 197 | 198 | void DualShock::Cmd1(const u8 data) 199 | { 200 | switch(data) 201 | { 202 | case 0x40: if(bConfig) memcpy(&dataBuffer[3], WTF, 6); // WTF ???!!! 203 | 204 | case 0x41: break; 205 | 206 | case 0x42: // Read_Data 207 | if(bConfig) memset(&dataBuffer[3], 0xFF, 6); 208 | else ReadInput(dataBuffer); 209 | break; 210 | 211 | case 0x43: // Config mode 212 | if(bConfig) memset(&dataBuffer[3], 0x00, 6); 213 | else ReadInput(dataBuffer); 214 | break; 215 | 216 | case 0x44: // Set mode and lock 217 | memset(&dataBuffer[3], 0x00, 6); 218 | break; 219 | 220 | case 0x45: if(bConfig) { // Query model, 5th means LED status 221 | memcpy(&dataBuffer[3], DUALSHOCK2_MODEL, 6); // Using DS2 Model for now 222 | dataBuffer[5] = padID == ID_DIGITAL? 0x00 : 0x01; } 223 | break; 224 | 225 | case 0x46: 226 | case 0x47: 227 | if(bConfig) dataBuffer[3] =0x00; 228 | break; 229 | 230 | case 0x48: break; 231 | case 0x49: break; 232 | case 0x4A: break; 233 | case 0x4B: break; 234 | 235 | case 0x4C: 236 | if(bConfig) dataBuffer[3] = 0x00; 237 | break; 238 | 239 | case 0x4D: if(bConfig) { // Sets which bytes will be for vibration on cmd42 240 | dataBuffer[3] = motorMapS; 241 | dataBuffer[4] = motorMapL; 242 | memset(&dataBuffer[5], 0xFF, 4); } 243 | break; 244 | 245 | case 0x4E: break; 246 | case 0x4F: break; 247 | } 248 | } 249 | 250 | void DualShock::Cmd4(const u8 data) 251 | { 252 | switch(data) 253 | { 254 | case 0x40: break; 255 | case 0x41: break; 256 | case 0x42: 257 | if(padID == ID_DIGITAL) 258 | vibration(motorMapS == 0xFF ? 0 : cmdBuffer[motorMapS + 3], 259 | motorMapL == 0xFF ? 0 : cmdBuffer[motorMapL + 3]); 260 | break; 261 | 262 | case 0x43: // Config mode 263 | bConfig = cmdBuffer[3] == 1; 264 | break; 265 | 266 | case 0x44: if(bConfig) {// Set mode and lock 267 | padID = cmdBuffer[3] == 0x01 ? ID_ANALOG_RED : ID_DIGITAL; 268 | bModeLock = cmdBuffer[4] == 0x03; } // Disgaea sends 0x01 here 269 | break; 270 | 271 | case 0x45: break; 272 | 273 | // Using DS2 ID code 274 | case 0x46: if(bConfig) {// Unknown constant part 1 and 2 275 | if(cmdBuffer[3] == 0x00) memcpy(&dataBuffer[4], DUALSHOCK2_ID[0], 5); 276 | else memcpy(&dataBuffer[4], DUALSHOCK2_ID[1], 5);} 277 | break; 278 | 279 | case 0x47: if(bConfig) {//Unknown constant part 3 280 | memcpy(&dataBuffer[4], DUALSHOCK2_ID[2], 5); } 281 | break; 282 | 283 | case 0x48: break; 284 | case 0x49: break; 285 | case 0x4A: break; 286 | case 0x4B: break; 287 | 288 | case 0x4C: if(bConfig) {// Unknown constant part 4 and 5 289 | if(cmdBuffer[3] == 0x00) memcpy(&dataBuffer[4], DUALSHOCK2_ID[3], 5); 290 | else memcpy(&dataBuffer[4], DUALSHOCK2_ID[4], 5);} 291 | break; 292 | 293 | case 0x4D: break; 294 | case 0x4E: break; 295 | case 0x4F: break; 296 | } 297 | } 298 | 299 | void DualShock::Cmd8(const u8 data) 300 | { 301 | switch(data) 302 | { 303 | case 0x40: break; 304 | case 0x41: break; 305 | 306 | case 0x42: 307 | vibration(motorMapS == 0xFF? 0: cmdBuffer[motorMapS+3], 308 | motorMapL == 0xFF? 0: cmdBuffer[motorMapL+3]); 309 | break; 310 | 311 | case 0x43: break; 312 | case 0x44: break; 313 | case 0x45: break; 314 | case 0x46: break; 315 | case 0x47: break; 316 | case 0x48: break; 317 | case 0x49: break; 318 | case 0x4A: break; 319 | case 0x4B: break; 320 | case 0x4C: break; 321 | 322 | case 0x4D: 323 | SetVibration(); 324 | break; 325 | 326 | case 0x4E: break; 327 | case 0x4F: break; 328 | } 329 | } 330 | 331 | void DualShock::poll() 332 | { 333 | u16 buffer[5]; 334 | Input::DualshockPoll(buffer, settings, gamepadPlugged, padID == ID_DIGITAL); 335 | 336 | buttons = buffer[0]; 337 | buttonsStick = buffer[1]; 338 | analogL = buffer[2]; 339 | analogR = buffer[3]; 340 | triggerR = buffer[4] & 0xFF; 341 | triggerL = (buffer[4]>>8) & 0xFF; 342 | } 343 | 344 | void DualShock::vibration(u8 smalldata, u8 bigdata) 345 | { 346 | Input::DualshockRumble(smalldata, bigdata, settings, gamepadPlugged); 347 | } 348 | 349 | void DualShock::SaveState(PlayStationDeviceState &state) 350 | { 351 | state.buttons = buttons; 352 | state.buttonsStick = buttonsStick; 353 | state.analogL = analogL; 354 | state.analogR = analogR; 355 | state.padID = padID; 356 | state.bConfig = bConfig; 357 | state.bModeLock = bModeLock; 358 | state.motorMapS = motorMapS; 359 | state.motorMapL = motorMapL; 360 | state.triggerL = triggerL; 361 | state.triggerR = triggerR; 362 | } 363 | 364 | void DualShock::LoadState(PlayStationDeviceState state) 365 | { 366 | buttons = state.buttons; 367 | buttonsStick = state.buttonsStick; 368 | analogL = state.analogL; 369 | analogR = state.analogR; 370 | padID = state.padID; 371 | bConfig = state.bConfig; 372 | bModeLock = state.bModeLock; 373 | motorMapS = state.motorMapS; 374 | motorMapL = state.motorMapL; 375 | triggerL = state.triggerL; 376 | triggerR = state.triggerR; 377 | } 378 | -------------------------------------------------------------------------------- /Pokopom/FileIO.cpp: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2012 KrossX 2 | * License: http://www.opensource.org/licenses/mit-license.html MIT License 3 | */ 4 | #include 5 | #include 6 | #include 7 | 8 | #include "General.h" 9 | #include "FileIO.h" 10 | #include "regini.h" 11 | 12 | extern char settingsDirectory[1024]; 13 | extern u8 multitap; 14 | 15 | extern bool disableLED; 16 | extern bool bPriority; 17 | extern void SetPriority(); 18 | 19 | #define PATH_LENGTH 1024 20 | #define LINE_LENGTH 512 21 | 22 | namespace FileIO 23 | { 24 | std::string GetFilename() 25 | { 26 | const std::string pcsx2_directory(settingsDirectory); 27 | const std::string plugin_filename("padPokopom.ini"); 28 | 29 | if (!pcsx2_directory.empty()) 30 | { 31 | return pcsx2_directory + plugin_filename; 32 | } 33 | else 34 | { 35 | #ifdef _WIN32 36 | const std::string plugin_directory("plugins/"); 37 | return plugin_directory + plugin_filename; 38 | #elif defined __linux__ 39 | return plugin_filename; 40 | #endif 41 | } 42 | } 43 | 44 | void INI_SaveSettings() 45 | { 46 | regini::regini_file inifile; 47 | inifile.open(GetFilename()); 48 | 49 | inifile.write("General", "INIversion", std::to_string(INIversion)); 50 | inifile.write("General", "ProcPriority", std::to_string(bPriority ? 1 : 0)); 51 | inifile.write("General", "KeepAwake", std::to_string(bKeepAwake ? 1 : 0)); 52 | inifile.write("General", "SwapPorts", std::to_string(SwapPortsEnabled ? 1 : 0)); 53 | inifile.write("General", "Multitap", std::to_string(multitap)); 54 | inifile.write("General", "DisableLED", std::to_string(disableLED ? 1 : 0)); 55 | 56 | for(s32 port = 0; port < 4; port++) 57 | { 58 | std::string section = "Controller" + std::to_string(port); 59 | _Settings &set = settings[port]; 60 | 61 | u32 AxisInverted, AxisRemap; 62 | 63 | { 64 | u8 *ai = set.axisInverted; 65 | u8 *ar = set.axisRemap; 66 | 67 | AxisInverted = ai[0] | (ai[1] << 8) | (ai[2] << 16) | (ai[3] << 24); 68 | AxisRemap = ar[0] | (ar[1] << 8) | (ar[2] << 16) | (ar[3] << 24); 69 | } 70 | 71 | inifile.write(section, "AxisInverted", std::to_string(AxisInverted)); 72 | inifile.write(section, "AxisRemap", std::to_string(AxisRemap)); 73 | 74 | inifile.write(section, "TriggerDeadzone", std::to_string(set.triggerDeadzone)); 75 | inifile.write(section, "Pressure", std::to_string(set.pressureRate)); 76 | inifile.write(section, "Rumble", std::to_string(set.rumble)); 77 | inifile.write(section, "SticksLocked", std::to_string(set.sticksLocked ? 1 : 0)); 78 | 79 | inifile.write(section, "XInputPort", std::to_string(set.xinputPort)); 80 | inifile.write(section, "Disabled", std::to_string(set.disabled ? 1 : 0)); 81 | inifile.write(section, "DefautMode", std::to_string(set.defaultAnalog ? 1 : 0)); 82 | inifile.write(section, "GreenAnalog", std::to_string(set.greenAnalog ? 1 : 0)); 83 | inifile.write(section, "GuitarController", std::to_string(set.isGuitar ? 1 : 0)); 84 | 85 | inifile.write(section, "SwapDCBumpers", std::to_string(set.SwapDCBumpers ? 1 : 0)); 86 | inifile.write(section, "SwapSticks", std::to_string(set.SwapSticksEnabled ? 1 : 0)); 87 | inifile.write(section, "SwapXO", std::to_string(set.SwapXO ? 1 : 0)); 88 | 89 | // Left Stick Settings 90 | 91 | inifile.write(section, "LS_4wayDAC", std::to_string(set.stickL.b4wayDAC ? 1 : 0)); 92 | inifile.write(section, "LS_EnableDAC", std::to_string(set.stickL.DACenabled ? 1 : 0)); 93 | inifile.write(section, "LS_DACthreshold", std::to_string(set.stickL.DACthreshold)); 94 | 95 | inifile.write(section, "LS_ExtentionThreshold", std::to_string(set.stickL.extThreshold)); 96 | 97 | inifile.write(section, "LS_Linearity", std::to_string(set.stickL.linearity)); 98 | inifile.write(section, "LS_AntiDeadzone", std::to_string(set.stickL.antiDeadzone)); 99 | inifile.write(section, "LS_Deadzone", std::to_string(set.stickL.deadzone)); 100 | 101 | // Right Stick Settings 102 | 103 | inifile.write(section, "RS_4wayDAC", std::to_string(set.stickR.b4wayDAC ? 1 : 0)); 104 | inifile.write(section, "RS_EnableDAC", std::to_string(set.stickR.DACenabled ? 1 : 0)); 105 | inifile.write(section, "RS_DACthreshold", std::to_string(set.stickR.DACthreshold)); 106 | 107 | inifile.write(section, "RS_ExtentionThreshold", std::to_string(set.stickR.extThreshold)); 108 | 109 | inifile.write(section, "RS_Linearity", std::to_string(set.stickR.linearity)); 110 | inifile.write(section, "RS_AntiDeadzone", std::to_string(set.stickR.antiDeadzone)); 111 | inifile.write(section, "RS_Deadzone", std::to_string(set.stickR.deadzone)); 112 | } 113 | 114 | inifile.save(); 115 | } 116 | 117 | void INI_LoadSettings() 118 | { 119 | settings[0].xinputPort = 0; 120 | settings[1].xinputPort = 1; 121 | settings[2].xinputPort = 2; 122 | settings[3].xinputPort = 3; 123 | 124 | regini::regini_file inifile; 125 | inifile.open(GetFilename()); 126 | 127 | if (inifile.readi("General", "INIversion", -1) != INIversion) 128 | { 129 | return; 130 | } 131 | 132 | bPriority = inifile.readi("General", "ProcPriority", 0) == 1; 133 | SetPriority(); 134 | 135 | disableLED = inifile.readi("General", "DisableLED", 0) == 1; 136 | SwapPortsEnabled = inifile.readi("General", "SwapPorts", 0) == 1; 137 | bKeepAwake = inifile.readi("General", "KeepAwake", 0) == 1; 138 | multitap = inifile.readi("General", "Multitap", 0) & 0xF; 139 | multitap = multitap > 2 ? 0 : multitap; 140 | 141 | for (s32 port = 0; port < 4; port++) 142 | { 143 | std::string section = "Controller" + std::to_string(port); 144 | _Settings &set = settings[port]; 145 | s32 result; 146 | 147 | result = inifile.readi(section, "AxisInverted", -1); 148 | if (result != -1) 149 | { 150 | u8 *ai = set.axisInverted; 151 | u32 res = result; 152 | 153 | ai[0] = res & 0xFF; 154 | ai[1] = (res >> 8 ) & 0xFF; 155 | ai[2] = (res >> 16) & 0xFF; 156 | ai[3] = (res >> 24) & 0xFF; 157 | } 158 | 159 | result = inifile.readi(section, "AxisRemap", -1); 160 | if (result != -1) 161 | { 162 | u8 *ar = set.axisRemap; 163 | u32 res = result; 164 | 165 | ar[0] = res & 0xFF; 166 | ar[1] = (res >> 8 ) & 0xFF; 167 | ar[2] = (res >> 16) & 0xFF; 168 | ar[3] = (res >> 24) & 0xFF; 169 | } 170 | 171 | set.triggerDeadzone = inifile.readi(section, "TriggerDeadzone", set.triggerDeadzone) & 0xFF; 172 | set.pressureRate = inifile.readi(section, "Pressure", set.pressureRate) & 0xFF; 173 | set.rumble = inifile.readf(section, "Rumble", set.rumble); 174 | set.xinputPort = inifile.readi(section, "XInputPort", set.xinputPort) & 0xF; 175 | 176 | DebugPrint("[%d] -> XInputPort [%d]", port, set.xinputPort); 177 | 178 | set.disabled = !!inifile.readi(section, "Disabled", 0); 179 | set.sticksLocked = !!inifile.readi(section, "SticksLocked", 1); 180 | set.defaultAnalog = !!inifile.readi(section, "DefautMode", 1); 181 | 182 | set.greenAnalog = !!inifile.readi(section, "GreenAnalog", 0); 183 | set.isGuitar = !!inifile.readi(section, "GuitarController", 0); 184 | set.SwapDCBumpers = !!inifile.readi(section, "SwapDCBumpers", 0); 185 | set.SwapSticksEnabled = !!inifile.readi(section, "SwapSticks", 0); 186 | set.SwapXO = !!inifile.readi(section, "SwapXO", 0); 187 | 188 | // Left Stick Settings 189 | 190 | set.stickL.b4wayDAC = !!inifile.readi(section, "LS_4wayDAC", 0); 191 | set.stickL.DACenabled = !!inifile.readi(section, "LS_EnableDAC", 0); 192 | 193 | set.stickL.DACthreshold = inifile.readd(section, "LS_DACthreshold", set.stickL.DACthreshold); 194 | set.stickL.extThreshold = inifile.readd(section, "LS_ExtentionThreshold", set.stickL.extThreshold); 195 | set.stickL.extMult = 46339.535798279205464084934426179 / set.stickL.extThreshold; 196 | 197 | set.stickL.linearity = inifile.readd(section, "LS_Linearity", set.stickL.linearity); 198 | set.stickL.antiDeadzone = inifile.readf(section, "LS_AntiDeadzone", set.stickL.antiDeadzone); 199 | set.stickL.deadzone = inifile.readf(section, "LS_Deadzone", set.stickL.deadzone); 200 | 201 | // Right Stick Settings 202 | 203 | set.stickR.b4wayDAC = !!inifile.readi(section, "RS_4wayDAC", 0); 204 | set.stickR.DACenabled = !!inifile.readi(section, "RS_EnableDAC", 0); 205 | 206 | set.stickR.DACthreshold = inifile.readd(section, "RS_DACthreshold", set.stickR.DACthreshold); 207 | set.stickR.extThreshold = inifile.readd(section, "RS_ExtentionThreshold", set.stickR.extThreshold); 208 | set.stickR.extMult = 46339.535798279205464084934426179 / set.stickR.extThreshold; 209 | 210 | set.stickR.linearity = inifile.readd(section, "RS_Linearity", set.stickR.linearity); 211 | set.stickR.antiDeadzone = inifile.readf(section, "RS_AntiDeadzone", set.stickR.antiDeadzone); 212 | set.stickR.deadzone = inifile.readf(section, "RS_Deadzone", set.stickR.deadzone); 213 | } 214 | 215 | } 216 | 217 | bool FASTCALL LoadMempak(u8 *data, u8 port) 218 | { 219 | #ifdef _WIN32 220 | char filename[256]; 221 | 222 | sprintf(filename, "MemPaks\\Pokopom%d.mempak", port+1); 223 | 224 | std::fstream file; 225 | file.open(filename, std::ios::binary | std::ios::in); 226 | 227 | if(!file.is_open()) return false; 228 | 229 | file.seekg(EOF, std::ios_base::end); 230 | s64 size = file.tellg(); 231 | 232 | if(size != 32767) { file.close(); return false; } 233 | 234 | file.seekg(0); 235 | file.read((char*)data, 0x8000); 236 | file.close(); 237 | 238 | return true; 239 | #else 240 | return false; 241 | #endif 242 | } 243 | 244 | void FASTCALL SaveMempak(u8* data, u8 port) 245 | { 246 | #ifdef _WIN32 247 | CreateDirectoryA("MemPaks", NULL); 248 | 249 | char filename[1024] = {0}; 250 | sprintf(filename, "MemPaks\\Pokopom%d.mempak", port+1); 251 | 252 | std::fstream file; 253 | file.open(filename, std::ios::binary | std::ios::out); 254 | 255 | if(!file.is_open()) return; 256 | 257 | file.write((char*)data, 0x8000); 258 | file.close(); 259 | #endif 260 | } 261 | 262 | 263 | 264 | bool FASTCALL LoadEEPROM(u8 *data) 265 | { 266 | #ifdef _WIN32 267 | FILE *file = NULL; 268 | file = fopen("Pokopom.eeprom", "r"); 269 | 270 | if(file != NULL) 271 | { 272 | fread(data, 1, 0x80, file); 273 | fclose(file); 274 | return true; 275 | } 276 | else 277 | return false; 278 | #else 279 | return false; 280 | #endif 281 | } 282 | 283 | void FASTCALL SaveEEPROM(u8 *data) 284 | { 285 | #ifdef _WIN32 286 | FILE *file = NULL; 287 | file = fopen("Pokopom.eeprom", "w"); 288 | 289 | if(file != NULL) 290 | { 291 | fwrite(data, 1, 0x80, file); 292 | fclose(file); 293 | } 294 | #endif 295 | } 296 | 297 | } // End namespace FileIO 298 | 299 | -------------------------------------------------------------------------------- /Pokopom/Input_Linux.cpp: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2012 KrossX 2 | * License: http://www.opensource.org/licenses/mit-license.html MIT License 3 | */ 4 | 5 | #include "General.h" 6 | #include "Input.h" 7 | #include "Input_Shared.h" 8 | 9 | #ifdef __linux__ 10 | 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | 20 | enum 21 | { 22 | LIN_BTN_A = 0, 23 | LIN_BTN_B, 24 | LIN_BTN_X, 25 | LIN_BTN_Y, 26 | LIN_BTN_LB, 27 | LIN_BTN_RB, 28 | LIN_BTN_BACK, 29 | LIN_BTN_START, 30 | LIN_BTN_BIGX, 31 | LIN_BTN_LS, 32 | LIN_BTN_RS, 33 | LIN_BTN_NUM 34 | }; 35 | 36 | enum 37 | { 38 | LIN_AXIS_LX = 0, // -left, +right 39 | LIN_AXIS_LY, // -top, +bottom 40 | LIN_AXIS_LT, // -32767 to 32767(pressed) 41 | LIN_AXIS_RX, 42 | LIN_AXIS_RY, 43 | LIN_AXIS_RT, 44 | LIN_AXIS_DX, // DPAD 45 | LIN_AXIS_DY, // DPAD 46 | LIN_AXIS_NUM 47 | }; 48 | 49 | namespace Input 50 | { 51 | 52 | u8 xpads = 0; 53 | const char xpad_name[] = "Microsoft X-Box 360"; 54 | 55 | struct devinfo 56 | { 57 | s32 fd; 58 | char path[32]; 59 | 60 | devinfo() 61 | { 62 | fd = 0; 63 | memset(path, 0, 32); 64 | } 65 | 66 | } joy_info[4]; 67 | 68 | struct ffinfo : public devinfo 69 | { 70 | ff_effect effect; 71 | input_event play; 72 | 73 | ffinfo() 74 | { 75 | effect.type = FF_RUMBLE; 76 | effect.id = -1; 77 | effect.u.rumble.strong_magnitude = 0; 78 | effect.u.rumble.weak_magnitude = 0; 79 | effect.replay.length = 150; 80 | effect.replay.delay = 0; 81 | 82 | play.type = EV_FF; 83 | play.value = 1; 84 | } 85 | } rumble_info[4]; 86 | 87 | 88 | 89 | struct jstate 90 | { 91 | s32 axis[LIN_AXIS_NUM]; 92 | u8 button[LIN_BTN_NUM]; 93 | } joy_state[4]; 94 | 95 | //////////////////////////////////////////////////////////////////////// 96 | // General 97 | //////////////////////////////////////////////////////////////////////// 98 | 99 | bool JoyPoll(u8 port) 100 | { 101 | bool polled = false; 102 | 103 | if(port < xpads) 104 | { 105 | if(joy_info[port].fd == 0) 106 | joy_info[port].fd = open(joy_info[port].path, O_RDONLY | O_NONBLOCK, 0); 107 | 108 | if(joy_info[port].fd > 0) 109 | { 110 | js_event joy; 111 | jstate &jstate = joy_state[port]; 112 | 113 | while(read(joy_info[port].fd, &joy, sizeof(js_event)) != -1) 114 | { 115 | switch (joy.type & ~JS_EVENT_INIT) 116 | { 117 | case JS_EVENT_AXIS: 118 | jstate.axis[joy.number] = joy.value; 119 | break; 120 | case JS_EVENT_BUTTON: 121 | jstate.button[joy.number] = joy.value; 122 | break; 123 | } 124 | } 125 | 126 | polled = true; 127 | //close(joy_fd); 128 | } 129 | else 130 | joy_info[port].fd = 0; 131 | } 132 | 133 | return polled; 134 | } 135 | 136 | bool Recheck(u8 port) 137 | { 138 | if(settings[port].disabled) return false; 139 | if(port > 0) return false; 140 | 141 | //printf("Pokopom(%d) -> Recheck\n", port); 142 | 143 | s32 joy_fd, count = 0; 144 | char name_of_joystick[80] = {0}; 145 | 146 | xpads = 0; 147 | 148 | while(xpads < 4) 149 | { 150 | memset(name_of_joystick, 0, 80); 151 | sprintf(joy_info[xpads].path, "/dev/input/js%d", count); 152 | 153 | joy_fd = open(joy_info[xpads].path, O_RDONLY | O_NONBLOCK, 0); 154 | 155 | if(joy_fd < 0 && errno == ENOENT) 156 | { 157 | memset(joy_info[xpads].path, 0, 32); 158 | break; 159 | } 160 | else 161 | { 162 | ioctl(joy_fd, JSIOCGNAME(80), &name_of_joystick); 163 | 164 | if(memcmp(xpad_name, name_of_joystick, 18) == 0) 165 | xpads++; 166 | 167 | close(joy_fd); 168 | } 169 | 170 | count++; 171 | } 172 | 173 | // Rumble check 174 | 175 | s32 rumble_fd, num_effects = 0; 176 | u8 rpads = 0; count = 0; 177 | 178 | if(xpads > 0) while(rpads < xpads) 179 | { 180 | sprintf(rumble_info[rpads].path, "/dev/input/event%d", count); 181 | 182 | rumble_fd = open(rumble_info[rpads].path, O_RDWR | O_NONBLOCK); 183 | 184 | if(rumble_fd < 0 && errno == ENOENT) 185 | { 186 | memset(rumble_info[xpads].path, 0, 32); 187 | break; 188 | } 189 | else 190 | { 191 | /* Should probably check for features too. RUMBLE at least. */ 192 | ioctl(rumble_fd, EVIOCGEFFECTS, &num_effects); 193 | 194 | if(num_effects == 16) 195 | rpads++; 196 | 197 | close(rumble_fd); 198 | } 199 | 200 | count++; 201 | } 202 | 203 | return port < xpads ? true : false; 204 | } 205 | 206 | void Pause(bool pewpew) 207 | { 208 | return; 209 | } 210 | 211 | void StopRumble(u8 port) 212 | { 213 | return; 214 | } 215 | 216 | bool CheckAnalogToggle(u8 port) 217 | { 218 | return joy_state[port].button[LIN_BTN_BIGX] ? true : false; 219 | } 220 | 221 | void SetAnalogLed(u8 port, bool digital) 222 | { 223 | //Debug("Pokopom -> [%d] Mode: (%s).\n", port, digital? "Digital" : "Analog"); 224 | } 225 | 226 | bool InputGetState(_Pad& pad, _Settings &set) 227 | { 228 | const bool pollSuccess = JoyPoll(set.xinputPort); 229 | 230 | if(pollSuccess) 231 | { 232 | jstate &js = joy_state[set.xinputPort]; 233 | 234 | pad.buttons[X360_DUP] = js.axis[LIN_AXIS_DY] < 0? 1:0; 235 | pad.buttons[X360_DDOWN] = js.axis[LIN_AXIS_DY] > 0? 1:0; 236 | pad.buttons[X360_DLEFT] = js.axis[LIN_AXIS_DX] < 0? 1:0; 237 | pad.buttons[X360_DRIGHT] = js.axis[LIN_AXIS_DX] > 0? 1:0; 238 | 239 | pad.buttons[X360_START] = js.button[LIN_BTN_START] ? 1:0; 240 | pad.buttons[X360_BACK] = js.button[LIN_BTN_BACK] ? 1:0; 241 | 242 | pad.buttons[X360_LS] = js.button[LIN_BTN_LS] ? 1:0; 243 | pad.buttons[X360_RS] = js.button[LIN_BTN_RS] ? 1:0; 244 | pad.buttons[X360_LB] = js.button[LIN_BTN_LB] ? 1:0; 245 | pad.buttons[X360_RB] = js.button[LIN_BTN_RB] ? 1:0; 246 | 247 | pad.buttons[X360_BIGX] = js.button[LIN_BTN_BIGX] ? 1:0; 248 | 249 | pad.buttons[X360_A] = js.button[LIN_BTN_A] ? 1:0; 250 | pad.buttons[X360_B] = js.button[LIN_BTN_B] ? 1:0; 251 | pad.buttons[X360_X] = js.button[LIN_BTN_X] ? 1:0; 252 | pad.buttons[X360_Y] = js.button[LIN_BTN_Y] ? 1:0; 253 | 254 | pad.analog[X360_STICKLX] = js.axis[LIN_AXIS_LX]; 255 | pad.analog[X360_STICKLY] = -js.axis[LIN_AXIS_LY]; 256 | pad.analog[X360_STICKRX] = js.axis[LIN_AXIS_RX]; 257 | pad.analog[X360_STICKRY] = -js.axis[LIN_AXIS_RY]; 258 | 259 | pad.analog[X360_TRIGGERL] = (js.axis[LIN_AXIS_LT] + 32767) / 256; 260 | pad.analog[X360_TRIGGERR] = (js.axis[LIN_AXIS_RT] + 32767) / 256; 261 | 262 | TriggerDeadzone(pad, set); 263 | 264 | pad.stickL.X = pad.analog[X360_STICKLX]; 265 | pad.stickL.Y = pad.analog[X360_STICKLY]; 266 | pad.stickR.X = pad.analog[X360_STICKRX]; 267 | pad.stickR.Y = pad.analog[X360_STICKRY]; 268 | 269 | set.axisValue[GP_AXIS_LY] = pad.analog[X360_STICKLY] * (set.axisInverted[GP_AXIS_LY] ? -1 : 1); 270 | set.axisValue[GP_AXIS_LX] = pad.analog[X360_STICKLX] * (set.axisInverted[GP_AXIS_LX] ? -1 : 1); 271 | set.axisValue[GP_AXIS_RY] = pad.analog[X360_STICKRY] * (set.axisInverted[GP_AXIS_RY] ? -1 : 1); 272 | set.axisValue[GP_AXIS_RX] = pad.analog[X360_STICKRX] * (set.axisInverted[GP_AXIS_RX] ? -1 : 1); 273 | 274 | pad.modL.X = set.axisValue[set.axisRemap[GP_AXIS_LX]]; 275 | pad.modL.Y = set.axisValue[set.axisRemap[GP_AXIS_LY]]; 276 | pad.modR.X = set.axisValue[set.axisRemap[GP_AXIS_RX]]; 277 | pad.modR.Y = set.axisValue[set.axisRemap[GP_AXIS_RY]]; 278 | 279 | GetRadius(pad.stickL); GetRadius(pad.stickR); 280 | GetRadius(pad.modL); GetRadius(pad.modR); 281 | } 282 | 283 | return pollSuccess; 284 | } 285 | 286 | //////////////////////////////////////////////////////////////////////// 287 | // DualShock 288 | //////////////////////////////////////////////////////////////////////// 289 | 290 | void DualshockRumble(u8 smalldata, u8 bigdata, _Settings &set, bool &gamepadPlugged) 291 | { 292 | if(!gamepadPlugged) return; 293 | 294 | static timespec timeS[4], timeB[4]; 295 | ffinfo &rumble = rumble_info[set.xinputPort]; 296 | 297 | if(rumble.fd == 0) 298 | rumble.fd = open(rumble.path, O_RDWR | O_NONBLOCK, 0); 299 | 300 | if(rumble.fd > 0) 301 | { 302 | u16 &smallMotor = rumble.effect.u.rumble.weak_magnitude; 303 | u16 &bigMotor = rumble.effect.u.rumble.strong_magnitude; 304 | 305 | timespec timeC; 306 | clock_gettime(CLOCK_MONOTONIC, &timeC); 307 | 308 | if(smalldata) 309 | { 310 | smallMotor = Clamp(0xFFFF * set.rumble); 311 | clock_gettime(CLOCK_MONOTONIC, &timeS[set.xinputPort]); 312 | } 313 | else if(smallMotor) 314 | { 315 | const long secDiff = timeC.tv_sec - timeS[set.xinputPort].tv_sec; 316 | const long nsecDiff = timeC.tv_nsec - timeS[set.xinputPort].tv_nsec; 317 | 318 | if(secDiff > 0 || nsecDiff > 150000000) 319 | smallMotor = 0; 320 | } 321 | 322 | if(bigdata) 323 | { 324 | f64 broom = 0.006474549734772402 * pow(bigdata, 3.0) - 325 | 1.258165252213538 * pow(bigdata, 2.0) + 326 | 156.82454281087692 * bigdata + 327 | 3.637978807091713e-11; 328 | 329 | bigMotor = Clamp(broom * set.rumble); 330 | clock_gettime(CLOCK_MONOTONIC, &timeB[set.xinputPort]); 331 | } 332 | else if(bigMotor) 333 | { 334 | const long secDiff = timeC.tv_sec - timeB[set.xinputPort].tv_sec; 335 | const long nsecDiff = timeC.tv_nsec - timeB[set.xinputPort].tv_nsec; 336 | 337 | if(secDiff > 0 || nsecDiff > 150000000) 338 | bigMotor = 0; 339 | } 340 | 341 | // Update the same effect... 342 | if (ioctl(rumble.fd, EVIOCSFF, &rumble.effect) == -1) 343 | { 344 | perror("Rumble Upload"); 345 | rumble.fd = 0; 346 | return; 347 | } 348 | 349 | rumble.play.code = rumble.effect.id; 350 | 351 | // And play it! 352 | if (write(rumble.fd, (const void*) &rumble.play, sizeof(rumble.play)) == -1) 353 | { 354 | perror("Rumble Playback"); 355 | rumble.fd = 0; 356 | return; 357 | } 358 | 359 | //Debug("Vibrate! [%2X] %04X : [%2X] %04X\n", smalldata, smallMotor, bigdata, bigMotor); 360 | } 361 | 362 | } 363 | 364 | bool FASTCALL DualshockPressure(u8 * bufferOut, u32 mask, _Settings &set, bool &gamepadPlugged) 365 | { 366 | return false; 367 | } 368 | 369 | //////////////////////////////////////////////////////////////////////// 370 | // Dreamcast 371 | //////////////////////////////////////////////////////////////////////// 372 | 373 | void VibrationWatchdog(void* param) 374 | { 375 | return; 376 | } 377 | 378 | void DreamcastRumble(s16 intensity, bool freqH, bool freqL, void* thread, 379 | _Settings &set, bool &gamepadPlugged) 380 | { 381 | return; 382 | } 383 | 384 | //////////////////////////////////////////////////////////////////////// 385 | // Zilmar 386 | //////////////////////////////////////////////////////////////////////// 387 | 388 | void N64rumbleSwitch(u8 port, bool &rumble, bool &gamepadPlugged) 389 | { 390 | return; 391 | } 392 | 393 | void N64rumble(bool on, _Settings &set, bool &gamepadPlugged) 394 | { 395 | return; 396 | } 397 | 398 | } // Input namespace 399 | #endif // Linux 400 | -------------------------------------------------------------------------------- /Pokopom/psemupro.cpp: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2012 KrossX 2 | * License: http://www.opensource.org/licenses/mit-license.html MIT License 3 | */ 4 | 5 | #include "psemupro.h" 6 | #include "ConfigDialog.h" 7 | #include "Input.h" 8 | 9 | PlayStationDevice * controller[2] = {NULL, NULL}; 10 | 11 | char settingsDirectory[1024]; // for PCSX2 12 | 13 | u32 buffer_count; 14 | u32 current_port, current_slot; 15 | extern u8 multitap; 16 | 17 | //////////////////////////////////////////////////////////////////////// 18 | // PPDK developer must change libraryName field and can change revision and build 19 | //////////////////////////////////////////////////////////////////////// 20 | 21 | const u32 revision = 2; 22 | const u32 build = 1; 23 | 24 | const u32 versionPS1 = (emupro::PLUGIN_VERSION << 16) | (revision << 8) | build; 25 | const u32 versionPS2 = (0x02 << 16) | (revision << 8) | build; 26 | 27 | char libraryName[] = "Pokopom XInput Pad Plugin"; // rewrite your plug-in name 28 | char PluginAuthor[] = "KrossX"; // rewrite your name 29 | 30 | //////////////////////////////////////////////////////////////////////// 31 | // stuff to make this a true PDK module 32 | //////////////////////////////////////////////////////////////////////// 33 | 34 | DllExport char* CALLBACK PSEgetLibName() 35 | { 36 | isPSemulator = true; 37 | return libraryName; 38 | } 39 | 40 | DllExport u32 CALLBACK PSEgetLibType() 41 | { 42 | isPSemulator = true; 43 | return emupro::LT_PAD; 44 | } 45 | 46 | DllExport u32 CALLBACK PSEgetLibVersion() 47 | { 48 | isPSemulator = true; 49 | return versionPS1; 50 | } 51 | 52 | DllExport char* CALLBACK PS2EgetLibName() 53 | { 54 | isPs2Emulator = true; 55 | return PSEgetLibName(); 56 | } 57 | 58 | DllExport u32 CALLBACK PS2EgetLibType() 59 | { 60 | isPs2Emulator = true; 61 | return 0x02; 62 | } 63 | 64 | DllExport u32 CALLBACK PS2EgetLibVersion2(u32 type) 65 | { 66 | isPs2Emulator = true; 67 | if (type == 0x02) return versionPS2; 68 | else return 0; 69 | } 70 | 71 | //////////////////////////////////////////////////////////////////////// 72 | // Init/shutdown, will be called just once on emu start/close 73 | //////////////////////////////////////////////////////////////////////// 74 | 75 | DllExport s32 CALLBACK PADinit(s32 flags) // PAD INIT 76 | { 77 | DebugPrint("[%X]", flags); 78 | 79 | static bool inited = false; 80 | if (inited) return emupro::INIT_ERR_SUCCESS; 81 | 82 | FileIO::INI_LoadSettings(); 83 | FileIO::INI_SaveSettings(); 84 | 85 | for (int pad = 0; pad < 2; pad++) 86 | { 87 | inited = true; 88 | 89 | _Settings &set = settings[pad]; 90 | 91 | if (set.disabled) 92 | controller[pad] = new PlayStationDevice(set, 1); 93 | else if (isPs2Emulator) 94 | { 95 | switch (multitap) 96 | { 97 | case 0: 98 | controller[pad] = set.isGuitar? new PS2_Guitar(set) : new DualShock2(set); 99 | break; 100 | 101 | case 1: 102 | if (pad == 0) controller[pad] = new MultiTap2(settings); 103 | else controller[pad] = new PlayStationDevice(set, 1); 104 | break; 105 | 106 | case 2: 107 | if (pad == 0) controller[pad] = new DualShock2(set); 108 | else controller[pad] = new MultiTap2(settings); 109 | break; 110 | } 111 | 112 | } 113 | else 114 | { 115 | switch (multitap) 116 | { 117 | case 0: 118 | controller[pad] = new DualShock(set); 119 | break; 120 | 121 | case 1: 122 | if (pad == 0) controller[pad] = new MultiTap(settings); 123 | else controller[pad] = new PlayStationDevice(set, 1); 124 | break; 125 | 126 | case 2: 127 | if (pad == 0) controller[pad] = new DualShock(set); 128 | else controller[pad] = new MultiTap(settings); 129 | break; 130 | } 131 | } 132 | 133 | if (controller[pad]) 134 | controller[pad]->SetPortX((u8)pad); 135 | else 136 | return emupro::ERR_FATAL; 137 | } 138 | 139 | return emupro::INIT_ERR_SUCCESS; 140 | } 141 | 142 | DllExport void CALLBACK PADshutdown() // PAD SHUTDOWN 143 | { 144 | DebugFunc(); 145 | 146 | //delete controller[0]; 147 | //delete controller[1]; 148 | 149 | //controller[0] = controller[1] = nullptr; 150 | } 151 | 152 | //////////////////////////////////////////////////////////////////////// 153 | // Open/close will be called when a games starts/stops 154 | //////////////////////////////////////////////////////////////////////// 155 | 156 | DllExport s32 CALLBACK PADopen(void* pDisplay) // PAD OPEN 157 | { 158 | DebugFunc(); 159 | 160 | Input::Pause(false); 161 | 162 | GetDisplay(pDisplay); 163 | KeyboardOpen(); 164 | KeepAwake(KEEPAWAKE_INIT); 165 | 166 | return emupro::pad::ERR_SUCCESS; 167 | } 168 | 169 | DllExport s32 CALLBACK PADclose() // PAD CLOSE 170 | { 171 | DebugFunc(); 172 | 173 | Input::Pause(true); 174 | KeyboardClose(); 175 | KeepAwake(KEEPAWAKE_CLOSE); 176 | 177 | return emupro::pad::ERR_SUCCESS; 178 | } 179 | 180 | //////////////////////////////////////////////////////////////////////// 181 | // call config dialog 182 | //////////////////////////////////////////////////////////////////////// 183 | 184 | DllExport s32 CALLBACK PADconfigure() 185 | { 186 | isPSemulator = true; 187 | 188 | FileIO::INI_LoadSettings(); 189 | CreateConfigDialog(); 190 | 191 | return emupro::pad::ERR_SUCCESS; 192 | } 193 | 194 | //////////////////////////////////////////////////////////////////////// 195 | // show about dialog 196 | //////////////////////////////////////////////////////////////////////// 197 | 198 | DllExport void CALLBACK PADabout() 199 | { 200 | ShowDialog(L"Pokopom XInput pad plugin - KrossX © 2012", L"About..."); 201 | } 202 | 203 | //////////////////////////////////////////////////////////////////////// 204 | // test... well, we are ever fine ;) 205 | //////////////////////////////////////////////////////////////////////// 206 | 207 | DllExport s32 CALLBACK PADtest() 208 | { 209 | return emupro::pad::ERR_SUCCESS; 210 | } 211 | 212 | //////////////////////////////////////////////////////////////////////// 213 | // tell the controller's port which can be used 214 | //////////////////////////////////////////////////////////////////////// 215 | 216 | DllExport s32 CALLBACK PADquery() 217 | { 218 | DebugFunc(); 219 | return emupro::pad::USE_PORT1 | emupro::pad::USE_PORT2; 220 | } 221 | 222 | //////////////////////////////////////////////////////////////////////// 223 | // tell the input of pad 224 | // this function should be replaced with PADstartPoll and PADpoll 225 | //////////////////////////////////////////////////////////////////////// 226 | 227 | s32 FASTCALL PADreadPort(s32 port, emupro::pad::DataS* ppds) 228 | { 229 | DebugPrint("[%X]", port); 230 | 231 | controller[port]->command(0, 0x01); 232 | u8 cType = controller[port]->command(1, 0x42); 233 | ppds->controllerType = cType >> 4; 234 | 235 | controller[port]->command(2, 0x00); 236 | ppds->buttonStatus = controller[port]->command(3, 0x00) | (controller[port]->command(4, 0x00) << 8); 237 | 238 | cType = cType & 0xF; 239 | 240 | if(cType > 2) 241 | { 242 | ppds->rightJoyX = ppds->moveX = controller[port]->command(5, 0x00); 243 | ppds->rightJoyY = ppds->moveY = controller[port]->command(6, 0x00); 244 | 245 | if (cType >= 0x03) 246 | { 247 | ppds->leftJoyX = controller[port]->command(7, 0x00); 248 | ppds->leftJoyY = controller[port]->command(8, 0x00); 249 | } 250 | } 251 | 252 | return emupro::pad::ERR_SUCCESS; 253 | } 254 | 255 | DllExport s32 CALLBACK PADreadPort1(emupro::pad::DataS* ppds) 256 | { 257 | return PADreadPort(0, ppds); 258 | } 259 | 260 | DllExport s32 CALLBACK PADreadPort2(emupro::pad::DataS* ppds) 261 | { 262 | return PADreadPort(1, ppds); 263 | } 264 | 265 | //////////////////////////////////////////////////////////////////////// 266 | // input and output of pad 267 | //////////////////////////////////////////////////////////////////////// 268 | 269 | DllExport u8 CALLBACK PADstartPoll(s32 port) 270 | { 271 | current_port = SwapPortsEnabled ? (u8)(port - 1) ^ SwapPorts() : (u8)(port - 1); 272 | buffer_count = 0; 273 | 274 | u8 data = controller[current_port]->command(buffer_count, current_slot & 0xFF); 275 | 276 | //if(current_port == 0) 277 | DebugPrint("[%02d|%02d] [%02X|%02X] ***", buffer_count, current_port, current_slot, data); 278 | 279 | return data; 280 | } 281 | 282 | DllExport u8 CALLBACK PADpoll(u8 data) 283 | { 284 | buffer_count++; 285 | 286 | u8 doto = controller[current_port]->command(buffer_count, data); 287 | 288 | //if(current_port == 0) 289 | DebugPrint(" [%02d|%02d] [%02X|%02X]", buffer_count, current_port, data, doto); 290 | 291 | return doto; 292 | } 293 | 294 | //////////////////////////////////////////////////////////////////////// 295 | // other stuff 296 | //////////////////////////////////////////////////////////////////////// 297 | 298 | struct freezeData 299 | { 300 | s32 size; 301 | u8 *data; 302 | }; 303 | 304 | 305 | DllExport u32 CALLBACK PADfreeze(s32 mode, freezeData *data) 306 | { 307 | DebugPrint("[%X]", mode); 308 | 309 | if(!data) return (u32)emupro::ERR_FATAL; 310 | 311 | switch(mode) 312 | { 313 | case emupro::Savestate::LOAD: 314 | { 315 | PlayStationDeviceState *state = (PlayStationDeviceState *)data->data; 316 | 317 | if(memcmp(state[0].libraryName, libraryName, 25) == 0 && 318 | state[0].version == ((revision << 8) | build)) 319 | { 320 | controller[0]->LoadState(state[0]); 321 | controller[1]->LoadState(state[1]); 322 | } 323 | else 324 | { 325 | printf("Pokopom -> Wrong savestate data to load."); 326 | } 327 | 328 | } break; 329 | 330 | case emupro::Savestate::SAVE: 331 | { 332 | PlayStationDeviceState state[2]; 333 | 334 | memset(state, 0, sizeof(state)); 335 | 336 | memcpy(state[0].libraryName, libraryName, 25); 337 | memcpy(state[1].libraryName, libraryName, 25); 338 | 339 | state[0].version = state[1].version = (revision << 8) | build; 340 | 341 | controller[0]->SaveState(state[0]); 342 | controller[1]->SaveState(state[1]); 343 | memcpy(data->data, state, sizeof(state)); 344 | } break; 345 | 346 | case emupro::Savestate::QUERY_SIZE: 347 | { 348 | data->size = sizeof(PlayStationDeviceState) * 2; 349 | } break; 350 | } 351 | 352 | return emupro::ERR_SUCCESS; 353 | } 354 | 355 | DllExport keyEvent* CALLBACK PADkeyEvent() 356 | { 357 | DebugFunc(); 358 | 359 | static keyEvent pochy; 360 | 361 | if(!isPs2Emulator) 362 | KeyboardCheck(); 363 | 364 | if(!keyEventList.empty()) 365 | { 366 | pochy = keyEventList.front(); 367 | keyEventList.pop_back(); 368 | return &pochy; 369 | } 370 | 371 | return NULL; 372 | } 373 | 374 | DllExport s32 PADkeypressed() 375 | { 376 | keyEvent *pochy = PADkeyEvent(); 377 | return pochy? pochy->key : 0; 378 | } 379 | 380 | DllExport u32 CALLBACK PADqueryMtap(u8 port) 381 | { 382 | DebugPrint("[%X]", port); 383 | return 0; 384 | 385 | if(multitap == 1 && port == 1) return 1; 386 | else if(multitap == 2) return 1; 387 | else return 0; 388 | } 389 | 390 | DllExport void CALLBACK PADsetSettingsDir(const char *dir) 391 | { 392 | DebugPrint("%s", dir); 393 | 394 | if(dir) 395 | memcpy(settingsDirectory, dir, strlen(dir)+1); 396 | } 397 | 398 | DllExport void PADWriteEvent(keyEvent &evt) 399 | { 400 | DebugFunc(); 401 | 402 | switch(evt.evt) 403 | { 404 | case 0x02: 405 | evt.evt -= 1; 406 | keyEventList.push_back(evt); 407 | break; 408 | 409 | case 0x03: 410 | evt.evt -= 1; 411 | evt.key |= 0x40000000; 412 | keyEventList.push_back(evt); 413 | break; 414 | } 415 | } 416 | 417 | DllExport u32 CALLBACK PADsetSlot(u8 port, u8 slot) 418 | { 419 | DebugPrint("[%X|%X]", port, slot); 420 | 421 | current_port = port - 1; 422 | current_slot = slot; 423 | 424 | switch(multitap) 425 | { 426 | case 0: 427 | if(slot == 1) return 1; 428 | 429 | case 1: 430 | if(port == 1) return 1; 431 | 432 | case 2: 433 | if(port == 1 && slot == 1) return 1; 434 | else if(port == 2 && slot < 4) return 1; 435 | } 436 | 437 | return 0; 438 | } 439 | 440 | DllExport void CALLBACK PADupdate(s32 port) 441 | { 442 | DebugPrint("[%X]", port); 443 | } 444 | 445 | 446 | 447 | 448 | -------------------------------------------------------------------------------- /Pokopom/Input_XInput.cpp: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2012 KrossX 2 | * License: http://www.opensource.org/licenses/mit-license.html MIT License 3 | */ 4 | 5 | #include "General.h" 6 | #include "Input.h" 7 | #include "Input_Shared.h" 8 | 9 | #ifdef _WIN32 10 | 11 | #include "../SCP/SCPExtensions.cpp" 12 | //#include "Controller.h" 13 | //#include "General.h" 14 | //#include "nullDC_Devices.h" 15 | //#include "Chankast.h" 16 | //#include "Zilmar_Devices.h" 17 | 18 | #include 19 | //#pragma comment(lib, "Xinput.lib") 20 | 21 | extern bool disableLED; 22 | 23 | typedef DWORD (WINAPI* XInputGetStateEx_t)(DWORD dwUserIndex, XINPUT_STATE *pState); 24 | typedef DWORD(WINAPI* XInputSetStateEx_t)(DWORD dwUserIndex, XINPUT_VIBRATION* pVibration); 25 | 26 | DWORD WINAPI XGS_NULL(DWORD dwUserIndex, XINPUT_STATE *pState); 27 | DWORD WINAPI XSS_NULL(DWORD dwUserIndex, XINPUT_VIBRATION* pVibration); 28 | 29 | XInputGetStateEx_t XInputGetStateEx = XGS_NULL; 30 | XInputSetStateEx_t XInputSetStateEx = XSS_NULL; 31 | 32 | DWORD WINAPI XGS_NULL(DWORD dwUserIndex, XINPUT_STATE *pState) 33 | { 34 | HINSTANCE hXInput = LoadLibraryA("xinput1_3.dll"); 35 | XInputGetStateEx = (XInputGetStateEx_t)GetProcAddress(hXInput, (LPCSTR)100); 36 | 37 | if (!XInputGetStateEx) // Might help with wrappers compatibility 38 | XInputGetStateEx = (XInputGetStateEx_t)GetProcAddress(hXInput, "XInputGetState"); 39 | 40 | return XInputGetStateEx(dwUserIndex, pState); 41 | } 42 | 43 | DWORD WINAPI XSS_NULL(DWORD dwUserIndex, XINPUT_VIBRATION* pVibration) 44 | { 45 | HINSTANCE hXInput = LoadLibraryA("xinput1_3.dll"); 46 | XInputSetStateEx = (XInputSetStateEx_t)GetProcAddress(hXInput, "XInputSetState"); 47 | 48 | return XInputSetStateEx(dwUserIndex, pVibration); 49 | } 50 | 51 | #define XINPUT_GAMEPAD_GUIDE 0x400 52 | 53 | XINPUT_STATE state[4]; 54 | 55 | namespace Input 56 | { 57 | 58 | //////////////////////////////////////////////////////////////////////// 59 | // General 60 | //////////////////////////////////////////////////////////////////////// 61 | 62 | bool FASTCALL Recheck(u8 port) 63 | { 64 | DWORD result = XInputGetStateEx(port, &state[port]); 65 | return (result == ERROR_SUCCESS); 66 | } 67 | 68 | void FASTCALL Pause(bool pewpew) 69 | { 70 | if(pewpew) StopRumbleAll(); 71 | //XInputEnable(!pewpew); 72 | } 73 | 74 | void StopRumbleAll() 75 | { 76 | StopRumble(0); StopRumble(1); 77 | StopRumble(2); StopRumble(3); 78 | } 79 | 80 | void FASTCALL StopRumble(u8 port) 81 | { 82 | XINPUT_VIBRATION vib; 83 | 84 | vib.wLeftMotorSpeed = 0; 85 | vib.wRightMotorSpeed = 0; 86 | 87 | XInputSetStateEx(port, &vib); 88 | } 89 | 90 | bool FASTCALL CheckAnalogToggle(u8 port) 91 | { 92 | int key = GetAsyncKeyState(0x31 + port) & 0x8000; 93 | int pad = state[port].Gamepad.wButtons & XINPUT_GAMEPAD_GUIDE; 94 | 95 | bool val = (key | pad) != 0; 96 | 97 | DebugPrint("[%02d] %s", port, val ? "TOGGLE" : ""); 98 | 99 | return val; 100 | } 101 | 102 | void FASTCALL SetAnalogLed(u8 port, bool digital) 103 | { 104 | if (disableLED) return; 105 | 106 | bool ledScrollLock = GetKeyState(VK_SCROLL)&0x1; 107 | 108 | if((!digital && !ledScrollLock) || (digital && ledScrollLock)) 109 | { 110 | keybd_event( VK_SCROLL, 0x45, KEYEVENTF_EXTENDEDKEY, 0 ); 111 | keybd_event( VK_SCROLL, 0x45, KEYEVENTF_EXTENDEDKEY | KEYEVENTF_KEYUP, 0 ); 112 | 113 | DebugPrint(" [%02d|%s] %s %s", port, ledScrollLock? "ON " : "OFF", digital? "DIGITAL" : "ANALOG ", "TOGGLE"); 114 | } 115 | else 116 | { 117 | DebugPrint(" [%02d|%s] %s %s", port, ledScrollLock ? "ON " : "OFF", digital ? "DIGITAL" : "ANALOG ", ""); 118 | } 119 | } 120 | 121 | bool FASTCALL InputGetState(_Pad& pad, _Settings &set) 122 | { 123 | const int xport = set.xinputPort; 124 | DWORD result = XInputGetStateEx(xport, &state[xport]); 125 | 126 | if(result == ERROR_SUCCESS) 127 | { 128 | pad.buttons[X360_DUP] = (state[xport].Gamepad.wButtons & XINPUT_GAMEPAD_DPAD_UP); 129 | pad.buttons[X360_DDOWN] = (state[xport].Gamepad.wButtons & XINPUT_GAMEPAD_DPAD_DOWN) >> 1; 130 | pad.buttons[X360_DLEFT] = (state[xport].Gamepad.wButtons & XINPUT_GAMEPAD_DPAD_LEFT) >> 2; 131 | pad.buttons[X360_DRIGHT] = (state[xport].Gamepad.wButtons & XINPUT_GAMEPAD_DPAD_RIGHT) >> 3; 132 | 133 | pad.buttons[X360_START] = (state[xport].Gamepad.wButtons & XINPUT_GAMEPAD_START) >> 4; 134 | pad.buttons[X360_BACK] = (state[xport].Gamepad.wButtons & XINPUT_GAMEPAD_BACK) >> 5; 135 | 136 | pad.buttons[X360_LS] = (state[xport].Gamepad.wButtons & XINPUT_GAMEPAD_LEFT_THUMB) >> 6; 137 | pad.buttons[X360_RS] = (state[xport].Gamepad.wButtons & XINPUT_GAMEPAD_RIGHT_THUMB) >> 7; 138 | pad.buttons[X360_LB] = (state[xport].Gamepad.wButtons & XINPUT_GAMEPAD_LEFT_SHOULDER) >> 8; 139 | pad.buttons[X360_RB] = (state[xport].Gamepad.wButtons & XINPUT_GAMEPAD_RIGHT_SHOULDER) >> 9; 140 | 141 | pad.buttons[X360_BIGX] = (state[xport].Gamepad.wButtons & XINPUT_GAMEPAD_GUIDE) >> 10; 142 | 143 | pad.buttons[X360_A] = (state[xport].Gamepad.wButtons & XINPUT_GAMEPAD_A) >> 12; 144 | pad.buttons[X360_B] = (state[xport].Gamepad.wButtons & XINPUT_GAMEPAD_B) >> 13; 145 | pad.buttons[X360_X] = (state[xport].Gamepad.wButtons & XINPUT_GAMEPAD_X) >> 14; 146 | pad.buttons[X360_Y] = (state[xport].Gamepad.wButtons & XINPUT_GAMEPAD_Y) >> 15; 147 | 148 | pad.analog[X360_STICKLX] = state[xport].Gamepad.sThumbLX; 149 | pad.analog[X360_STICKLY] = state[xport].Gamepad.sThumbLY; 150 | pad.analog[X360_STICKRX] = state[xport].Gamepad.sThumbRX; 151 | pad.analog[X360_STICKRY] = state[xport].Gamepad.sThumbRY; 152 | 153 | pad.analog[X360_TRIGGERL] = state[xport].Gamepad.bLeftTrigger; 154 | pad.analog[X360_TRIGGERR] = state[xport].Gamepad.bRightTrigger; 155 | 156 | TriggerDeadzone(pad, set); 157 | 158 | pad.stickL.X = pad.analog[X360_STICKLX]; 159 | pad.stickL.Y = pad.analog[X360_STICKLY]; 160 | pad.stickR.X = pad.analog[X360_STICKRX]; 161 | pad.stickR.Y = pad.analog[X360_STICKRY]; 162 | 163 | set.axisValue[GP_AXIS_LY] = pad.analog[X360_STICKLY] * (set.axisInverted[GP_AXIS_LY] ? -1 : 1); 164 | set.axisValue[GP_AXIS_LX] = pad.analog[X360_STICKLX] * (set.axisInverted[GP_AXIS_LX] ? -1 : 1); 165 | set.axisValue[GP_AXIS_RY] = pad.analog[X360_STICKRY] * (set.axisInverted[GP_AXIS_RY] ? -1 : 1); 166 | set.axisValue[GP_AXIS_RX] = pad.analog[X360_STICKRX] * (set.axisInverted[GP_AXIS_RX] ? -1 : 1); 167 | 168 | pad.modL.X = set.axisValue[set.axisRemap[GP_AXIS_LX]]; 169 | pad.modL.Y = set.axisValue[set.axisRemap[GP_AXIS_LY]]; 170 | pad.modR.X = set.axisValue[set.axisRemap[GP_AXIS_RX]]; 171 | pad.modR.Y = set.axisValue[set.axisRemap[GP_AXIS_RY]]; 172 | 173 | GetRadius(pad.stickL); GetRadius(pad.stickR); 174 | GetRadius(pad.modL); GetRadius(pad.modR); 175 | } 176 | 177 | return result == ERROR_SUCCESS; 178 | }; 179 | 180 | //////////////////////////////////////////////////////////////////////// 181 | // DualShock 182 | //////////////////////////////////////////////////////////////////////// 183 | 184 | void FASTCALL DualshockRumble(u8 smalldata, u8 bigdata, _Settings &set, bool &gamepadPlugged) 185 | { 186 | if(!gamepadPlugged) return; 187 | 188 | //Debug("Vibrate! [%X] [%X]\n", smalldata, bigdata); 189 | const u8 xport = set.xinputPort; 190 | 191 | static XINPUT_VIBRATION vib[4]; 192 | static DWORD timerS[4], timerB[4]; 193 | 194 | if(smalldata) 195 | { 196 | vib[xport].wRightMotorSpeed = Clamp(0xFFFF * set.rumble); 197 | timerS[xport] = GetTickCount(); 198 | } 199 | else if (vib[xport].wRightMotorSpeed && GetTickCount() - timerS[xport] > 150) 200 | { 201 | vib[xport].wRightMotorSpeed = 0; 202 | } 203 | 204 | /* 205 | 3.637978807091713*^-11 + 206 | 156.82454281087692 * x + -1.258165252213538 * x^2 + 207 | 0.006474549734772402 * x^3; 208 | */ 209 | 210 | if(bigdata) 211 | { 212 | f64 broom = 0.006474549734772402 * pow(bigdata, 3.0) - 213 | 1.258165252213538 * pow(bigdata, 2.0) + 214 | 156.82454281087692 * bigdata + 215 | 3.637978807091713e-11; 216 | 217 | 218 | /* 219 | u32 broom = bigdata; 220 | 221 | if(bigdata <= 0x2C) broom *= 0x72; 222 | else if(bigdata <= 0x53) broom = 0x13C7 + bigdata * 0x24; 223 | else broom *= 0x205; 224 | */ 225 | 226 | vib[xport].wLeftMotorSpeed = Clamp(broom * set.rumble); 227 | timerB[xport] = GetTickCount(); 228 | } 229 | else if (vib[xport].wLeftMotorSpeed && GetTickCount() - timerB[xport] > 150) 230 | { 231 | vib[xport].wLeftMotorSpeed = 0; 232 | } 233 | 234 | /* 235 | 236 | vib.wRightMotorSpeed = smalldata == 0? 0 : 0xFFFF; 237 | vib.wLeftMotorSpeed = bigdata * 0x101; 238 | 239 | vib.wRightMotorSpeed = Clamp(vib.wRightMotorSpeed * settings.rumble); 240 | vib.wLeftMotorSpeed = Clamp(vib.wLeftMotorSpeed * settings.rumble); 241 | */ 242 | 243 | if( XInputSetStateEx(xport, &vib[xport]) != ERROR_SUCCESS ) 244 | gamepadPlugged = false; 245 | } 246 | 247 | bool FASTCALL DualshockPressure(u8 * bufferOut, u32 mask, _Settings &set, bool &gamepadPlugged) 248 | { 249 | SCP_EXTN pressure; 250 | 251 | if(XInputGetExtended(set.xinputPort, &pressure) == ERROR_SUCCESS) 252 | { 253 | //Right, left, up, down 254 | bufferOut[0x00] = (mask & 0x01) ? (u8)(pressure.SCP_RIGHT* 255) : 0x00; 255 | bufferOut[0x01] = (mask & 0x02) ? (u8)(pressure.SCP_LEFT * 255) : 0x00; 256 | bufferOut[0x02] = (mask & 0x04) ? (u8)(pressure.SCP_UP * 255) : 0x00; 257 | bufferOut[0x03] = (mask & 0x08) ? (u8)(pressure.SCP_DOWN * 255) : 0x00; 258 | 259 | //triangle, circle, cross, square 260 | bufferOut[0x04] = (mask & 0x10) ? (u8)(pressure.SCP_T * 255) : 0x00; 261 | bufferOut[0x05] = (mask & 0x20) ? (u8)(pressure.SCP_C * 255) : 0x00; 262 | bufferOut[0x06] = (mask & 0x40) ? (u8)(pressure.SCP_X * 255) : 0x00; 263 | bufferOut[0x07] = (mask & 0x80) ? (u8)(pressure.SCP_S * 255) : 0x00; 264 | 265 | //l1, r1, l2, r2 266 | bufferOut[0x08] = (mask & 0x100) ? (u8)(pressure.SCP_L1 * 255) : 0x00; 267 | bufferOut[0x09] = (mask & 0x200) ? (u8)(pressure.SCP_R1 * 255) : 0x00; 268 | bufferOut[0x0A] = (mask & 0x400) ? (u8)(pressure.SCP_L2 * 255) : 0x00; 269 | bufferOut[0x0B] = (mask & 0x800) ? (u8)(pressure.SCP_R2 * 255) : 0x00; 270 | 271 | return true; 272 | } 273 | else 274 | return false; 275 | } 276 | 277 | //////////////////////////////////////////////////////////////////////// 278 | // Dreamcast 279 | //////////////////////////////////////////////////////////////////////// 280 | 281 | struct watchdogThread 282 | { 283 | u16 wait; 284 | u8 port; 285 | }; 286 | 287 | void VibrationWatchdog(LPVOID param) 288 | { 289 | if(param == NULL) return; 290 | watchdogThread *pochy = (watchdogThread*)param; 291 | Sleep(pochy->wait); 292 | StopRumble(pochy->port); 293 | } 294 | 295 | void FASTCALL DreamcastRumble(s16 intensity, bool freqH, bool freqL, u16 wait, 296 | _Settings &set, bool &gamepadPlugged, HANDLE &thread) 297 | { 298 | if(!gamepadPlugged) return; 299 | 300 | XINPUT_VIBRATION vib; 301 | 302 | u16 uIntensity = intensity < 0 ? -intensity : intensity; 303 | 304 | vib.wLeftMotorSpeed = freqH ? 0 : (WORD)((uIntensity * 9362) * set.rumble); 305 | vib.wRightMotorSpeed = freqL ? 0 : (WORD)((uIntensity * 8192 + 8190) * set.rumble); 306 | 307 | if(thread) 308 | { 309 | TerminateThread(thread, 0); 310 | CloseHandle(thread); 311 | thread = NULL; 312 | } 313 | 314 | watchdogThread * th = new watchdogThread(); 315 | th->wait = wait; 316 | th->port = set.xinputPort; 317 | 318 | thread = CreateThread(0, 0, (LPTHREAD_START_ROUTINE)VibrationWatchdog, th, 0, NULL); 319 | 320 | if(XInputSetStateEx(set.xinputPort, &vib) != ERROR_SUCCESS) 321 | gamepadPlugged = false; 322 | } 323 | 324 | //////////////////////////////////////////////////////////////////////// 325 | // Zilmar 326 | //////////////////////////////////////////////////////////////////////// 327 | 328 | void FASTCALL N64rumbleSwitch(u8 port, bool &rumble, bool &gamepadPlugged) 329 | { 330 | if(!gamepadPlugged) return; 331 | 332 | static bool pressed[4] = {false}; 333 | 334 | if(!pressed[port] && (state[port].Gamepad.wButtons & XINPUT_GAMEPAD_BACK)) 335 | { 336 | pressed[port] = true; 337 | rumble = !rumble; 338 | } 339 | else if(pressed[port] && !(state[port].Gamepad.wButtons & XINPUT_GAMEPAD_BACK)) 340 | { 341 | pressed[port] = false; 342 | } 343 | 344 | bool ledScrollLock = GetKeyState(VK_SCROLL)&0x1; 345 | 346 | if((!rumble && !ledScrollLock) || (rumble && ledScrollLock)) 347 | { 348 | keybd_event( VK_SCROLL, 0x45, KEYEVENTF_EXTENDEDKEY, 0 ); 349 | keybd_event( VK_SCROLL, 0x45, KEYEVENTF_EXTENDEDKEY | KEYEVENTF_KEYUP, 0 ); 350 | } 351 | } 352 | 353 | void FASTCALL N64rumble(bool on, _Settings &set, bool &gamepadPlugged) 354 | { 355 | if(!gamepadPlugged) return; 356 | 357 | XINPUT_VIBRATION vib; 358 | 359 | if(on) 360 | { 361 | vib.wRightMotorSpeed = Clamp(0xFFFF * set.rumble); 362 | vib.wLeftMotorSpeed = Clamp(0xFFFF * set.rumble); 363 | } 364 | else 365 | { 366 | vib.wRightMotorSpeed = 0; 367 | vib.wLeftMotorSpeed = 0; 368 | } 369 | 370 | if(XInputSetStateEx(set.xinputPort, &vib) == ERROR_SUCCESS) 371 | gamepadPlugged = false; 372 | } 373 | 374 | } // End namespace Input 375 | #endif // WIN32 376 | -------------------------------------------------------------------------------- /Pokopom/ConfigDialog.cpp: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2012 KrossX 2 | * License: http://www.opensource.org/licenses/mit-license.html MIT License 3 | */ 4 | 5 | #include "General.h" 6 | #include "ConfigDialog.h" 7 | #include "FileIO.h" 8 | 9 | u8 multitap; 10 | 11 | #ifdef _WIN32 12 | #include 13 | #include 14 | 15 | #include "resource.h" 16 | 17 | HWND hChild, hParent; 18 | //extern u8 multitap; 19 | 20 | extern HINSTANCE h_instance; 21 | //extern u8 dcPlatform; 22 | 23 | wchar_t tab_label[4][16] = { L"Controller 1", L"Controller 2", L"Controller 3", L"Controller 4" }; 24 | 25 | f64 SliderUpdate(HWND hDialog, s32 sliderID, s32 textID, bool Linearity = false) 26 | { 27 | wchar_t text[8]; 28 | f64 value = 0.0; 29 | 30 | LRESULT res = SendMessage(GetDlgItem(hDialog, sliderID),TBM_GETPOS,0,0); 31 | 32 | if(Linearity) 33 | { 34 | res = res < 0? res -10 : res > 0? res +10: res; 35 | value = res / 10.00; 36 | 37 | swprintf(text, 6, L"%1.2f", value); 38 | } 39 | else 40 | { 41 | swprintf(text, 5, L"%d%%", res); 42 | value = res / 100.00; 43 | } 44 | 45 | SetDlgItemText(hDialog, textID, text); 46 | 47 | return value; 48 | } 49 | 50 | void SliderSet(HWND hDialog, s32 sliderID, f64 value, bool Linearity = false) 51 | { 52 | LRESULT position; 53 | 54 | if(Linearity) 55 | { 56 | position = (LRESULT)(value * 10.1); 57 | position = position > 0? position - 10 : position < 0 ? position +10 : position; 58 | } 59 | else 60 | { 61 | position = (LRESULT)(value * 100.1); 62 | } 63 | 64 | SendMessage(GetDlgItem(hDialog, sliderID), TBM_SETPOS, TRUE, position); 65 | SendMessage(hDialog, WM_HSCROLL, 0, (LPARAM)GetDlgItem(hDialog, sliderID)); 66 | } 67 | 68 | void UpdateControls(HWND hDialog, s32 port) 69 | { 70 | for(s32 i = 0; i<4; i++) 71 | { 72 | SendMessage(GetDlgItem(hDialog, i + IDC_COMBO_LX), CB_SETCURSEL, settings[port].axisRemap[i], 0); 73 | CheckDlgButton(hDialog, i + IDC_INVERT_LX, settings[port].axisInverted[i] ? BST_CHECKED : BST_UNCHECKED); 74 | CheckDlgButton(hDialog, i + IDC_XINPUT1, settings[port].xinputPort == i ? BST_CHECKED : BST_UNCHECKED); 75 | } 76 | 77 | CheckDlgButton(hDialog, IDC_DISABLED, settings[port].disabled ? BST_CHECKED : BST_UNCHECKED); 78 | CheckDlgButton(hDialog, IDC_GUITAR, settings[port].isGuitar ? BST_CHECKED : BST_UNCHECKED); 79 | CheckDlgButton(hDialog, IDC_ANALOG_GREEN, settings[port].greenAnalog ? BST_CHECKED : BST_UNCHECKED); 80 | CheckDlgButton(hDialog, IDC_LOCKSLIDERS, settings[port].sticksLocked ? BST_CHECKED : BST_UNCHECKED); 81 | //CheckDlgButton(hDialog, IDC_4WAYSTICK, settings[port].b4wayStick ? BST_CHECKED : BST_UNCHECKED); 82 | CheckDlgButton(hDialog, IDC_SWAPSTICKS, settings[port].SwapSticksEnabled ? BST_CHECKED : BST_UNCHECKED); 83 | CheckDlgButton(hDialog, IDC_SWAPXO, settings[port].SwapXO ? BST_CHECKED : BST_UNCHECKED); 84 | 85 | CheckDlgButton(hDialog, settings[port].defaultAnalog ? IDC_MODE_ANALOG : IDC_MODE_DIGITAL, BST_CHECKED); 86 | CheckDlgButton(hDialog, settings[port].defaultAnalog ? IDC_MODE_DIGITAL : IDC_MODE_ANALOG, BST_UNCHECKED); 87 | 88 | EnableWindow(GetDlgItem(hDialog, IDC_4WAYSTICK), FALSE); // Disabled for now. 89 | 90 | EnableWindow(GetDlgItem(hDialog, IDC_MODE_DIGITAL), isPSemulator); 91 | EnableWindow(GetDlgItem(hDialog, IDC_MODE_ANALOG), isPSemulator); 92 | EnableWindow(GetDlgItem(hDialog, IDC_MULTITAP), isPSemulator); 93 | EnableWindow(GetDlgItem(hDialog, IDC_ANALOG_GREEN), isPSemulator && !isPs2Emulator); 94 | EnableWindow(GetDlgItem(hDialog, IDC_GUITAR), isPs2Emulator); 95 | EnableWindow(GetDlgItem(hDialog, IDC_SWAPSTICKS), !isPSemulator); 96 | EnableWindow(GetDlgItem(hDialog, IDC_SWAPXO), isPSemulator); 97 | 98 | SliderSet(hDialog, IDC_SLIDER_RUMBLE, settings[port].rumble); 99 | 100 | SliderSet(hDialog, IDC_SLIDER_DEADZONE2, settings[port].stickR.deadzone); 101 | SliderSet(hDialog, IDC_SLIDER_ANTIDEADZONE2, settings[port].stickR.antiDeadzone); 102 | SliderSet(hDialog, IDC_SLIDER_LINEARITY2, settings[port].stickR.linearity, true); 103 | 104 | SliderSet(hDialog, IDC_SLIDER_DEADZONE, settings[port].stickL.deadzone); 105 | SliderSet(hDialog, IDC_SLIDER_ANTIDEADZONE, settings[port].stickL.antiDeadzone); 106 | SliderSet(hDialog, IDC_SLIDER_LINEARITY, settings[port].stickL.linearity, true); 107 | 108 | EnableWindow(GetDlgItem(hDialog, IDC_SLIDER_DEADZONE2), !settings[port].sticksLocked); 109 | EnableWindow(GetDlgItem(hDialog, IDC_SLIDER_ANTIDEADZONE2), !settings[port].sticksLocked); 110 | EnableWindow(GetDlgItem(hDialog, IDC_SLIDER_LINEARITY2), !settings[port].sticksLocked); 111 | } 112 | 113 | 114 | INT_PTR CALLBACK DialogProc2(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) 115 | { 116 | static s32 port; 117 | 118 | switch(uMsg) 119 | { 120 | case WM_INITDIALOG: 121 | { 122 | port = TabCtrl_GetCurSel(GetDlgItem(GetParent(hwndDlg), IDC_TAB1)); 123 | 124 | for(s32 control = IDC_COMBO_LX; control <= IDC_COMBO_RY; control++) 125 | { 126 | SendMessage(GetDlgItem(hwndDlg, control), CB_ADDSTRING, 0, (LPARAM)L"Axis LX"); 127 | SendMessage(GetDlgItem(hwndDlg, control), CB_ADDSTRING, 0, (LPARAM)L"Axis LY"); 128 | SendMessage(GetDlgItem(hwndDlg, control), CB_ADDSTRING, 0, (LPARAM)L"Axis RX"); 129 | SendMessage(GetDlgItem(hwndDlg, control), CB_ADDSTRING, 0, (LPARAM)L"Axis RY"); 130 | } 131 | 132 | SendMessage(GetDlgItem(hwndDlg, IDC_SLIDER_RUMBLE), TBM_SETRANGE, TRUE, MAKELONG(0, 200)); 133 | SendMessage(GetDlgItem(hwndDlg, IDC_SLIDER_DEADZONE), TBM_SETRANGE, TRUE, MAKELONG(0, 100)); 134 | SendMessage(GetDlgItem(hwndDlg, IDC_SLIDER_ANTIDEADZONE), TBM_SETRANGE, TRUE, MAKELONG(0, 90)); 135 | SendMessage(GetDlgItem(hwndDlg, IDC_SLIDER_LINEARITY), TBM_SETRANGE, TRUE, MAKELONG(-30, 30)); 136 | 137 | SendMessage(GetDlgItem(hwndDlg, IDC_SLIDER_DEADZONE2), TBM_SETRANGE, TRUE, MAKELONG(0, 100)); 138 | SendMessage(GetDlgItem(hwndDlg, IDC_SLIDER_ANTIDEADZONE2), TBM_SETRANGE, TRUE, MAKELONG(0, 90)); 139 | SendMessage(GetDlgItem(hwndDlg, IDC_SLIDER_LINEARITY2), TBM_SETRANGE, TRUE, MAKELONG(-30, 30)); 140 | 141 | UpdateControls(hwndDlg, port); 142 | 143 | ShowWindow(hwndDlg, SW_SHOW); 144 | } break; 145 | 146 | case WM_HSCROLL: 147 | { 148 | if((HWND)lParam == GetDlgItem(hwndDlg, IDC_SLIDER_RUMBLE)) 149 | { 150 | settings[port].rumble = (f32)SliderUpdate(hwndDlg, IDC_SLIDER_RUMBLE, IDC_TEXT_RUMBLE); 151 | } 152 | else if((HWND)lParam == GetDlgItem(hwndDlg, IDC_SLIDER_DEADZONE)) 153 | { 154 | settings[port].stickL.deadzone = (f32)SliderUpdate(hwndDlg, IDC_SLIDER_DEADZONE, IDC_TEXT_DEADZONE); 155 | if(settings[port].sticksLocked) SliderSet(hwndDlg, IDC_SLIDER_DEADZONE2, settings[port].stickL.deadzone); 156 | } 157 | else if((HWND)lParam == GetDlgItem(hwndDlg, IDC_SLIDER_ANTIDEADZONE)) 158 | { 159 | settings[port].stickL.antiDeadzone = (f32)SliderUpdate(hwndDlg, IDC_SLIDER_ANTIDEADZONE, IDC_TEXT_ANTIDEADZONE); 160 | if(settings[port].sticksLocked) SliderSet(hwndDlg, IDC_SLIDER_ANTIDEADZONE2, settings[port].stickL.antiDeadzone); 161 | } 162 | else if((HWND)lParam == GetDlgItem(hwndDlg, IDC_SLIDER_LINEARITY)) 163 | { 164 | settings[port].stickL.linearity = SliderUpdate(hwndDlg, IDC_SLIDER_LINEARITY, IDC_TEXT_LINEARITY, true); 165 | if(settings[port].sticksLocked) SliderSet(hwndDlg, IDC_SLIDER_LINEARITY2, settings[port].stickL.linearity, true); 166 | } 167 | else if((HWND)lParam == GetDlgItem(hwndDlg, IDC_SLIDER_DEADZONE2)) 168 | { 169 | settings[port].stickR.deadzone = (f32)SliderUpdate(hwndDlg, IDC_SLIDER_DEADZONE2, IDC_TEXT_DEADZONE2); 170 | } 171 | else if((HWND)lParam == GetDlgItem(hwndDlg, IDC_SLIDER_ANTIDEADZONE2)) 172 | { 173 | settings[port].stickR.antiDeadzone = (f32)SliderUpdate(hwndDlg, IDC_SLIDER_ANTIDEADZONE2, IDC_TEXT_ANTIDEADZONE2); 174 | } 175 | else if((HWND)lParam == GetDlgItem(hwndDlg, IDC_SLIDER_LINEARITY2)) 176 | { 177 | settings[port].stickR.linearity = SliderUpdate(hwndDlg, IDC_SLIDER_LINEARITY2, IDC_TEXT_LINEARITY2, true); 178 | } 179 | 180 | } break; 181 | 182 | case WM_COMMAND: 183 | { 184 | s16 command = LOWORD(wParam); 185 | 186 | switch(command) 187 | { 188 | case IDC_XINPUT1: settings[port].xinputPort = 0; break; 189 | case IDC_XINPUT2: settings[port].xinputPort = 1; break; 190 | case IDC_XINPUT3: settings[port].xinputPort = 2; break; 191 | case IDC_XINPUT4: settings[port].xinputPort = 3; break; 192 | 193 | case IDC_MODE_DIGITAL: settings[port].defaultAnalog = false; break; 194 | case IDC_MODE_ANALOG: settings[port].defaultAnalog = true; break; 195 | 196 | case IDC_COMBO_LX: if(HIWORD(wParam) == CBN_SELCHANGE) 197 | settings[port].axisRemap[GP_AXIS_LX] = (u8)SendMessage(GetDlgItem(hwndDlg, IDC_COMBO_LX), CB_GETCURSEL, 0, 0); 198 | break; 199 | case IDC_COMBO_LY: if(HIWORD(wParam) == CBN_SELCHANGE) 200 | settings[port].axisRemap[GP_AXIS_LY] = (u8)SendMessage(GetDlgItem(hwndDlg, IDC_COMBO_LY), CB_GETCURSEL, 0, 0); 201 | break; 202 | case IDC_COMBO_RX: if(HIWORD(wParam) == CBN_SELCHANGE) 203 | settings[port].axisRemap[GP_AXIS_RX] = (u8)SendMessage(GetDlgItem(hwndDlg, IDC_COMBO_RX), CB_GETCURSEL, 0, 0); 204 | break; 205 | case IDC_COMBO_RY: if(HIWORD(wParam) == CBN_SELCHANGE) 206 | settings[port].axisRemap[GP_AXIS_RY] = (u8)SendMessage(GetDlgItem(hwndDlg, IDC_COMBO_RY), CB_GETCURSEL, 0, 0); 207 | break; 208 | 209 | case IDC_INVERT_LX: 210 | settings[port].axisInverted[GP_AXIS_LX] = IsDlgButtonChecked(hwndDlg, IDC_INVERT_LX) == BST_CHECKED; 211 | break; 212 | case IDC_INVERT_LY: 213 | settings[port].axisInverted[GP_AXIS_LY] = IsDlgButtonChecked(hwndDlg, IDC_INVERT_LY) == BST_CHECKED; 214 | break; 215 | case IDC_INVERT_RX: 216 | settings[port].axisInverted[GP_AXIS_RX] = IsDlgButtonChecked(hwndDlg, IDC_INVERT_RX) == BST_CHECKED; 217 | break; 218 | case IDC_INVERT_RY: 219 | settings[port].axisInverted[GP_AXIS_RY] = IsDlgButtonChecked(hwndDlg, IDC_INVERT_RY) == BST_CHECKED; 220 | break; 221 | 222 | case IDC_GUITAR: 223 | settings[port].isGuitar = IsDlgButtonChecked(hwndDlg, IDC_GUITAR) == BST_CHECKED; 224 | break; 225 | 226 | case IDC_DISABLED: 227 | settings[port].disabled = IsDlgButtonChecked(hwndDlg, IDC_DISABLED) == BST_CHECKED; 228 | break; 229 | 230 | case IDC_ANALOG_GREEN: 231 | settings[port].greenAnalog = IsDlgButtonChecked(hwndDlg, IDC_ANALOG_GREEN) == BST_CHECKED; 232 | break; 233 | 234 | case IDC_LOCKSLIDERS: 235 | settings[port].sticksLocked = IsDlgButtonChecked(hwndDlg, IDC_LOCKSLIDERS) == BST_CHECKED; 236 | 237 | EnableWindow(GetDlgItem(hwndDlg, IDC_SLIDER_DEADZONE2), !settings[port].sticksLocked); 238 | EnableWindow(GetDlgItem(hwndDlg, IDC_SLIDER_ANTIDEADZONE2), !settings[port].sticksLocked); 239 | EnableWindow(GetDlgItem(hwndDlg, IDC_SLIDER_LINEARITY2), !settings[port].sticksLocked); 240 | break; 241 | 242 | case IDC_4WAYSTICK: 243 | //settings[port].b4wayStick = IsDlgButtonChecked(hwndDlg, IDC_4WAYSTICK) == BST_CHECKED; 244 | break; 245 | 246 | case IDC_SWAPSTICKS: 247 | settings[port].SwapSticksEnabled = IsDlgButtonChecked(hwndDlg, IDC_SWAPSTICKS) == BST_CHECKED; 248 | break; 249 | 250 | case IDC_SWAPXO: 251 | settings[port].SwapXO = IsDlgButtonChecked(hwndDlg, IDC_SWAPXO) == BST_CHECKED; 252 | break; 253 | } 254 | 255 | } break; 256 | 257 | case WM_USER: if(wParam == 0xDEADBEEF) 258 | { 259 | port = lParam; 260 | UpdateControls(hChild, port); 261 | } 262 | break; 263 | 264 | default: return FALSE; 265 | } 266 | 267 | return TRUE; 268 | } 269 | 270 | INT_PTR CALLBACK DialogProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) 271 | { 272 | switch(uMsg) 273 | { 274 | case WM_INITDIALOG: 275 | { 276 | HWND hTabControl = GetDlgItem(hwndDlg, IDC_TAB1); 277 | 278 | TCITEM tci; 279 | tci.mask = TCIF_TEXT | TCIF_IMAGE; 280 | tci.iImage = -1; 281 | 282 | tci.pszText = tab_label[0]; 283 | TabCtrl_InsertItem(hTabControl, 0, &tci); 284 | 285 | tci.pszText = tab_label[1]; 286 | TabCtrl_InsertItem(hTabControl, 1, &tci); 287 | 288 | //if(dcPlatform != 2 && (!isPSemulator || multitap > 0)) 289 | if (!isPSemulator || multitap > 0) 290 | { 291 | tci.pszText = tab_label[2]; 292 | TabCtrl_InsertItem(hTabControl, 2, &tci); 293 | 294 | tci.pszText = tab_label[3]; 295 | TabCtrl_InsertItem(hTabControl, 3, &tci); 296 | } 297 | 298 | hChild = CreateDialog((HINSTANCE)lParam, MAKEINTRESOURCE(IDD_INTAB), hwndDlg, DialogProc2); 299 | EnableThemeDialogTexture(hChild, ETDT_ENABLETAB); 300 | 301 | EnableWindow(GetDlgItem(hwndDlg, IDC_MULTITAP), isPSemulator); 302 | EnableWindow(GetDlgItem(hwndDlg, IDC_SWAPPORTS), isPSemulator); 303 | 304 | CheckDlgButton(hwndDlg, IDC_SWAPPORTS, SwapPortsEnabled ? BST_CHECKED : BST_UNCHECKED); 305 | CheckDlgButton(hwndDlg, IDC_PROCPRIORITY, bPriority ? BST_CHECKED : BST_UNCHECKED); 306 | CheckDlgButton(hwndDlg, IDC_SCREENSAVER, bKeepAwake ? BST_CHECKED : BST_UNCHECKED); 307 | CheckDlgButton(hwndDlg, IDC_MULTITAP, multitap % 4); 308 | 309 | ShowWindow(hwndDlg, SW_SHOW); 310 | } break; 311 | 312 | case WM_COMMAND: 313 | { 314 | s16 command = LOWORD(wParam); 315 | 316 | switch(command) 317 | { 318 | case IDC_PROCPRIORITY: 319 | bPriority = IsDlgButtonChecked(hwndDlg, IDC_PROCPRIORITY) == BST_CHECKED; 320 | break; 321 | 322 | case IDC_SWAPPORTS: 323 | SwapPortsEnabled = IsDlgButtonChecked(hwndDlg, IDC_SWAPPORTS) == BST_CHECKED; 324 | break; 325 | 326 | 327 | 328 | case IDC_SCREENSAVER: 329 | bKeepAwake = IsDlgButtonChecked(hwndDlg, IDC_SCREENSAVER) == BST_CHECKED; 330 | break; 331 | 332 | case IDC_MULTITAP: 333 | { 334 | multitap = IsDlgButtonChecked(hwndDlg, IDC_MULTITAP) & 0xFF; 335 | HWND hTabControl = GetDlgItem(hwndDlg, IDC_TAB1); 336 | u8 tabs = (u8)TabCtrl_GetItemCount(hTabControl); 337 | 338 | if(multitap > 0) 339 | { 340 | if(tabs < 3) 341 | { 342 | TCITEM tci; 343 | tci.mask = TCIF_TEXT | TCIF_IMAGE; 344 | tci.iImage = -1; 345 | 346 | tci.pszText = tab_label[2]; 347 | TabCtrl_InsertItem(hTabControl, 2, &tci); 348 | 349 | tci.pszText = tab_label[3]; 350 | TabCtrl_InsertItem(hTabControl, 3, &tci); 351 | } 352 | } 353 | else 354 | { 355 | TabCtrl_SetCurSel(hTabControl, 0); 356 | 357 | TabCtrl_DeleteItem(hTabControl, 3); 358 | TabCtrl_DeleteItem(hTabControl, 2); 359 | } 360 | 361 | RedrawWindow(hChild, NULL, NULL, RDW_ERASE | RDW_INVALIDATE); 362 | } 363 | break; 364 | 365 | case IDRESET: 366 | { 367 | s32 port = TabCtrl_GetCurSel(GetDlgItem(hwndDlg, IDC_TAB1)); 368 | settings[port].SetDefaults(); 369 | SendMessage(hChild, WM_USER, 0xDEADBEEF, port); 370 | } 371 | break; 372 | 373 | case ID_OK: 374 | FileIO::INI_SaveSettings(); // SAVE SETTINGS 375 | case ID_CANCEL: 376 | EndDialog(hwndDlg, command); // .. and QUIT 377 | PostQuitMessage(0); 378 | break; 379 | } 380 | 381 | } break; 382 | 383 | case WM_NOTIFY: 384 | if ( ((LPNMHDR)lParam)->idFrom==IDC_TAB1 && ((LPNMHDR)lParam)->code == TCN_SELCHANGE ) 385 | { 386 | s32 port = TabCtrl_GetCurSel(GetDlgItem(hwndDlg, IDC_TAB1)); 387 | SendMessage(hChild, WM_USER, 0xDEADBEEF, port); 388 | } 389 | break; 390 | 391 | default: return FALSE; 392 | } 393 | 394 | return TRUE; 395 | } 396 | 397 | void CreateConfigDialog() 398 | { 399 | hParent = GetActiveWindow(); 400 | 401 | DialogBoxParam(h_instance, MAKEINTRESOURCE(IDD_CONFIG), hParent, DialogProc, (LPARAM)h_instance); 402 | MSG message; 403 | 404 | while(GetMessage(&message, NULL, 0, 0)) 405 | { 406 | if(hChild == NULL || !IsDialogMessage(hChild, &message)) 407 | { 408 | TranslateMessage(&message); 409 | DispatchMessage(&message); 410 | } 411 | } 412 | } 413 | #endif // WIN32 414 | 415 | #ifdef __linux__ 416 | 417 | void CreateConfigDialog() 418 | { 419 | // There is no config dialog, so at least save some settings. 420 | FileIO::INI_SaveSettings(); 421 | } 422 | 423 | #endif 424 | -------------------------------------------------------------------------------- /Pokopom/Input_Shared.cpp: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2012 KrossX 2 | * License: http://www.opensource.org/licenses/mit-license.html MIT License 3 | */ 4 | 5 | #include "General.h" 6 | #include "Input.h" 7 | #include "Input_Shared.h" 8 | 9 | namespace Input 10 | { 11 | 12 | const u16 ANALOG_TRESHOLD = 12540; 13 | 14 | const f64 PI = 3.14159265358979323846; 15 | const f64 PI_HALF = PI / 2.0; 16 | const f64 PI_2 = 2 * PI; 17 | 18 | void FASTCALL GetRadius(_Stick& stick) 19 | { 20 | f64 X = stick.X; 21 | f64 Y = stick.Y; 22 | stick.radius = sqrt(X*X + Y*Y); 23 | } 24 | 25 | void FASTCALL TriggerDeadzone(_Pad& pad, _Settings &set) 26 | { 27 | if(!set.triggerDeadzone) return; 28 | 29 | float dz = set.triggerDeadzone; 30 | 31 | for(int i = 0; i < 2; i++) 32 | { 33 | float tg = (float)pad.analog[X360_TRIGGERL + i]; 34 | 35 | tg = tg < dz ? 0 : (tg - dz) * 255.0f / (255.0f - dz); 36 | 37 | pad.analog[X360_TRIGGERL + i] = ((s32)tg) & 0xFF; 38 | } 39 | } 40 | 41 | static u8 FASTCALL GetAnalogDigital(_Stick& stick, StickSettings &aset) 42 | { 43 | u8 data = 0; 44 | 45 | if(aset.DACenabled && (stick.radius > aset.DACthreshold)) 46 | { 47 | f64 angle = atan2((f64)stick.Y, (f64)stick.X) / PI_2; 48 | stick.angle = angle = angle < 0 ? angle + 1 : angle; 49 | 50 | if(aset.b4wayDAC) 51 | { 52 | u8 angled = (u8)(angle * 8); 53 | 54 | switch(angled) 55 | { 56 | case 0: 57 | data = ANALOGD_XP; 58 | break; 59 | 60 | case 1: case 2: 61 | data = ANALOGD_YP; 62 | break; 63 | 64 | case 3: case 4: 65 | data = ANALOGD_XN; 66 | break; 67 | 68 | case 5: case 6: 69 | data = ANALOGD_YN; 70 | break; 71 | 72 | case 7: 73 | data = ANALOGD_XP; 74 | break; 75 | } 76 | 77 | } 78 | else 79 | { 80 | u8 angled = (u8)(angle * 16); 81 | 82 | switch(angled) 83 | { 84 | case 0: 85 | data = ANALOGD_XP; 86 | break; 87 | 88 | case 1: case 2: 89 | data = ANALOGD_XP | ANALOGD_YP; 90 | break; 91 | 92 | case 3: case 4: 93 | data = ANALOGD_YP; 94 | break; 95 | 96 | case 5: case 6: 97 | data = ANALOGD_XN | ANALOGD_YP; 98 | break; 99 | 100 | case 7: case 8: 101 | data = ANALOGD_XN; 102 | break; 103 | 104 | case 9: case 10: 105 | data = ANALOGD_XN | ANALOGD_YN; 106 | break; 107 | 108 | case 11: case 12: 109 | data = ANALOGD_YN; 110 | break; 111 | 112 | case 13: case 14: 113 | data = ANALOGD_XP | ANALOGD_YN; 114 | break; 115 | 116 | case 15: 117 | data = ANALOGD_XP; 118 | break; 119 | } 120 | } 121 | } 122 | 123 | return data; 124 | } 125 | 126 | static u16 FASTCALL ConvertAnalog(_Stick& stick, StickSettings &aset, u8 mode) 127 | { 128 | s32 X = stick.X; 129 | s32 Y = stick.Y; 130 | u16 result = mode == 0? 0x7F7F : 0; 131 | 132 | // If input is dead, no need to check or do anything else 133 | if((X == 0) && (Y == 0)) return result; 134 | 135 | f64 radius = stick.radius; 136 | const f64 deadzone = aset.extThreshold * aset.deadzone; 137 | 138 | // Input should be effectively dead under deadzone, no need to do more 139 | if(radius <= deadzone) return result; 140 | 141 | f64 rX = X/radius, rY = Y/radius; 142 | 143 | if(aset.linearity != 0) 144 | radius = pow(radius / aset.extThreshold, aset.linearity) * aset.extThreshold; 145 | 146 | if(deadzone > 0) 147 | radius = (radius - deadzone) * aset.extThreshold / (aset.extThreshold - deadzone); 148 | 149 | //Antideadzone, inspired by x360ce's setting 150 | if(aset.antiDeadzone > 0) 151 | { 152 | const f64 antiDeadzone = aset.extThreshold * aset.antiDeadzone; 153 | radius = radius * ((aset.extThreshold - antiDeadzone) / aset.extThreshold) + antiDeadzone; 154 | } 155 | 156 | if(radius > aset.extThreshold) radius *= aset.extMult; 157 | 158 | X = ClampAnalog(rX * radius); 159 | Y = ClampAnalog(rY * radius); 160 | 161 | switch(mode) 162 | { 163 | case 0: // Dualshock, Dreamcast... 164 | { 165 | Y = 32767 - Y; 166 | X = X + 32767; 167 | 168 | X = X < 0 ? 0 : X > 0xFFFF ? 0xFFFF : X; 169 | Y = Y < 0 ? 0 : Y > 0xFFFF ? 0xFFFF : Y; 170 | 171 | X = (s32)(X / 256.5f); 172 | Y = (s32)(Y / 256.5f); 173 | 174 | result = (u16)((Y << 8) | X); 175 | } break; 176 | 177 | case 1: // N64 178 | { 179 | s8 res[2]; 180 | res[0] = (s8)(X / 256.5f); 181 | res[1] = (s8)(Y / 256.5f); 182 | 183 | u16 * r16 = (u16*)&res[0]; 184 | result = r16[0]; 185 | } break; 186 | } 187 | 188 | return result; 189 | } 190 | 191 | //////////////////////////////////////////////////////////////////////// 192 | // DualShock 193 | //////////////////////////////////////////////////////////////////////// 194 | 195 | 196 | void FASTCALL DualshockPoll(u16 * bufferOut, _Settings &set, bool &gamepadPlugged, const bool digital) 197 | { 198 | _Pad pad; 199 | 200 | u16 buttons, buttonsStick, analogL, analogR; 201 | u8 triggerL, triggerR; 202 | 203 | buttons = buttonsStick = 0xFFFF; 204 | analogL = analogR = 0x7F7F; 205 | triggerL = triggerR = 0; 206 | 207 | if(InputGetState(pad, set)) 208 | { 209 | buttons = 0; 210 | buttons |= (~pad.buttons[X360_BACK] & 0x1) << DS_SELECT; 211 | buttons |= (~pad.buttons[X360_LS] & 0x1) << DS_L3; 212 | buttons |= (~pad.buttons[X360_RS] & 0x1) << DS_R3; 213 | buttons |= (~pad.buttons[X360_START] & 0x1) << DS_START; 214 | buttons |= (~pad.buttons[X360_DUP] & 0x1) << DS_UP; 215 | buttons |= (~pad.buttons[X360_DRIGHT]& 0x1) << DS_RIGHT; 216 | buttons |= (~pad.buttons[X360_DDOWN] & 0x1) << DS_DOWN; 217 | buttons |= (~pad.buttons[X360_DLEFT] & 0x1) << DS_LEFT; 218 | 219 | buttons |= (pad.analog[X360_TRIGGERL] > 10 ? 0:1) << DS_L2; 220 | buttons |= (pad.analog[X360_TRIGGERR] > 10 ? 0:1) << DS_R2; 221 | 222 | buttons |= (~pad.buttons[X360_LB] & 0x1) << DS_L1; 223 | buttons |= (~pad.buttons[X360_RB] & 0x1) << DS_R1; 224 | 225 | buttons |= (~pad.buttons[X360_Y] & 0x1) << DS_TRIANGLE; 226 | buttons |= (~pad.buttons[X360_X] & 0x1) << DS_SQUARE; 227 | 228 | if(set.SwapXO) 229 | { 230 | buttons |= (~pad.buttons[X360_A] & 0x1) << DS_CIRCLE; 231 | buttons |= (~pad.buttons[X360_B] & 0x1) << DS_CROSS; 232 | } 233 | else 234 | { 235 | buttons |= (~pad.buttons[X360_B] & 0x1) << DS_CIRCLE; 236 | buttons |= (~pad.buttons[X360_A] & 0x1) << DS_CROSS; 237 | } 238 | 239 | if(digital) 240 | { 241 | u8 stickLD = GetAnalogDigital(pad.stickL, set.stickL); 242 | u8 stickRD = GetAnalogDigital(pad.stickR, set.stickR); 243 | 244 | buttonsStick = buttons | 0x06; 245 | buttonsStick &= ~((stickLD & ANALOGD_XP) << DS_RIGHT); 246 | buttonsStick &= ~(((stickLD & ANALOGD_XN) >> 1) << DS_LEFT); 247 | buttonsStick &= ~(((stickLD & ANALOGD_YP) >> 2) << DS_UP); 248 | buttonsStick &= ~(((stickLD & ANALOGD_YN) >> 3) << DS_DOWN); 249 | 250 | buttonsStick &= ~(((stickRD & ANALOGD_XN) >> 1) << DS_SQUARE); 251 | buttonsStick &= ~(((stickRD & ANALOGD_YP) >> 2) << DS_TRIANGLE); 252 | 253 | if(set.SwapXO) 254 | { 255 | buttonsStick &= ~((stickRD & ANALOGD_XP) << DS_CROSS); 256 | buttonsStick &= ~(((stickRD & ANALOGD_YN) >> 3) << DS_CIRCLE); 257 | } 258 | else 259 | { 260 | buttonsStick &= ~((stickRD & ANALOGD_XP) << DS_CIRCLE); 261 | buttonsStick &= ~(((stickRD & ANALOGD_YN) >> 3) << DS_CROSS); 262 | } 263 | } 264 | else 265 | { 266 | analogL = ConvertAnalog(pad.modL, set.stickL, 0); 267 | analogR = ConvertAnalog(pad.modR, set.stickR, 0); 268 | 269 | triggerL = pad.analog[X360_TRIGGERL] & 0xFF; 270 | triggerR = pad.analog[X360_TRIGGERR] & 0xFF; 271 | } 272 | 273 | //Debug("Pokopom: %04X %04X\n", analogL, analogR); 274 | } 275 | else 276 | gamepadPlugged = false; 277 | 278 | bufferOut[0] = buttons; 279 | bufferOut[1] = buttonsStick; 280 | bufferOut[2] = analogL; 281 | bufferOut[3] = analogR; 282 | bufferOut[4] = (triggerL << 8) | triggerR; 283 | } 284 | 285 | //////////////////////////////////////////////////////////////////////// 286 | // Dreamcast 287 | //////////////////////////////////////////////////////////////////////// 288 | 289 | void FASTCALL DreamcastPoll(u32* buffer_out, _Settings &set, bool &gamepadPlugged) 290 | { 291 | _Pad pad; 292 | 293 | u16* buffer = (u16*) buffer_out; 294 | 295 | // Some magic number... 296 | buffer[0] = 0x0000; 297 | buffer[1] = 0x0100; 298 | 299 | u16 buttons = 0xFFFF; 300 | u16 analog = 0x8080; 301 | u16 triggers = 0x0000; 302 | 303 | static bool analogToggle = false; 304 | 305 | if(InputGetState(pad, set)) 306 | { 307 | buttons = 0; 308 | 309 | buttons |= pad.buttons[X360_A] << DC_A; 310 | buttons |= pad.buttons[X360_B] << DC_B; 311 | buttons |= pad.buttons[X360_X] << DC_X; 312 | buttons |= pad.buttons[X360_Y] << DC_Y; 313 | 314 | buttons |= pad.buttons[X360_DUP] << DC_UP; 315 | buttons |= pad.buttons[X360_DDOWN] << DC_DOWN; 316 | buttons |= pad.buttons[X360_DLEFT] << DC_LEFT; 317 | buttons |= pad.buttons[X360_DRIGHT]<< DC_RIGHT; 318 | 319 | buttons |= pad.buttons[X360_START] << DC_START; 320 | 321 | if(set.SwapDCBumpers) 322 | { 323 | triggers = (pad.buttons[X360_RB] ? 0xFF : (pad.analog[X360_TRIGGERL]&0xFF))<<8; 324 | triggers |= pad.buttons[X360_LB] ? 0xFF : pad.analog[X360_TRIGGERR]&0xFF; 325 | } 326 | else 327 | { 328 | triggers = (pad.buttons[X360_LB] ? 0xFF : (pad.analog[X360_TRIGGERL]&0xFF))<<8; 329 | triggers |= pad.buttons[X360_RB] ? 0xFF : pad.analog[X360_TRIGGERR]&0xFF; 330 | } 331 | 332 | if(pad.buttons[X360_LS]) analogToggle = false; 333 | else if (pad.buttons[X360_RS]) analogToggle = true; 334 | 335 | if(set.SwapSticksEnabled && analogToggle) 336 | { 337 | analog = ConvertAnalog(pad.modR, set.stickR, 0); 338 | 339 | _Stick stickL = pad.modL; 340 | stickL.X *= set.axisInverted[GP_AXIS_LX] ? -1 : 1; 341 | stickL.Y *= set.axisInverted[GP_AXIS_LY] ? -1 : 1; 342 | 343 | u8 stickD = GetAnalogDigital(stickL, set.stickL); 344 | 345 | // Inactive left stick to work as dpad 346 | buttons |= (stickD & ANALOGD_XP) << DC_RIGHT; 347 | buttons |= ((stickD & ANALOGD_XN) >> 1) << DC_LEFT; 348 | buttons |= ((stickD & ANALOGD_YP) >> 2) << DC_UP; 349 | buttons |= ((stickD & ANALOGD_YN) >> 3) << DC_DOWN; 350 | } 351 | else 352 | { 353 | analog = ConvertAnalog(pad.modL, set.stickL, 0); 354 | 355 | _Stick stickR = pad.modR; 356 | stickR.X *= set.axisInverted[GP_AXIS_RX] ? -1 : 1; 357 | stickR.Y *= set.axisInverted[GP_AXIS_RY] ? -1 : 1; 358 | 359 | u8 stickD = GetAnalogDigital(stickR, set.stickR); 360 | 361 | // Inactive right stick to work as face buttons 362 | buttons |= (stickD & ANALOGD_XP) << DC_B; 363 | buttons |= ((stickD & ANALOGD_YP) >> 2) << DC_Y; 364 | buttons |= ((stickD & ANALOGD_XN) >> 1) << DC_X; 365 | buttons |= ((stickD & ANALOGD_YN) >> 3) << DC_A; 366 | } 367 | 368 | buttons = ~buttons; 369 | } 370 | else 371 | gamepadPlugged = false; 372 | 373 | // Buttons 374 | buffer[2] = buttons | 0xF901; 375 | 376 | // Triggers 377 | buffer[3] = triggers; 378 | 379 | // Left Stick 380 | buffer[4] = analog; 381 | 382 | // Right Stick... not present. 383 | buffer[5] = 0x8080; 384 | } 385 | 386 | //////////////////////////////////////////////////////////////////////// 387 | // NAOMI 388 | //////////////////////////////////////////////////////////////////////// 389 | 390 | void FASTCALL NaomiPoll(u32* buffer_out, _Settings &set, bool &gamepadPlugged) 391 | { 392 | _Pad pad[2]; 393 | 394 | u8 * buffer = (u8*)buffer_out; 395 | buffer = &buffer[26]; 396 | 397 | u8 service = 0; 398 | 399 | //DWord analog[2]; 400 | Word player; 401 | 402 | player.bits32 = 0; 403 | //analog[0].bits64 = 0; 404 | //analog[1].bits64 = 0; 405 | 406 | static Word coin; 407 | static bool coinPressed[2] = {false}; 408 | 409 | for(u8 i = 0; i < 2; i++) 410 | if(InputGetState(pad[i], settings[i])) 411 | { 412 | player.bits16[i] |= pad[i].buttons[X360_DRIGHT]<< NAOMI_DRIGHT; 413 | player.bits16[i] |= pad[i].buttons[X360_DLEFT] << NAOMI_DLEFT; 414 | player.bits16[i] |= pad[i].buttons[X360_DDOWN] << NAOMI_DDOWN; 415 | player.bits16[i] |= pad[i].buttons[X360_DUP] << NAOMI_DUP; 416 | 417 | player.bits16[i] |= pad[i].buttons[X360_A] << NAOMI_BUTTON1; 418 | player.bits16[i] |= pad[i].buttons[X360_B] << NAOMI_BUTTON2; 419 | 420 | player.bits16[i] |= pad[i].buttons[X360_X] << NAOMI_BUTTON3; 421 | player.bits16[i] |= pad[i].buttons[X360_Y] << NAOMI_BUTTON4; 422 | player.bits16[i] |= pad[i].buttons[X360_LB] << NAOMI_BUTTON5; 423 | player.bits16[i] |= pad[i].buttons[X360_RB] << NAOMI_BUTTON6; 424 | 425 | /* 426 | analog[i].bits16[0] = (pad[i].analog[X360_STICKLX] + 32768) & 0xFFFF; 427 | analog[i].bits16[1] = (pad[i].analog[X360_STICKLY] + 32768) & 0xFFFF; 428 | analog[i].bits16[2] = (pad[i].analog[X360_STICKRX] + 32768) & 0xFFFF; 429 | analog[i].bits16[3] = (pad[i].analog[X360_STICKRY] + 32768) & 0xFFFF; 430 | */ 431 | 432 | u8 stickD = GetAnalogDigital(pad[i].modL, set.stickL); 433 | 434 | player.bits16[i] |= (stickD & ANALOGD_XP) << NAOMI_DRIGHT; 435 | player.bits16[i] |= ((stickD & ANALOGD_XN) >> 1) << NAOMI_DLEFT; 436 | player.bits16[i] |= ((stickD & ANALOGD_YP) >> 2) << NAOMI_DUP; 437 | player.bits16[i] |= ((stickD & ANALOGD_YN) >> 3) << NAOMI_DDOWN; 438 | 439 | if(pad[i].analog[X360_TRIGGERL] > 100) 440 | { 441 | service |= pad[i].buttons[X360_START] << NAOMI_START; 442 | player.bits16[i] |= pad[i].buttons[X360_BACK] << NAOMI_TEST; 443 | } 444 | else 445 | { 446 | player.bits16[i] |= pad[i].buttons[X360_START] << NAOMI_START; 447 | 448 | if(pad[i].buttons[X360_BACK] && !coinPressed[i]) 449 | { 450 | coinPressed[i] = true; 451 | coin.bits16[i]++; 452 | } 453 | else if(coinPressed[i] && !pad[i].buttons[X360_BACK]) 454 | coinPressed[i] = false; 455 | } 456 | } 457 | 458 | buffer[ 0] = 1; // Enabled? 459 | buffer[ 1] = service; 460 | buffer[ 2] = player.bits8[0]; 461 | buffer[ 3] = player.bits8[1]; 462 | buffer[ 4] = player.bits8[2]; 463 | buffer[ 5] = player.bits8[3]; 464 | buffer[ 6] = 1; 465 | buffer[ 7] = coin.bits8[1]; 466 | buffer[ 8] = coin.bits8[0]; 467 | buffer[ 9] = coin.bits8[3]; 468 | buffer[10] = coin.bits8[2]; 469 | buffer[11] = 0; 470 | 471 | /* Analogs screw things up... =S */ 472 | /* 473 | buffer[12] = analog[0].bits8[1]; 474 | buffer[13] = analog[0].bits8[0]; 475 | buffer[14] = analog[0].bits8[3]; 476 | buffer[15] = analog[0].bits8[2]; 477 | buffer[16] = analog[0].bits8[5]; 478 | buffer[17] = analog[0].bits8[4]; 479 | buffer[18] = analog[0].bits8[7]; 480 | buffer[19] = analog[0].bits8[6]; 481 | buffer[20] = 1;//analog[0].bits8[1]; 482 | buffer[21] = analog[0].bits8[0]; 483 | buffer[22] = analog[0].bits8[3]; 484 | buffer[23] = analog[0].bits8[2]; 485 | buffer[24] = analog[0].bits8[5]; 486 | buffer[25] = analog[0].bits8[4]; 487 | buffer[26] = analog[0].bits8[7]; 488 | buffer[27] = analog[0].bits8[6]; 489 | */ 490 | } 491 | 492 | 493 | //////////////////////////////////////////////////////////////////////// 494 | // Zilmar 495 | //////////////////////////////////////////////////////////////////////// 496 | 497 | void FASTCALL N64controllerPoll(u8 *outBuffer, _Settings &set, bool &gamepadPlugged) 498 | { 499 | _Pad pad; 500 | 501 | u16 buttons = 0; 502 | u16 analog = 0x0000; 503 | 504 | static bool analogToggle = false; 505 | 506 | if(InputGetState(pad, set)) 507 | { 508 | buttons = 0; 509 | 510 | buttons |= pad.buttons[X360_DRIGHT]<< N64_RIGHT; 511 | buttons |= pad.buttons[X360_DLEFT] << N64_LEFT; 512 | buttons |= pad.buttons[X360_DDOWN] << N64_DOWN; 513 | buttons |= pad.buttons[X360_DUP] << N64_UP; 514 | buttons |= pad.buttons[X360_START] << N64_START; 515 | 516 | buttons |= (pad.analog[X360_TRIGGERL] > 10? 1:0) << N64_TRIGGERZ; 517 | 518 | if(pad.analog[X360_TRIGGERR] > 100) 519 | { 520 | buttons |= pad.buttons[X360_X] << N64_CLEFT; 521 | buttons |= pad.buttons[X360_Y] << N64_CUP; 522 | buttons |= pad.buttons[X360_A] << N64_CDOWN; 523 | buttons |= pad.buttons[X360_B] << N64_CRIGHT; 524 | } 525 | else 526 | { 527 | buttons |= pad.buttons[X360_A] << N64_A; 528 | buttons |= pad.buttons[X360_X] << N64_B; 529 | 530 | buttons |= pad.buttons[X360_B] << N64_CDOWN; 531 | buttons |= pad.buttons[X360_Y] << N64_CLEFT; 532 | } 533 | 534 | buttons |= pad.buttons[X360_RB] << N64_TRIGGERR; 535 | buttons |= pad.buttons[X360_LB] << N64_TRIGGERL; 536 | 537 | if(pad.buttons[X360_LS]) analogToggle = false; 538 | else if (pad.buttons[X360_RS]) analogToggle = true; 539 | 540 | if(set.SwapSticksEnabled && analogToggle) 541 | { 542 | analog = ConvertAnalog(pad.modR, set.stickR, 1); 543 | 544 | _Stick stickL = pad.modL; 545 | stickL.X *= set.axisInverted[GP_AXIS_LX] ? -1 : 1; 546 | stickL.Y *= set.axisInverted[GP_AXIS_LY] ? -1 : 1; 547 | 548 | u8 stickD = GetAnalogDigital(stickL, set.stickL); 549 | 550 | buttons |= ((stickD & ANALOGD_XP) << N64_CRIGHT); 551 | buttons |= (((stickD & ANALOGD_XN) >> 1) << N64_CLEFT); 552 | buttons |= (((stickD & ANALOGD_YP) >> 2) << N64_CUP); 553 | buttons |= (((stickD & ANALOGD_YN) >> 3) << N64_CDOWN); 554 | } 555 | else 556 | { 557 | analog = ConvertAnalog(pad.modL, set.stickL, 1); 558 | 559 | _Stick stickR = pad.modR; 560 | stickR.X *= set.axisInverted[GP_AXIS_RX] ? -1 : 1; 561 | stickR.Y *= set.axisInverted[GP_AXIS_RY] ? -1 : 1; 562 | 563 | u8 stickD = GetAnalogDigital(stickR, set.stickR); 564 | 565 | buttons |= ((stickD & ANALOGD_XP) << N64_CRIGHT); 566 | buttons |= (((stickD & ANALOGD_XN) >> 1) << N64_CLEFT); 567 | buttons |= (((stickD & ANALOGD_YP) >> 2) << N64_CUP); 568 | buttons |= (((stickD & ANALOGD_YN) >> 3) << N64_CDOWN); 569 | } 570 | } 571 | else 572 | gamepadPlugged = false; 573 | 574 | u16 * outBig = (u16*)outBuffer; 575 | 576 | outBig[0] = buttons; 577 | outBig[1] = analog; 578 | } 579 | 580 | } // End namespace Input 581 | --------------------------------------------------------------------------------