mirror of
https://github.com/wiiu-env/WiiUPluginSystem.git
synced 2026-03-21 17:54:10 -05:00
264 lines
9.6 KiB
C++
264 lines
9.6 KiB
C++
#include <coreinit/debug.h>
|
|
#include <coreinit/thread.h>
|
|
#include <cstdio>
|
|
#include <cstdlib>
|
|
#include <string>
|
|
#include <wups.h>
|
|
#include <wups/config/WUPSConfigItemIPAddress.h>
|
|
|
|
namespace {
|
|
void modifyIpOctet(ConfigItemIPAddress *item, int octetIndex, const int delta) {
|
|
const int shift = (3 - octetIndex) * 8;
|
|
uint8_t octet = (item->currentValue >> shift) & 0xFF;
|
|
octet += delta;
|
|
const uint32_t mask = ~(0xFF << shift);
|
|
item->currentValue = (item->currentValue & mask) | (static_cast<uint32_t>(octet) << shift);
|
|
}
|
|
|
|
int32_t getCurrentValueDisplayGeneric(void *context, bool isSelected, char *out_buf, int32_t out_size) {
|
|
auto *item = static_cast<ConfigItemIPAddress *>(context);
|
|
|
|
const uint8_t o1 = (item->currentValue >> 24) & 0xFF;
|
|
const uint8_t o2 = (item->currentValue >> 16) & 0xFF;
|
|
const uint8_t o3 = (item->currentValue >> 8) & 0xFF;
|
|
const uint8_t o4 = (item->currentValue) & 0xFF;
|
|
|
|
switch (item->itemState) {
|
|
case WUPS_CONFIG_ITEM_IP_ADDRESS_STATE_EDIT_INPUT_FIELD1:
|
|
snprintf(out_buf, out_size, "[%u].%u.%u.%u", o1, o2, o3, o4);
|
|
break;
|
|
|
|
case WUPS_CONFIG_ITEM_IP_ADDRESS_STATE_EDIT_INPUT_FIELD2:
|
|
snprintf(out_buf, out_size, "%u.[%u].%u.%u", o1, o2, o3, o4);
|
|
break;
|
|
|
|
case WUPS_CONFIG_ITEM_IP_ADDRESS_STATE_EDIT_INPUT_FIELD3:
|
|
snprintf(out_buf, out_size, "%u.%u.[%u].%u", o1, o2, o3, o4);
|
|
break;
|
|
|
|
case WUPS_CONFIG_ITEM_IP_ADDRESS_STATE_EDIT_INPUT_FIELD4:
|
|
snprintf(out_buf, out_size, "%u.%u.%u.[%u]", o1, o2, o3, o4);
|
|
break;
|
|
|
|
default:
|
|
if (isSelected) {
|
|
snprintf(out_buf, out_size, "(Press A to edit) %u.%u.%u.%u", o1, o2, o3, o4);
|
|
} else {
|
|
snprintf(out_buf, out_size, "%u.%u.%u.%u", o1, o2, o3, o4);
|
|
}
|
|
break;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
} // namespace
|
|
|
|
static int32_t WUPSConfigItemIPAddress_getCurrentValueDisplay(void *context, char *out_buf, int32_t out_size) {
|
|
return getCurrentValueDisplayGeneric(context, false, out_buf, out_size);
|
|
}
|
|
|
|
static void WUPSConfigItemIPAddress_onCloseCallback(void *context) {
|
|
auto *item = static_cast<ConfigItemIPAddress *>(context);
|
|
if (item->currentValue != item->valueAtCreation && item->valueChangedCallback != nullptr) {
|
|
reinterpret_cast<IPAddressValueChangedCallback>(item->valueChangedCallback)(item, item->currentValue);
|
|
}
|
|
}
|
|
|
|
#define IP_VALUE_EDIT_INITIAL_DELAY 5
|
|
static void WUPSConfigItemIPAddress_onInput(void *context, WUPSConfigSimplePadData input) {
|
|
auto *item = static_cast<ConfigItemIPAddress *>(context);
|
|
|
|
// Handle edit request
|
|
if (item->itemState == WUPS_CONFIG_ITEM_IP_ADDRESS_STATE_NONE) {
|
|
if (input.buttons_d & WUPS_CONFIG_BUTTON_A) {
|
|
item->valueBeforeEdit = item->currentValue;
|
|
item->itemState = WUPS_CONFIG_ITEM_IP_ADDRESS_STATE_EDIT_INPUT_FIELD1;
|
|
item->frameTimer = 0;
|
|
}
|
|
return;
|
|
}
|
|
|
|
// When editing press A to accept, press B to abort
|
|
if ((input.buttons_d & WUPS_CONFIG_BUTTON_A) || (input.buttons_d & WUPS_CONFIG_BUTTON_B)) {
|
|
if (input.buttons_d & WUPS_CONFIG_BUTTON_B) {
|
|
item->currentValue = item->valueBeforeEdit;
|
|
}
|
|
item->itemState = WUPS_CONFIG_ITEM_IP_ADDRESS_STATE_NONE;
|
|
return;
|
|
}
|
|
|
|
int fieldIndex = 0;
|
|
switch (item->itemState) {
|
|
case WUPS_CONFIG_ITEM_IP_ADDRESS_STATE_EDIT_INPUT_FIELD1: {
|
|
fieldIndex = 0;
|
|
break;
|
|
}
|
|
case WUPS_CONFIG_ITEM_IP_ADDRESS_STATE_EDIT_INPUT_FIELD2: {
|
|
fieldIndex = 1;
|
|
break;
|
|
}
|
|
case WUPS_CONFIG_ITEM_IP_ADDRESS_STATE_EDIT_INPUT_FIELD3: {
|
|
fieldIndex = 2;
|
|
break;
|
|
}
|
|
case WUPS_CONFIG_ITEM_IP_ADDRESS_STATE_EDIT_INPUT_FIELD4: {
|
|
fieldIndex = 3;
|
|
break;
|
|
}
|
|
default:
|
|
return;
|
|
}
|
|
|
|
// Handle navigation between field
|
|
if (input.buttons_d & WUPS_CONFIG_BUTTON_LEFT) {
|
|
if (fieldIndex > 0) {
|
|
item->itemState = static_cast<ConfigItemIPAddress_State>(item->itemState - 1);
|
|
} else
|
|
item->itemState = WUPS_CONFIG_ITEM_IP_ADDRESS_STATE_EDIT_INPUT_FIELD4;
|
|
return;
|
|
}
|
|
if (input.buttons_d & WUPS_CONFIG_BUTTON_RIGHT) {
|
|
if (fieldIndex < 3) {
|
|
item->itemState = static_cast<ConfigItemIPAddress_State>(item->itemState + 1);
|
|
} else {
|
|
item->itemState = WUPS_CONFIG_ITEM_IP_ADDRESS_STATE_EDIT_INPUT_FIELD1;
|
|
}
|
|
return;
|
|
}
|
|
|
|
// Handle modify ocet
|
|
bool isUp = input.buttons_h & WUPS_CONFIG_BUTTON_UP;
|
|
bool isDown = input.buttons_h & WUPS_CONFIG_BUTTON_DOWN;
|
|
|
|
if (isUp || isDown) {
|
|
bool applyChange = false;
|
|
|
|
if ((isUp && (input.buttons_d & WUPS_CONFIG_BUTTON_UP)) ||
|
|
(isDown && (input.buttons_d & WUPS_CONFIG_BUTTON_DOWN))) {
|
|
applyChange = true;
|
|
item->frameTimer = IP_VALUE_EDIT_INITIAL_DELAY;
|
|
} else {
|
|
if (item->frameTimer > 0) {
|
|
item->frameTimer--;
|
|
} else {
|
|
applyChange = true;
|
|
}
|
|
}
|
|
|
|
if (applyChange) {
|
|
modifyIpOctet(item, fieldIndex, isUp ? 1 : -1);
|
|
}
|
|
} else {
|
|
item->frameTimer = 0;
|
|
}
|
|
}
|
|
|
|
static int32_t
|
|
WUPSConfigItemIPAddress_getCurrentValueSelectedDisplay(void *context, char *out_buf, int32_t out_size) {
|
|
return getCurrentValueDisplayGeneric(context, true, out_buf, out_size);
|
|
}
|
|
|
|
static void WUPSConfigItemIPAddress_restoreDefault(void *context) {
|
|
auto *item = static_cast<ConfigItemIPAddress *>(context);
|
|
|
|
item->currentValue = item->defaultValue;
|
|
}
|
|
|
|
static bool WUPSConfigItemIPAddress_isMovementAllowed(void *context) {
|
|
const auto *item = static_cast<ConfigItemIPAddress *>(context);
|
|
return item->itemState == WUPS_CONFIG_ITEM_IP_ADDRESS_STATE_NONE;
|
|
}
|
|
|
|
static void WUPSConfigItemIPAddress_Cleanup(ConfigItemIPAddress *item) {
|
|
if (!item) {
|
|
return;
|
|
}
|
|
if (item->identifier) {
|
|
free(item->identifier);
|
|
}
|
|
free(item);
|
|
}
|
|
|
|
static void WUPSConfigItemIPAddress_onDelete(void *context) {
|
|
WUPSConfigItemIPAddress_Cleanup(static_cast<ConfigItemIPAddress *>(context));
|
|
}
|
|
|
|
WUPSConfigAPIStatus
|
|
WUPSConfigItemIPAddress_Create(const char *identifier,
|
|
const char *displayName,
|
|
const uint32_t defaultIPAddress,
|
|
IPAddressValueChangedCallback callback,
|
|
WUPSConfigItemHandle *outItemHandle) {
|
|
if (outItemHandle == nullptr) {
|
|
return WUPSCONFIG_API_RESULT_INVALID_ARGUMENT;
|
|
}
|
|
auto *item = static_cast<ConfigItemIPAddress *>(malloc(sizeof(ConfigItemIPAddress)));
|
|
if (item == nullptr) {
|
|
OSReport("WUPSConfigItemIPAddress_CreateEx: Failed to allocate memory for item data.\n");
|
|
return WUPSCONFIG_API_RESULT_INVALID_ARGUMENT;
|
|
}
|
|
|
|
if (identifier != nullptr) {
|
|
item->identifier = strdup(identifier);
|
|
} else {
|
|
item->identifier = nullptr;
|
|
}
|
|
|
|
item->currentValue = defaultIPAddress;
|
|
item->defaultValue = defaultIPAddress;
|
|
item->valueAtCreation = defaultIPAddress;
|
|
item->valueChangedCallback = reinterpret_cast<void *>(callback);
|
|
|
|
item->itemState = WUPS_CONFIG_ITEM_IP_ADDRESS_STATE_NONE;
|
|
|
|
constexpr WUPSConfigAPIItemCallbacksV2 callbacks = {
|
|
.getCurrentValueDisplay = &WUPSConfigItemIPAddress_getCurrentValueDisplay,
|
|
.getCurrentValueSelectedDisplay = &WUPSConfigItemIPAddress_getCurrentValueSelectedDisplay,
|
|
.onSelected = nullptr,
|
|
.restoreDefault = &WUPSConfigItemIPAddress_restoreDefault,
|
|
.isMovementAllowed = &WUPSConfigItemIPAddress_isMovementAllowed,
|
|
.onCloseCallback = &WUPSConfigItemIPAddress_onCloseCallback,
|
|
.onInput = &WUPSConfigItemIPAddress_onInput,
|
|
.onInputEx = nullptr,
|
|
.onDelete = &WUPSConfigItemIPAddress_onDelete,
|
|
};
|
|
|
|
const WUPSConfigAPIItemOptionsV2 options = {
|
|
.displayName = displayName,
|
|
.context = item,
|
|
.callbacks = callbacks,
|
|
};
|
|
|
|
if (const WUPSConfigAPIStatus err = WUPSConfigAPI_Item_Create(options, &item->itemHandle); err != WUPSCONFIG_API_RESULT_SUCCESS) {
|
|
OSReport("WUPSConfigItemIPAddress_Create: Failed to create config item.\n");
|
|
WUPSConfigItemIPAddress_Cleanup(item);
|
|
return err;
|
|
}
|
|
|
|
*outItemHandle = item->itemHandle;
|
|
return WUPSCONFIG_API_RESULT_SUCCESS;
|
|
}
|
|
|
|
|
|
WUPSConfigAPIStatus
|
|
WUPSConfigItemIPAddress_AddToCategory(const WUPSConfigCategoryHandle cat,
|
|
const char *identifier, const char *displayName,
|
|
const uint32_t defaultIPAddress,
|
|
const IPAddressValueChangedCallback callback) {
|
|
WUPSConfigItemHandle itemHandle;
|
|
WUPSConfigAPIStatus res;
|
|
if ((res = WUPSConfigItemIPAddress_Create(identifier,
|
|
displayName,
|
|
defaultIPAddress,
|
|
callback, &itemHandle)) != WUPSCONFIG_API_RESULT_SUCCESS) {
|
|
return res;
|
|
}
|
|
|
|
if ((res = WUPSConfigAPI_Category_AddItem(cat, itemHandle)) != WUPSCONFIG_API_RESULT_SUCCESS) {
|
|
WUPSConfigAPI_Item_Destroy(itemHandle);
|
|
return res;
|
|
}
|
|
return WUPSCONFIG_API_RESULT_SUCCESS;
|
|
}
|