Skip to content
This repository has been archived by the owner on Sep 16, 2024. It is now read-only.

Commit

Permalink
More stuff
Browse files Browse the repository at this point in the history
  • Loading branch information
OFFTKP committed Jan 26, 2024
1 parent fd7fe80 commit 38e3be3
Show file tree
Hide file tree
Showing 14 changed files with 526 additions and 2,874 deletions.
1 change: 1 addition & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -185,6 +185,7 @@ set(HYDRA_QT_FILES

set(HYDRA_IMGUI_FILES
src/app.cxx
src/input.cxx
src/gamewindow.cxx
src/mainwindow.cxx
src/filepicker.cxx
Expand Down
2 changes: 1 addition & 1 deletion core
96 changes: 45 additions & 51 deletions include/corewrapper.hxx
Original file line number Diff line number Diff line change
Expand Up @@ -2,19 +2,40 @@

#include <cstring>
#include <string>
#include <unordered_map>
#include <vector>
#if defined(HYDRA_LIBDL)
#include <dlfcn.h>
#elif defined(HYDRA_WINDOWS)
#include <windows.h>
#endif
#include "stb_image_write.h"
#include <array>
#include <filesystem>
#include <glad/glad.h>
#include <hydra/core.hxx>
#include <memory>

namespace hydra
{

struct CoreInfo
{
std::string path;
std::string core_name;
std::string system_name;
std::string author;
std::string version;
std::string description;
std::string license;
std::string url;
std::time_t last_played;
int max_players;
std::vector<std::string> extensions;
std::vector<std::string> required_files;
unsigned int icon_texture = 0;
};

typedef void* dynlib_handle_t;

inline dynlib_handle_t dynlib_open(const char* path)
Expand Down Expand Up @@ -112,31 +133,44 @@ namespace hydra
const std::vector<CheatMetadata>& GetCheats();

bool LoadGame(const std::filesystem::path& path);

// IFrontendDriven
void RunFrame();
uint16_t GetFps();

// IOpenGlRendered
void ResetContext();
void DestroyContext();
void SetFbo(GLuint fbo);
void SetGetProcAddress(void* func);

// ISoftwareRendered
void SetVideoCallback(void (*callback)(void* data, hydra::Size size));
hydra::PixelFormat GetPixelFormat();

// ICheat
uint32_t EditCheat(const CheatMetadata& cheat, uint32_t old_handle = hydra::BAD_CHEAT);
void RemoveCheat(uint32_t handle);
void EnableCheat(uint32_t handle);
void DisableCheat(uint32_t handle);

void RunFrame();

private:
dynlib_handle_t handle;
void (*destroy_function)(IBase*);
const char* (*get_info_function)(hydra::InfoType);
std::string game_hash_;
std::filesystem::path core_path_;
std::string core_name_;

EmulatorWrapper(IBase* shl, dynlib_handle_t hdl, void (*dfunc)(IBase*),
const char* (*gfunc)(hydra::InfoType), const std::filesystem::path& path);
const char* (*gfunc)(hydra::InfoType), const hydra::CoreInfo& info);

void init_cheats();
void save_cheats();

static const char* get_setting_wrapper(const char* setting);
static void set_setting_wrapper(const char* setting, const char* value);

dynlib_handle_t handle;
void (*destroy_function)(IBase*);
const char* (*get_info_function)(hydra::InfoType);
std::string game_hash_;
hydra::CoreInfo core_info_;
std::vector<CheatMetadata> cheats_;
std::array<bool, (size_t)hydra::InterfaceType::InterfaceCount> has;

static EmulatorWrapper* instance;

Expand All @@ -146,47 +180,7 @@ namespace hydra

struct EmulatorFactory
{
static std::shared_ptr<EmulatorWrapper> Create(const std::string& path)
{
dynlib_handle_t handle = dynlib_open(path.c_str());

if (!handle)
{
printf("Failed to load library %s: %s\n", path.c_str(), dynlib_get_error().c_str());
return nullptr;
}
auto create_emu_p =
(decltype(hydra::createEmulator)*)dynlib_get_symbol(handle, "createEmulator");
if (!create_emu_p)
{
printf("Failed to find createEmulator in %s\n", path.c_str());
dynlib_close(handle);
return nullptr;
}

auto destroy_emu_p =
(decltype(hydra::destroyEmulator)*)dynlib_get_symbol(handle, "destroyEmulator");

if (!destroy_emu_p)
{
printf("Failed to find destroyEmulator in %s\n", path.c_str());
dynlib_close(handle);
return nullptr;
}

auto get_info_p = (decltype(hydra::getInfo)*)dynlib_get_symbol(handle, "getInfo");

if (!get_info_p)
{
printf("Failed to find getInfo in %s\n", path.c_str());
dynlib_close(handle);
return nullptr;
}

auto emulator = std::shared_ptr<EmulatorWrapper>(
new EmulatorWrapper(create_emu_p(), handle, destroy_emu_p, get_info_p, path));
return emulator;
}
static std::shared_ptr<EmulatorWrapper> Create(const std::string& path);

static std::shared_ptr<EmulatorWrapper> Create(const std::filesystem::path& path)
{
Expand Down
144 changes: 22 additions & 122 deletions include/input.hxx
Original file line number Diff line number Diff line change
@@ -1,134 +1,34 @@
#pragma once

#include "error_factory.hxx"
#include <filesystem>
#include <fstream>
#include <array>
#include <cstdint>
#include <hydra/core.hxx>
#include <json.hpp>
#include <map>
#include <QKeySequence>
#include <SDL2/SDL_keyboard.h>
#include <string>
#include <unordered_map>
#include <vector>

namespace hydra
{

using KeyMappings = std::array<QKeySequence, (int)hydra::ButtonType::InputCount>;

class Input
struct KeyMappings
{
using json = nlohmann::json;
Input() = delete;
~Input() = delete;

public:
static QKeySequence StringToKey(const std::string& str)
{
if (str.empty())
return QKeySequence();
QKeySequence key(str.c_str());
if (key.isEmpty())
{
throw ErrorFactory::generate_exception(__func__, __LINE__,
"Invalid key sequence: " + str);
}
return key;
}

static std::string KeyToString(const QKeySequence& key)
{
return key.toString().toStdString();
}

static KeyMappings Load(const std::string& data)
{
KeyMappings mappings;
std::map<std::string, std::string> map;
json j_map = json::parse(data);
map = j_map.get<std::map<std::string, std::string>>();

for (auto& [key, value] : map)
{
int button_type = 0;

try
{
button_type = std::stoi(key);
} catch (std::exception& e)
{
throw ErrorFactory::generate_exception(__func__, __LINE__,
"Invalid button type");
}
if (button_type < 0 || button_type >= (int)hydra::ButtonType::InputCount)
{
throw ErrorFactory::generate_exception(__func__, __LINE__,
"Invalid button range");
}

mappings[button_type] = StringToKey(value);
}

return mappings;
}

static KeyMappings Open(const std::filesystem::path& path)
{
if (!std::filesystem::exists(path))
{
throw ErrorFactory::generate_exception(__func__, __LINE__,
"Input file does not exist");
}

std::ifstream ifs(path);
if (!ifs.good())
{
throw ErrorFactory::generate_exception(__func__, __LINE__,
"Failed to open input file");
}

return Load(std::string((std::istreambuf_iterator<char>(ifs)),
std::istreambuf_iterator<char>()));
}

static void Save(const std::filesystem::path& path, const KeyMappings& mappings)
{
std::map<std::string, std::string> map;

for (int key = 0; key < (int)hydra::ButtonType::InputCount; ++key)
{
map[std::to_string(key)] = KeyToString(mappings[key]);
}

if (!std::filesystem::create_directories(path.parent_path()))
{
if (!std::filesystem::exists(path.parent_path()))
{
throw ErrorFactory::generate_exception(__func__, __LINE__,
"Failed to create input directory");
}
}

json j_map = map;
std::ofstream ofs(path);
ofs << j_map.dump(4);
}

static std::vector<std::filesystem::path> Scan(const std::filesystem::path& root,
const std::string& ext)
{
std::vector<std::filesystem::path> paths;

if (std::filesystem::exists(root) && std::filesystem::is_directory(root))
{
for (const auto& entry : std::filesystem::recursive_directory_iterator(root))
{
if (std::filesystem::is_regular_file(entry) && entry.path().extension() == ext)
paths.emplace_back(entry.path());
}
}

return paths;
}
std::array<SDL_Scancode, (int)hydra::ButtonType::InputCount> mappings;
};

struct Input
{
static void Init();
static void Poll();
static int32_t Check(uint32_t player, hydra::ButtonType button);
static bool Add(const std::string& name, const KeyMappings& mapping);
static bool Remove(const std::string& name);
static bool IsAssociated(const std::string& name);
static bool Associate(uint32_t player, const std::string& name);

private:
static const uint8_t* keyboardState;
static int keyboardStateSize;
static std::unordered_map<std::string, KeyMappings> mappings;
static std::vector<KeyMappings*> playerMappings;
};
} // namespace hydra
Loading

0 comments on commit 38e3be3

Please sign in to comment.