use SDL2 instead of xlib
2 files changed, 90 insertions(+), 71 deletions(-)

M build.sh
M src/tnyemu.c
M build.sh +1 -1
@@ 1,5 1,5 @@ 
 #!/bin/sh -e
 
-cc -g -std=c89 -Wall -pedantic -o bin/tnyemu src/tnyemu.c -lX11
+cc -g -std=c89 -Wall -pedantic -o bin/tnyemu src/tnyemu.c $(sdl2-config --cflags --libs)
 cc -g -std=c89 -Wall -pedantic -o bin/tnyasm src/tnyasm.c
 

          
M src/tnyemu.c +89 -70
@@ 1,13 1,11 @@ 
 #include <stdio.h>
 #include <stdlib.h>
 #include <time.h>
-#include <poll.h>
-#include <X11/Xlib.h>
-#include <X11/Xutil.h>
+#include <SDL.h>
 
 #define LEN 256
-
-typedef unsigned char Uint8;
+#define FRAME_DURATION (1000 / 60)
+#define PIX_WIDTH 10
 
 typedef struct Stack {
 	Uint8 dat[LEN];

          
@@ 19,15 17,13 @@ typedef struct Tny {
 	Stack ps, rs;
 } Tny;
 
-Uint8 scn[32] = {0};
-Uint8 buffer[LEN] = {0};
-Uint8 controller = 0;
-Uint8 frame = 0;
+Uint8 scn[32];
+Uint8 buffer[LEN];
+Uint8 controller;
+Uint8 frame;
 
-Display *dis;
-int screen;
-Window win;
-GC gc;
+SDL_Window *window;
+SDL_Renderer *renderer;
 
 int halt(Tny *t, Uint8 op, Uint8 ip, Uint8 err)
 {

          
@@ 133,88 129,108 @@ int start(Tny *t, char *rom)
 	return 1;
 }
 
-void init_x()
-{
-	Atom wmDelete;
-	unsigned long black, white;
-
-	dis = XOpenDisplay(NULL);
-	screen = DefaultScreen(dis);
-	black = BlackPixel(dis, screen),
-	white = WhitePixel(dis, screen);
-	win = XCreateSimpleWindow(dis, DefaultRootWindow(dis), 0, 0, 160, 160, 0, 0, black);
-	wmDelete = XInternAtom(dis, "WM_DELETE_WINDOW", False);
-	XSetWMProtocols(dis, win, &wmDelete, 1);
-	XSelectInput(dis, win, ExposureMask | ButtonPressMask | KeyPressMask | KeyReleaseMask);
-	gc = XCreateGC(dis, win, 0, NULL);
-	XSetForeground(dis, gc, white);
-	XStoreName(dis, win, "tny");
-	XClearWindow(dis, win);
-	XMapWindow(dis, win);
-}
-
-void close_x()
-{
-	XFreeGC(dis, gc);
-	XDestroyWindow(dis, win);
-	XCloseDisplay(dis);
-}
-
-#define FRAME_DURATION (1000 / 60)
-
 void redraw()
 {
 	int i, j;
-	XClearWindow(dis, win);
+	SDL_Rect rect;
+	rect.w = PIX_WIDTH;
+	rect.h = PIX_WIDTH;
+	SDL_SetRenderDrawColor(renderer, 0, 0, 0, 255);
+	SDL_RenderClear(renderer);
+	SDL_SetRenderDrawColor(renderer, 255, 255, 255, 255);
 	for (i = 0; i < 32; i++) {
 		for (j = 0; j < 8; j++) {
 			if (scn[i] & (128 >> j)) {
-				XFillRectangle(dis, win, gc, (i % 2 * 8 + j) * 10, i / 2 * 10, 10, 10);
+				rect.x = (i % 2 * 8 + j) * PIX_WIDTH;
+				rect.y = i / 2 * PIX_WIDTH;
+				SDL_RenderFillRect(renderer, &rect);
 			}
 		}
 	}
 }
 
-void x_loop(Tny *t)
+int init()
 {
-	XEvent event;
-	struct pollfd pfd;
-	KeySym keysym;
+	if (SDL_Init(SDL_INIT_VIDEO) < 0) {
+		fprintf(stderr, "Error initializing SDL: %s.\n", SDL_GetError());
+		return 0;
+	}
+
+	window = SDL_CreateWindow("Tny",
+		SDL_WINDOWPOS_UNDEFINED,
+		SDL_WINDOWPOS_UNDEFINED,
+		16 * PIX_WIDTH,
+		16 * PIX_WIDTH,
+		SDL_WINDOW_SHOWN | SDL_WINDOW_ALLOW_HIGHDPI);
+	if (window == NULL) {
+		fprintf(stderr, "Error creating window: %s.\n", SDL_GetError());
+		return 0;
+	}
 
-	pfd.fd = -1;
-	pfd.events = 0;
+	renderer = SDL_CreateRenderer(window, -1, 0);
+	if (renderer == NULL) {
+		fprintf(stderr, "Error creating renderer: %s.\n", SDL_GetError());
+		return 0;
+	}
 
-	init_x();
+	return 1;
+}
+
+void loop(Tny *t)
+{
+	SDL_Event e;
+	Uint64 now = SDL_GetPerformanceCounter();
+	Uint64 frame_interval = SDL_GetPerformanceFrequency() / 60;
+	Uint64 ms_interval = SDL_GetPerformanceFrequency() / 1000;
+	Uint64 frame_end;
 
 	for (;;) {
-		while (XPending(dis)) {
-			XNextEvent(dis, &event);
-			if (event.type == KeyPress || event.type == KeyRelease) {
-				keysym = XLookupKeysym(&event.xkey, 0);
-				switch (keysym) {
-				case XK_Up: controller ^= 0x01; break;
-				case XK_Down: controller ^= 0x02; break;
-				case XK_Left: controller ^= 0x04; break;
-				case XK_Right: controller ^= 0x08; break;
-				case XK_x: controller ^= 0x10; break;
-				case XK_c: controller ^= 0x20; break;
+		frame_end = now + frame_interval;
+
+		while (SDL_PollEvent(&e) != 0) {
+			if (e.type == SDL_QUIT) {
+				SDL_DestroyRenderer(renderer);
+				SDL_DestroyWindow(window);
+				SDL_Quit();
+				return;
+			} else if (e.type == SDL_KEYDOWN) {
+				switch (e.key.keysym.sym) {
+				case SDLK_UP: controller |= 0x01; break;
+				case SDLK_DOWN: controller |= 0x02; break;
+				case SDLK_LEFT: controller |= 0x04; break;
+				case SDLK_RIGHT: controller |= 0x08; break;
+				case SDLK_x: controller |= 0x10; break;
+				case SDLK_c: controller |= 0x20; break;
 				}
-				if (event.type == KeyPress) {
+				if (e.type == SDL_KEYDOWN) {
 					if (t->ram[1]) {
 						eval(t, t->ram[1]);
 					}
 				}
-			} else if (event.type == ClientMessage) {
-				close_x();
-				return;
+			} else if (e.type == SDL_KEYUP) {
+				switch (e.key.keysym.sym) {
+				case SDLK_UP: controller &= ~0x01; break;
+				case SDLK_DOWN: controller &= ~0x02; break;
+				case SDLK_LEFT: controller &= ~0x04; break;
+				case SDLK_RIGHT: controller &= ~0x08; break;
+				case SDLK_x: controller &= ~0x10; break;
+				case SDLK_c: controller &= ~0x20; break;
+				}
 			}
 		}
+
 		if (t->ram[0]) {
 			eval(t, t->ram[0]);
 		}
+		frame = (frame + 1) % 60;
 		redraw();
-		frame = (frame + 1) % 60;
-		poll(&pfd, 1, FRAME_DURATION);
+		SDL_RenderPresent(renderer);
+
+		now = SDL_GetPerformanceCounter();
+		if ((Sint64)(frame_end - now) > 0) {
+			SDL_Delay((frame_end - now) / ms_interval);
+			now = frame_end;
+		}
 	}
 }
 

          
@@ 223,17 239,20 @@ int main(int argc, char **argv)
 	Tny t = {0};
 	int i;
 
+	srand(time(NULL));
+
 	if (argc != 2) {
 		printf("usage: tny file.rom\n");
 		return 1;
 	}
 
-	srand(time(NULL));
+	if (!init())
+		return 1;
 
 	if (!start(&t, argv[1]))
 		return 1;
 
-	x_loop(&t);
+	loop(&t);
 
 	printf("pstack:");
 	for (i = 0; i < t.ps.top; i++)