/** @file frontend_sdl.c X11 frontend for Licar. */ #include #include #include #include #include #include #include // for usleep #define LCR_SETTING_LOG_LEVEL 2 #define LCR_SETTING_RESOLUTION_X 320 #define LCR_SETTING_RESOLUTION_Y 240 #define LCR_SETTING_MUSIC 0 #define DATA_FILE_NAME "data" #include "game.h" char framebuffer[LCR_SETTING_RESOLUTION_X * LCR_SETTING_RESOLUTION_Y * 4]; FILE *dataFile = 0; uint8_t buttonStates[8]; void LCR_drawPixel(unsigned long index, uint16_t color) { char *p = framebuffer + 4 * index; *p = (color << 3) & 0xff; p++; *p = (color >> 3) & 0xfc; p++; *p = (color >> 8) & 0xf8; } char LCR_getNextDataFileChar(void) { if (!dataFile) return 0; int c = fgetc(dataFile); if (c == EOF) { rewind(dataFile); return 0; } return c; } void LCR_appendDataStr(const char *str) { if (!dataFile) return; if (str == 0 || *str == 0) rewind(dataFile); else { fclose(dataFile); dataFile = fopen(DATA_FILE_NAME,"a"); if (dataFile) { fprintf(dataFile,"%s",str); fclose(dataFile); dataFile = fopen(DATA_FILE_NAME,"r"); } } } uint8_t LCR_keyPressed(uint8_t key) { return buttonStates[key % 8]; } void LCR_sleep(uint16_t timeMs) { usleep(timeMs * 1000); } void LCR_log(const char *str) { printf("LOG: %s\n",str); } int main(int argc, char **argv) { int running = 1; struct timeval now; LCR_gameInit(argc,(const char **) argv); Display *display = XOpenDisplay(0); int screen = DefaultScreen(display); dataFile = fopen(DATA_FILE_NAME,"r"); if (!dataFile) LCR_log("couldn't open data file"); Window window = XCreateSimpleWindow(display,RootWindow(display,screen),10,10, LCR_SETTING_RESOLUTION_X,LCR_SETTING_RESOLUTION_Y,1, BlackPixel(display,screen),WhitePixel(display,screen)); XSizeHints *sizeHints = XAllocSizeHints(); sizeHints->flags = PMaxSize | PMinSize; sizeHints->max_width = LCR_SETTING_RESOLUTION_X; sizeHints->min_width = LCR_SETTING_RESOLUTION_X; sizeHints->max_height = LCR_SETTING_RESOLUTION_Y; sizeHints->min_height = LCR_SETTING_RESOLUTION_Y; XSetWMNormalHints(display,window,sizeHints); XFree(sizeHints); XMapWindow(display,window); XSelectInput(display,window,KeyPressMask | KeyReleaseMask); GC context = DefaultGC(display,screen); XStoreName(display,window,"Licar"); /* Hardcoded constants here may perhaps cause trouble on some platforms, but doing X11 "the right way" would mean 1 billion lines of code, so fuck it. */ XImage *image = XCreateImage(display,DefaultVisual(display,screen), /*DefaultDepth(display,screen)*/24,ZPixmap,0,framebuffer, LCR_SETTING_RESOLUTION_X,LCR_SETTING_RESOLUTION_Y,8,0); while (running) // main loop { XEvent event; gettimeofday(&now,NULL); running &= LCR_gameStep(now.tv_sec * 1000 + now.tv_usec / 1000); XPutImage(display,window,context,image,0,0,0,0,LCR_SETTING_RESOLUTION_X, LCR_SETTING_RESOLUTION_Y); while (XCheckWindowEvent(display,window,KeyPressMask | KeyReleaseMask,&event) != False) { uint8_t state = event.xkey.type == KeyPress; switch (XKeycodeToKeysym(display,event.xkey.keycode,0)) { case XK_Up: case XK_w: buttonStates[LCR_KEY_UP % 8] = state; break; case XK_Left: case XK_a: buttonStates[LCR_KEY_LEFT % 8] = state; break; case XK_Right: case XK_d: buttonStates[LCR_KEY_RIGHT % 8] = state; break; case XK_Down: case XK_s: buttonStates[LCR_KEY_DOWN % 8] = state; break; case XK_j: case XK_Return: buttonStates[LCR_KEY_A % 8] = state; break; case XK_k: case XK_Escape: buttonStates[LCR_KEY_B % 8] = state; break; default: break; } } } XDestroyImage(image); XCloseDisplay(display); if (dataFile) fclose(dataFile); LCR_gameEnd(); return 0; }