Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ set(ADDITIONAL_LIB_INCLUDES "")
# ========= Configuration Options =========
option(INCLUDE_MPQ_SUPPORT "Enable StormLib and MPQ archive support" OFF)
option(GBI_UCODE "Specify the GBI ucode version" F3DEX_GBI_2)
option(ENABLE_PRESS_TO_JOIN "Enable press-to-join multiplayer controller assignment" OFF)

# =========== Dependencies =============
if (CMAKE_SYSTEM_NAME STREQUAL "Windows")
Expand Down
3 changes: 2 additions & 1 deletion include/libultraship/bridge.h
Original file line number Diff line number Diff line change
Expand Up @@ -8,4 +8,5 @@
#include "libultraship/bridge/crashhandlerbridge.h"
#include "libultraship/bridge/gfxdebuggerbridge.h"
#include "libultraship/bridge/gfxbridge.h"
#include "libultraship/bridge/eventsbridge.h"
#include "libultraship/bridge/eventsbridge.h"
#include "libultraship/bridge/multiplayerbridge.h"
21 changes: 21 additions & 0 deletions include/libultraship/bridge/multiplayerbridge.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
#pragma once

#ifdef ENABLE_PRESS_TO_JOIN

#include <stdint.h>

#ifdef __cplusplus
extern "C" {
#endif

void MultiplayerStart(uint8_t portCount);
void MultiplayerStopPressToJoin(void);
void MultiplayerStartPressToJoin(void);
void MultiplayerStop(void);
int8_t MultiplayerGetPortStatus(uint8_t port);

#ifdef __cplusplus
};
#endif

#endif // ENABLE_PRESS_TO_JOIN
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,10 @@

namespace Ship {

#ifdef ENABLE_PRESS_TO_JOIN
static constexpr int32_t KEYBOARD_PSEUDO_INSTANCE_ID = -2;
#endif

class ConnectedPhysicalDeviceManager {
public:
ConnectedPhysicalDeviceManager();
Expand All @@ -24,9 +28,30 @@ class ConnectedPhysicalDeviceManager {
void HandlePhysicalDeviceDisconnect(int32_t sdlJoystickInstanceId);
void RefreshConnectedSDLGamepads();

#ifdef ENABLE_PRESS_TO_JOIN
void StartMultiplayer(uint8_t portCount);
void StopPressToJoin();
void StartPressToJoin();
void StopMultiplayer();
int8_t GetPortDeviceStatus(uint8_t port);
void PollPressToJoin();
#endif

private:
std::unordered_map<int32_t, SDL_GameController*> mConnectedSDLGamepads;
std::unordered_map<int32_t, std::string> mConnectedSDLGamepadNames;
std::unordered_map<uint8_t, std::unordered_set<int32_t>> mIgnoredInstanceIds;

#ifdef ENABLE_PRESS_TO_JOIN
bool mMultiplayerActive = false;
bool mPressToJoinActive = false;
uint8_t mMultiplayerPortCount = 1;
std::unordered_map<uint8_t, int32_t> mPressToJoinAssignments;

void AssignDeviceToPort(int32_t instanceId, uint8_t port);
void UnassignPort(uint8_t port);
void RebuildIgnoreListsFromAssignments();
bool PortHasKeyboardMappings(uint8_t port);
#endif
};
} // namespace Ship
4 changes: 4 additions & 0 deletions src/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,10 @@ target_link_libraries(libultraship PUBLIC prism)

target_compile_definitions(libultraship PRIVATE ${GBI_UCODE})

if (ENABLE_PRESS_TO_JOIN)
target_compile_definitions(libultraship PUBLIC ENABLE_PRESS_TO_JOIN)
endif()

if (CMAKE_SYSTEM_NAME STREQUAL "Windows")
target_compile_definitions(${PROJECT_NAME} PRIVATE
WIN32
Expand Down
27 changes: 27 additions & 0 deletions src/libultraship/bridge/multiplayerbridge.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
#ifdef ENABLE_PRESS_TO_JOIN

#include "libultraship/bridge/multiplayerbridge.h"
#include "ship/controller/controldeck/ControlDeck.h"
#include "ship/Context.h"

void MultiplayerStart(uint8_t portCount) {
Ship::Context::GetInstance()->GetControlDeck()->GetConnectedPhysicalDeviceManager()->StartMultiplayer(portCount);
}

void MultiplayerStopPressToJoin(void) {
Ship::Context::GetInstance()->GetControlDeck()->GetConnectedPhysicalDeviceManager()->StopPressToJoin();
}

void MultiplayerStartPressToJoin(void) {
Ship::Context::GetInstance()->GetControlDeck()->GetConnectedPhysicalDeviceManager()->StartPressToJoin();
}

void MultiplayerStop(void) {
Ship::Context::GetInstance()->GetControlDeck()->GetConnectedPhysicalDeviceManager()->StopMultiplayer();
}

int8_t MultiplayerGetPortStatus(uint8_t port) {
return Ship::Context::GetInstance()->GetControlDeck()->GetConnectedPhysicalDeviceManager()->GetPortDeviceStatus(port);
}

#endif // ENABLE_PRESS_TO_JOIN
4 changes: 4 additions & 0 deletions src/libultraship/controller/controldeck/ControlDeck.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,10 @@ void ControlDeck::WriteToOSContPad(OSContPad* pad) {
SDL_PumpEvents();
Ship::WheelHandler::GetInstance()->Update();

#ifdef ENABLE_PRESS_TO_JOIN
GetConnectedPhysicalDeviceManager()->PollPressToJoin();
#endif

if (AllGameInputBlocked()) {
return;
}
Expand Down
11 changes: 11 additions & 0 deletions src/ship/controller/controldeck/ControlDeck.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,17 @@ void ControlDeck::Init(uint8_t* controllerBits) {
mPorts[0]->GetConnectedController()->AddDefaultMappings(PhysicalDeviceType::Mouse);
mPorts[0]->GetConnectedController()->AddDefaultMappings(PhysicalDeviceType::SDLGamepad);
}

#ifdef ENABLE_PRESS_TO_JOIN
// POC: apply SDLGamepad defaults to all other ports so press-to-join works
// out of the box. A proper solution would let games define per-port defaults
// via ControllerDefaultMappings rather than hardcoding this loop in library code.
for (size_t i = 1; i < mPorts.size(); i++) {
if (!mPorts[i]->GetConnectedController()->HasConfig()) {
mPorts[i]->GetConnectedController()->AddDefaultMappings(PhysicalDeviceType::SDLGamepad);
}
}
#endif
}

bool ControlDeck::ProcessKeyboardEvent(KbEventType eventType, KbScancode scancode) {
Expand Down
Loading
Loading