mirror of
https://github.com/azahar-emu/ArticBaseServer
synced 2025-11-06 15:10:04 +01:00
Add Artic Controller support
This commit is contained in:
parent
be877e7dfb
commit
fea0a62d06
2
Makefile
2
Makefile
@ -1,5 +1,5 @@
|
||||
VERSION_MAJOR := 1
|
||||
VERSION_MINOR := 1
|
||||
VERSION_MINOR := 2
|
||||
VERSION_REVISION := 0
|
||||
|
||||
all:
|
||||
|
||||
@ -13,6 +13,7 @@ Artic Base Server is a Luma3DS 3GX plugin that allows using the Artic Base proto
|
||||
### Features
|
||||
- Play games from your console without having to dump them, with purchased updates and DLC.
|
||||
- Sync the savedata/extdata of the broadcasted game during the play session.
|
||||
- Use the console as the input device by enabling the Artic Controller feature on the emulator.
|
||||
- Load shared ext data and NCCH archives from your console.
|
||||
- Remove the need to dump AES keys, as the decryption is done by the console's OS.
|
||||
|
||||
@ -39,7 +40,6 @@ NOTE: A recent version of Luma3DS (v13.1.1 or newer) is requires to use Artic Ba
|
||||
This section lists features that Artic Base Server cannot currently provide. Some of these features may be added in the future.
|
||||
|
||||
### Things that might be implemented
|
||||
- Use the console as a controller itself.
|
||||
- Broadcasting homebrew applications
|
||||
|
||||
### Things that will never be implemented
|
||||
|
||||
@ -25,7 +25,7 @@ LIBRARY_DIRS := $(PORTLIBS) $(CTRULIB) $(DEVKITPRO)/libcwav $(DEVKITPRO)/libncsn
|
||||
LIBRARIES := ctru
|
||||
|
||||
VERSION_MAJOR := 1
|
||||
VERSION_MINOR := 1
|
||||
VERSION_MINOR := 2
|
||||
VERSION_MICRO := 0
|
||||
|
||||
BUILD_FLAGS := -march=armv6k -mtune=mpcore -mfloat-abi=hard
|
||||
|
||||
@ -15,7 +15,7 @@ INCLUDES := includes
|
||||
SOURCES := sources sources/CTRPluginFramework
|
||||
|
||||
VERSION_MAJOR := 1
|
||||
VERSION_MINOR := 1
|
||||
VERSION_MINOR := 2
|
||||
VERSION_REVISION := 0
|
||||
SERVER_PORT := 5543
|
||||
|
||||
|
||||
@ -16,4 +16,13 @@ namespace ArticBaseFunctions {
|
||||
DIR,
|
||||
ARCHIVE
|
||||
};
|
||||
|
||||
// Controller_Start
|
||||
namespace ArticController {
|
||||
extern Thread thread;
|
||||
extern bool thread_run;
|
||||
extern int socket_fd;
|
||||
extern volatile bool socket_ready;
|
||||
void Handler(void* arg);
|
||||
};
|
||||
};
|
||||
@ -13,15 +13,16 @@ public:
|
||||
void Serve();
|
||||
void QueryStop();
|
||||
|
||||
static bool SetNonBlock(int sockFD, bool blocking);
|
||||
static bool SetNonBlock(int sockFD, bool nonBlocking);
|
||||
static bool Read(int& sockFD, void* buffer, size_t size);
|
||||
static bool Write(int& sockFD, void* buffer, size_t size);
|
||||
static size_t RecvFrom(int& sockFD, void* buffer, size_t size, void* addr, void* addr_size);
|
||||
static size_t SendTo(int& sockFD, void* buffer, size_t size, void* addr, void* addr_size);
|
||||
private:
|
||||
void Stop();
|
||||
static constexpr size_t MAX_WORK_BUF_SIZE = 4 * 1024 * 1024 + 512 * 1024; // 4.5MB
|
||||
static constexpr size_t MAX_PARAM_AMOUNT = 10;
|
||||
|
||||
static bool Read(int& sockFD, void* buffer, size_t size);
|
||||
static bool Write(int& sockFD, void* buffer, size_t size);
|
||||
|
||||
class RequestHandler {
|
||||
public:
|
||||
RequestHandler(ArticBaseServer* serv, int id);
|
||||
@ -45,7 +46,7 @@ private:
|
||||
std::vector<ArticBaseCommon::RequestParameter> reqParameters;
|
||||
};
|
||||
|
||||
static constexpr const char* VERSION = "1";
|
||||
static constexpr const char* VERSION = "2";
|
||||
|
||||
int socketFd;
|
||||
bool run = true;
|
||||
|
||||
12
plugin/includes/hidExtension.hpp
Normal file
12
plugin/includes/hidExtension.hpp
Normal file
@ -0,0 +1,12 @@
|
||||
#pragma once
|
||||
#include "3ds.h"
|
||||
|
||||
struct GyroscopeCalibrateParam {
|
||||
struct {
|
||||
s16 zero_point;
|
||||
s16 positive_unit_point;
|
||||
s16 negative_unit_point;
|
||||
} x, y, z;
|
||||
};
|
||||
|
||||
Result HIDUSER_GetGyroscopeCalibrateParam(GyroscopeCalibrateParam* calibrateParam);
|
||||
@ -1,8 +1,18 @@
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include <sys/socket.h>
|
||||
#include <netinet/in.h>
|
||||
#include <arpa/inet.h>
|
||||
|
||||
#include "ArticBaseFunctions.hpp"
|
||||
#include "Main.hpp"
|
||||
#include "amExtension.hpp"
|
||||
#include "fsExtension.hpp"
|
||||
#include "hidExtension.hpp"
|
||||
#include "CTRPluginFramework/CTRPluginFramework.hpp"
|
||||
#include "CTRPluginFramework/Clock.hpp"
|
||||
|
||||
extern bool isControllerMode;
|
||||
|
||||
namespace ArticBaseFunctions {
|
||||
|
||||
@ -1547,9 +1557,224 @@ namespace ArticBaseFunctions {
|
||||
mi.FinishGood(res);
|
||||
}
|
||||
|
||||
void ArticController::Handler(void* arg) {
|
||||
using namespace ArticController;
|
||||
|
||||
struct ControllerPacket {
|
||||
u32 id;
|
||||
u32 pad;
|
||||
circlePosition c_pad;
|
||||
touchPosition touch;
|
||||
circlePosition c_stick;
|
||||
accelVector accel;
|
||||
angularRate gyro;
|
||||
} packet;
|
||||
u32 current_id = 0;
|
||||
static_assert(sizeof(packet) == 0x20, "ControllerPacket invalid size");
|
||||
|
||||
constexpr int port = SERVER_PORT + 10;
|
||||
struct sockaddr_in addr = {0};
|
||||
socklen_t addr_size = static_cast<socklen_t>(sizeof(addr));
|
||||
int res, failedCount = 0;
|
||||
|
||||
socket_fd = socket(AF_INET, SOCK_DGRAM, 0);
|
||||
if (socket_fd < 0) {
|
||||
logger.Error("ArticController: Cannot create socket");
|
||||
socket_ready = true;
|
||||
threadExit(1);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!ArticBaseServer::SetNonBlock(socket_fd, true)) {
|
||||
logger.Error("ArticController: Cannot set non-block");
|
||||
close(socket_fd);
|
||||
socket_fd = -1;
|
||||
socket_ready = true;
|
||||
threadExit(1);
|
||||
return;
|
||||
}
|
||||
|
||||
addr.sin_family = AF_INET;
|
||||
addr.sin_addr.s_addr = htonl(INADDR_ANY);
|
||||
addr.sin_port = htons(port);
|
||||
res = bind(socket_fd, (struct sockaddr *)&addr, addr_size);
|
||||
if (res < 0) {
|
||||
logger.Error("ArticController: Failed to bind() to port %d", port);
|
||||
close(socket_fd);
|
||||
socket_fd = -1;
|
||||
socket_ready = true;
|
||||
threadExit(1);
|
||||
return;
|
||||
}
|
||||
|
||||
socket_ready = true;
|
||||
|
||||
u8 a;
|
||||
size_t transfered = ArticBaseServer::RecvFrom(socket_fd, &a, sizeof(a), &addr, &addr_size);
|
||||
if (transfered > 0) {
|
||||
logger.Debug("ArticController: Started");
|
||||
} else {
|
||||
logger.Error("ArticController: Error reading from socket");
|
||||
close(socket_fd);
|
||||
socket_fd = -1;
|
||||
threadExit(1);
|
||||
return;
|
||||
}
|
||||
|
||||
constexpr CTRPluginFramework::Time INTERVAL = CTRPluginFramework::Milliseconds(2);
|
||||
// hid scan input is done on the main thread, no need to do it here.
|
||||
while (thread_run) {
|
||||
CTRPluginFramework::Clock clock;
|
||||
|
||||
if (isControllerMode) {
|
||||
packet.id = current_id++;
|
||||
packet.pad = hidKeysHeld();
|
||||
hidCircleRead(&packet.c_pad);
|
||||
hidTouchRead(&packet.touch);
|
||||
irrstCstickRead(&packet.c_stick);
|
||||
hidAccelRead(&packet.accel);
|
||||
hidGyroRead(&packet.gyro);
|
||||
|
||||
if (ArticBaseServer::SendTo(socket_fd, &packet, sizeof(packet), &addr, &addr_size) <= 0) {
|
||||
if (failedCount++ >= 1000) {
|
||||
logger.Error("ArticController: Error writing to socket");
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
failedCount = 0;
|
||||
}
|
||||
}
|
||||
|
||||
CTRPluginFramework::Time elapsed = clock.GetElapsedTime();
|
||||
if (elapsed < INTERVAL) {
|
||||
svcSleepThread((INTERVAL - elapsed).AsMicroseconds() * 1000);
|
||||
}
|
||||
}
|
||||
|
||||
close(socket_fd);
|
||||
socket_fd = -1;
|
||||
threadExit(1);
|
||||
}
|
||||
|
||||
static bool stopController(void);
|
||||
void Controller_Start(ArticBaseServer::MethodInterface& mi) {
|
||||
bool good = true;
|
||||
|
||||
if (good) good = mi.FinishInputParameters();
|
||||
|
||||
if (!good) return;
|
||||
|
||||
constexpr int port = SERVER_PORT + 10;
|
||||
ArticBaseCommon::Buffer* conf_buf = mi.ReserveResultBuffer(0, sizeof(int));
|
||||
if (!conf_buf) {
|
||||
return;
|
||||
}
|
||||
*(int*)conf_buf->data = port;
|
||||
|
||||
stopController();
|
||||
|
||||
s32 prio = 0;
|
||||
svcGetThreadPriority(&prio, CUR_THREAD_HANDLE);
|
||||
ArticController::socket_ready = false;
|
||||
ArticController::thread_run = true;
|
||||
ArticController::thread = threadCreate(ArticController::Handler, nullptr, 0x800, prio + 1, -2, false);
|
||||
logger.Debug("ArticController: Starting...");
|
||||
isControllerMode = true;
|
||||
|
||||
while (!ArticController::socket_ready) {
|
||||
svcSleepThread(1000000);
|
||||
}
|
||||
ArticController::socket_ready = false;
|
||||
|
||||
mi.FinishGood(0);
|
||||
}
|
||||
|
||||
void HIDUSER_EnableAccelerometer_(ArticBaseServer::MethodInterface& mi) {
|
||||
bool good = true;
|
||||
|
||||
if (good) mi.FinishInputParameters();
|
||||
|
||||
Result res = HIDUSER_EnableAccelerometer();
|
||||
|
||||
mi.FinishGood(res);
|
||||
}
|
||||
|
||||
void HIDUSER_DisableAccelerometer_(ArticBaseServer::MethodInterface& mi) {
|
||||
bool good = true;
|
||||
|
||||
if (good) mi.FinishInputParameters();
|
||||
|
||||
Result res = HIDUSER_DisableAccelerometer();
|
||||
|
||||
mi.FinishGood(res);
|
||||
}
|
||||
|
||||
void HIDUSER_EnableGyroscope_(ArticBaseServer::MethodInterface& mi) {
|
||||
bool good = true;
|
||||
|
||||
if (good) mi.FinishInputParameters();
|
||||
|
||||
Result res = HIDUSER_EnableGyroscope();
|
||||
|
||||
mi.FinishGood(res);
|
||||
}
|
||||
|
||||
void HIDUSER_DisableGyroscope_(ArticBaseServer::MethodInterface& mi) {
|
||||
bool good = true;
|
||||
|
||||
if (good) mi.FinishInputParameters();
|
||||
|
||||
Result res = HIDUSER_DisableGyroscope();
|
||||
|
||||
mi.FinishGood(res);
|
||||
}
|
||||
|
||||
void HIDUSER_GetGyroscopeRawToDpsCoefficient_(ArticBaseServer::MethodInterface& mi) {
|
||||
bool good = true;
|
||||
|
||||
if (good) mi.FinishInputParameters();
|
||||
|
||||
float coef;
|
||||
Result res = HIDUSER_GetGyroscopeRawToDpsCoefficient(&coef);
|
||||
if (R_FAILED(res)) {
|
||||
mi.FinishGood(res);
|
||||
return;
|
||||
}
|
||||
|
||||
ArticBaseCommon::Buffer* coef_buf = mi.ReserveResultBuffer(0, sizeof(float));
|
||||
if (!coef_buf) {
|
||||
return;
|
||||
}
|
||||
*(float*)coef_buf->data = coef;
|
||||
|
||||
mi.FinishGood(res);
|
||||
}
|
||||
|
||||
|
||||
void HIDUSER_GetGyroscopeCalibrateParam_(ArticBaseServer::MethodInterface& mi) {
|
||||
bool good = true;
|
||||
|
||||
if (good) mi.FinishInputParameters();
|
||||
|
||||
GyroscopeCalibrateParam param = { 0 };
|
||||
Result res = HIDUSER_GetGyroscopeCalibrateParam(¶m);
|
||||
if (R_FAILED(res)) {
|
||||
mi.FinishGood(res);
|
||||
return;
|
||||
}
|
||||
|
||||
ArticBaseCommon::Buffer* coef_buf = mi.ReserveResultBuffer(0, sizeof(param));
|
||||
if (!coef_buf) {
|
||||
return;
|
||||
}
|
||||
*(GyroscopeCalibrateParam*)coef_buf->data = param;
|
||||
|
||||
mi.FinishGood(res);
|
||||
}
|
||||
|
||||
template<std::size_t N>
|
||||
constexpr auto& METHOD_NAME(char const (&s)[N]) {
|
||||
static_assert(N < sizeof(ArticBaseCommon::RequestPacket::method), "String exceeds 10 bytes!");
|
||||
static_assert(N < sizeof(ArticBaseCommon::RequestPacket::method), "String exceeds 32 bytes!");
|
||||
return s;
|
||||
}
|
||||
|
||||
@ -1607,6 +1832,15 @@ namespace ArticBaseFunctions {
|
||||
{METHOD_NAME("AMAPP_ListDataTitleTicketInfos"), AMAPP_ListDataTitleTicketInfos_},
|
||||
{METHOD_NAME("AMAPP_GetPatchTitleInfos"), AMAPP_GetPatchTitleInfos_},
|
||||
{METHOD_NAME("CFGU_GetConfigInfoBlk2"), CFGU_GetConfigInfoBlk2_},
|
||||
{METHOD_NAME("HIDUSER_EnableAccelerometer"), HIDUSER_EnableAccelerometer_},
|
||||
{METHOD_NAME("HIDUSER_DisableAccelerometer"), HIDUSER_DisableAccelerometer_},
|
||||
{METHOD_NAME("HIDUSER_EnableGyroscope"), HIDUSER_EnableGyroscope_},
|
||||
{METHOD_NAME("HIDUSER_DisableGyroscope"), HIDUSER_DisableGyroscope_},
|
||||
{METHOD_NAME("HIDUSER_GetGyroRawToDpsCoef"), HIDUSER_GetGyroscopeRawToDpsCoefficient_},
|
||||
{METHOD_NAME("HIDUSER_GetGyroCalibrateParam"), HIDUSER_GetGyroscopeCalibrateParam_},
|
||||
|
||||
// UDP Streams
|
||||
{METHOD_NAME("#ArticController"), Controller_Start},
|
||||
};
|
||||
|
||||
bool obtainExheader() {
|
||||
@ -1654,11 +1888,33 @@ namespace ArticBaseFunctions {
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool stopController(void) {
|
||||
if (ArticController::thread_run) {
|
||||
logger.Debug("ArticController: Stopping...");
|
||||
ArticController::thread_run = false;
|
||||
if (ArticController::socket_fd != -1) {
|
||||
close(ArticController::socket_fd);
|
||||
ArticController::socket_fd = -1;
|
||||
}
|
||||
threadJoin(ArticController::thread, U64_MAX);
|
||||
threadFree(ArticController::thread);
|
||||
ArticController::thread = nullptr;
|
||||
logger.Debug("ArticController: Stopped...");
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
std::vector<bool(*)()> setupFunctions {
|
||||
obtainExheader,
|
||||
};
|
||||
|
||||
std::vector<bool(*)()> destructFunctions {
|
||||
closeHandles,
|
||||
stopController,
|
||||
};
|
||||
|
||||
Thread ArticController::thread = nullptr;
|
||||
bool ArticController::thread_run = false;
|
||||
int ArticController::socket_fd = -1;
|
||||
volatile bool ArticController::socket_ready = false;
|
||||
}
|
||||
|
||||
@ -221,6 +221,37 @@ bool ArticBaseServer::Write(int& sockFD, void* buffer, size_t size) {
|
||||
return write_bytes == size;
|
||||
}
|
||||
|
||||
size_t ArticBaseServer::RecvFrom(int& sockFD, void* buffer, size_t size, void* addr, void* addr_size) {
|
||||
while (true) {
|
||||
int new_read = recvfrom(sockFD, buffer, size, 0, (sockaddr*)addr, (socklen_t*)addr_size);
|
||||
if (new_read < 0) {
|
||||
if (errno == EWOULDBLOCK) {
|
||||
svcSleepThread(1000000);
|
||||
continue;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
transferedBytes += new_read;
|
||||
return new_read;
|
||||
}
|
||||
}
|
||||
|
||||
size_t ArticBaseServer::SendTo(int& sockFD, void* buffer, size_t size, void* addr, void* addr_size) {
|
||||
socklen_t addr_len = *(socklen_t*)addr_size;
|
||||
while (true) {
|
||||
int new_written = sendto(sockFD, buffer, size, 0, (sockaddr*)addr, addr_len);
|
||||
if (new_written < 0) {
|
||||
if (errno == EWOULDBLOCK) {
|
||||
svcSleepThread(1000000);
|
||||
continue;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
transferedBytes += new_written;
|
||||
return new_written;
|
||||
}
|
||||
}
|
||||
|
||||
ArticBaseServer::RequestHandler::RequestHandler(ArticBaseServer* serv, int id) {
|
||||
server = serv;
|
||||
this->id = id;
|
||||
|
||||
@ -141,7 +141,10 @@ void Logger::Handler() {
|
||||
switch (log.type)
|
||||
{
|
||||
case PendingLog::Type::RAW:
|
||||
back = bottomScreenConsole.cursorY;
|
||||
bottomScreenConsole.cursorY = 0;
|
||||
printf("%s\n", log.string.c_str());
|
||||
bottomScreenConsole.cursorY = back;
|
||||
break;
|
||||
case PendingLog::Type::DEBUG:
|
||||
printf("[D] %s\n", log.string.c_str());
|
||||
|
||||
26
plugin/sources/hidExtension.cpp
Normal file
26
plugin/sources/hidExtension.cpp
Normal file
@ -0,0 +1,26 @@
|
||||
#include "hidExtension.hpp"
|
||||
#include <string.h>
|
||||
#include <3ds/types.h>
|
||||
#include <3ds/result.h>
|
||||
#include <3ds/svc.h>
|
||||
#include <3ds/srv.h>
|
||||
#include <3ds/synchronization.h>
|
||||
#include <3ds/services/fs.h>
|
||||
#include <3ds/ipc.h>
|
||||
#include <3ds/env.h>
|
||||
|
||||
extern Handle hidHandle;
|
||||
|
||||
Result HIDUSER_GetGyroscopeCalibrateParam(GyroscopeCalibrateParam* calibrateParam) {
|
||||
u32 *cmdbuf = getThreadCommandBuffer();
|
||||
|
||||
cmdbuf[0] = IPC_MakeHeader(0x16,0,0);
|
||||
|
||||
Result ret = 0;
|
||||
if(R_FAILED(ret = svcSendSyncRequest(hidHandle))) return ret;
|
||||
|
||||
if (R_SUCCEEDED(cmdbuf[1])) {
|
||||
memcpy(calibrateParam, &cmdbuf[2], sizeof(GyroscopeCalibrateParam));
|
||||
}
|
||||
return cmdbuf[1];
|
||||
}
|
||||
@ -30,6 +30,12 @@ static bool should_run = true;
|
||||
static int listen_fd = -1;
|
||||
static int accept_fd = -1;
|
||||
static ArticBaseServer* articBase = nullptr;
|
||||
static bool wasControllerMode = false;
|
||||
static bool everControllerMode = false;
|
||||
static bool reloadBottomText = false;
|
||||
|
||||
int transferedBytes = 0;
|
||||
bool isControllerMode = false;
|
||||
|
||||
extern "C" {
|
||||
#include "csvc.h"
|
||||
@ -159,13 +165,15 @@ void Start(void* arg) {
|
||||
for (auto it = ArticBaseFunctions::destructFunctions.begin(); it != ArticBaseFunctions::destructFunctions.end(); it++) {
|
||||
(*it)();
|
||||
}
|
||||
isControllerMode = false;
|
||||
everControllerMode = false;
|
||||
}
|
||||
socExit();
|
||||
free(SOC_buffer);
|
||||
}
|
||||
|
||||
PrintConsole topScreenConsole, bottomScreenConsole;
|
||||
int transferedBytes = 0;
|
||||
|
||||
void Main() {
|
||||
logger.Start();
|
||||
|
||||
@ -195,13 +203,39 @@ void Main() {
|
||||
{
|
||||
CTRPluginFramework::BCLIM((void*)__data_logo_bin, __data_logo_bin_size).Render(CTRPluginFramework::Rect<int>((320 - 128) / 2, (240 - 128) / 2, 128, 128));
|
||||
}
|
||||
logger.Raw(false, "\n ArticBase v%d.%d.%d\n", VERSION_MAJOR, VERSION_MINOR, VERSION_REVISION);
|
||||
logger.Raw(false, " Press A to enter sleep.");
|
||||
logger.Raw(false, " Press X to show debug log.");
|
||||
logger.Raw(false, " Press Y to restart server.");
|
||||
logger.Raw(false, " Press START to exit.");
|
||||
|
||||
auto print_bottom_info = [](bool controller_mode) {
|
||||
if (controller_mode) {
|
||||
logger.Raw(false, "\n ArticBase v%d.%d.%d\n\n"
|
||||
" Artic Controller enabled \n"
|
||||
" \n"
|
||||
" - X + START + SELECT: Exit \n"
|
||||
" Artic Controller mode \n"
|
||||
" "
|
||||
, VERSION_MAJOR, VERSION_MINOR, VERSION_REVISION);
|
||||
} else {
|
||||
if (everControllerMode) {
|
||||
logger.Raw(false, "\n ArticBase v%d.%d.%d\n\n"
|
||||
" - A: Enter sleep \n"
|
||||
" - X: Show debug log \n"
|
||||
" - Y: Restart server \n"
|
||||
" - START: Exit \n"
|
||||
" - SELECT: Enter Artic controller mode "
|
||||
, VERSION_MAJOR, VERSION_MINOR, VERSION_REVISION);
|
||||
} else {
|
||||
logger.Raw(false, "\n ArticBase v%d.%d.%d\n\n"
|
||||
" - A: Enter sleep \n"
|
||||
" - X: Show debug log \n"
|
||||
" - Y: Restart server \n"
|
||||
" - START: Exit \n"
|
||||
" "
|
||||
, VERSION_MAJOR, VERSION_MINOR, VERSION_REVISION);
|
||||
}
|
||||
|
||||
}
|
||||
};
|
||||
|
||||
print_bottom_info(false);
|
||||
logger.Raw(true, "");
|
||||
|
||||
bool setupCorrect = true;
|
||||
@ -225,29 +259,44 @@ void Main() {
|
||||
|
||||
while (aptMainLoop())
|
||||
{
|
||||
//Scan all the inputs. This should be done once for each frame
|
||||
if (isControllerMode != wasControllerMode || reloadBottomText) {
|
||||
reloadBottomText = false;
|
||||
everControllerMode |= isControllerMode;
|
||||
if (isControllerMode) {
|
||||
logger.Info("Server: Controller mode enabled");
|
||||
} else {
|
||||
logger.Info("Server: Controller mode disabled");
|
||||
}
|
||||
print_bottom_info(isControllerMode);
|
||||
wasControllerMode = isControllerMode;
|
||||
}
|
||||
|
||||
hidScanInput();
|
||||
|
||||
//hidKeysDown returns information about which buttons have been just pressed (and they weren't in the previous frame)
|
||||
u32 kDown = hidKeysDown();
|
||||
u32 kHeld = hidKeysHeld();
|
||||
|
||||
if ((kDown != 0) && sleeping) {
|
||||
if (((kDown & ~KEY_SELECT) != 0) && sleeping && !isControllerMode) {
|
||||
sleeping = false;
|
||||
GSPLCD_PowerOnBacklight(3);
|
||||
continue;
|
||||
}
|
||||
|
||||
if ((kDown & KEY_A) && !sleeping) {
|
||||
if ((kDown & KEY_A) && !sleeping && !isControllerMode) {
|
||||
sleeping = true;
|
||||
GSPLCD_PowerOffBacklight(3);
|
||||
}
|
||||
|
||||
if (kDown & KEY_START) {
|
||||
if ((kDown & KEY_START) && !isControllerMode) {
|
||||
logger.Info("Server: Exiting");
|
||||
break;
|
||||
}
|
||||
|
||||
if (kDown & KEY_Y) {
|
||||
if ((kDown & KEY_SELECT) && !isControllerMode && everControllerMode) {
|
||||
isControllerMode = true;
|
||||
}
|
||||
|
||||
if ((kDown & KEY_Y) && !isControllerMode) {
|
||||
if (articBase) {
|
||||
logger.Info("Server: Restarting");
|
||||
articBase->QueryStop();
|
||||
@ -256,7 +305,7 @@ void Main() {
|
||||
}
|
||||
}
|
||||
|
||||
if (kDown & KEY_X) {
|
||||
if ((kDown & KEY_X) && !isControllerMode) {
|
||||
if (logger.debug_enable) {
|
||||
logger.Info("Server: Debug log disabled");
|
||||
logger.debug_enable = false;
|
||||
@ -266,6 +315,10 @@ void Main() {
|
||||
}
|
||||
}
|
||||
|
||||
if (((kHeld & (KEY_X | KEY_START | KEY_SELECT)) == (KEY_X | KEY_START | KEY_SELECT)) && isControllerMode) {
|
||||
isControllerMode = false;
|
||||
}
|
||||
|
||||
if (clock.HasTimePassed(CTRPluginFramework::Seconds(1)))
|
||||
{
|
||||
if (articBase) {
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user