mirror of
https://git.sr.ht/~thestr4ng3r/chiaki
synced 2025-08-19 13:09:39 -07:00
Add switch rumble and motion feedbacks
This commit is contained in:
parent
9ab84e6054
commit
acf15480f2
7 changed files with 255 additions and 100 deletions
|
@ -69,12 +69,6 @@ class PSRemotePlay : public brls::View
|
||||||
// to send gamepad inputs
|
// to send gamepad inputs
|
||||||
Host *host;
|
Host *host;
|
||||||
brls::Label *label;
|
brls::Label *label;
|
||||||
ChiakiControllerState state = {0};
|
|
||||||
// FPS calculation
|
|
||||||
// double base_time;
|
|
||||||
// int frame_counter = 0;
|
|
||||||
// int fps = 0;
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
PSRemotePlay(Host *host);
|
PSRemotePlay(Host *host);
|
||||||
~PSRemotePlay();
|
~PSRemotePlay();
|
||||||
|
|
|
@ -54,7 +54,9 @@ class Host
|
||||||
std::function<void()> chiaki_regist_event_type_finished_success = nullptr;
|
std::function<void()> chiaki_regist_event_type_finished_success = nullptr;
|
||||||
std::function<void()> chiaki_event_connected_cb = nullptr;
|
std::function<void()> chiaki_event_connected_cb = nullptr;
|
||||||
std::function<void(bool)> chiaki_even_login_pin_request_cb = nullptr;
|
std::function<void(bool)> chiaki_even_login_pin_request_cb = nullptr;
|
||||||
|
std::function<void(uint8_t, uint8_t)> chiaki_event_rumble_cb = nullptr;
|
||||||
std::function<void(ChiakiQuitEvent *)> chiaki_event_quit_cb = nullptr;
|
std::function<void(ChiakiQuitEvent *)> chiaki_event_quit_cb = nullptr;
|
||||||
|
std::function<void(ChiakiControllerState *)> io_read_controller_cb = nullptr;
|
||||||
|
|
||||||
// internal state
|
// internal state
|
||||||
bool discovered = false;
|
bool discovered = false;
|
||||||
|
@ -73,6 +75,7 @@ class Host
|
||||||
std::string server_nickname;
|
std::string server_nickname;
|
||||||
ChiakiTarget target = CHIAKI_TARGET_PS4_UNKNOWN;
|
ChiakiTarget target = CHIAKI_TARGET_PS4_UNKNOWN;
|
||||||
ChiakiDiscoveryHostState state = CHIAKI_DISCOVERY_HOST_STATE_UNKNOWN;
|
ChiakiDiscoveryHostState state = CHIAKI_DISCOVERY_HOST_STATE_UNKNOWN;
|
||||||
|
ChiakiControllerState controller_state = {0};
|
||||||
|
|
||||||
// mac address = 48 bits
|
// mac address = 48 bits
|
||||||
uint8_t server_mac[6] = {0};
|
uint8_t server_mac[6] = {0};
|
||||||
|
@ -96,7 +99,7 @@ class Host
|
||||||
int FiniSession();
|
int FiniSession();
|
||||||
void StopSession();
|
void StopSession();
|
||||||
void StartSession();
|
void StartSession();
|
||||||
void SendFeedbackState(ChiakiControllerState *);
|
void SendFeedbackState();
|
||||||
void RegistCB(ChiakiRegistEvent *);
|
void RegistCB(ChiakiRegistEvent *);
|
||||||
void ConnectionEventCB(ChiakiEvent *);
|
void ConnectionEventCB(ChiakiEvent *);
|
||||||
bool GetVideoResolution(int *ret_width, int *ret_height);
|
bool GetVideoResolution(int *ret_width, int *ret_height);
|
||||||
|
@ -110,7 +113,9 @@ class Host
|
||||||
void SetRegistEventTypeFinishedSuccess(std::function<void()> chiaki_regist_event_type_finished_success);
|
void SetRegistEventTypeFinishedSuccess(std::function<void()> chiaki_regist_event_type_finished_success);
|
||||||
void SetEventConnectedCallback(std::function<void()> chiaki_event_connected_cb);
|
void SetEventConnectedCallback(std::function<void()> chiaki_event_connected_cb);
|
||||||
void SetEventLoginPinRequestCallback(std::function<void(bool)> chiaki_even_login_pin_request_cb);
|
void SetEventLoginPinRequestCallback(std::function<void(bool)> chiaki_even_login_pin_request_cb);
|
||||||
|
void SetEventRumbleCallback(std::function<void(uint8_t, uint8_t)> chiaki_event_rumble_cb);
|
||||||
void SetEventQuitCallback(std::function<void(ChiakiQuitEvent *)> chiaki_event_quit_cb);
|
void SetEventQuitCallback(std::function<void(ChiakiQuitEvent *)> chiaki_event_quit_cb);
|
||||||
|
void SetReadControllerCallback(std::function<void(ChiakiControllerState *)> io_read_controller_cb);
|
||||||
bool IsRegistered();
|
bool IsRegistered();
|
||||||
bool IsDiscovered();
|
bool IsDiscovered();
|
||||||
bool IsReady();
|
bool IsReady();
|
||||||
|
|
|
@ -28,6 +28,12 @@ Omit khrplatform: False
|
||||||
Reproducible: False
|
Reproducible: False
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#ifdef __SWITCH__
|
||||||
|
#include <switch.h>
|
||||||
|
#else
|
||||||
|
#include <iostream>
|
||||||
|
#endif
|
||||||
|
|
||||||
#include <mutex>
|
#include <mutex>
|
||||||
extern "C"
|
extern "C"
|
||||||
{
|
{
|
||||||
|
@ -65,6 +71,11 @@ class IO
|
||||||
SDL_AudioDeviceID sdl_audio_device_id = 0;
|
SDL_AudioDeviceID sdl_audio_device_id = 0;
|
||||||
SDL_Event sdl_event;
|
SDL_Event sdl_event;
|
||||||
SDL_Joystick *sdl_joystick_ptr[SDL_JOYSTICK_COUNT] = {0};
|
SDL_Joystick *sdl_joystick_ptr[SDL_JOYSTICK_COUNT] = {0};
|
||||||
|
#ifdef __SWITCH__
|
||||||
|
PadState pad;
|
||||||
|
HidSixAxisSensorHandle sixaxis_handles[4];
|
||||||
|
HidVibrationDeviceHandle vibration_handles[2][2];
|
||||||
|
#endif
|
||||||
GLuint vao;
|
GLuint vao;
|
||||||
GLuint vbo;
|
GLuint vbo;
|
||||||
GLuint tex[PLANES_COUNT];
|
GLuint tex[PLANES_COUNT];
|
||||||
|
@ -86,7 +97,7 @@ class IO
|
||||||
void SetOpenGlYUVPixels(AVFrame *frame);
|
void SetOpenGlYUVPixels(AVFrame *frame);
|
||||||
bool ReadGameKeys(SDL_Event *event, ChiakiControllerState *state);
|
bool ReadGameKeys(SDL_Event *event, ChiakiControllerState *state);
|
||||||
bool ReadGameTouchScreen(ChiakiControllerState *state);
|
bool ReadGameTouchScreen(ChiakiControllerState *state);
|
||||||
|
bool ReadGameSixAxis(ChiakiControllerState *state);
|
||||||
public:
|
public:
|
||||||
// singleton configuration
|
// singleton configuration
|
||||||
IO(const IO&) = delete;
|
IO(const IO&) = delete;
|
||||||
|
@ -100,9 +111,11 @@ class IO
|
||||||
void AudioCB(int16_t *buf, size_t samples_count);
|
void AudioCB(int16_t *buf, size_t samples_count);
|
||||||
bool InitVideo(int video_width, int video_height, int screen_width, int screen_height);
|
bool InitVideo(int video_width, int video_height, int screen_width, int screen_height);
|
||||||
bool FreeVideo();
|
bool FreeVideo();
|
||||||
bool InitJoystick();
|
bool InitController();
|
||||||
bool FreeJoystick();
|
bool FreeController();
|
||||||
bool MainLoop(ChiakiControllerState *state);
|
bool MainLoop();
|
||||||
|
void UpdateControllerState(ChiakiControllerState *state);
|
||||||
|
void SetRumble(uint8_t left, uint8_t right);
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif //CHIAKI_IO_H
|
#endif //CHIAKI_IO_H
|
||||||
|
|
|
@ -42,6 +42,9 @@ HostInterface::HostInterface(Host *host)
|
||||||
// when the host is connected
|
// when the host is connected
|
||||||
this->host->SetEventConnectedCallback(std::bind(&HostInterface::Stream, this));
|
this->host->SetEventConnectedCallback(std::bind(&HostInterface::Stream, this));
|
||||||
this->host->SetEventQuitCallback(std::bind(&HostInterface::CloseStream, this, std::placeholders::_1));
|
this->host->SetEventQuitCallback(std::bind(&HostInterface::CloseStream, this, std::placeholders::_1));
|
||||||
|
// allow host to update controller state
|
||||||
|
this->host->SetEventRumbleCallback(std::bind(&IO::SetRumble, this->io, std::placeholders::_1, std::placeholders::_2));
|
||||||
|
this->host->SetReadControllerCallback(std::bind(&IO::UpdateControllerState, this->io, std::placeholders::_1));
|
||||||
}
|
}
|
||||||
|
|
||||||
HostInterface::~HostInterface()
|
HostInterface::~HostInterface()
|
||||||
|
@ -245,7 +248,7 @@ MainApplication::MainApplication(DiscoveryManager *discoverymanager)
|
||||||
MainApplication::~MainApplication()
|
MainApplication::~MainApplication()
|
||||||
{
|
{
|
||||||
this->discoverymanager->SetService(false);
|
this->discoverymanager->SetService(false);
|
||||||
//this->io->FreeJoystick();
|
this->io->FreeController();
|
||||||
this->io->FreeVideo();
|
this->io->FreeVideo();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -264,16 +267,15 @@ bool MainApplication::Load()
|
||||||
|
|
||||||
// init chiaki gl after borealis
|
// init chiaki gl after borealis
|
||||||
// let borealis manage the main screen/window
|
// let borealis manage the main screen/window
|
||||||
|
|
||||||
if(!io->InitVideo(0, 0, SCREEN_W, SCREEN_H))
|
if(!io->InitVideo(0, 0, SCREEN_W, SCREEN_H))
|
||||||
{
|
{
|
||||||
brls::Logger::error("Failed to initiate Video");
|
brls::Logger::error("Failed to initiate Video");
|
||||||
}
|
}
|
||||||
|
|
||||||
brls::Logger::info("Load sdl joysticks");
|
brls::Logger::info("Load sdl/hid controller");
|
||||||
if(!io->InitJoystick())
|
if(!io->InitController())
|
||||||
{
|
{
|
||||||
brls::Logger::error("Faled to initiate Joysticks");
|
brls::Logger::error("Faled to initiate Controller");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create a view
|
// Create a view
|
||||||
|
@ -541,38 +543,12 @@ PSRemotePlay::PSRemotePlay(Host *host)
|
||||||
: host(host)
|
: host(host)
|
||||||
{
|
{
|
||||||
this->io = IO::GetInstance();
|
this->io = IO::GetInstance();
|
||||||
|
|
||||||
// store joycon/touchpad keys
|
|
||||||
for(int x = 0; x < CHIAKI_CONTROLLER_TOUCHES_MAX; x++)
|
|
||||||
// start touchpad as "untouched"
|
|
||||||
this->state.touches[x].id = -1;
|
|
||||||
|
|
||||||
// this->base_time=glfwGetTime();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void PSRemotePlay::draw(NVGcontext *vg, int x, int y, unsigned width, unsigned height, brls::Style *style, brls::FrameContext *ctx)
|
void PSRemotePlay::draw(NVGcontext *vg, int x, int y, unsigned width, unsigned height, brls::Style *style, brls::FrameContext *ctx)
|
||||||
{
|
{
|
||||||
this->io->MainLoop(&this->state);
|
this->io->MainLoop();
|
||||||
this->host->SendFeedbackState(&this->state);
|
this->host->SendFeedbackState();
|
||||||
|
|
||||||
// FPS calculation
|
|
||||||
// this->frame_counter += 1;
|
|
||||||
// double frame_time = glfwGetTime();
|
|
||||||
// if((frame_time - base_time) >= 1.0)
|
|
||||||
// {
|
|
||||||
// base_time += 1;
|
|
||||||
// //printf("FPS: %d\n", this->frame_counter);
|
|
||||||
// this->fps = this->frame_counter;
|
|
||||||
// this->frame_counter = 0;
|
|
||||||
// }
|
|
||||||
// nvgBeginPath(vg);
|
|
||||||
// nvgFillColor(vg, nvgRGBA(255,192,0,255));
|
|
||||||
// nvgFontFaceId(vg, ctx->fontStash->regular);
|
|
||||||
// nvgFontSize(vg, style->Label.smallFontSize);
|
|
||||||
// nvgTextAlign(vg, NVG_ALIGN_LEFT | NVG_ALIGN_MIDDLE);
|
|
||||||
// char fps_str[9] = {0};
|
|
||||||
// sprintf(fps_str, "FPS: %000d", this->fps);
|
|
||||||
// nvgText(vg, 5,10, fps_str, NULL);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
PSRemotePlay::~PSRemotePlay()
|
PSRemotePlay::~PSRemotePlay()
|
||||||
|
|
|
@ -156,9 +156,17 @@ int Host::InitSession(IO *user)
|
||||||
// audio setting_cb and frame_cb
|
// audio setting_cb and frame_cb
|
||||||
chiaki_opus_decoder_set_cb(&this->opus_decoder, InitAudioCB, AudioCB, user);
|
chiaki_opus_decoder_set_cb(&this->opus_decoder, InitAudioCB, AudioCB, user);
|
||||||
chiaki_opus_decoder_get_sink(&this->opus_decoder, &audio_sink);
|
chiaki_opus_decoder_get_sink(&this->opus_decoder, &audio_sink);
|
||||||
chiaki_session_set_audio_sink(&(this->session), &audio_sink);
|
chiaki_session_set_audio_sink(&this->session, &audio_sink);
|
||||||
chiaki_session_set_video_sample_cb(&(this->session), VideoCB, user);
|
chiaki_session_set_video_sample_cb(&this->session, VideoCB, user);
|
||||||
chiaki_session_set_event_cb(&(this->session), EventCB, this);
|
chiaki_session_set_event_cb(&this->session, EventCB, this);
|
||||||
|
|
||||||
|
// init controller states
|
||||||
|
chiaki_controller_state_set_idle(&this->controller_state);
|
||||||
|
|
||||||
|
for(int x = 0; x < CHIAKI_CONTROLLER_TOUCHES_MAX; x++)
|
||||||
|
// start touchpad as "untouched"
|
||||||
|
this->controller_state.touches[x].id = -1;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -189,10 +197,13 @@ void Host::StartSession()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Host::SendFeedbackState(ChiakiControllerState *state)
|
void Host::SendFeedbackState()
|
||||||
{
|
{
|
||||||
// send controller/joystick key
|
// send controller/joystick key
|
||||||
chiaki_session_set_controller_state(&this->session, state);
|
if(this->io_read_controller_cb != nullptr)
|
||||||
|
this->io_read_controller_cb(&this->controller_state);
|
||||||
|
|
||||||
|
chiaki_session_set_controller_state(&this->session, &this->controller_state);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Host::ConnectionEventCB(ChiakiEvent *event)
|
void Host::ConnectionEventCB(ChiakiEvent *event)
|
||||||
|
@ -209,6 +220,11 @@ void Host::ConnectionEventCB(ChiakiEvent *event)
|
||||||
if(this->chiaki_even_login_pin_request_cb != nullptr)
|
if(this->chiaki_even_login_pin_request_cb != nullptr)
|
||||||
this->chiaki_even_login_pin_request_cb(event->login_pin_request.pin_incorrect);
|
this->chiaki_even_login_pin_request_cb(event->login_pin_request.pin_incorrect);
|
||||||
break;
|
break;
|
||||||
|
case CHIAKI_EVENT_RUMBLE:
|
||||||
|
CHIAKI_LOGD(this->log, "EventCB CHIAKI_EVENT_RUMBLE");
|
||||||
|
if(this->chiaki_event_rumble_cb != nullptr)
|
||||||
|
this->chiaki_event_rumble_cb(event->rumble.left, event->rumble.right);
|
||||||
|
break;
|
||||||
case CHIAKI_EVENT_QUIT:
|
case CHIAKI_EVENT_QUIT:
|
||||||
CHIAKI_LOGI(this->log, "EventCB CHIAKI_EVENT_QUIT");
|
CHIAKI_LOGI(this->log, "EventCB CHIAKI_EVENT_QUIT");
|
||||||
if(this->chiaki_event_quit_cb != nullptr)
|
if(this->chiaki_event_quit_cb != nullptr)
|
||||||
|
@ -352,6 +368,16 @@ void Host::SetEventQuitCallback(std::function<void(ChiakiQuitEvent *)> chiaki_ev
|
||||||
this->chiaki_event_quit_cb = chiaki_event_quit_cb;
|
this->chiaki_event_quit_cb = chiaki_event_quit_cb;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Host::SetEventRumbleCallback(std::function<void(uint8_t, uint8_t)> chiaki_event_rumble_cb)
|
||||||
|
{
|
||||||
|
this->chiaki_event_rumble_cb = chiaki_event_rumble_cb;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Host::SetReadControllerCallback(std::function<void(ChiakiControllerState *)> io_read_controller_cb)
|
||||||
|
{
|
||||||
|
this->io_read_controller_cb = io_read_controller_cb;
|
||||||
|
}
|
||||||
|
|
||||||
bool Host::IsRegistered()
|
bool Host::IsRegistered()
|
||||||
{
|
{
|
||||||
return this->registered;
|
return this->registered;
|
||||||
|
|
|
@ -1,11 +1,5 @@
|
||||||
// SPDX-License-Identifier: LicenseRef-AGPL-3.0-only-OpenSSL
|
// SPDX-License-Identifier: LicenseRef-AGPL-3.0-only-OpenSSL
|
||||||
|
|
||||||
#ifdef __SWITCH__
|
|
||||||
#include <switch.h>
|
|
||||||
#else
|
|
||||||
#include <iostream>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include "io.h"
|
#include "io.h"
|
||||||
#include "settings.h"
|
#include "settings.h"
|
||||||
|
|
||||||
|
@ -345,22 +339,23 @@ bool IO::FreeVideo()
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool IO::ReadGameTouchScreen(ChiakiControllerState *state)
|
bool IO::ReadGameTouchScreen(ChiakiControllerState *chiaki_state)
|
||||||
{
|
{
|
||||||
#ifdef __SWITCH__
|
#ifdef __SWITCH__
|
||||||
hidScanInput();
|
HidTouchScreenState sw_state = {0};
|
||||||
int touch_count = hidTouchCount();
|
|
||||||
bool ret = false;
|
bool ret = false;
|
||||||
if(!touch_count)
|
if(!hidGetTouchScreenStates(&sw_state, 1) || sw_state.count == 0)
|
||||||
{
|
{
|
||||||
|
// flush state
|
||||||
|
chiaki_state->buttons &= ~CHIAKI_CONTROLLER_BUTTON_TOUCHPAD; // touchscreen release
|
||||||
for(int i = 0; i < CHIAKI_CONTROLLER_TOUCHES_MAX; i++)
|
for(int i = 0; i < CHIAKI_CONTROLLER_TOUCHES_MAX; i++)
|
||||||
{
|
{
|
||||||
if(state->touches[i].id != -1)
|
if(chiaki_state->touches[i].id != -1)
|
||||||
{
|
{
|
||||||
state->touches[i].x = 0;
|
chiaki_state->touches[i].x = 0;
|
||||||
state->touches[i].y = 0;
|
chiaki_state->touches[i].y = 0;
|
||||||
state->touches[i].id = -1;
|
chiaki_state->touches[i].id = -1;
|
||||||
state->buttons &= ~CHIAKI_CONTROLLER_BUTTON_TOUCHPAD; // touchscreen release
|
|
||||||
// the state changed
|
// the state changed
|
||||||
ret = true;
|
ret = true;
|
||||||
}
|
}
|
||||||
|
@ -368,32 +363,25 @@ bool IO::ReadGameTouchScreen(ChiakiControllerState *state)
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
touchPosition touch;
|
// scale switch screen to the PS trackpad
|
||||||
for(int i = 0; i < touch_count && i < CHIAKI_CONTROLLER_TOUCHES_MAX; i++)
|
for(int i = 0; i < sw_state.count && i < CHIAKI_CONTROLLER_TOUCHES_MAX; i++)
|
||||||
{
|
{
|
||||||
hidTouchRead(&touch, i);
|
|
||||||
|
|
||||||
// 1280×720 px (16:9)
|
// 1280×720 px (16:9)
|
||||||
// ps4 controller aspect ratio looks closer to 29:10
|
// ps4 controller aspect ratio looks closer to 29:10
|
||||||
uint16_t x = touch.px * (DS4_TRACKPAD_MAX_X / SWITCH_TOUCHSCREEN_MAX_X);
|
uint16_t x = sw_state.touches[i].x * (DS4_TRACKPAD_MAX_X / SWITCH_TOUCHSCREEN_MAX_X);
|
||||||
uint16_t y = touch.py * (DS4_TRACKPAD_MAX_Y / SWITCH_TOUCHSCREEN_MAX_Y);
|
uint16_t y = sw_state.touches[i].y * (DS4_TRACKPAD_MAX_Y / SWITCH_TOUCHSCREEN_MAX_Y);
|
||||||
|
|
||||||
// use nintendo switch border's 5% to
|
// use nintendo switch border's 5% to
|
||||||
if(x <= (SWITCH_TOUCHSCREEN_MAX_X * 0.05) || x >= (SWITCH_TOUCHSCREEN_MAX_X * 0.95) || y <= (SWITCH_TOUCHSCREEN_MAX_Y * 0.05) || y >= (SWITCH_TOUCHSCREEN_MAX_Y * 0.95))
|
if(x <= (SWITCH_TOUCHSCREEN_MAX_X * 0.05) || x >= (SWITCH_TOUCHSCREEN_MAX_X * 0.95) || y <= (SWITCH_TOUCHSCREEN_MAX_Y * 0.05) || y >= (SWITCH_TOUCHSCREEN_MAX_Y * 0.95))
|
||||||
{
|
chiaki_state->buttons |= CHIAKI_CONTROLLER_BUTTON_TOUCHPAD; // touchscreen
|
||||||
state->buttons |= CHIAKI_CONTROLLER_BUTTON_TOUCHPAD; // touchscreen
|
|
||||||
// printf("CHIAKI_CONTROLLER_BUTTON_TOUCHPAD\n");
|
|
||||||
}
|
|
||||||
else
|
else
|
||||||
{
|
chiaki_state->buttons &= ~CHIAKI_CONTROLLER_BUTTON_TOUCHPAD; // touchscreen release
|
||||||
state->buttons &= ~CHIAKI_CONTROLLER_BUTTON_TOUCHPAD; // touchscreen release
|
|
||||||
}
|
|
||||||
|
|
||||||
state->touches[i].x = x;
|
chiaki_state->touches[i].x = x;
|
||||||
state->touches[i].y = y;
|
chiaki_state->touches[i].y = y;
|
||||||
state->touches[i].id = i;
|
chiaki_state->touches[i].id = i;
|
||||||
// printf("[point_id=%d] px=%03d, py=%03d, dx=%03d, dy=%03d, angle=%03d\n",
|
// printf("[point_id=%d] x=%03d, y=%03d\n", i, x, y);
|
||||||
// i, touch.px, touch.py, touch.dx, touch.dy, touch.angle);
|
|
||||||
ret = true;
|
ret = true;
|
||||||
}
|
}
|
||||||
return ret;
|
return ret;
|
||||||
|
@ -402,14 +390,127 @@ bool IO::ReadGameTouchScreen(ChiakiControllerState *state)
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void IO::SetRumble(uint8_t left, uint8_t right)
|
||||||
|
{
|
||||||
|
#ifdef __SWITCH__
|
||||||
|
Result rc = 0;
|
||||||
|
HidVibrationValue vibration_values[] = {
|
||||||
|
{
|
||||||
|
.amp_low = 0.0f,
|
||||||
|
.freq_low = 160.0f,
|
||||||
|
.amp_high = 0.0f,
|
||||||
|
.freq_high = 320.0f,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.amp_low = 0.0f,
|
||||||
|
.freq_low = 160.0f,
|
||||||
|
.amp_high = 0.0f,
|
||||||
|
.freq_high = 320.0f,
|
||||||
|
}};
|
||||||
|
|
||||||
|
int target_device = padIsHandheld(&pad) ? 0 : 1;
|
||||||
|
if(left > 0)
|
||||||
|
{
|
||||||
|
// SDL_HapticRumblePlay(this->sdl_haptic_ptr[0], left / 100, 5000);
|
||||||
|
vibration_values[0].amp_low = (float)left / (float)100;
|
||||||
|
vibration_values[0].amp_high = (float)left / (float)100;
|
||||||
|
vibration_values[0].freq_low *= (float)left / (float)100;
|
||||||
|
vibration_values[0].freq_high *= (float)left / (float)100;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(right > 0)
|
||||||
|
{
|
||||||
|
// SDL_HapticRumblePlay(this->sdl_haptic_ptr[1], right / 100, 5000);
|
||||||
|
vibration_values[1].amp_low = (float)right / (float)100;
|
||||||
|
vibration_values[1].amp_high = (float)right / (float)100;
|
||||||
|
vibration_values[1].freq_low *= (float)left / (float)100;
|
||||||
|
vibration_values[1].freq_high *= (float)left / (float)100;
|
||||||
|
}
|
||||||
|
|
||||||
|
// printf("left ptr %p amp_low %f amp_high %f freq_low %f freq_high %f\n",
|
||||||
|
// &vibration_values[0],
|
||||||
|
// vibration_values[0].amp_low,
|
||||||
|
// vibration_values[0].amp_high,
|
||||||
|
// vibration_values[0].freq_low,
|
||||||
|
// vibration_values[0].freq_high);
|
||||||
|
|
||||||
|
// printf("right ptr %p amp_low %f amp_high %f freq_low %f freq_high %f\n",
|
||||||
|
// &vibration_values[1],
|
||||||
|
// vibration_values[1].amp_low,
|
||||||
|
// vibration_values[1].amp_high,
|
||||||
|
// vibration_values[1].freq_low,
|
||||||
|
// vibration_values[1].freq_high);
|
||||||
|
|
||||||
|
rc = hidSendVibrationValues(this->vibration_handles[target_device], vibration_values, 2);
|
||||||
|
if(R_FAILED(rc))
|
||||||
|
CHIAKI_LOGE(this->log, "hidSendVibrationValues() returned: 0x%x", rc);
|
||||||
|
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
bool IO::ReadGameSixAxis(ChiakiControllerState *state)
|
||||||
|
{
|
||||||
|
#ifdef __SWITCH__
|
||||||
|
// Read from the correct sixaxis handle depending on the current input style
|
||||||
|
HidSixAxisSensorState sixaxis = {0};
|
||||||
|
uint64_t style_set = padGetStyleSet(&pad);
|
||||||
|
if(style_set & HidNpadStyleTag_NpadHandheld)
|
||||||
|
hidGetSixAxisSensorStates(this->sixaxis_handles[0], &sixaxis, 1);
|
||||||
|
else if(style_set & HidNpadStyleTag_NpadFullKey)
|
||||||
|
hidGetSixAxisSensorStates(this->sixaxis_handles[1], &sixaxis, 1);
|
||||||
|
else if(style_set & HidNpadStyleTag_NpadJoyDual)
|
||||||
|
{
|
||||||
|
// For JoyDual, read from either the Left or Right Joy-Con depending on which is/are connected
|
||||||
|
u64 attrib = padGetAttributes(&pad);
|
||||||
|
if(attrib & HidNpadAttribute_IsLeftConnected)
|
||||||
|
hidGetSixAxisSensorStates(this->sixaxis_handles[2], &sixaxis, 1);
|
||||||
|
else if(attrib & HidNpadAttribute_IsRightConnected)
|
||||||
|
hidGetSixAxisSensorStates(this->sixaxis_handles[3], &sixaxis, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
// printf("Acceleration: x=% .4f, y=% .4f, z=% .4f\n", sixaxis.acceleration.x, sixaxis.acceleration.y, sixaxis.acceleration.z);
|
||||||
|
// printf("Angular velocity: x=% .4f, y=% .4f, z=% .4f\n", sixaxis.angular_velocity.x, sixaxis.angular_velocity.y, sixaxis.angular_velocity.z);
|
||||||
|
// printf("Angle: x=% .4f, y=% .4f, z=% .4f\n", sixaxis.angle.x, sixaxis.angle.y, sixaxis.angle.z);
|
||||||
|
// printf("Direction matrix:\n"
|
||||||
|
// " [ % .4f, % .4f, % .4f ]\n"
|
||||||
|
// " [ % .4f, % .4f, % .4f ]\n"
|
||||||
|
// " [ % .4f, % .4f, % .4f ]\n",
|
||||||
|
// sixaxis.direction.direction[0][0], sixaxis.direction.direction[1][0], sixaxis.direction.direction[2][0],
|
||||||
|
// sixaxis.direction.direction[0][1], sixaxis.direction.direction[1][1], sixaxis.direction.direction[2][1],
|
||||||
|
// sixaxis.direction.direction[0][2], sixaxis.direction.direction[1][2], sixaxis.direction.direction[2][2]);
|
||||||
|
|
||||||
|
state->gyro_x = sixaxis.angular_velocity.x;
|
||||||
|
state->gyro_y = sixaxis.angular_velocity.y;
|
||||||
|
state->gyro_z = sixaxis.angular_velocity.z;
|
||||||
|
state->accel_x = sixaxis.acceleration.x;
|
||||||
|
state->accel_y = sixaxis.acceleration.y;
|
||||||
|
state->accel_z = sixaxis.acceleration.z;
|
||||||
|
|
||||||
|
// thank you @thestr4ng3r for the hint
|
||||||
|
// https://en.wikipedia.org/wiki/Conversion_between_quaternions_and_Euler_angles#Euler_angles_to_quaternion_conversion
|
||||||
|
double cy = cos(sixaxis.angle.z * 0.5);
|
||||||
|
double sy = sin(sixaxis.angle.z * 0.5);
|
||||||
|
double cp = cos(sixaxis.angle.y * 0.5);
|
||||||
|
double sp = sin(sixaxis.angle.y * 0.5);
|
||||||
|
double cr = cos(sixaxis.angle.x * 0.5);
|
||||||
|
double sr = sin(sixaxis.angle.x * 0.5);
|
||||||
|
|
||||||
|
state->orient_x = sr * cp * cy - cr * sp * sy;
|
||||||
|
state->orient_y = cr * sp * cy + sr * cp * sy;
|
||||||
|
state->orient_z = cr * cp * sy - sr * sp * cy;
|
||||||
|
state->orient_w = cr * cp * cy + sr * sp * sy;
|
||||||
|
return true;
|
||||||
|
#else
|
||||||
|
return false;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
bool IO::ReadGameKeys(SDL_Event *event, ChiakiControllerState *state)
|
bool IO::ReadGameKeys(SDL_Event *event, ChiakiControllerState *state)
|
||||||
{
|
{
|
||||||
// return true if an event changed (gamepad input)
|
// return true if an event changed (gamepad input)
|
||||||
|
|
||||||
// TODO
|
// TODO
|
||||||
// share vs PS button
|
// share vs PS button
|
||||||
// Gyro ?
|
|
||||||
// rumble ?
|
|
||||||
bool ret = true;
|
bool ret = true;
|
||||||
switch(event->type)
|
switch(event->type)
|
||||||
{
|
{
|
||||||
|
@ -620,7 +721,7 @@ bool IO::InitOpenGlTextures()
|
||||||
|
|
||||||
D(glGenTextures(PLANES_COUNT, this->tex));
|
D(glGenTextures(PLANES_COUNT, this->tex));
|
||||||
D(glGenBuffers(PLANES_COUNT, this->pbo));
|
D(glGenBuffers(PLANES_COUNT, this->pbo));
|
||||||
uint8_t uv_default[] = { 0x7f, 0x7f };
|
uint8_t uv_default[] = {0x7f, 0x7f};
|
||||||
for(int i = 0; i < PLANES_COUNT; i++)
|
for(int i = 0; i < PLANES_COUNT; i++)
|
||||||
{
|
{
|
||||||
D(glBindTexture(GL_TEXTURE_2D, this->tex[i]));
|
D(glBindTexture(GL_TEXTURE_2D, this->tex[i]));
|
||||||
|
@ -633,7 +734,7 @@ bool IO::InitOpenGlTextures()
|
||||||
|
|
||||||
D(glUseProgram(this->prog));
|
D(glUseProgram(this->prog));
|
||||||
// bind only as many planes as we need
|
// bind only as many planes as we need
|
||||||
const char *plane_names[] = { "plane1", "plane2", "plane3" };
|
const char *plane_names[] = {"plane1", "plane2", "plane3"};
|
||||||
for(int i = 0; i < PLANES_COUNT; i++)
|
for(int i = 0; i < PLANES_COUNT; i++)
|
||||||
D(glUniform1i(glGetUniformLocation(this->prog, plane_names[i]), i));
|
D(glUniform1i(glGetUniformLocation(this->prog, plane_names[i]), i));
|
||||||
|
|
||||||
|
@ -786,7 +887,7 @@ inline void IO::OpenGlDraw()
|
||||||
D(glFinish());
|
D(glFinish());
|
||||||
}
|
}
|
||||||
|
|
||||||
bool IO::InitJoystick()
|
bool IO::InitController()
|
||||||
{
|
{
|
||||||
// https://github.com/switchbrew/switch-examples/blob/master/graphics/sdl2/sdl2-simple/source/main.cpp#L57
|
// https://github.com/switchbrew/switch-examples/blob/master/graphics/sdl2/sdl2-simple/source/main.cpp#L57
|
||||||
// open CONTROLLER_PLAYER_1 and CONTROLLER_PLAYER_2
|
// open CONTROLLER_PLAYER_1 and CONTROLLER_PLAYER_2
|
||||||
|
@ -800,24 +901,64 @@ bool IO::InitJoystick()
|
||||||
CHIAKI_LOGE(this->log, "SDL_JoystickOpen: %s\n", SDL_GetError());
|
CHIAKI_LOGE(this->log, "SDL_JoystickOpen: %s\n", SDL_GetError());
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
// this->sdl_haptic_ptr[i] = SDL_HapticOpenFromJoystick(sdl_joystick_ptr[i]);
|
||||||
|
// SDL_HapticRumbleInit(this->sdl_haptic_ptr[i]);
|
||||||
|
// if(sdl_haptic_ptr[i] == nullptr)
|
||||||
|
// {
|
||||||
|
// CHIAKI_LOGE(this->log, "SDL_HapticRumbleInit: %s\n", SDL_GetError());
|
||||||
|
// }
|
||||||
}
|
}
|
||||||
|
#ifdef __SWITCH__
|
||||||
|
Result rc = 0;
|
||||||
|
// Configure our supported input layout: a single player with standard controller styles
|
||||||
|
padConfigureInput(1, HidNpadStyleSet_NpadStandard);
|
||||||
|
|
||||||
|
// Initialize the default gamepad (which reads handheld mode inputs as well as the first connected controller)
|
||||||
|
padInitializeDefault(&this->pad);
|
||||||
|
// touchpad
|
||||||
|
hidInitializeTouchScreen();
|
||||||
|
// It's necessary to initialize these separately as they all have different handle values
|
||||||
|
hidGetSixAxisSensorHandles(&this->sixaxis_handles[0], 1, HidNpadIdType_Handheld, HidNpadStyleTag_NpadHandheld);
|
||||||
|
hidGetSixAxisSensorHandles(&this->sixaxis_handles[1], 1, HidNpadIdType_No1, HidNpadStyleTag_NpadFullKey);
|
||||||
|
hidGetSixAxisSensorHandles(&this->sixaxis_handles[2], 2, HidNpadIdType_No1, HidNpadStyleTag_NpadJoyDual);
|
||||||
|
hidStartSixAxisSensor(this->sixaxis_handles[0]);
|
||||||
|
hidStartSixAxisSensor(this->sixaxis_handles[1]);
|
||||||
|
hidStartSixAxisSensor(this->sixaxis_handles[2]);
|
||||||
|
hidStartSixAxisSensor(this->sixaxis_handles[3]);
|
||||||
|
|
||||||
|
rc = hidInitializeVibrationDevices(this->vibration_handles[0], 2, HidNpadIdType_Handheld, HidNpadStyleTag_NpadHandheld);
|
||||||
|
if(R_FAILED(rc))
|
||||||
|
CHIAKI_LOGE(this->log, "hidInitializeVibrationDevices() HidNpadIdType_Handheld returned: 0x%x", rc);
|
||||||
|
|
||||||
|
rc = hidInitializeVibrationDevices(this->vibration_handles[1], 2, HidNpadIdType_No1, HidNpadStyleTag_NpadJoyDual);
|
||||||
|
if(R_FAILED(rc))
|
||||||
|
CHIAKI_LOGE(this->log, "hidInitializeVibrationDevices() HidNpadIdType_No1 returned: 0x%x", rc);
|
||||||
|
|
||||||
|
#endif
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool IO::FreeJoystick()
|
bool IO::FreeController()
|
||||||
{
|
{
|
||||||
for(int i = 0; i < SDL_JOYSTICK_COUNT; i++)
|
for(int i = 0; i < SDL_JOYSTICK_COUNT; i++)
|
||||||
{
|
{
|
||||||
if(SDL_JoystickGetAttached(sdl_joystick_ptr[i]))
|
SDL_JoystickClose(this->sdl_joystick_ptr[i]);
|
||||||
SDL_JoystickClose(sdl_joystick_ptr[i]);
|
// SDL_HapticClose(this->sdl_haptic_ptr[i]);
|
||||||
}
|
}
|
||||||
|
#ifdef __SWITCH__
|
||||||
|
hidStopSixAxisSensor(this->sixaxis_handles[0]);
|
||||||
|
hidStopSixAxisSensor(this->sixaxis_handles[1]);
|
||||||
|
hidStopSixAxisSensor(this->sixaxis_handles[2]);
|
||||||
|
hidStopSixAxisSensor(this->sixaxis_handles[3]);
|
||||||
|
#endif
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool IO::MainLoop(ChiakiControllerState *state)
|
void IO::UpdateControllerState(ChiakiControllerState *state)
|
||||||
{
|
{
|
||||||
D(glUseProgram(this->prog));
|
#ifdef __SWITCH__
|
||||||
|
padUpdate(&this->pad);
|
||||||
|
#endif
|
||||||
// handle SDL events
|
// handle SDL events
|
||||||
while(SDL_PollEvent(&this->sdl_event))
|
while(SDL_PollEvent(&this->sdl_event))
|
||||||
{
|
{
|
||||||
|
@ -825,11 +966,17 @@ bool IO::MainLoop(ChiakiControllerState *state)
|
||||||
switch(this->sdl_event.type)
|
switch(this->sdl_event.type)
|
||||||
{
|
{
|
||||||
case SDL_QUIT:
|
case SDL_QUIT:
|
||||||
return false;
|
this->quit = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ReadGameTouchScreen(state);
|
ReadGameTouchScreen(state);
|
||||||
|
ReadGameSixAxis(state);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool IO::MainLoop()
|
||||||
|
{
|
||||||
|
D(glUseProgram(this->prog));
|
||||||
|
|
||||||
glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
|
glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
|
||||||
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
||||||
|
|
|
@ -83,12 +83,6 @@ extern "C" void userAppInit()
|
||||||
// load socket custom config
|
// load socket custom config
|
||||||
socketInitialize(&g_chiakiSocketInitConfig);
|
socketInitialize(&g_chiakiSocketInitConfig);
|
||||||
setsysInitialize();
|
setsysInitialize();
|
||||||
|
|
||||||
// padConfigureInput(1, HidNpadStyleSet_NpadStandard);
|
|
||||||
// PadState pad;
|
|
||||||
// padInitializeDefault(&pad);
|
|
||||||
|
|
||||||
//hidInitializeTouchScreen();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
extern "C" void userAppExit()
|
extern "C" void userAppExit()
|
||||||
|
@ -126,7 +120,7 @@ int main(int argc, char *argv[])
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
CHIAKI_LOGI(log, "Loading SDL audio / joystick");
|
CHIAKI_LOGI(log, "Loading SDL audio / joystick / haptic");
|
||||||
if(SDL_Init(SDL_INIT_AUDIO | SDL_INIT_JOYSTICK))
|
if(SDL_Init(SDL_INIT_AUDIO | SDL_INIT_JOYSTICK))
|
||||||
{
|
{
|
||||||
CHIAKI_LOGE(log, "SDL initialization failed: %s", SDL_GetError());
|
CHIAKI_LOGE(log, "SDL initialization failed: %s", SDL_GetError());
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue