src/platform/example/client-server/client.c (view raw)
1/* Copyright (c) 2013-2016 Jeffrey Pfau
2 *
3 * This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6#include <mgba/core/core.h>
7#include <mgba/core/version.h>
8#include <mgba-util/socket.h>
9
10#include <SDL.h>
11
12#define DEFAULT_PORT 13721
13
14int main() {
15 SocketSubsystemInit();
16 struct Address serverIP = {
17 .version = IPV4,
18 .ipv4 = 0x7F000001
19 };
20 Socket server = SocketConnectTCP(DEFAULT_PORT, &serverIP);
21 if (SOCKET_FAILED(server)) {
22 SocketSubsystemDeinit();
23 return 1;
24 }
25
26 unsigned width, height, bpp;
27 SocketRecv(server, &width, sizeof(width));
28 SocketRecv(server, &height, sizeof(height));
29 SocketRecv(server, &bpp, sizeof(bpp));
30 width = ntohl(width);
31 height = ntohl(height);
32 bpp = ntohl(bpp);
33 ssize_t bufferSize = width * height * bpp;
34
35#if !SDL_VERSION_ATLEAST(2, 0, 0)
36 if (bpp == 2) {
37 SDL_SetVideoMode(width, height, 16, SDL_DOUBLEBUF | SDL_HWSURFACE);
38 } else if (bpp == 4) {
39 SDL_SetVideoMode(width, height, 32, SDL_DOUBLEBUF | SDL_HWSURFACE);
40 } else {
41 SocketClose(server);
42 SocketSubsystemDeinit();
43 return 1;
44 }
45#endif
46
47#if SDL_VERSION_ATLEAST(2, 0, 0)
48 SDL_Window* window = SDL_CreateWindow(projectName, SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, width, height, SDL_WINDOW_OPENGL);
49 SDL_Renderer* renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC);
50
51 Uint32 pixfmt;
52 if (bpp == 2) {
53 pixfmt = SDL_PIXELFORMAT_RGB565;
54 } else if (bpp == 4) {
55 pixfmt = SDL_PIXELFORMAT_ABGR8888;
56 } else {
57 SocketClose(server);
58 SocketSubsystemDeinit();
59 return 1;
60 }
61
62 SDL_Texture* sdlTex = SDL_CreateTexture(renderer, pixfmt, SDL_TEXTUREACCESS_STREAMING, width, height);
63#endif
64
65
66 SDL_Event event;
67#if !SDL_VERSION_ATLEAST(2, 0, 0)
68 SDL_Surface* surface = SDL_GetVideoSurface();
69#endif
70
71 int keys = 0;
72 while (true) {
73 while (SDL_PollEvent(&event)) {
74 if (event.type == SDL_QUIT) {
75 SocketClose(server);
76 break;
77 }
78 if (event.type != SDL_KEYDOWN && event.type != SDL_KEYUP) {
79 continue;
80 }
81 int key = 0;
82 switch (event.key.keysym.sym) {
83 case SDLK_x:
84 key = 1;
85 break;
86 case SDLK_z:
87 key = 2;
88 break;
89 case SDLK_BACKSPACE:
90 key = 4;
91 break;
92 case SDLK_RETURN:
93 key = 8;
94 break;
95 case SDLK_RIGHT:
96 key = 16;
97 break;
98 case SDLK_LEFT:
99 key = 32;
100 break;
101 case SDLK_UP:
102 key = 64;
103 break;
104 case SDLK_DOWN:
105 key = 128;
106 break;
107 case SDLK_s:
108 key = 256;
109 break;
110 case SDLK_a:
111 key = 512;
112 break;
113 default:
114 break;
115 }
116 if (event.type == SDL_KEYDOWN) {
117 keys |= key;
118 } else {
119 keys &= ~key;
120 }
121 }
122 uint16_t keysNO = htons(keys);
123 if (SocketSend(server, &keysNO, sizeof(keysNO)) != sizeof(keysNO)) {
124 break;
125 }
126 void* pixels;
127#if SDL_VERSION_ATLEAST(2, 0, 0)
128 int pitch;
129 SDL_LockTexture(sdlTex, NULL, &pixels, &pitch);
130#else
131 SDL_LockSurface(surface);
132 pixels = surface->pixels;
133#endif
134
135 ssize_t expected = bufferSize;
136 ssize_t gotten;
137 while ((gotten = SocketRecv(server, pixels, expected)) != expected) {
138 if (gotten < 0) {
139 break;
140 }
141 pixels = (void*) ((uintptr_t) pixels + gotten);
142 expected -= gotten;
143 }
144 if (gotten < 0) {
145 break;
146 }
147
148#if SDL_VERSION_ATLEAST(2, 0, 0)
149 SDL_UnlockTexture(sdlTex);
150 SDL_RenderCopy(renderer, sdlTex, NULL, NULL);
151 SDL_RenderPresent(renderer);
152#else
153 SDL_UnlockSurface(surface);
154 SDL_Flip(surface);
155#endif
156 }
157 SocketSubsystemDeinit();
158
159 return 0;
160}