font rendering fixed, input (WASD and camera rotation) still a little bit buggy

This commit is contained in:
Dennis Eichhorn 2024-10-28 23:11:18 +01:00
parent c7db2069c0
commit c2f4862f22
14 changed files with 438 additions and 166 deletions

View File

@ -186,6 +186,14 @@ void font_from_file(
memcpy(font->glyphs, pos, font->glyph_count * sizeof(Glyph));
#if OPENGL
for (int32 i = 0; i < font->glyph_count; ++i) {
float temp = font->glyphs[i].coords.y1;
font->glyphs[i].coords.y1 = 1.0f - font->glyphs[i].coords.y2;
font->glyphs[i].coords.y2 = 1.0f - temp;
}
#endif
SWAP_ENDIAN_LITTLE_SIMD(
(int32 *) font->glyphs,
(int32 *) font->glyphs,

View File

@ -105,107 +105,4 @@ uint32 hash_ejb(const char* str)
return h % PRIME2;
}
// CONSTEXPR
constexpr
uint64 hash_djb2_const(const char* key) {
uint64 hash = 5381;
int32 c;
while ((c = *key++)) {
hash = ((hash << 5) + hash) + c;
}
return hash;
}
constexpr
uint64 hash_sdbm_const(const byte* key)
{
uint64 hash = 0;
int32 c;
while (c = *key++) {
hash = c + (hash << 6) + (hash << 16) - hash;
}
return hash;
}
constexpr
uint64 hash_lose_lose_const(const byte* key)
{
uint64 hash = 0;
int32 c;
while (c = *key++) {
hash += c;
}
return hash;
}
constexpr
uint64 hash_polynomial_rolling_const(const char* str) {
const int32 p = 31;
const int32 m = 1000000009;
uint64 hash = 0;
uint64 p_pow = 1;
while (*str) {
hash = (hash + (*str - 'a' + 1) * p_pow) % m;
p_pow = (p_pow * p) % m;
str++;
}
return hash;
}
constexpr
uint64 hash_fnv1a_const(const char* str) {
const uint64 FNV_OFFSET_BASIS = 14695981039346656037UL;
const uint64 FNV_PRIME = 1099511628211UL;
uint64 hash = FNV_OFFSET_BASIS;
while (*str) {
hash ^= (byte) *str;
hash *= FNV_PRIME;
str++;
}
return hash;
}
constexpr
uint32 hash_oat_const(const char* str)
{
uint32 h = 0;
while(*str) {
h += *str++;
h += (h << 10);
h ^= (h >> 6);
}
h += (h << 3);
h ^= (h >> 11);
h += (h << 15);
return h;
}
constexpr
uint32 hash_ejb_const(const char* str)
{
const uint32 PRIME1 = 37;
const uint32 PRIME2 = 1048583;
uint32 h = 0;
while (*str) {
h = h * PRIME1 ^ (*str++ - ' ');
}
return h % PRIME2;
}
#endif

View File

@ -24,7 +24,7 @@
struct Image {
uint32 width;
uint32 height;
uint32 pixel_count;
uint32 pixel_count; // @question Do we even need this?
// Image settings
bool has_alpha;

View File

@ -13,6 +13,7 @@
#include "../utils/BitUtils.h"
#include "../memory/BufferMemory.h"
#include "ControllerInput.h"
#include "InputConnectionType.h"
// How many concurrent mouse/secondary input device presses to we recognize
#define MAX_MOUSE_PRESSES 3
@ -50,6 +51,7 @@
#ifdef _WIN32
#include <windows.h>
#include <dinput.h>
#endif
typedef void (*InputCallback)(void* data);
@ -117,14 +119,18 @@ struct InputState {
struct Input {
// Device
bool is_connected;
InputConnectionType connection_type;
#ifdef _WIN32
// @question maybe replace with id?!
// -> remove _WIN32 section?
HANDLE handle_keyboard;
HANDLE handle_mouse;
HANDLE handle_controller;
// @todo support all three versions
int32 controller_id; // used by XInput
HANDLE handle_controller; // used by raw input controller
LPDIRECTINPUTDEVICE8* direct_controller; // used by direct input controller
#endif
bool state_change_button;

View File

@ -0,0 +1,21 @@
/**
* Jingga
*
* @copyright Jingga
* @license OMS License 2.0
* @version 1.0.0
* @link https://jingga.app
*/
#ifndef TOS_PLATFORM_WIN32_INPUT_CONNECTION_TYPE_H
#define TOS_PLATFORM_WIN32_INPUT_CONNECTION_TYPE_H
// Important, since some connection protocols differ between for example USB and Bluetooth (see Playstation DualSense)
enum InputConnectionType {
INPUT_CONNECTION_TYPE_NONE,
INPUT_CONNECTION_TYPE_USB,
INPUT_CONNECTION_TYPE_BLUETOOTH,
INPUT_CONNECTION_TYPE_WIRELESS,
};
#endif

View File

@ -16,6 +16,7 @@
#if _WIN32
#include <windows.h>
#include "../../platform/win32/input/controller/ControllerHandler.h"
#else __linux__
#include <linux/limits.h>
#define MAX_PATH PATH_MAX
@ -352,6 +353,8 @@ struct CSettings {
byte game_interact_radius = 1;
// Game pad settings
byte input_device_types = SETTING_INPUT_DEVICE_TYPE_MOUSE_KEYBOARD;
byte input_controller_handler = CONTROLLER_HANDLER_TYPE_AUTO;
byte stick_left_deadzone = 0;
byte stick_right_deadzone = 0;

View File

@ -78,4 +78,7 @@
#define SETTING_UI_VISIBILITY_DEBUG 2
#define SETTING_UI_VISIBILITY_WIREFRAME 4
#define SETTING_INPUT_DEVICE_TYPE_MOUSE_KEYBOARD 1
#define SETTING_INPUT_DEVICE_TYPE_CONTROLLER 2
#endif

View File

@ -0,0 +1,129 @@
/**
* Jingga
*
* @copyright Jingga
* @license OMS License 2.0
* @version 1.0.0
* @link https://jingga.app
*/
#ifndef TOS_PLATFORM_WIN32_INPUT_DIRECTINPUT_H
#define TOS_PLATFORM_WIN32_INPUT_DIRECTINPUT_H
#include <dinput.h>
#include "../../../input/Input.h"
#include "../../../input/ControllerInput.h"
#include "../../../stdlib/Types.h"
BOOL CALLBACK EnumJoysticksCallback(const DIDEVICEINSTANCE* instance, void* pDevicePtr)
{
LPDIRECTINPUT8 pDirectInput = (LPDIRECTINPUT8)pDevicePtr;
LPDIRECTINPUTDEVICE8* pDIDevice = (LPDIRECTINPUTDEVICE8*)pDevicePtr;
if (SUCCEEDED(pDirectInput->CreateDevice(instance->guidInstance, pDIDevice, NULL))) {
return DIENUM_STOP;
}
return DIENUM_CONTINUE;
}
int32 directinput_init_controllers(HWND hwnd, Input* __restrict states)
{
LPDIRECTINPUT8* pDirectInput = NULL;
HRESULT hr;
// Initialize DirectInput interface if its not already initialized
hr = DirectInput8Create(GetModuleHandle(NULL), DIRECTINPUT_VERSION, IID_IDirectInput8, (void**)pDirectInput, NULL);
if (FAILED(hr)) {
return 0;
}
// Enumerate devices to find a connected game controller
hr = (*pDirectInput)->EnumDevices(DI8DEVCLASS_GAMECTRL, EnumJoysticksCallback, states->direct_controller, DIEDFL_ATTACHEDONLY);
if (FAILED(hr) || *states->direct_controller == NULL) {
return 0;
}
// Set data format for the device to use the joystick state format
hr = (*states->direct_controller)->SetDataFormat(&c_dfDIJoystick2);
if (FAILED(hr)) {
(*states->direct_controller)->Release();
*states->direct_controller = NULL;
return 0;
}
// Set the cooperative level for the device
hr = (*states->direct_controller)->SetCooperativeLevel(hwnd, DISCL_FOREGROUND | DISCL_EXCLUSIVE);
if (FAILED(hr)) {
(*states->direct_controller)->Release();
*states->direct_controller = NULL;
return 0;
}
// Acquire the device for use
hr = (*states->direct_controller)->Acquire();
if (FAILED(hr)) {
(*states->direct_controller)->Release();
*states->direct_controller = NULL;
return 0;
}
return 1;
}
inline void input_map_directinput(ControllerInput* controller, LPDIRECTINPUTDEVICE8 pDIDevice)
{
if (FAILED(pDIDevice->Poll())) {
if (FAILED(pDIDevice->Acquire())) {
return;
}
}
// Define a buffer for DirectInput state
DIJOYSTATE2 controller_state;
if (FAILED(pDIDevice->GetDeviceState(sizeof(DIJOYSTATE2), &controller_state))) {
return;
}
controller->button[CONTROLLER_BUTTON_DPAD_UP] = (controller_state.rgdwPOV[0] == 0) ? 127 : 0;
controller->button[CONTROLLER_BUTTON_DPAD_RIGHT] = (controller_state.rgdwPOV[0] == 9000) ? 127 : 0;
controller->button[CONTROLLER_BUTTON_DPAD_DOWN] = (controller_state.rgdwPOV[0] == 18000) ? 127 : 0;
controller->button[CONTROLLER_BUTTON_DPAD_LEFT] = (controller_state.rgdwPOV[0] == 27000) ? 127 : 0;
controller->button[CONTROLLER_BUTTON_OTHER_0] = (controller_state.rgbButtons[7] & 0x80) ? 127 : 0; // Start
controller->button[CONTROLLER_BUTTON_OTHER_1] = (controller_state.rgbButtons[6] & 0x80) ? 127 : 0; // Back
controller->button[CONTROLLER_BUTTON_SHOULDER_RIGHT_BUTTON] = (controller_state.rgbButtons[5] & 0x80) ? 127 : 0;
controller->button[CONTROLLER_BUTTON_SHOULDER_LEFT_BUTTON] = (controller_state.rgbButtons[4] & 0x80) ? 127 : 0;
controller->button[CONTROLLER_BUTTON_SHOULDER_RIGHT_TRIGGER] = controller_state.lZ > 0 ? controller_state.lZ : 0;
controller->is_analog[CONTROLLER_BUTTON_SHOULDER_RIGHT_TRIGGER] = true;
controller->button[CONTROLLER_BUTTON_SHOULDER_LEFT_TRIGGER] = controller_state.lZ < 0 ? -controller_state.lZ : 0;
controller->is_analog[CONTROLLER_BUTTON_SHOULDER_LEFT_TRIGGER] = true;
controller->button[CONTROLLER_BUTTON_T] = (controller_state.rgbButtons[3] & 0x80) ? 127 : 0;
controller->button[CONTROLLER_BUTTON_C] = (controller_state.rgbButtons[1] & 0x80) ? 127 : 0;
controller->button[CONTROLLER_BUTTON_X] = (controller_state.rgbButtons[0] & 0x80) ? 127 : 0;
controller->button[CONTROLLER_BUTTON_S] = (controller_state.rgbButtons[2] & 0x80) ? 127 : 0;
controller->button[CONTROLLER_BUTTON_STICK_LEFT_HORIZONTAL] = controller_state.lX;
controller->button[CONTROLLER_BUTTON_STICK_LEFT_VERTICAL] = controller_state.lY;
controller->is_analog[CONTROLLER_BUTTON_STICK_LEFT_HORIZONTAL] = true;
controller->is_analog[CONTROLLER_BUTTON_STICK_LEFT_VERTICAL] = true;
controller->button[CONTROLLER_BUTTON_STICK_LEFT_BUTTON] = (controller_state.rgbButtons[8] & 0x80) ? 127 : 0;
controller->button[CONTROLLER_BUTTON_STICK_RIGHT_HORIZONTAL] = controller_state.lRx;
controller->button[CONTROLLER_BUTTON_STICK_RIGHT_VERTICAL] = controller_state.lRy;
controller->is_analog[CONTROLLER_BUTTON_STICK_RIGHT_HORIZONTAL] = true;
controller->is_analog[CONTROLLER_BUTTON_STICK_RIGHT_VERTICAL] = true;
controller->button[CONTROLLER_BUTTON_STICK_RIGHT_BUTTON] = (controller_state.rgbButtons[9] & 0x80) ? 127 : 0;
controller->button[CONTROLLER_BUTTON_OTHER_2] = (controller_state.rgbButtons[10] & 0x80) ? 127 : 0;
controller->button[CONTROLLER_BUTTON_OTHER_3] = (controller_state.rgbButtons[11] & 0x80) ? 127 : 0;
controller->button[CONTROLLER_BUTTON_OTHER_4] = (controller_state.rgbButtons[12] & 0x80) ? 127 : 0;
controller->button[CONTROLLER_BUTTON_OTHER_5] = (controller_state.rgbButtons[13] & 0x80) ? 127 : 0;
controller->button[CONTROLLER_BUTTON_OTHER_6] = (controller_state.rgbButtons[14] & 0x80) ? 127 : 0;
controller->button[CONTROLLER_BUTTON_OTHER_7] = (controller_state.rgbButtons[15] & 0x80) ? 127 : 0;
}
#endif

View File

@ -32,7 +32,7 @@
// Even if it is nowhere documented (at least not to our knowledge) the GetRawInputDeviceInfoA, GetRawInputBuffer functions requried
// aligned memory. So far we only figured out that 4 bytes works, maybe this needs to be 8 in the future?!
int input_raw_init(HWND hwnd, Input* __restrict states, RingMemory* ring)
int rawinput_init_mousekeyboard(HWND hwnd, Input* __restrict states, RingMemory* ring)
{
uint32 device_count;
GetRawInputDeviceList(NULL, &device_count, sizeof(RAWINPUTDEVICELIST));
@ -66,7 +66,7 @@ int input_raw_init(HWND hwnd, Input* __restrict states, RingMemory* ring)
}
states[mouse_found].handle_mouse = pRawInputDeviceList[i].hDevice;
states[mouse_found].is_connected = true;
states[mouse_found].connection_type = INPUT_CONNECTION_TYPE_USB;
// Mouse
rid[0].usUsagePage = 0x01; // @todo doesn't work with 0x05 for games?
@ -85,7 +85,7 @@ int input_raw_init(HWND hwnd, Input* __restrict states, RingMemory* ring)
}
states[keyboard_found].handle_keyboard = pRawInputDeviceList[i].hDevice;
states[keyboard_found].is_connected = true;
states[keyboard_found].connection_type = INPUT_CONNECTION_TYPE_USB;
// Keyboard
rid[0].usUsagePage = 0x01; // @todo doesn't work with 0x05 for games?
@ -98,6 +98,40 @@ int input_raw_init(HWND hwnd, Input* __restrict states, RingMemory* ring)
ASSERT_SIMPLE(false);
}
} break;
}
}
return i;
}
int rawinput_init_controllers(HWND hwnd, Input* __restrict states, RingMemory* ring)
{
uint32 device_count;
GetRawInputDeviceList(NULL, &device_count, sizeof(RAWINPUTDEVICELIST));
PRAWINPUTDEVICELIST pRawInputDeviceList = (PRAWINPUTDEVICELIST) ring_get_memory(ring, sizeof(RAWINPUTDEVICELIST) * device_count, 4);
device_count = GetRawInputDeviceList(pRawInputDeviceList, &device_count, sizeof(RAWINPUTDEVICELIST));
// We always want at least one empty input device slot
// @todo Change so that we store the actual number of devices
if (device_count == 0) {
return 0;
}
uint32 cb_size = 256;
int32 mouse_found = 0;
int32 keyboard_found = 0;
int32 controller_found = 0;
int32 i;
for (i = 0; i < device_count; ++i) {
cb_size = sizeof(RID_DEVICE_INFO);
RID_DEVICE_INFO rdi;
GetRawInputDeviceInfoA(pRawInputDeviceList[i].hDevice, RIDI_DEVICEINFO, &rdi, &cb_size);
RAWINPUTDEVICE rid[1];
switch (rdi.dwType) {
case RIM_TYPEHID: {
if (rdi.hid.usUsage == 0x05) {
if (states[controller_found].handle_controller != NULL) {
@ -105,7 +139,8 @@ int input_raw_init(HWND hwnd, Input* __restrict states, RingMemory* ring)
}
states[controller_found].handle_controller = pRawInputDeviceList[i].hDevice;
states[controller_found].is_connected = true;
// @bug This is not always true, how to check?
states[controller_found].connection_type = INPUT_CONNECTION_TYPE_USB;
// Gamepad
rid[0].usUsagePage = 0x01;
@ -123,7 +158,8 @@ int input_raw_init(HWND hwnd, Input* __restrict states, RingMemory* ring)
}
states[controller_found].handle_controller = pRawInputDeviceList[i].hDevice;
states[controller_found].is_connected = true;
// @bug This is not always true, how to check?
states[controller_found].connection_type = INPUT_CONNECTION_TYPE_USB;
// Joystick
rid[0].usUsagePage = 0x01;
@ -155,11 +191,11 @@ void input_mouse_position(HWND hwnd, v2_int32* pos)
}
}
int32 input_raw_handle(RAWINPUT* __restrict raw, Input* states, int state_count, uint64 time)
int32 input_raw_handle(RAWINPUT* __restrict raw, Input* states, int32 state_count, uint64 time)
{
int32 input_count = 0;
uint32 i = 0;
int32 i = 0;
if (raw->header.dwType == RIM_TYPEMOUSE) {
// @performance Change so we can directly access the correct state (maybe map handle address to index?)
while (i < state_count
@ -168,7 +204,7 @@ int32 input_raw_handle(RAWINPUT* __restrict raw, Input* states, int state_count,
++i;
}
if (i >= state_count || !states[i].is_connected) {
if (i >= state_count || !states[i].connection_type) {
return 0;
}
@ -273,7 +309,7 @@ int32 input_raw_handle(RAWINPUT* __restrict raw, Input* states, int state_count,
++i;
}
if (i >= state_count || !states[i].is_connected) {
if (i >= state_count || !states[i].connection_type) {
return 0;
}
@ -294,27 +330,28 @@ int32 input_raw_handle(RAWINPUT* __restrict raw, Input* states, int state_count,
states[i].state_change_button = true;
} else if (raw->header.dwType == RIM_TYPEHID) {
if (raw->header.dwSize > sizeof(RAWINPUT)) {
// @todo Find a way to handle most common controllers
// DualSense
// Xbox
// @performance This shouldn't be done every time, it should be polling based
// Controllers often CONSTANTLY send data -> really bad
// Maybe we can add timer usage
// Maybe we can add timer usage instead of polling?
while (i < state_count
&& states[i].handle_controller != raw->header.hDevice
) {
++i;
}
if (i >= state_count || !states[i].is_connected
if (i >= state_count || !states[i].connection_type
|| time - states[i].time_last_input_check < 5
) {
return 0;
}
// @todo Find a way to handle most common controllers
// DualSense
// Xbox
// Xinput
// Best way would probably to define the controller type in the input
ControllerInput controller = {};
input_map_dualshock4(&controller, raw->data.hid.bRawData);
input_map_dualshock4(&controller, states[i].connection_type, raw->data.hid.bRawData);
input_set_controller_state(&states[i], &controller, time);
states[i].time_last_input_check = time;

View File

@ -56,7 +56,7 @@ void xinput_load() {
}
// END: Dynamically load XInput
ControllerInput* init_controllers()
ControllerInput* xinput_init_controllers()
{
uint32 c = 0;
for (uint32 controller_index = 0; controller_index < XUSER_MAX_COUNT; ++controller_index) {
@ -85,49 +85,45 @@ ControllerInput* init_controllers()
return controllers;
}
void handle_controller_input(ControllerInput* states)
inline
void input_map_xinput(ControllerInput* controller, int32 controller_id)
{
/*
uint32 controller_index = 0;
while(states[controller_index].is_connected) {
XINPUT_STATE controller_state;
if (XInputGetState(controller_index, &controller_state) != ERROR_SUCCESS) {
++controller_index;
continue;
if (XInputGetState(controller_id, &controller_state) != ERROR_SUCCESS) {
return;
}
controller->button[CONTROLLER_BUTTON_DPAD_LEFT] = (controller_state.Gamepad.wButtons & XINPUT_GAMEPAD_DPAD_LEFT) * 127;
controller->button[CONTROLLER_BUTTON_DPAD_RIGHT] = (controller_state.Gamepad.wButtons & XINPUT_GAMEPAD_DPAD_RIGHT) * 127;
controller->button[CONTROLLER_BUTTON_DPAD_UP] = (controller_state.Gamepad.wButtons & XINPUT_GAMEPAD_DPAD_UP) * 127;
controller->button[CONTROLLER_BUTTON_DPAD_DOWN] = (controller_state.Gamepad.wButtons & XINPUT_GAMEPAD_DPAD_DOWN) * 127;
states[controller_index].up = controller_state.Gamepad.wButtons & XINPUT_GAMEPAD_DPAD_UP;
states[controller_index].down = controller_state.Gamepad.wButtons & XINPUT_GAMEPAD_DPAD_DOWN;
states[controller_index].left = controller_state.Gamepad.wButtons & XINPUT_GAMEPAD_DPAD_LEFT;
states[controller_index].right = controller_state.Gamepad.wButtons & XINPUT_GAMEPAD_DPAD_RIGHT;
states[controller_index].button[6] = controller_state.Gamepad.wButtons & XINPUT_GAMEPAD_START;
states[controller_index].button[7] = controller_state.Gamepad.wButtons & XINPUT_GAMEPAD_BACK;
controller->button[CONTROLLER_BUTTON_OTHER_0] = controller_state.Gamepad.wButtons & XINPUT_GAMEPAD_START;
controller->button[CONTROLLER_BUTTON_OTHER_1] = controller_state.Gamepad.wButtons & XINPUT_GAMEPAD_BACK;
states[controller_index].button[4] = controller_state.Gamepad.wButtons & XINPUT_GAMEPAD_LEFT_SHOULDER;
states[controller_index].button[5] = controller_state.Gamepad.wButtons & XINPUT_GAMEPAD_RIGHT_SHOULDER;
controller->button[CONTROLLER_BUTTON_SHOULDER_RIGHT_BUTTON] = controller_state.Gamepad.wButtons & XINPUT_GAMEPAD_RIGHT_SHOULDER ? 1: 0;
controller->button[CONTROLLER_BUTTON_SHOULDER_LEFT_BUTTON] = controller_state.Gamepad.wButtons & XINPUT_GAMEPAD_LEFT_SHOULDER ? 1: 0;
states[controller_index].trigger[0] = controller_state.Gamepad.bLeftTrigger;
states[controller_index].trigger[1] = controller_state.Gamepad.bRightTrigger;
controller->button[CONTROLLER_BUTTON_SHOULDER_RIGHT_TRIGGER] = controller_state.Gamepad.bRightTrigger;
controller->is_analog[CONTROLLER_BUTTON_SHOULDER_RIGHT_TRIGGER] = true;
states[controller_index].button[0] = controller_state.Gamepad.wButtons & XINPUT_GAMEPAD_A;
states[controller_index].button[1] = controller_state.Gamepad.wButtons & XINPUT_GAMEPAD_B;
states[controller_index].button[2] = controller_state.Gamepad.wButtons & XINPUT_GAMEPAD_X;
states[controller_index].button[3] = controller_state.Gamepad.wButtons & XINPUT_GAMEPAD_Y;
controller->button[CONTROLLER_BUTTON_SHOULDER_LEFT_TRIGGER] = controller_state.Gamepad.bLeftTrigger;
controller->is_analog[CONTROLLER_BUTTON_SHOULDER_LEFT_TRIGGER] = true;
states[controller_index].stickl_x = controller_state.Gamepad.sThumbLX;
states[controller_index].stickl_y = controller_state.Gamepad.sThumbLY;
states[controller_index].stickl_press = controller_state.Gamepad.wButtons & XINPUT_GAMEPAD_LEFT_THUMB;
controller->button[CONTROLLER_BUTTON_T] = controller_state.Gamepad.wButtons & XINPUT_GAMEPAD_Y ? 1: 0;
controller->button[CONTROLLER_BUTTON_C] = controller_state.Gamepad.wButtons & XINPUT_GAMEPAD_B ? 1: 0;
controller->button[CONTROLLER_BUTTON_X] = controller_state.Gamepad.wButtons & XINPUT_GAMEPAD_A ? 1: 0;
controller->button[CONTROLLER_BUTTON_S] = controller_state.Gamepad.wButtons & XINPUT_GAMEPAD_X ? 1: 0;
states[controller_index].stickr_x = controller_state.Gamepad.sThumbRX;
states[controller_index].stickr_y = controller_state.Gamepad.sThumbRY;
states[controller_index].stickr_press = controller_state.Gamepad.wButtons & XINPUT_GAMEPAD_RIGHT_THUMB;
controller->button[CONTROLLER_BUTTON_STICK_LEFT_HORIZONTAL] = (byte) OMS_MIN(controller_state.Gamepad.sThumbLX, 127);
controller->button[CONTROLLER_BUTTON_STICK_LEFT_VERTICAL] = (byte) OMS_MIN(controller_state.Gamepad.sThumbLY, 127);
controller->is_analog[CONTROLLER_BUTTON_STICK_LEFT_VERTICAL] = true;
controller->button[CONTROLLER_BUTTON_STICK_LEFT_BUTTON] = controller_state.Gamepad.wButtons & XINPUT_GAMEPAD_LEFT_THUMB;
++controller_index;
}
*/
controller->button[CONTROLLER_BUTTON_STICK_RIGHT_HORIZONTAL] = (byte) OMS_MIN(controller_state.Gamepad.sThumbRX, 127);
controller->button[CONTROLLER_BUTTON_STICK_RIGHT_VERTICAL] = (byte) OMS_MIN(controller_state.Gamepad.sThumbRY, 127);
controller->is_analog[CONTROLLER_BUTTON_STICK_RIGHT_VERTICAL] = true;
controller->button[CONTROLLER_BUTTON_STICK_RIGHT_BUTTON] = controller_state.Gamepad.wButtons & XINPUT_GAMEPAD_RIGHT_THUMB;
}
#endif

View File

@ -0,0 +1,21 @@
/**
* Jingga
*
* @copyright Jingga
* @license OMS License 2.0
* @version 1.0.0
* @link https://jingga.app
*/
#ifndef TOS_PLATFORM_WIN32_INPUT_CONTROLLER_HANDLER_H
#define TOS_PLATFORM_WIN32_INPUT_CONTROLLER_HANDLER_H
enum ControllerHandlerType {
CONTROLLER_HANDLER_TYPE_AUTO, // Automatically picks a handler based on the device info and hard coded preferences
CONTROLLER_HANDLER_TYPE_XINPUT,
CONTROLLER_HANDLER_TYPE_DIRECTINPUT,
CONTROLLER_HANDLER_TYPE_RAWINPUT_DS,
CONTROLLER_HANDLER_TYPE_RAWINPUT_DS4,
CONTROLLER_HANDLER_TYPE_RAWINPUT_XBOXS,
};
#endif

View File

@ -0,0 +1,142 @@
/**
* Jingga
*
* @copyright Jingga
* @license OMS License 2.0
* @version 1.0.0
* @link https://jingga.app
* @see https://dsremap.readthedocs.io/en/latest/reverse.html
*/
#ifndef TOS_PLATFORM_WIN32_INPUT_CONTROLLER_DUALSENSE_H
#define TOS_PLATFORM_WIN32_INPUT_CONTROLLER_DUALSENSE_H
#include "../../../../stdlib/Types.h"
#include "../../../../input/ControllerInput.h"
#include "../../../../input/InputConnectionType.h"
#include "../../../../utils/BitUtils.h"
#include "../../../../utils/MathUtils.h"
// @bug bluetooth and USB have different formats?!
// https://github.com/nondebug/dualsense
inline
void input_map_dualsense(ControllerInput* controller, InputConnectionType connection_type, byte* data)
{
// 0 is not the origin -> need to shift
++data;
controller->button[CONTROLLER_BUTTON_STICK_LEFT_HORIZONTAL] = *data++;
controller->button[CONTROLLER_BUTTON_STICK_LEFT_HORIZONTAL] = OMS_MIN(controller->button[CONTROLLER_BUTTON_STICK_LEFT_HORIZONTAL] - 128, 127);
controller->is_analog[CONTROLLER_BUTTON_STICK_LEFT_HORIZONTAL] = true;
controller->button[CONTROLLER_BUTTON_STICK_LEFT_VERTICAL] = *data++;
controller->button[CONTROLLER_BUTTON_STICK_LEFT_VERTICAL] = OMS_MIN(controller->button[CONTROLLER_BUTTON_STICK_LEFT_VERTICAL] - 128, 127);
controller->is_analog[CONTROLLER_BUTTON_STICK_LEFT_VERTICAL] = true;
controller->button[CONTROLLER_BUTTON_STICK_RIGHT_HORIZONTAL] = *data++;
controller->button[CONTROLLER_BUTTON_STICK_RIGHT_HORIZONTAL] = OMS_MIN(controller->button[CONTROLLER_BUTTON_STICK_RIGHT_HORIZONTAL] - 128, 127);
controller->is_analog[CONTROLLER_BUTTON_STICK_RIGHT_HORIZONTAL] = true;
controller->button[CONTROLLER_BUTTON_STICK_RIGHT_VERTICAL] = *data++;
controller->button[CONTROLLER_BUTTON_STICK_RIGHT_VERTICAL] = OMS_MIN(controller->button[CONTROLLER_BUTTON_STICK_RIGHT_VERTICAL] - 128, 127);
controller->is_analog[CONTROLLER_BUTTON_STICK_RIGHT_VERTICAL] = true;
if (connection_type == INPUT_CONNECTION_TYPE_USB) {
controller->button[CONTROLLER_BUTTON_SHOULDER_LEFT_TRIGGER] = *data++;
controller->is_analog[CONTROLLER_BUTTON_SHOULDER_LEFT_TRIGGER] = true;
controller->button[CONTROLLER_BUTTON_SHOULDER_RIGHT_TRIGGER] = *data++;
controller->is_analog[CONTROLLER_BUTTON_SHOULDER_RIGHT_TRIGGER] = true;
// Some counter
++data;
}
controller->button[CONTROLLER_BUTTON_T] = BITS_GET_8_L2R(*data, 0, 1);
controller->button[CONTROLLER_BUTTON_C] = BITS_GET_8_L2R(*data, 1, 1);
controller->button[CONTROLLER_BUTTON_X] = BITS_GET_8_L2R(*data, 2, 1);
controller->button[CONTROLLER_BUTTON_S] = BITS_GET_8_L2R(*data, 3, 1);
uint32 d_pad_state = BITS_GET_8_L2R(*data, 4, 4);
if (d_pad_state == 8) {
controller->button[CONTROLLER_BUTTON_DPAD_LEFT] = 0;
controller->button[CONTROLLER_BUTTON_DPAD_RIGHT] = 0;
controller->button[CONTROLLER_BUTTON_DPAD_UP] = 0;
controller->button[CONTROLLER_BUTTON_DPAD_DOWN] = 0;
} else if (d_pad_state == 0) {
controller->button[CONTROLLER_BUTTON_DPAD_LEFT] = 0;
controller->button[CONTROLLER_BUTTON_DPAD_RIGHT] = 0;
controller->button[CONTROLLER_BUTTON_DPAD_UP] = 127;
controller->button[CONTROLLER_BUTTON_DPAD_DOWN] = 0;
} else if (d_pad_state == 1) {
controller->button[CONTROLLER_BUTTON_DPAD_LEFT] = 0;
controller->button[CONTROLLER_BUTTON_DPAD_RIGHT] = 127;
controller->button[CONTROLLER_BUTTON_DPAD_UP] = 127;
controller->button[CONTROLLER_BUTTON_DPAD_DOWN] = 0;
} else if (d_pad_state == 2) {
controller->button[CONTROLLER_BUTTON_DPAD_LEFT] = 0;
controller->button[CONTROLLER_BUTTON_DPAD_RIGHT] = 127;
controller->button[CONTROLLER_BUTTON_DPAD_UP] = 0;
controller->button[CONTROLLER_BUTTON_DPAD_DOWN] = 0;
} else if (d_pad_state == 3) {
controller->button[CONTROLLER_BUTTON_DPAD_LEFT] = 0;
controller->button[CONTROLLER_BUTTON_DPAD_RIGHT] = 127;
controller->button[CONTROLLER_BUTTON_DPAD_UP] = 0;
controller->button[CONTROLLER_BUTTON_DPAD_DOWN] = 127;
} else if (d_pad_state == 4) {
controller->button[CONTROLLER_BUTTON_DPAD_LEFT] = 0;
controller->button[CONTROLLER_BUTTON_DPAD_RIGHT] = 0;
controller->button[CONTROLLER_BUTTON_DPAD_UP] = 0;
controller->button[CONTROLLER_BUTTON_DPAD_DOWN] = 127;
} else if (d_pad_state == 5) {
controller->button[CONTROLLER_BUTTON_DPAD_LEFT] = 127;
controller->button[CONTROLLER_BUTTON_DPAD_RIGHT] = 0;
controller->button[CONTROLLER_BUTTON_DPAD_UP] = 0;
controller->button[CONTROLLER_BUTTON_DPAD_DOWN] = 127;
} else if (d_pad_state == 6) {
controller->button[CONTROLLER_BUTTON_DPAD_LEFT] = 127;
controller->button[CONTROLLER_BUTTON_DPAD_RIGHT] = 0;
controller->button[CONTROLLER_BUTTON_DPAD_UP] = 0;
controller->button[CONTROLLER_BUTTON_DPAD_DOWN] = 0;
} else if (d_pad_state == 7) {
controller->button[CONTROLLER_BUTTON_DPAD_LEFT] = 127;
controller->button[CONTROLLER_BUTTON_DPAD_RIGHT] = 0;
controller->button[CONTROLLER_BUTTON_DPAD_UP] = 127;
controller->button[CONTROLLER_BUTTON_DPAD_DOWN] = 0;
}
++data;
controller->button[CONTROLLER_BUTTON_STICK_RIGHT_BUTTON] = BITS_GET_8_L2R(*data, 0, 1);
controller->button[CONTROLLER_BUTTON_STICK_LEFT_BUTTON] = BITS_GET_8_L2R(*data, 1, 1);
controller->button[CONTROLLER_BUTTON_OTHER_0] = BITS_GET_8_L2R(*data, 2, 1); // option
controller->button[CONTROLLER_BUTTON_OTHER_1] = BITS_GET_8_L2R(*data, 3, 1); // share
controller->button[CONTROLLER_BUTTON_SHOULDER_RIGHT_BUTTON] = BITS_GET_8_L2R(*data, 6, 1);
controller->button[CONTROLLER_BUTTON_SHOULDER_LEFT_BUTTON] = BITS_GET_8_L2R(*data, 7, 1);
++data;
controller->button[CONTROLLER_BUTTON_OTHER_2] = BITS_GET_8_L2R(*data, 5, 1); // mute
controller->button[CONTROLLER_BUTTON_OTHER_3] = BITS_GET_8_L2R(*data, 6, 1); // tpad
controller->button[CONTROLLER_BUTTON_OTHER_4] = BITS_GET_8_L2R(*data, 7, 1); // ps
++data;
if (connection_type == INPUT_CONNECTION_TYPE_BLUETOOTH) {
controller->button[CONTROLLER_BUTTON_SHOULDER_LEFT_TRIGGER] = *data++;
controller->is_analog[CONTROLLER_BUTTON_SHOULDER_LEFT_TRIGGER] = true;
controller->button[CONTROLLER_BUTTON_SHOULDER_RIGHT_TRIGGER] = *data++;
controller->is_analog[CONTROLLER_BUTTON_SHOULDER_RIGHT_TRIGGER] = true;
}
data += 22;
// @question pure guess
controller->gyro_x = *data++;
controller->gyro_y = *data++;
controller->gyro_z = *data++;
}
#endif

View File

@ -5,20 +5,28 @@
* @license OMS License 2.0
* @version 1.0.0
* @link https://jingga.app
* @see https://dsremap.readthedocs.io/en/latest/reverse.html
*/
#ifndef TOS_PLATFORM_WIN32_INPUT_CONTROLLER_DUALSHOCK4_H
#define TOS_PLATFORM_WIN32_INPUT_CONTROLLER_DUALSHOCK4_H
#include "../../../../stdlib/Types.h"
#include "../../../../input/ControllerInput.h"
#include "../../../../input/InputConnectionType.h"
#include "../../../../utils/BitUtils.h"
#include "../../../../utils/MathUtils.h"
inline
void input_map_dualshock4(ControllerInput* controller, byte* data)
void input_map_dualshock4(ControllerInput* controller, InputConnectionType connection_type, byte* data)
{
// 0 is not the origin -> need to shift
++data;
// 0 is not the origin -> need to shift
// @question Do we even need this? This might not be send on Windows
if (connection_type == INPUT_CONNECTION_TYPE_BLUETOOTH) {
++data;
}
controller->button[CONTROLLER_BUTTON_STICK_LEFT_HORIZONTAL] = *data++;
controller->button[CONTROLLER_BUTTON_STICK_LEFT_HORIZONTAL] = OMS_MIN(controller->button[CONTROLLER_BUTTON_STICK_LEFT_HORIZONTAL] - 128, 127);
controller->is_analog[CONTROLLER_BUTTON_STICK_LEFT_HORIZONTAL] = true;

View File

@ -33,6 +33,7 @@
#define BIT_UNSET_R2L(num, pos) ((num) & ~((uint32) 1 << (pos)))
#define BIT_FLIP_R2L(num, pos) ((num) ^ ((uint32) 1 << (pos)))
#define BIT_SET_TO_R2L(num, pos, x) ((num) & ~((uint32) 1 << (pos)) | ((uint32) (x) << (pos)))
// @performance Try to use this version over the L2R version for performance reasons
#define BITS_GET_8_R2L(num, pos, to_read) (((num) >> (pos)) & ((1U << (to_read)) - 1))
#define BITS_GET_16_R2L(num, pos, to_read) (((num) >> (pos)) & ((1U << (to_read)) - 1))
#define BITS_GET_32_R2L(num, pos, to_read) (((num) >> (pos)) & ((1U << (to_read)) - 1))