Mercurial > remote-gamepad
view source/main.c @ 3:4c4be527a8d5
Send the entire state (including both pads and touch screen), and other fixes.
author | Emmanuel Gil Peyrot <linkmauve@linkmauve.fr> |
---|---|
date | Tue, 18 Aug 2015 00:25:10 +0100 |
parents | 5ba54fc65608 |
children | 557d35fcf15a |
line wrap: on
line source
/* Circle Pad example made by Aurelio Mannara for ctrulib Please refer to https://github.com/smealum/ctrulib/blob/master/libctru/include/3ds/services/hid.h for more information This code was modified for the last time on: 12/13/2014 2:20 UTC+1 This wouldn't be possible without the amazing work done by: -Smealum -fincs -WinterMute -yellows8 -plutoo -mtheall -Many others who worked on 3DS and I'm surely forgetting about */ #include <3ds.h> #include <arpa/inet.h> #include <assert.h> #include <malloc.h> #include <netdb.h> #include <stdio.h> #include <string.h> #include <sys/socket.h> struct state_t { u32 keys; circlePosition pad, cpad; touchPosition touch; }; static u32 *SOC_buffer = NULL; int create_socket(int domain, int type, struct sockaddr *addr) { int fd = socket(domain, type, 0); if (fd < 0) { puts("socket() failed."); return -1; } if (addr) { if (connect(fd, addr, sizeof(*addr)) < 0) { puts("connect() failed."); return -1; } } return fd; } struct sockaddr* get_sockaddr_from_hostname(const char *hostname, int port) { struct hostent *server = gethostbyname(hostname); if (!server) { puts("gethostbyname() failed."); return NULL; } struct sockaddr_in *addr = calloc(1, sizeof(struct sockaddr_in)); if (!addr) { puts("calloc() failed."); return NULL; } //memset(&addr, 0, sizeof(struct sockaddr_in)); addr->sin_family = AF_INET; addr->sin_port = htons(port); memcpy(&addr->sin_addr.s_addr, server->h_addr_list[0], server->h_length); return (struct sockaddr*) addr; } struct sockaddr* get_sockaddr_from_ip(const char *hostname, int port) { struct sockaddr_in *addr = calloc(1, sizeof(struct sockaddr_in)); if (!addr) { puts("calloc() failed."); return NULL; } //memset(&addr, 0, sizeof(struct sockaddr_in)); addr->sin_family = AF_INET; addr->sin_port = htons(port); addr->sin_addr.s_addr = inet_addr(hostname); return (struct sockaddr*) addr; } struct network_t { int tcp_fd; int udp_fd; struct sockaddr *addr; int addr_size; }; struct network_t *networkInit(const char *hostname, int port) { const unsigned SOC_ALIGN = 0x1000; const unsigned SOC_BUFFERSIZE = 0x100000; SOC_buffer = (u32*)memalign(SOC_ALIGN, SOC_BUFFERSIZE); if (!SOC_buffer) { puts("memalign() failed."); return NULL; } unsigned initialized = SOC_Initialize(SOC_buffer, SOC_BUFFERSIZE); if (initialized) { puts("SOC_Initialize() failed."); return NULL; } //struct sockaddr *addr = get_sockaddr_from_hostname(hostname, port); struct sockaddr *addr = get_sockaddr_from_ip(hostname, port); if (!addr) { puts("get_sockaddr_from_ip() failed."); return NULL; } // TODO: IPv6 int domain = AF_INET; struct network_t *n = malloc(sizeof(struct network_t)); //n->tcp_fd = create_socket(domain, SOCK_STREAM, addr); n->udp_fd = create_socket(domain, SOCK_DGRAM, NULL); n->addr = addr; n->addr_size = sizeof(struct sockaddr_in); return n; } int sendState(struct network_t *n, struct state_t *state) { const char *msg = (const char*) state; const int msglen = sizeof(struct state_t); return sendto(n->udp_fd, msg, msglen, 0, n->addr, n->addr_size); } void exitWithMessage(const char *message) { puts(message); fflush(stdout); gfxFlushBuffers(); gfxSwapBuffers(); for (int i=0; i < 60; ++i) gspWaitForVBlank(); gfxExit(); } int main(void) { //Matrix containing the name of each key. Useful for printing when a key is pressed char keysNames[32][32] = { "KEY_A", "KEY_B", "KEY_SELECT", "KEY_START", "KEY_DRIGHT", "KEY_DLEFT", "KEY_DUP", "KEY_DDOWN", "KEY_R", "KEY_L", "KEY_X", "KEY_Y", "", "", "KEY_ZL", "KEY_ZR", "", "", "", "", "KEY_TOUCH", "", "", "", "KEY_CSTICK_RIGHT", "KEY_CSTICK_LEFT", "KEY_CSTICK_UP", "KEY_CSTICK_DOWN", "KEY_CPAD_RIGHT", "KEY_CPAD_LEFT", "KEY_CPAD_UP", "KEY_CPAD_DOWN" }; // Initialize services gfxInitDefault(); //Initialize console on top screen. Using NULL as the second argument tells the console library to use the internal console structure as current one consoleInit(GFX_TOP, NULL); struct state_t old_state = {0xffffffff, {0xffff, 0xffff}, {0xffff, 0xffff}, {0xffff, 0xffff}}; //In these variables there will be information about keys detected in the previous frame // Initialize the network struct network_t *n = networkInit("192.168.0.13", 16150); if (!n) { exitWithMessage("networkInit() failed."); return 1; } // Main loop while (aptMainLoop()) { static struct state_t state; //Scan all the inputs. This should be done once for each frame hidScanInput(); //hidKeysHeld returns information about which buttons have are held down in this frame state.keys = hidKeysHeld(); //Read both pads position hidCircleRead(&state.pad); hidCstickRead(&state.cpad); // FIXME: use HOME instead if (state.keys & KEY_START) break; // break in order to return to hbmenu //Do the keys printing only if keys have changed if (memcmp(&state, &old_state, sizeof(struct state_t))) { //Clear console consoleClear(); //Every line must be rewritten because we cleared the whole console printf("\x1b[0;0HPress Start to exit.\n"); //Print both pads position printf("CirclePad position: %04d; %04d\n", state.pad.dx, state.pad.dy); printf("CPad position: %04d; %04d\n", state.cpad.dx, state.cpad.dy); //Move the cursor to the fourth row because on the third one we'll write the circle pad position printf("\x1b[3;0H"); //Check if some of the keys are down, held or up for (int i = 0; i < 32; i++) { if (state.keys & BIT(i)) printf("%s\n", keysNames[i]); } if (sendState(n, &state) < 0) { exitWithMessage("sendState() failed."); return 1; } } //Set keys old values for the next frame memcpy(&old_state, &state, sizeof(struct state_t)); // Flush and swap framebuffers gfxFlushBuffers(); gfxSwapBuffers(); //Wait for VBlank gspWaitForVBlank(); } // Exit services exitWithMessage("Exiting..."); return 0; }