From d81712aaeb78a393e66814efe97b95df823ab1b6 Mon Sep 17 00:00:00 2001 From: Jamiras <32680403+Jamiras@users.noreply.github.com> Date: Thu, 26 Sep 2024 07:45:26 -0600 Subject: [PATCH] add hotkeys for changing disks (#425) --- src/Application.cpp | 134 +++++++++++++++++++++++++++++------------- src/Application.h | 4 ++ src/KeyBinds.cpp | 18 ++++++ src/KeyBinds.h | 7 ++- src/libretro/Core.cpp | 4 +- src/libretro/Core.h | 4 +- 6 files changed, 125 insertions(+), 46 deletions(-) diff --git a/src/Application.cpp b/src/Application.cpp index eb46871..a333b88 100644 --- a/src/Application.cpp +++ b/src/Application.cpp @@ -1656,6 +1656,62 @@ void Application::enableRecent() } } +void Application::toggleTray() +{ + if (_core.getNumDiscs() > 0) + { + _core.setTrayOpen(!_core.getTrayOpen()); + updateDiscMenu(false); + + if (_core.getTrayOpen()) + { + _video.showMessage(_isDriveFloppy ? "Floppy ejected" : "Disc ejected", 200); + } + else + { + std::string message = "Inserted " + getDiscLabel(_core.getCurrentDiscIndex()); + _video.showMessage(message.c_str(), 200); + } + } +} + +void Application::readyNextDisc(int offset) +{ + const unsigned numDiscs = _core.getNumDiscs(); + if (numDiscs > 0) + { + if (_core.getTrayOpen()) + readyDisc((_core.getCurrentDiscIndex() + numDiscs + offset) % numDiscs); + else + _video.showMessage(_isDriveFloppy ? "Cannot change floppy until previous floppy ejected" : "Cannot change disc until previous disc ejected", 200); + } +} + +void Application::readyDisc(unsigned newDiscIndex) +{ + if (_core.getCurrentDiscIndex() != newDiscIndex) + { + std::string path; + if (_core.getDiscPath(newDiscIndex, path)) + { + if (!romLoaded(&_core, &_logger, _system, path, NULL, 0, true)) + return; + } + else if (newDiscIndex < _discPaths.size()) + { + path = util::replaceFileName(_gamePath, _discPaths.at(newDiscIndex).c_str()); + if (!romLoaded(&_core, &_logger, _system, path, NULL, 0, true)) + return; + } + + _core.setCurrentDiscIndex(newDiscIndex); + updateDiscMenu(false); + + std::string message = "Readied " + getDiscLabel(newDiscIndex); + _video.showMessage(message.c_str(), 200); + } +} + void Application::updateDiscMenu(bool updateLabels) { size_t i = 0; @@ -1706,27 +1762,8 @@ void Application::updateDiscMenu(bool updateLabels) if (updateLabels) { - if (_core.getDiscLabel(i, discLabel)) - { - info.dwTypeData = (char*)discLabel.data(); - } - else if (i < _discPaths.size()) - { - const std::string& path = _discPaths.at(i); - size_t index = path.find_last_of('\\'); - if (index == std::string::npos) - index = path.find_last_of('/'); - - if (index != std::string::npos) - info.dwTypeData = (LPSTR)&path.at(index + 1); - else - info.dwTypeData = (LPSTR)&path.at(0); - } - else - { - sprintf(buffer, "Disc %d", (int)(i + 1)); - info.dwTypeData = buffer; - } + discLabel = getDiscLabel(i); + info.dwTypeData = (char*)discLabel.data(); } info.fState = (i == selectedDisc) ? MFS_CHECKED : MFS_UNCHECKED; @@ -1740,6 +1777,33 @@ void Application::updateDiscMenu(bool updateLabels) } } +std::string Application::getDiscLabel(unsigned index) const +{ + std::string discLabel; + + if (_core.getDiscLabel(index, discLabel)) + return discLabel; + + if (index < _discPaths.size()) + { + const std::string& path = _discPaths.at(index); + size_t lastSlashIndex = path.find_last_of('\\'); + if (lastSlashIndex == std::string::npos) + lastSlashIndex = path.find_last_of('/'); + + if (lastSlashIndex != std::string::npos) + discLabel = path.substr(lastSlashIndex + 1); + else + discLabel = path; + } + else + { + discLabel = "Disc " + index; + } + + return discLabel; +} + std::string Application::getStatePath(unsigned ndx) { return _states.getStatePath(ndx); @@ -2263,8 +2327,7 @@ void Application::handle(const SDL_SysWMEvent* syswm) } case IDM_CD_OPEN_TRAY: - _core.setTrayOpen(!_core.getTrayOpen()); - updateDiscMenu(false); + toggleTray(); break; case IDM_PAUSE_GAME: @@ -2382,24 +2445,7 @@ void Application::handle(const SDL_SysWMEvent* syswm) else if (cmd >= IDM_CD_DISC_FIRST && cmd <= IDM_CD_DISC_LAST) { unsigned newDiscIndex = cmd - IDM_CD_DISC_FIRST; - if (_core.getCurrentDiscIndex() != newDiscIndex) - { - std::string path; - if (_core.getDiscPath(newDiscIndex, path)) - { - if (!romLoaded(&_core, &_logger, _system, path, NULL, 0, true)) - break; - } - else if (newDiscIndex < _discPaths.size()) - { - path = util::replaceFileName(_gamePath, _discPaths.at(newDiscIndex).c_str()); - if (!romLoaded(&_core, &_logger, _system, path, NULL, 0, true)) - break; - } - - _core.setCurrentDiscIndex(newDiscIndex); - updateDiscMenu(false); - } + readyDisc(newDiscIndex); } else if (cmd >= IDM_SYSTEM_FIRST && cmd <= IDM_SYSTEM_LAST) { @@ -2550,6 +2596,11 @@ void Application::handle(const KeyBinds::Action action, unsigned extra) case KeyBinds::Action::kLoadState: loadState(extra); break; case KeyBinds::Action::kChangeCurrentState: changeCurrentState(extra); break; + // Disc management + case KeyBinds::Action::kToggleTray: toggleTray(); break; + case KeyBinds::Action::kReadyNextDisc: readyNextDisc(1); break; + case KeyBinds::Action::kReadyPreviousDisc:readyNextDisc(-1); break; + // Window size case KeyBinds::Action::kSetWindowSize1: resizeWindow(1); break; case KeyBinds::Action::kSetWindowSize2: resizeWindow(2); break; @@ -2621,6 +2672,7 @@ void Application::handle(const KeyBinds::Action action, unsigned extra) updateMenu(); _video.showMessage(_keybinds.hasGameFocus() ? "Game focus enabled" : "Game focus disabled", 60); + SDL_SetRelativeMouseMode(_keybinds.hasGameFocus() ? SDL_TRUE : SDL_FALSE); break; } } diff --git a/src/Application.h b/src/Application.h index 6de52aa..fe0a202 100644 --- a/src/Application.h +++ b/src/Application.h @@ -129,6 +129,10 @@ class Application void toggleFastForwarding(unsigned extra); void toggleBackgroundInput(); void setBackgroundInput(bool enabled); + void toggleTray(); + void readyNextDisc(int offset); + void readyDisc(unsigned newDiscIndex); + std::string getDiscLabel(unsigned index) const; Fsm _fsm; bool lastHardcore; diff --git a/src/KeyBinds.cpp b/src/KeyBinds.cpp index 266efbd..122d7c2 100644 --- a/src/KeyBinds.cpp +++ b/src/KeyBinds.cpp @@ -120,6 +120,11 @@ enum kLoadCurrent, kSaveCurrent, + // Disc management + kToggleTray, + kReadyNextDisc, + kReadyPreviousDisc, + // Window size kSetWindowSize1, kSetWindowSize2, @@ -166,6 +171,8 @@ static const char* bindingNames[] = { "SLOT1", "SLOT2", "SLOT3", "SLOT4", "SLOT5", "SLOT6", "SLOT7", "SLOT8", "SLOT9", "SLOT0", "LOAD_SLOT", "SAVE_SLOT", + "TRAY_OPEN", "DISK_NEXT", "DISK_PREV", + "WINDOW_1X", "WINDOW_2X", "WINDOW_3X", "WINDOW_4X", "WINDOW_5X", "TOGGLE_FULLSCREEN", "ROTATE_RIGHT", "ROTATE_LEFT", @@ -286,6 +293,9 @@ bool KeyBinds::init(Logger* logger) _bindings[kToggleFullscreen] = { 0, SDLK_RETURN, Binding::Type::Key, KMOD_ALT }; _bindings[kRotateRight] = { 0, SDLK_r, Binding::Type::Key, KMOD_CTRL }; _bindings[kRotateLeft] = { 0, SDLK_r, Binding::Type::Key, KMOD_CTRL | KMOD_SHIFT }; + _bindings[kToggleTray] = { 0, SDLK_MINUS, Binding::Type::Key, KMOD_ALT }; + _bindings[kReadyNextDisc] = { 0, SDLK_EQUALS, Binding::Type::Key, KMOD_ALT }; + _bindings[kReadyPreviousDisc] = { 0, SDLK_0, Binding::Type::Key, KMOD_ALT }; _bindings[kPauseToggle] = { 0, SDLK_ESCAPE, Binding::Type::Key, 0 }; _bindings[kPauseToggleNoOvl] = { 0, SDLK_p, Binding::Type::Key, 0 }; @@ -422,6 +432,11 @@ KeyBinds::Action KeyBinds::translateButtonPress(int button, unsigned* extra) case kLoadCurrent: *extra = _slot; return Action::kLoadState; case kSaveCurrent: *extra = _slot; return Action::kSaveState; + // Disc management + case kToggleTray: return Action::kToggleTray; + case kReadyNextDisc: return Action::kReadyNextDisc; + case kReadyPreviousDisc: return Action::kReadyPreviousDisc; + // Window size case kSetWindowSize1: return Action::kSetWindowSize1; case kSetWindowSize2: return Action::kSetWindowSize2; @@ -1494,6 +1509,9 @@ class InputDialog : public Dialog addButtonInput(4, 0, "Frame Advance", kStep); addButtonInput(5, 0, "Fast Forward (Hold)", kFastForward); addButtonInput(6, 0, "Fast Forward (Toggle)", kFastForwardToggle); + addButtonInput(7, 0, "Insert/Eject Disc", kToggleTray); + addButtonInput(8, 0, "Ready Next Disc", kReadyNextDisc); + addButtonInput(9, 0, "Ready Previous Disc", kReadyPreviousDisc); addButtonInput(0, 2, "Window Size 1x", kSetWindowSize1); addButtonInput(1, 2, "Window Size 2x", kSetWindowSize2); diff --git a/src/KeyBinds.h b/src/KeyBinds.h index 3c57d70..d38125a 100644 --- a/src/KeyBinds.h +++ b/src/KeyBinds.h @@ -64,6 +64,11 @@ class KeyBinds kLoadState, kChangeCurrentState, + // Disc management + kToggleTray, + kReadyNextDisc, + kReadyPreviousDisc, + // Window size kSetWindowSize1, kSetWindowSize2, @@ -120,7 +125,7 @@ class KeyBinds Type type; uint16_t modifiers; }; - typedef std::array BindingList; + typedef std::array BindingList; static void getBindingString(char buffer[32], const KeyBinds::Binding& desc); diff --git a/src/libretro/Core.cpp b/src/libretro/Core.cpp index e322180..1a021ca 100644 --- a/src/libretro/Core.cpp +++ b/src/libretro/Core.cpp @@ -862,7 +862,7 @@ bool libretro::Core::setDiskControlExtInterface(const struct retro_disk_control_ return true; } -bool libretro::Core::getDiscLabel(unsigned index, std::string& label) +bool libretro::Core::getDiscLabel(unsigned index, std::string& label) const { if (_diskControlInterface.get_image_label) { @@ -877,7 +877,7 @@ bool libretro::Core::getDiscLabel(unsigned index, std::string& label) return false; } -bool libretro::Core::getDiscPath(unsigned index, std::string& path) +bool libretro::Core::getDiscPath(unsigned index, std::string& path) const { if (_diskControlInterface.get_image_path) { diff --git a/src/libretro/Core.h b/src/libretro/Core.h index 138f2f8..b7d54e6 100644 --- a/src/libretro/Core.h +++ b/src/libretro/Core.h @@ -69,8 +69,8 @@ namespace libretro inline unsigned getNumDiscs() const { return (_diskControlInterface.get_num_images != NULL) ? _diskControlInterface.get_num_images() : 0; } inline unsigned getCurrentDiscIndex() const { return (_diskControlInterface.get_image_index != NULL) ? _diskControlInterface.get_image_index() : 0; } void setCurrentDiscIndex(unsigned index); - bool getDiscLabel(unsigned index, std::string& label); - bool getDiscPath(unsigned index, std::string& path); + bool getDiscLabel(unsigned index, std::string& label) const; + bool getDiscPath(unsigned index, std::string& path) const; inline bool getTrayOpen() const { return (_diskControlInterface.get_eject_state != NULL) ? (bool)_diskControlInterface.get_eject_state() : false; } void setTrayOpen(bool open);