all repos — mgba @ 7ea054ee01d0203fd9e50bc6263344d185cb6176

mGBA Game Boy Advance Emulator

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}