Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[WIP] Expansion of button controls for intent-based control modifications #638

Draft
wants to merge 7 commits into
base: main
Choose a base branch
from
42 changes: 42 additions & 0 deletions include/libultraship/libultra/controller.h
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,24 @@ typedef struct {
/* 0x03 */ uint8_t err_no;
} OSContStatus; // size = 0x04

typedef struct IntentControls IntentControls;

#define BUTTON_STATE_CUR 0
#define BUTTON_STATE_PREV 1
#define BUTTON_STATE_PRESS 2
#define BUTTON_STATE_REL 3

struct IntentControls {
void* userData;
uint8_t (*checkIntentButton)(void* userData, uint16_t intentId, uint8_t buttonStateVersion);
void(*registerButtonState)(void* userData, uint16_t specialButtonId, uint8_t);
void(*updateState)(void* userData);
// void(*updateCurState)(void* userData, IntentControls* cur, IntentControls* prev, IntentControls* press, IntentControls* rel);
// void(*updatePrevState)(void* userData, IntentControls* cur, IntentControls* prev, IntentControls* press, IntentControls* rel);
// void(*updatePressState)(void* userData, IntentControls* cur, IntentControls* prev, IntentControls* press, IntentControls* rel);
// void(*updateRelState)(void* userData, IntentControls* cur, IntentControls* prev, IntentControls* press, IntentControls* rel);
};

