#include #include #include #include #include #include #include #include #include #include #include #include "common.h" #include "doomkeys.h" #include "i_system.h" #include "m_argv.h" #include "d_main.h" #include "doomdef.h" static int video_initialized = 0; extern byte *screens[5]; typedef struct Color { unsigned char b; unsigned char g; unsigned char r; unsigned char a; } Color; static Color current_palette[256]; static char framebuffer[SCREENWIDTH*SCREENHEIGHT*4]; static int window_w; static int window_h; static int offset_x; int multiply = 1; static long frame_num = 0; //static int mouse_captured = 0; XEvent X_event; Display *display; Window window; GC context; XImage *image; void I_ShutdownGraphics(void) { if (!video_initialized) return; // called from I_Quit also I_Error in i_system.c XDestroyImage(image); XCloseDisplay(display); } void I_StartFrame (void) { // called from d_main // er? /*if (WindowShouldClose()) I_Quit();*/ } /* struct joystick_state { int axis1; int axis2; int buttons; }; struct joystick_state poll_joystick() { struct joystick_state js = {0,0,0}; if (!IsGamepadAvailable(0)) return js; float a1 = GetGamepadAxisMovement(0, 0); js.axis1 = a1 < -0.1 ? -1 : (a1 > 0.1 ? 1 : 0); float a2 = GetGamepadAxisMovement(0, 1); js.axis2 = a2 < -0.1 ? -1 : (a2 > 0.1 ? 1 : 0); js.buttons |= IsGamepadButtonDown(0, GAMEPAD_BUTTON_RIGHT_FACE_LEFT) ? 1 : 0; js.buttons |= IsGamepadButtonDown(0, GAMEPAD_BUTTON_RIGHT_FACE_DOWN) ? 2 : 0; js.buttons |= IsGamepadButtonDown(0, GAMEPAD_BUTTON_RIGHT_FACE_UP) ? 4 : 0; js.buttons |= IsGamepadButtonDown(0, GAMEPAD_BUTTON_RIGHT_FACE_RIGHT) ? 8 : 0; js.buttons |= IsGamepadButtonDown(0, GAMEPAD_BUTTON_LEFT_TRIGGER_1) ? 16 : 0; js.buttons |= IsGamepadButtonDown(0, GAMEPAD_BUTTON_RIGHT_TRIGGER_1) ? 32 : 0; return js; } struct joystick_state joystate = {0,0,0}; */ int xlatekey() { int rc; switch(rc = XKeycodeToKeysym(display, X_event.xkey.keycode, 0)) { case XK_Left: rc = KEY_LEFTARROW; break; case XK_Right: rc = KEY_RIGHTARROW; break; case XK_Down: rc = KEY_DOWNARROW; break; case XK_Up: rc = KEY_UPARROW; break; case XK_Escape: rc = KEY_ESCAPE; break; case XK_Return: rc = KEY_ENTER; break; case XK_Tab: rc = KEY_TAB; break; case XK_F1: rc = KEY_F1; break; case XK_F2: rc = KEY_F2; break; case XK_F3: rc = KEY_F3; break; case XK_F4: rc = KEY_F4; break; case XK_F5: rc = KEY_F5; break; case XK_F6: rc = KEY_F6; break; case XK_F7: rc = KEY_F7; break; case XK_F8: rc = KEY_F8; break; case XK_F9: rc = KEY_F9; break; case XK_F10: rc = KEY_F10; break; case XK_F11: rc = KEY_F11; break; case XK_F12: rc = KEY_F12; break; case XK_BackSpace: case XK_Delete: rc = KEY_BACKSPACE; break; case XK_Pause: rc = KEY_PAUSE; break; case XK_KP_Equal: case XK_equal: rc = KEY_EQUALS; break; case XK_KP_Subtract: case XK_minus: rc = KEY_MINUS; break; case XK_Shift_L: case XK_Shift_R: rc = KEY_RSHIFT; break; case XK_Control_L: case XK_Control_R: rc = KEY_RCTRL; break; case XK_Alt_L: case XK_Meta_L: case XK_Alt_R: case XK_Meta_R: rc = KEY_RALT; break; default: if (rc >= XK_space && rc <= XK_asciitilde) rc = rc - XK_space + ' '; if (rc >= 'A' && rc <= 'Z') rc = rc - 'A' + 'a'; break; } return rc; } void I_GetEvent(void) { // was called from I_StartTic // get events and post them with D_PostEvent // also updated mousemoved event_t ev; /* cat mouse */ /* Vector2 delta = GetMouseDelta(); int motion = delta.x || delta.y; int button = IsMouseButtonPressed(0) || IsMouseButtonPressed(1) || IsMouseButtonPressed(2) || IsMouseButtonReleased(0) || IsMouseButtonReleased(1) || IsMouseButtonReleased(2); if (mouse_captured && (button || motion)) { ev.type = ev_mouse; ev.data1 = IsMouseButtonDown(0) | (IsMouseButtonDown(1) ? 2 : 0) | (IsMouseButtonDown(2) ? 4 : 0); ev.data2 = (int)delta.x; ev.data3 = (int)-delta.y; D_PostEvent(&ev); }*/ /* joy stick */ /* struct joystick_state jcurrent = poll_joystick(); int jchange = jcurrent.axis1 != joystate.axis1 || jcurrent.axis2 != joystate.axis2 || jcurrent.buttons != joystate.buttons; if(jchange) { joystate = jcurrent; ev.type = ev_joystick; ev.data3 = joystate.axis2; ev.data2 = joystate.axis1; ev.data1 = joystate.buttons; D_PostEvent(&ev); }*/ /* kbd */ if (XCheckWindowEvent(display,window,KeyPressMask | KeyReleaseMask,&X_event) != False) switch (X_event.xkey.type) { case KeyPress: ev.type = ev_keydown; ev.data1 = xlatekey(); D_PostEvent(&ev); // fprintf(stderr, "k"); break; case KeyRelease: ev.type = ev_keyup; ev.data1 = xlatekey(); D_PostEvent(&ev); // fprintf(stderr, "ku"); break; } /*if (rc==xlatekey()) { EnableCursor(); mouse_captured = false; } if (IsMouseButtonDown(1)) { DisableCursor(); mouse_captured = true; }*/ } void I_StartTic (void) { // called from d_net, d_main // calls I_GetEvent repeatedly I_GetEvent(); } void I_UpdateNoBlit (void) { // called from d_main } void I_FinishUpdate (void) { // called from d_main // copied image data from screens[0] into some shm image and synced // optionally expanding the picture 2x 3x ... Color *writing = framebuffer; for (int i = 0; i < SCREENWIDTH*SCREENHEIGHT; i++) { *writing++ = current_palette[screens[0][i]]; } /* doesn't work. don't use */ // scales the screen size before blitting it if (multiply == 2) { unsigned int *olineptrs[2]; unsigned int *ilineptr; int x, y, i; unsigned int twoopixels; unsigned int twomoreopixels; unsigned int fouripixels; ilineptr = (unsigned int *) (screens[0]); for (i=0 ; i<2 ; i++) olineptrs[i] = (unsigned int *) &image->data[i*window_w]; y = SCREENHEIGHT; while (y--) { x = SCREENWIDTH; do { fouripixels = *ilineptr++; twoopixels = (fouripixels & 0xff000000) | ((fouripixels>>8) & 0xffff00) | ((fouripixels>>16) & 0xff); twomoreopixels = ((fouripixels<<16) & 0xff000000) | ((fouripixels<<8) & 0xffff00) | (fouripixels & 0xff); #ifdef __BIG_ENDIAN__ *olineptrs[0]++ = twoopixels; *olineptrs[1]++ = twoopixels; *olineptrs[0]++ = twomoreopixels; *olineptrs[1]++ = twomoreopixels; #else *olineptrs[0]++ = twomoreopixels; *olineptrs[1]++ = twomoreopixels; *olineptrs[0]++ = twoopixels; *olineptrs[1]++ = twoopixels; #endif } while (x-=4); olineptrs[0] += window_w/4; olineptrs[1] += window_w/4; } } else if (multiply == 3) { unsigned int *olineptrs[3]; unsigned int *ilineptr; int x, y, i; unsigned int fouropixels[3]; unsigned int fouripixels; ilineptr = (unsigned int *) (screens[0]); for (i=0 ; i<3 ; i++) olineptrs[i] = (unsigned int *) &image->data[i*window_w]; y = SCREENHEIGHT; while (y--) { x = SCREENWIDTH; do { fouripixels = *ilineptr++; fouropixels[0] = (fouripixels & 0xff000000) | ((fouripixels>>8) & 0xff0000) | ((fouripixels>>16) & 0xffff); fouropixels[1] = ((fouripixels<<8) & 0xff000000) | (fouripixels & 0xffff00) | ((fouripixels>>8) & 0xff); fouropixels[2] = ((fouripixels<<16) & 0xffff0000) | ((fouripixels<<8) & 0xff00) | (fouripixels & 0xff); #ifdef __BIG_ENDIAN__ *olineptrs[0]++ = fouropixels[0]; *olineptrs[1]++ = fouropixels[0]; *olineptrs[2]++ = fouropixels[0]; *olineptrs[0]++ = fouropixels[1]; *olineptrs[1]++ = fouropixels[1]; *olineptrs[2]++ = fouropixels[1]; *olineptrs[0]++ = fouropixels[2]; *olineptrs[1]++ = fouropixels[2]; *olineptrs[2]++ = fouropixels[2]; #else *olineptrs[0]++ = fouropixels[2]; *olineptrs[1]++ = fouropixels[2]; *olineptrs[2]++ = fouropixels[2]; *olineptrs[0]++ = fouropixels[1]; *olineptrs[1]++ = fouropixels[1]; *olineptrs[2]++ = fouropixels[1]; *olineptrs[0]++ = fouropixels[0]; *olineptrs[1]++ = fouropixels[0]; *olineptrs[2]++ = fouropixels[0]; #endif } while (x-=4); olineptrs[0] += 2*window_w/4; olineptrs[1] += 2*window_w/4; olineptrs[2] += 2*window_w/4; } } XPutImage(display,window,context,image,0,0,0,0,window_w,window_h); I_Sleep(0.025); /* do? */ frame_num++; } void I_ReadScreen (byte* scr) { // called from f_wipe to read the screen memcpy (scr, screens[0], SCREENWIDTH*SCREENHEIGHT); } void I_SetPalette (byte* palette) { // called from m_menu, d_main, st_stuff // to set the palette for (int i = 0; i < 256; i++) { current_palette[i].r = palette[3*i + 0]; current_palette[i].g = palette[3*i + 1]; current_palette[i].b = palette[3*i + 2]; current_palette[i].a = 255; } } void I_InitGraphics(void) { // called from d_main // set up video backend and possibly override screen[0] // which is where rendering ultimately writes to // before FinishUpdate presents it, whatever is in screen[0] /* if (M_CheckParm("-fullscreen")) { int monitor = GetCurrentMonitor(); window_h = GetMonitorHeight(monitor); window_w = window_h * 4 / 3; offset_x = GetMonitorWidth(monitor)/2 - window_w/2; SetWindowSize(window_w, window_h); ToggleBorderlessWindowed(); }*/ /*else {*/ /*if (M_CheckParm("-1")) multiply = 1; useless */ if (M_CheckParm("-2")) multiply = 2; else if (M_CheckParm("-3")) multiply = 3; /*else if (M_CheckParm("-4")) multiply = 4; else if (M_CheckParm("-5")) multiply = 5; else if (M_CheckParm("-10")) multiply = 10;*/ /* wtf */ /* that'd be 3200x2400... you have a 4K capitalist mon or smth? */ window_w = SCREENWIDTH * multiply; window_h = SCREENHEIGHT * multiply; offset_x = 0; /* based on Licar git.coom.tech/drummyfish/licar */ display = XOpenDisplay(0); int screen = DefaultScreen(display); window = XCreateSimpleWindow(display,RootWindow(display,screen),10,10, window_w,window_h,1, BlackPixel(display,screen),WhitePixel(display,screen)); XSizeHints *sizeHints = XAllocSizeHints(); sizeHints->flags = PMaxSize | PMinSize; sizeHints->max_width = window_w; sizeHints->min_width = window_w; sizeHints->max_height = window_h; sizeHints->min_height = window_h; XSetWMNormalHints(display,window,sizeHints); XFree(sizeHints); XMapWindow(display,window); XSelectInput(display,window,KeyPressMask | KeyReleaseMask); context = DefaultGC(display,screen); XStoreName(display,window,"DOOM"); /* 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. */ image = XCreateImage(display,DefaultVisual(display,screen), /*DefaultDepth(display,screen)*/24,ZPixmap,0,framebuffer, window_w,window_h,8,0); /* forking autorepeat */ XkbSetDetectableAutoRepeat(display,True,0); video_initialized = 1; // two obscure controllers I have /*SetGamepadMappings("03000000790000004e95000011010000,DragonRise Inc. NGC USB Gamepad,a:b1,b:b0,dpdown:b14,dpleft:b15,dpright:b13,dpup:b12,leftshoulder:b4,lefttrigger:a3,leftx:a0,lefty:a1~,rightshoulder:b5,righttrigger:a4,rightx:a5,righty:a2~,start:b9,x:b2,y:b3,platform:Linux,"); SetGamepadMappings("03000000790000001100000010010000,!NNEXT Gamepad,a:b2,b:b1,x:b3,y:b0,leftshoulder:b4,rightshoulder:b5,back:b8,start:b9,leftx:a0,lefty:a1,dpup:-a1,dpdown:+a1,dpleft:-a0,dpright:+a0");*/ }