Mercurial > remote-gamepad
view source/main.c @ 2:5ee81fece0fa
Fill the .hgignore, so that binaries don’t get listed in hg st.
author | Emmanuel Gil Peyrot <linkmauve@linkmauve.fr> |
---|---|
date | Sun, 22 Feb 2015 18:22:35 +0100 |
parents | 5ba54fc65608 |
children | 4c4be527a8d5 |
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> static u32 *SOC_buffer = NULL; int create_socket(int domain, int type, struct sockaddr *addr) { int fd = socket(domain, type, 0); if (fd < 0) { printf("socket() failed.\n"); return -1; } if (addr) { if (connect(fd, addr, sizeof(*addr)) < 0) { printf("connect() failed.\n"); return -1; } } return fd; } struct sockaddr* get_sockaddr_from_hostname(const char *hostname, int port) { struct hostent *server = gethostbyname(hostname); if (!server) { printf("gethostbyname() failed.\n"); return NULL; } struct sockaddr_in *addr = calloc(1, sizeof(struct sockaddr_in)); if (!addr) { printf("calloc() failed.\n"); 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) { printf("calloc() failed.\n"); 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) { printf("calloc() failed.\n"); return NULL; } unsigned initialized = SOC_Initialize(SOC_buffer, SOC_BUFFERSIZE); if (initialized) { printf("SOC_Initialize() failed.\n"); return NULL; } //struct sockaddr *addr = get_sockaddr_from_hostname(hostname, port); struct sockaddr *addr = get_sockaddr_from_ip(hostname, port); if (!addr) 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 sendKeys(struct network_t *n, u32 keys) { const char *msg = (const char*) &keys; int msglen = sizeof(keys); return sendto(n->udp_fd, msg, msglen, 0, n->addr, n->addr_size); } int main(int argc, char **argv) { //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); u32 old_keys = 0; //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) { printf("HORROR!"); fflush(stdout); gfxFlushBuffers(); gfxSwapBuffers(); for(;;); } printf("\x1b[0;0HPress Start to exit."); printf("\x1b[1;0HCirclePad position:"); // Main loop while (aptMainLoop()) { //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 u32 keys = hidKeysHeld(); //if (keys & KEY_START) break; // break in order to return to hbmenu //Do the keys printing only if keys have changed if (keys != old_keys) { //Clear console consoleClear(); //These two lines must be rewritten because we cleared the whole console printf("\x1b[0;0HPress Start to exit."); printf("\x1b[1;0HCirclePad position:"); printf("\x1b[3;0H"); //Move the cursor to the fourth row because on the third one we'll write the circle pad position //Check if some of the keys are down, held or up for (int i = 0; i < 32; i++) { if (keys & BIT(i)) printf("%s\n", keysNames[i]); } if (sendKeys(n, keys) < 0) { perror("sendKeys"); printf("HORROR! sendKeys()!"); fflush(stdout); gfxFlushBuffers(); gfxSwapBuffers(); for(;;); } } //Set keys old values for the next frame old_keys = keys; circlePosition pos; //Read the CirclePad position hidCircleRead(&pos); //Print the CirclePad position printf("\x1b[2;0H%04d; %04d", pos.dx, pos.dy); // Flush and swap framebuffers gfxFlushBuffers(); gfxSwapBuffers(); //Wait for VBlank gspWaitForVBlank(); } // Exit services gfxExit(); return 0; }