typedef struct {
/* 0x00 */ CONTROLLERBUTTONS_T button;
/* 0x02 */ int8_t stick_x;
Expand All @@ -129,8 +147,32 @@ typedef struct {
/* 0x09 */ float gyro_y;
/* 0x1C */ int8_t right_stick_x;
/* 0x20 */ int8_t right_stick_y;
IntentControls* intentControls;
} OSContPad; // size = 0x24

typedef struct {
uint16_t id;
char* name;
} IntentControlDefinition;

typedef struct {
IntentControlDefinition* definitions;
uint16_t count;
} IntentControlDefinitionSet;

#ifdef __cplusplus
extern "C" {
#endif
extern IntentControlDefinitionSet getIntentControlDefinitions();
extern void setIntentControlDefinitions(IntentControlDefinitionSet controls);
#ifdef __cplusplus
}
#endif

#define GET_INTENTS(pad, f, default) (pad->intentControls == NULL ? default : pad->intentControls->f)

#define CHECK_INTENT(intentControls, intent, state, defaultVal) ( intentControls == NULL ? defaultVal : intentControls->checkIntentButton(intentControls->userData, intent, state))

typedef struct {
/* 0x00 */ void* address;
/* 0x04 */ uint8_t databuffer[32];
Expand Down
12 changes: 9 additions & 3 deletions src/Context.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
#include "install_config.h"
#include "debug/GfxDebugger.h"
#include "graphic/Fast3D/Fast3dWindow.h"
#include "IntentControlManager.h"

#ifdef _WIN32
#include <tchar.h>
Expand Down Expand Up @@ -80,7 +81,12 @@ void Context::Init(const std::vector<std::string>& otrFiles, const std::unordere
InitConfiguration();
InitConsoleVariables();
InitResourceManager(otrFiles, validHashes, reservedThreadCount);
InitControlDeck();
std::vector<uint16_t> specialControls;
IntentControlDefinitionSet intentDefs = getIntentControlDefinitions();
for(size_t i = 0; i < intentDefs.count; i++){
specialControls.push_back(intentDefs.definitions[i].id);
}
InitControlDeck({}, specialControls);
InitCrashHandler();
InitConsole();
InitWindow();
Expand Down Expand Up @@ -211,12 +217,12 @@ void Context::InitResourceManager(const std::vector<std::string>& otrFiles,
}
}

void Context::InitControlDeck(std::vector<CONTROLLERBUTTONS_T> additionalBitmasks) {
void Context::InitControlDeck(std::vector<CONTROLLERBUTTONS_T> additionalBitmasks, std::vector<uint16_t> specialControls) {
if (GetControlDeck() != nullptr) {
return;
}

mControlDeck = std::make_shared<ControlDeck>(additionalBitmasks);
mControlDeck = std::make_shared<ControlDeck>(additionalBitmasks, specialControls);
}

void Context::InitCrashHandler() {
Expand Down
2 changes: 1 addition & 1 deletion src/Context.h
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ class Context {
void InitConsoleVariables();
void InitResourceManager(const std::vector<std::string>& otrFiles = {},
const std::unordered_set<uint32_t>& validHashes = {}, uint32_t reservedThreadCount = 1);
void InitControlDeck(std::vector<CONTROLLERBUTTONS_T> additionalBitmasks = {});
void InitControlDeck(std::vector<CONTROLLERBUTTONS_T> additionalBitmasks = {}, std::vector<uint16_t> specialControls = {});
void InitCrashHandler();
void InitAudio();
void InitGfxDebugger();
Expand Down
84 changes: 84 additions & 0 deletions src/IntentControlManager.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
#include <libultraship/libultra/controller.h>
#include <map>

class IntentControlManager {
public:
IntentControls* intentControls = new IntentControls();

std::map<uint16_t, uint8_t> pendingStates = std::map<uint16_t, uint8_t>();

std::map<uint16_t, uint8_t> curStates = std::map<uint16_t, uint8_t>();
std::map<uint16_t, uint8_t> prevStates = std::map<uint16_t, uint8_t>();
std::map<uint16_t, uint8_t> pressStates = std::map<uint16_t, uint8_t>();
std::map<uint16_t, uint8_t> relStates = std::map<uint16_t, uint8_t>();

IntentControlManager(){
intentControls->userData = this;
intentControls->checkIntentButton = +[](void* userData, uint16_t intentId, uint8_t stateVersionId){
return ((IntentControlManager*) userData)->checkIntentButton(intentId, stateVersionId);
};

intentControls->registerButtonState = [](void* userData, uint16_t intentId, uint8_t pressed){
return ((IntentControlManager*) userData)->registerButtonState(intentId, pressed);
};

intentControls->updateState = +[](void* userData){
((IntentControlManager*) userData)->updateState();
};
}

uint8_t checkIntentButton(uint16_t intentId, uint8_t stateVersionId){
std::map<uint16_t, uint8_t>* stateVersion = nullptr;
switch (stateVersionId)
{
case BUTTON_STATE_CUR:
stateVersion = &this->curStates;
break;
case BUTTON_STATE_PREV:
stateVersion = &this->prevStates;
break;
case BUTTON_STATE_PRESS:
stateVersion = &this->pressStates;
break;
case BUTTON_STATE_REL:
stateVersion = &this->relStates;
break;

default:
return 0;
}

stateVersion->try_emplace(intentId, 0);
uint8_t result = stateVersion->at(intentId);
return result;
}

void registerButtonState(uint16_t intentId, uint8_t pressed){
pendingStates.insert_or_assign(intentId, pressed);
}

void updateState(){
this->prevStates.clear();
for(auto s : this->curStates){
prevStates.insert_or_assign(s.first, s.second);
}

this->curStates.clear();
for(auto s : this->pendingStates){
curStates.insert_or_assign(s.first, s.second);
}

for(auto s : this->prevStates){
this->curStates.try_emplace(s.first, 0);
uint8_t cur = this->curStates.at(s.first);
uint8_t diff = !cur != !s.second;

this->pressStates.insert_or_assign(s.first, (diff && cur));
this->relStates.insert_or_assign(s.first, (diff && s.second));
}
}

~IntentControlManager(){

}
};
8 changes: 5 additions & 3 deletions src/controller/controldeck/ControlDeck.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,19 +9,21 @@
#endif
#include <imgui.h>
#include "controller/deviceindex/ShipDeviceIndexMappingManager.h"
#include <IntentControlManager.h>

namespace Ship {

ControlDeck::ControlDeck(std::vector<CONTROLLERBUTTONS_T> additionalBitmasks)
ControlDeck::ControlDeck(std::vector<CONTROLLERBUTTONS_T> additionalBitmasks, std::vector<uint16_t> specialButtons)
: mPads(nullptr), mSinglePlayerMappingMode(false) {
for (int32_t i = 0; i < MAXCONTROLLERS; i++) {
mPorts.push_back(std::make_shared<ControlPort>(i, std::make_shared<Controller>(i, additionalBitmasks)));
IntentControlManager* intentManager = new IntentControlManager();
mPorts.push_back(std::make_shared<ControlPort>(i, std::make_shared<Controller>(i, additionalBitmasks, intentManager->intentControls, specialButtons)));
}

mDeviceIndexMappingManager = std::make_shared<ShipDeviceIndexMappingManager>();
}

ControlDeck::ControlDeck() : ControlDeck(std::vector<CONTROLLERBUTTONS_T>()) {
ControlDeck::ControlDeck() : ControlDeck(std::vector<CONTROLLERBUTTONS_T>(), std::vector<uint16_t>()) {
}

ControlDeck::~ControlDeck() {
Expand Down
2 changes: 1 addition & 1 deletion src/controller/controldeck/ControlDeck.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ namespace Ship {
class ControlDeck {
public:
ControlDeck();
ControlDeck(std::vector<CONTROLLERBUTTONS_T> additionalBitmasks);
ControlDeck(std::vector<CONTROLLERBUTTONS_T> additionalBitmasks, std::vector<uint16_t> intentButtons);
~ControlDeck();

void Init(uint8_t* controllerBits);
Expand Down
Loading