From 97273ac0b89ab4d54cb82fcc8a296b910cba1556 Mon Sep 17 00:00:00 2001 From: oreo639 <31916379+Oreo639@users.noreply.github.com> Date: Fri, 14 Jan 2022 15:52:45 -0800 Subject: [PATCH] Add 3dslink stdio redirection --- libctru/include/3ds.h | 1 + libctru/include/3ds/3dslink.h | 34 ++++++++++++++++++++++ libctru/source/3dslink.c | 48 ++++++++++++++++++++++++++++++++ libctru/source/system/initArgv.c | 12 ++++++++ 4 files changed, 95 insertions(+) create mode 100644 libctru/include/3ds/3dslink.h create mode 100644 libctru/source/3dslink.c diff --git a/libctru/include/3ds.h b/libctru/include/3ds.h index dc7c6caf4..9aeb842d6 100644 --- a/libctru/include/3ds.h +++ b/libctru/include/3ds.h @@ -99,6 +99,7 @@ extern "C" { #include <3ds/mii.h> #include <3ds/gdbhio_dev.h> +#include <3ds/3dslink.h> #ifdef __cplusplus } diff --git a/libctru/include/3ds/3dslink.h b/libctru/include/3ds/3dslink.h new file mode 100644 index 000000000..234f941f4 --- /dev/null +++ b/libctru/include/3ds/3dslink.h @@ -0,0 +1,34 @@ +/** + * @file 3dslink.h + * @brief Netloader (3dslink) utilities + */ + +#pragma once + +#include + +struct in_addr; + +/// Address of the host connected through 3dslink +extern struct in_addr __3dslink_host; + +#define LINK3DS_COMM_PORT 17491 ///< 3dslink TCP server port + +/** + * @brief Connects to the 3dslink host, setting up an output stream. + * @param[in] redirStdout Whether to redirect stdout to nxlink output. + * @param[in] redirStderr Whether to redirect stderr to nxlink output. + * @return Socket fd on success, negative number on failure. + * @note The socket should be closed with close() during application cleanup. + */ +int link3dsConnectToHost(bool redirStdout, bool redirStderr); + +/// Same as \ref link3dsConnectToHost but redirecting both stdout/stderr. +static inline int link3dsStdio(void) { + return link3dsConnectToHost(true, true); +} + +/// Same as \ref link3dsConnectToHost but redirecting only stderr. +static inline int link3dsStdioForDebug(void) { + return link3dsConnectToHost(false, true); +} diff --git a/libctru/source/3dslink.c b/libctru/source/3dslink.c new file mode 100644 index 000000000..8dc038137 --- /dev/null +++ b/libctru/source/3dslink.c @@ -0,0 +1,48 @@ +#include +#include +#include +#include +#include +#include + +#include <3ds/3dslink.h> + +struct in_addr __3dslink_host = {0}; + +static int sock = -1; + +int link3dsConnectToHost(bool redirStdout, bool redirStderr) +{ + int ret = -1; + struct sockaddr_in srv_addr; + + sock = socket(AF_INET, SOCK_STREAM, 0); + if (!sock) { + return ret; + } + + bzero(&srv_addr, sizeof srv_addr); + srv_addr.sin_family = AF_INET; + srv_addr.sin_addr = __3dslink_host; + srv_addr.sin_port = htons(LINK3DS_COMM_PORT); + + ret = connect(sock, (struct sockaddr *) &srv_addr, sizeof(srv_addr)); + if (ret != 0) { + close(sock); + return -1; + } + + if (redirStdout) { + // redirect stdout + fflush(stdout); + dup2(sock, STDOUT_FILENO); + } + + if (redirStderr) { + // redirect stderr + fflush(stderr); + dup2(sock, STDERR_FILENO); + } + + return sock; +} diff --git a/libctru/source/system/initArgv.c b/libctru/source/system/initArgv.c index c34843e01..a91b851ad 100644 --- a/libctru/source/system/initArgv.c +++ b/libctru/source/system/initArgv.c @@ -1,7 +1,10 @@ #include <3ds/types.h> #include <3ds/env.h> +#include <3ds/3dslink.h> #include +#include +#include // System globals we define here int __system_argc; @@ -47,5 +50,14 @@ void __attribute__((weak)) __system_initArgv(void) for (; *temp; temp ++); temp ++; } + + // Grab 3dslink host address if avaliable + if ( __system_argc > 1 && + strlen(__system_argv[__system_argc - 1]) == 17 && + strncmp(&__system_argv[__system_argc - 1][8], "_3DSLINK_", 8) == 0 ) + { + __system_argc--; + __3dslink_host.s_addr = strtoul(__system_argv[__system_argc], NULL, 16); + } __system_argv[__system_argc] = NULL; }