diff --git a/rpcs3/Emu/Cell/Modules/cellGem.cpp b/rpcs3/Emu/Cell/Modules/cellGem.cpp index d92eba49d9..ab4c3e27a1 100644 --- a/rpcs3/Emu/Cell/Modules/cellGem.cpp +++ b/rpcs3/Emu/Cell/Modules/cellGem.cpp @@ -6,6 +6,7 @@ #include "Emu/Cell/PPUModule.h" #include "Emu/Cell/timers.hpp" #include "Emu/Io/MouseHandler.h" +#include "Emu/Io/gem_config.h" #include "Emu/system_config.h" #include "Emu/System.h" #include "Emu/IdManager.h" @@ -140,6 +141,7 @@ public: static constexpr auto thread_name = "Gem Thread"sv; + cfg_gems gem_cfg; atomic_t state = 0; struct gem_color @@ -286,7 +288,13 @@ public: } } - gem_config_data() = default; + gem_config_data() + { + if (!gem_cfg.load()) + { + cellGem.notice("Could not load gem config. Using defaults."); + } + }; SAVESTATE_INIT_POS(15); @@ -318,6 +326,11 @@ public: gem_config_data(utils::serial& ar) { save(ar); + + if (!ar.is_writing() && !gem_cfg.load()) + { + cellGem.notice("Could not load gem config. Using defaults."); + } } }; @@ -635,6 +648,9 @@ static void ds3_input_to_pad(const u32 port_no, be_t& digital_buttons, be_t return; } + const auto& gem = g_fxo->get(); + const auto& cfg = ::at32(gem.gem_cfg.players, port_no); + for (const Button& button : pad->m_buttons) { if (!button.m_pressed) @@ -642,46 +658,35 @@ static void ds3_input_to_pad(const u32 port_no, be_t& digital_buttons, be_t continue; } - // here we check btns, and set pad accordingly - if (button.m_offset == CELL_PAD_BTN_OFFSET_DIGITAL1) + if (const auto btn = cfg->find_button(button.m_offset, button.m_outKeyCode)) { - switch (button.m_outKeyCode) + switch (btn.value()) { - case CELL_PAD_CTRL_START: + case gem_btn::start: digital_buttons |= CELL_GEM_CTRL_START; break; - case CELL_PAD_CTRL_SELECT: + case gem_btn::select: digital_buttons |= CELL_GEM_CTRL_SELECT; break; - default: - break; - } - } - else if (button.m_offset == CELL_PAD_BTN_OFFSET_DIGITAL2) - { - switch (button.m_outKeyCode) - { - case CELL_PAD_CTRL_SQUARE: + case gem_btn::square: digital_buttons |= CELL_GEM_CTRL_SQUARE; break; - case CELL_PAD_CTRL_CROSS: + case gem_btn::cross: digital_buttons |= CELL_GEM_CTRL_CROSS; break; - case CELL_PAD_CTRL_CIRCLE: + case gem_btn::circle: digital_buttons |= CELL_GEM_CTRL_CIRCLE; break; - case CELL_PAD_CTRL_TRIANGLE: + case gem_btn::triangle: digital_buttons |= CELL_GEM_CTRL_TRIANGLE; break; - case CELL_PAD_CTRL_R1: + case gem_btn::move: digital_buttons |= CELL_GEM_CTRL_MOVE; break; - case CELL_PAD_CTRL_R2: + case gem_btn::t: digital_buttons |= CELL_GEM_CTRL_T; analog_t = std::max(analog_t, button.m_value); break; - default: - break; } } } diff --git a/rpcs3/Emu/Io/gem_config.cpp b/rpcs3/Emu/Io/gem_config.cpp new file mode 100644 index 0000000000..32d99535ea --- /dev/null +++ b/rpcs3/Emu/Io/gem_config.cpp @@ -0,0 +1,81 @@ +#include "stdafx.h" +#include "gem_config.h" + +LOG_CHANNEL(cellGem); + +std::optional cfg_gem::find_button(u32 offset, u32 keycode) const +{ + if (const auto it = buttons.find(offset); it != buttons.cend()) + { + if (const auto it2 = it->second.find(keycode); it2 != it->second.cend()) + { + return it2->second; + } + } + + return std::nullopt; +} + +bool cfg_gems::load() +{ + bool result = false; + const std::string cfg_name = fs::get_config_dir() + "config/gem.yml"; + cellGem.notice("Loading gem config: %s", cfg_name); + + from_default(); + + for (cfg_gem* player : players) + { + player->buttons.clear(); + } + + if (fs::file cfg_file{ cfg_name, fs::read }) + { + if (std::string content = cfg_file.to_string(); !content.empty()) + { + result = from_string(content); + } + } + else + { + save(); + } + + for (cfg_gem* player : players) + { + const auto set_button = [&player](pad_button pbtn, gem_btn bbtn) + { + const u32 offset = pad_button_offset(pbtn); + const u32 keycode = pad_button_keycode(pbtn); + player->buttons[(offset >> 8) & 0xFF][keycode & 0xFF] = bbtn; + }; + set_button(player->start, gem_btn::start); + set_button(player->select, gem_btn::select); + set_button(player->triangle, gem_btn::triangle); + set_button(player->circle, gem_btn::circle); + set_button(player->cross, gem_btn::cross); + set_button(player->square, gem_btn::square); + set_button(player->move, gem_btn::move); + set_button(player->t, gem_btn::t); + } + + return result; +} + +void cfg_gems::save() const +{ + const std::string cfg_name = fs::get_config_dir() + "config/gem.yml"; + cellGem.notice("Saving gem config to '%s'", cfg_name); + + if (!fs::create_path(fs::get_parent_dir(cfg_name))) + { + cellGem.fatal("Failed to create path: %s (%s)", cfg_name, fs::g_tls_error); + } + + fs::pending_file cfg_file(cfg_name); + + if (!cfg_file.file || (cfg_file.file.write(to_string()), !cfg_file.commit())) + { + cellGem.error("Failed to save gem config to '%s' (error=%s)", cfg_name, fs::g_tls_error); + } +} diff --git a/rpcs3/Emu/Io/gem_config.h b/rpcs3/Emu/Io/gem_config.h new file mode 100644 index 0000000000..b4b06e2ec4 --- /dev/null +++ b/rpcs3/Emu/Io/gem_config.h @@ -0,0 +1,51 @@ +#pragma once + +#include "Utilities/Config.h" +#include "pad_types.h" + +#include + +enum class gem_btn +{ + start, + select, + triangle, + circle, + cross, + square, + move, + t, +}; + +struct cfg_gem final : cfg::node +{ + cfg_gem(node* owner, const std::string& name) : cfg::node(owner, name) {} + + cfg::_enum start{ this, "Start", pad_button::start }; + cfg::_enum select{ this, "Select", pad_button::select }; + cfg::_enum triangle{ this, "Triangle", pad_button::triangle }; + cfg::_enum circle{ this, "Circle", pad_button::circle }; + cfg::_enum cross{ this, "Cross", pad_button::cross }; + cfg::_enum square{ this, "Square", pad_button::square }; + cfg::_enum move{ this, "Move", pad_button::R1 }; + cfg::_enum t{ this, "T", pad_button::R2 }; + + std::map> buttons; + std::optional find_button(u32 offset, u32 keycode) const; +}; + +struct cfg_gems final : cfg::node +{ + cfg_gem player1{ this, "Player 1" }; + cfg_gem player2{ this, "Player 2" }; + cfg_gem player3{ this, "Player 3" }; + cfg_gem player4{ this, "Player 4" }; + cfg_gem player5{ this, "Player 5" }; + cfg_gem player6{ this, "Player 6" }; + cfg_gem player7{ this, "Player 7" }; + + std::array players{ &player1, &player2, &player3, &player4, &player5, &player6, &player7 }; // Thanks gcc! + + bool load(); + void save() const; +};