Skip to content

Commit

Permalink
Merge pull request #153 from igor725/hotkeys
Browse files Browse the repository at this point in the history
Rework hotkey handling + cleanup
  • Loading branch information
SysRay authored May 6, 2024
2 parents 4953e3e + 75290d4 commit ae928c6
Show file tree
Hide file tree
Showing 27 changed files with 430 additions and 366 deletions.
3 changes: 2 additions & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -112,10 +112,11 @@ add_executable(psoff
main.cpp
)

add_dependencies(psoff logging core psOff_utility)
add_dependencies(psoff logging core psOff_utility gamereport)

target_link_libraries(psoff PRIVATE
core.lib
gamereport.lib
psOff_utility
libboost_filesystem
$<TARGET_OBJECTS:asmHelper>
Expand Down
5 changes: 3 additions & 2 deletions core/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ add_subdirectory(initParams)
add_subdirectory(timer)
add_subdirectory(systemContent)
add_subdirectory(networking)
add_subdirectory(hotkeys)
add_subdirectory(trophies)
add_subdirectory(fileManager)
add_subdirectory(memory)
Expand All @@ -24,6 +25,7 @@ add_library(core SHARED
$<TARGET_OBJECTS:timer>
$<TARGET_OBJECTS:systemContent>
$<TARGET_OBJECTS:networking>
$<TARGET_OBJECTS:hotkeys>
$<TARGET_OBJECTS:trophies>
$<TARGET_OBJECTS:videoout>
$<TARGET_OBJECTS:fileManager>
Expand All @@ -33,7 +35,7 @@ add_library(core SHARED
$<TARGET_OBJECTS:runtime>
)

add_dependencies(core logging third_party config_emu gamereport psoff_render)
add_dependencies(core logging third_party config_emu psoff_render)
target_link_libraries(core PRIVATE
libboost_url
libboost_thread
Expand All @@ -42,7 +44,6 @@ target_link_libraries(core PRIVATE
libboost_filesystem
sdl2
psoff_render.lib
gamereport.lib
OptickCore
psOff_utility
config_emu.lib
Expand Down
7 changes: 7 additions & 0 deletions core/hotkeys/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
add_library(hotkeys OBJECT
hotkeys.cpp
)

add_dependencies(hotkeys third_party config_emu)

target_compile_definitions(hotkeys PUBLIC WIN32_LEAN_AND_MEAN)
142 changes: 142 additions & 0 deletions core/hotkeys/hotkeys.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,142 @@
#define __APICALL_EXTERN
#include "hotkeys.h"
#undef __APICALL_EXTERN

#include "config_emu.h"

#include <unordered_map>

class Hotkeys: public IHotkeys {
private:
struct HkBacks {
HkCommand cmd;
HkFunc func;
};

struct KBind {
SDL_Keycode kc;
uint16_t mod;
};

std::vector<HkBacks> m_cbacks = {};
std::array<KBind, (size_t)HkCommand::COMMANDS_MAX> m_binds = {{SDLK_UNKNOWN, 0}};
uint32_t m_state = 0;

HkCommand lookupCommand(SDL_Keycode kc, uint16_t mod) {
for (uint32_t c = uint32_t(HkCommand::UNKNOWN); c < uint32_t(HkCommand::COMMANDS_MAX); ++c) {
auto& bind = m_binds[(uint32_t)c];
if (kc == bind.kc && mod == bind.mod) return HkCommand(c);
}

return HkCommand::UNKNOWN;
}

public:
Hotkeys() {
static std::unordered_map<std::string, HkCommand> map = {
{"gamereport.send", HkCommand::GAMEREPORT_SEND_REPORT},
{"controller.l3", HkCommand::CONTROLLER_L3},
{"controller.r3", HkCommand::CONTROLLER_R3},
{"controller.options", HkCommand::CONTROLLER_OPTIONS},
{"controller.dpad_up", HkCommand::CONTROLLER_DPAD_UP},
{"controller.dpad_right", HkCommand::CONTROLLER_DPAD_RIGHT},
{"controller.dpad_down", HkCommand::CONTROLLER_DPAD_DOWN},
{"controller.dpad_left", HkCommand::CONTROLLER_DPAD_LEFT},
{"controller.l2", HkCommand::CONTROLLER_L2},
{"controller.r2", HkCommand::CONTROLLER_R2},
{"controller.l1", HkCommand::CONTROLLER_L1},
{"controller.r1", HkCommand::CONTROLLER_R1},
{"controller.triangle", HkCommand::CONTROLLER_TRIANGLE},
{"controller.circle", HkCommand::CONTROLLER_CIRCLE},
{"controller.cross", HkCommand::CONTROLLER_CROSS},
{"controller.square", HkCommand::CONTROLLER_SQUARE},
{"controller.touchpad", HkCommand::CONTROLLER_TOUCH_PAD},
{"controller.lx+", HkCommand::CONTROLLER_LX_UP},
{"controller.lx-", HkCommand::CONTROLLER_LX_DOWN},
{"controller.ly+", HkCommand::CONTROLLER_LY_UP},
{"controller.ly-", HkCommand::CONTROLLER_LY_DOWN},
{"controller.rx+", HkCommand::CONTROLLER_RX_UP},
{"controller.rx-", HkCommand::CONTROLLER_RX_DOWN},
{"controller.ry+", HkCommand::CONTROLLER_RY_UP},
{"controller.ry-", HkCommand::CONTROLLER_RY_DOWN},
};

auto readBind = [](std::string& str, KBind* kb) -> bool {
auto delim = str.find_last_of("||");
if (delim != std::string::npos) {
auto mod = str.substr(0, delim - 1);
auto key = str.substr(delim + 1);
kb->kc = SDL_GetScancodeFromName(key.c_str());

switch (SDL_GetScancodeFromName(mod.c_str())) {
case SDL_SCANCODE_LALT: kb->mod = KMOD_LALT; return true;
case SDL_SCANCODE_LCTRL: kb->mod = KMOD_LCTRL; return true;
case SDL_SCANCODE_LSHIFT: kb->mod = KMOD_LSHIFT; return true;

case SDL_SCANCODE_RALT: kb->mod = KMOD_RALT; return true;
case SDL_SCANCODE_RCTRL: kb->mod = KMOD_RCTRL; return true;
case SDL_SCANCODE_RSHIFT: kb->mod = KMOD_RSHIFT; return true;

default: return false;
}
}

kb->kc = SDL_GetScancodeFromName(str.c_str());
kb->mod = 0x0000;
return true;
};

auto [lock, jData] = accessConfig()->accessModule(ConfigModFlag::CONTROLS);
for (auto& [bname, sdlkeys]: (*jData)["keybinds"].items()) {
auto it = map.find(bname.c_str());
if (it == map.end()) continue;
std::string temp;
sdlkeys.get_to(temp);

auto& bind = m_binds[(uint32_t)it->second];
if (!readBind(temp, &bind)) {
bind = {0, 0};
continue;
}

for (uint32_t c = uint32_t(HkCommand::UNKNOWN); c < uint32_t(HkCommand::COMMANDS_MAX); ++c) {
auto& tbind = m_binds[(uint32_t)c];
if (bind.kc == SDL_SCANCODE_UNKNOWN || tbind.kc == SDL_SCANCODE_UNKNOWN) continue;
if (tbind.kc == bind.kc && tbind.mod == bind.mod && (uint32_t)it->second != c) {
printf("Key conflict found! Please rebind your \"%s\" key.\n", bname.c_str());
bind = {0, 0};
continue;
}
}
}
}

void registerCallback(HkCommand cmd, HkFunc func) final { m_cbacks.emplace_back(cmd, func); }

bool isPressed(HkCommand cmd) final { return (m_state & (1ull << (uint8_t)cmd)) != 0; }

int32_t isPressedEx(HkCommand cmd1, HkCommand cmd2, int32_t ifcmd1, int32_t ifcmd2, int32_t def) final {
return isPressed(cmd1) ? ifcmd1 : (isPressed(cmd2) ? ifcmd2 : def);
}

void update(const SDL_KeyboardEvent* event) final {
bool pressed = event->type == SDL_KEYDOWN;
HkCommand cmd = lookupCommand(event->keysym.scancode, event->keysym.mod & 0x03C3);
if (cmd == HkCommand::UNKNOWN) return;
uint32_t bit = (1ull << (uint8_t)cmd);

if (pressed && ((m_state & bit) == 0)) {
for (auto& hkc: m_cbacks)
if (hkc.cmd == cmd) hkc.func(cmd);

m_state |= bit;
} else if (!pressed && ((m_state & bit) != 0)) {
m_state &= ~bit;
}
}
};

IHotkeys& accessHotkeys() {
static Hotkeys ih;
return ih;
}
71 changes: 71 additions & 0 deletions core/hotkeys/hotkeys.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
#pragma once

#include "utility/utility.h"

#include <SDL2/SDL.h>
#include <functional>

enum class HkCommand {
UNKNOWN = 0,

// System commands
GAMEREPORT_SEND_REPORT,

// Gamepad emulation
CONTROLLER_L3,
CONTROLLER_R3,
CONTROLLER_OPTIONS,
CONTROLLER_DPAD_UP,
CONTROLLER_DPAD_RIGHT,
CONTROLLER_DPAD_DOWN,
CONTROLLER_DPAD_LEFT,
CONTROLLER_L2,
CONTROLLER_R2,
CONTROLLER_L1,
CONTROLLER_R1,
CONTROLLER_TRIANGLE,
CONTROLLER_CIRCLE,
CONTROLLER_CROSS,
CONTROLLER_SQUARE,
CONTROLLER_TOUCH_PAD,
CONTROLLER_LX_UP,
CONTROLLER_LX_DOWN,
CONTROLLER_LY_UP,
CONTROLLER_LY_DOWN,
CONTROLLER_RX_UP,
CONTROLLER_RX_DOWN,
CONTROLLER_RY_UP,
CONTROLLER_RY_DOWN,

/**
* Warning! If this value ever exceeds 32 you should increase
* the size of `m_state` variable in `class Hotkeys` aswell!
*/
COMMANDS_MAX,
};

typedef std::function<void(HkCommand)> HkFunc;

class IHotkeys {
CLASS_NO_COPY(IHotkeys);
CLASS_NO_MOVE(IHotkeys);

public:
IHotkeys() = default;
virtual ~IHotkeys() = default;

virtual void registerCallback(HkCommand cmd, HkFunc func) = 0;
virtual bool isPressed(HkCommand cmd) = 0;
virtual int32_t isPressedEx(HkCommand cmd1, HkCommand cmd2, int32_t ifcmd1, int32_t ifcmd2, int32_t def) = 0;
virtual void update(const SDL_KeyboardEvent* event) = 0;
};

#if defined(__APICALL_EXTERN)
#define __APICALL __declspec(dllexport)
#elif defined(__APICALL_IMPORT)
#define __APICALL __declspec(dllimport)
#else
#define __APICALL
#endif
__APICALL IHotkeys& accessHotkeys();
#undef __APICALL
9 changes: 5 additions & 4 deletions core/trophies/trophies.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -228,7 +228,7 @@ class Trophies: public ITrophies {
// Data decipher context
EVP_CIPHER_CTX* data_ctx = EVP_CIPHER_CTX_new();
{
if (!EVP_DecryptInit(data_ctx, EVP_aes_128_cbc(), outbuffer, d_iv)) {
if (!EVP_DecryptInit(data_ctx, EVP_aes_128_cbc(), outbuffer /* the buffer holds the decryption key now */, d_iv)) {
EVP_CIPHER_CTX_free(data_ctx);
return false;
}
Expand All @@ -250,8 +250,8 @@ class Trophies: public ITrophies {
// Seeking to unread encrypted data position (skip Init Vector + Signature Comkment Part)
trfile.seekg(ent.pos + TR_AES_BLOCK_SIZE + ENC_SCE_SIGN_SIZE);

size_t copied;
while ((copied = size_t(mem_off - mem.get())) < ent.len) {
size_t copied = ENC_SCE_SIGN_SIZE;
while (copied < ent.len) {
size_t len = std::min(ent.len - copied, sizeof(inbuffer));
// Reading the rest of AES data block by block
if (!trfile.read((char*)inbuffer, len)) {
Expand All @@ -264,6 +264,7 @@ class Trophies: public ITrophies {
}

mem_off += outlen;
copied += len;
}

if (!EVP_DecryptFinal(data_ctx, (uint8_t*)mem_off, &outlen)) {
Expand All @@ -280,7 +281,7 @@ class Trophies: public ITrophies {
*/
auto p = std::string_view(mem.get()).find("</trophyconf>");
if (p != std::string_view::npos) *(mem.get() + p + 13) = '\0';
*mem_off = '\0'; // Finally
*(mem_off + outlen) = '\0'; // Finally
}
//- Data decipher context

Expand Down
2 changes: 1 addition & 1 deletion core/videoout/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ add_library(videoout OBJECT
overlay/overtrophy/overtrophy.cpp
)

add_dependencies(videoout third_party psOff_utility gamereport initParams config_emu psoff_render)
add_dependencies(videoout third_party psOff_utility initParams config_emu psoff_render)

target_include_directories(videoout PRIVATE
${Vulkan_INCLUDE_DIRS}
Expand Down
26 changes: 5 additions & 21 deletions core/videoout/videoout.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,11 @@
#undef __APICALL_EXTERN

#include "config_emu.h"
#include "core/hotkeys/hotkeys.h"
#include "core/initParams/initParams.h"
#include "core/kernel/eventqueue.h"
#include "core/systemContent/systemContent.h"
#include "core/timer/timer.h"
#include "gamereport.h"
#include "imageHandler.h"
#include "logging.h"
#include "modules/libSceVideoOut/codes.h"
Expand Down Expand Up @@ -242,6 +242,8 @@ class VideoOut: public IVideoOut, private IEventsGraphics {

bool SDLEventUnreg(SDLEventFunc func) { return m_sdlEvents.removeListener(func); }

SDL_Window* SDLWindow() { return m_windows[0].window; }

void vblankEnd(int handle, uint64_t curTime, uint64_t curProcTime);

// Callback Graphics
Expand Down Expand Up @@ -794,7 +796,7 @@ void cbWindow_moveresize(SDL_Window* window) {
(*jData)["xpos"] = x, (*jData)["ypos"] = y;
}

void cbWindow_keyhandler(SDL_Window* window, SDL_Event* event) {
void cbWindow_keyhandler(SDL_Window* window, SDL_Event* event) { // todo: Move these to hotkey handler too?
switch (event->key.keysym.scancode) {
case SDL_SCANCODE_ESCAPE: return cbWindow_close(window);
case SDL_SCANCODE_RETURN: {
Expand All @@ -808,25 +810,6 @@ void cbWindow_keyhandler(SDL_Window* window, SDL_Event* event) {
}
}
} break;
case GAMEREPORT_USER_SEND_SCANCODE: {
auto title = accessSystemContent().getString("TITLE");
auto title_id = accessSystemContent().getString("TITLE_ID");
auto app_ver = accessSystemContent().getString("APP_VER");

accessGameReport().ShowReportWindow({
.title = title ? title.value().data() : "Your PS4 Game Name",
.title_id = title_id ? title_id.value().data() : "CUSA00000",
.app_ver = app_ver ? app_ver.value().data() : "v0.0",
.emu_ver = PSOFF_RENDER_VERSION,
.wnd = window,

.type = IGameReport::Type::USER,
.add =
{
.ex = nullptr,
},
});
} break;

default: break;
}
Expand All @@ -847,6 +830,7 @@ std::thread VideoOut::createSDLThread() {
SDL_Event event;
while (SDL_PollEvent(&event)) {
m_overlayHandler->processEvent(&event);
if (event.type == SDL_KEYUP || event.type == SDL_KEYDOWN) accessHotkeys().update(&event.key);

switch (event.type) {
case SDL_WINDOWEVENT:
Expand Down
Loading

0 comments on commit ae928c6

Please sign in to comment.