@@ 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++)