- #include <glad/glad.h> 
-   
- // this needs to be included after glad.h 
- #include <SDL.h> 
- #include <SDL_opengl.h> 
-   
- #include "../renderers/gl/gl_renderer.h" 
- #include "harness/config.h" 
- #include "harness/hooks.h" 
- #include "harness/trace.h" 
- #include "sdl2_scancode_to_dinput.h" 
-   
- #include "globvars.h" 
- #include "grafdata.h" 
- #include "pd/sys.h" 
-   
- SDL_Window* window; 
- SDL_GLContext context; 
- uint8_t directinput_key_state[SDL_NUM_SCANCODES]; 
- int render_width, render_height; 
- int window_width, window_height; 
- int vp_x, vp_y, vp_width, vp_height; 
-   
- static const int scalefactor = 2; // Pierre-Marie Baty -- scale factor addition 
-   
- struct { 
-     float x; 
-     float y; 
- } sdl_window_scale; 
-   
- static void update_viewport(void) { 
-     const float target_aspect_ratio = (float)render_width / render_height; 
-     const float aspect_ratio = (float)window_width / window_height; 
-   
-     vp_width = window_width; 
-     vp_height = window_height; 
-     if (aspect_ratio != target_aspect_ratio) { 
-         if (aspect_ratio > target_aspect_ratio) { 
-             vp_width = window_height * target_aspect_ratio + .5f; 
-         } else { 
-             vp_height = window_width / target_aspect_ratio + .5f; 
-         } 
-     } 
-     vp_x = (window_width - vp_width) / 2; 
-     vp_y = (window_height - vp_height) / 2; 
-     GLRenderer_SetViewport(vp_x, vp_y, vp_width, vp_height); 
- } 
-   
- static void* create_window_and_renderer(char* title, int x, int y, int width, int height) { 
-   
-     window_width = width; 
-     window_height = height; 
-     render_width = width; 
-     render_height = height; 
-   
-     if (SDL_Init(SDL_INIT_VIDEO) != 0) { 
-         LOG_PANIC("SDL_INIT_VIDEO error: %s", SDL_GetError()); 
-     } 
-   
-     if (SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE) != 0) { 
-         LOG_PANIC("Failed to set SDL_GL_CONTEXT_PROFILE_MASK attribute. %s", SDL_GetError()); 
-     }; 
-     SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3); 
-     SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 1); 
-   
-     SDL_GL_SetSwapInterval(1); 
-   
-     window = SDL_CreateWindow(title, 
-         SDL_WINDOWPOS_CENTERED, 
-         SDL_WINDOWPOS_CENTERED, 
-         scalefactor * width, scalefactor * height, // Pierre-Marie Baty -- scale factor addition 
-         SDL_WINDOW_OPENGL | SDL_WINDOW_RESIZABLE); 
-   
-     if (window == NULL) { 
-         LOG_PANIC("Failed to create window. %s", SDL_GetError()); 
-     } 
-   
-     sdl_window_scale.x = ((float)render_width) / (scalefactor * width); // Pierre-Marie Baty -- scale factor addition 
-     sdl_window_scale.y = ((float)render_height) / (scalefactor * height); // Pierre-Marie Baty -- scale factor addition 
-   
-     if (harness_game_config.start_full_screen) { 
-         SDL_SetWindowFullscreen(window, SDL_WINDOW_FULLSCREEN_DESKTOP); 
-     } 
-   
-     context = SDL_GL_CreateContext(window); 
-     if (!context) { 
-         LOG_PANIC("Failed to call SDL_GL_CreateContext. %s", SDL_GetError()); 
-     } 
-   
-     // Load GL extensions using glad 
-     if (!gladLoadGLLoader((GLADloadproc)SDL_GL_GetProcAddress)) { 
-         LOG_PANIC("Failed to initialize the OpenGL context with GLAD."); 
-     } 
-   
-     GLRenderer_Init(render_width, render_height); 
-     update_viewport(); 
-   
-     return window; 
- } 
-   
- static int set_window_pos(void* hWnd, int x, int y, int nWidth, int nHeight) { 
-     // SDL_SetWindowPosition(hWnd, x, y); 
- //    if (nWidth == 320 && nHeight == 200) { 
-         nWidth = scalefactor * nWidth; // Pierre-Marie Baty -- scale factor addition 
-         nHeight = scalefactor * nHeight - 1; // Pierre-Marie Baty -- scale factor addition. FIXME: find out why the minus one is necessary. 
- //    } 
-     SDL_SetWindowSize(hWnd, nWidth, nHeight); 
-     return 0; 
- } 
-   
- static void destroy_window(void* hWnd) { 
-     SDL_GL_DeleteContext(context); 
-     SDL_DestroyWindow(window); 
-     SDL_Quit(); 
-     window = NULL; 
- } 
-   
- // Checks whether the `flag_check` is the only modifier applied. 
- // e.g. is_only_modifier(event.key.keysym.mod, KMOD_ALT) returns true when only the ALT key was pressed 
- static int is_only_key_modifier(int modifier_flags, int flag_check) { 
-     return (modifier_flags & flag_check) && (modifier_flags & (KMOD_CTRL | KMOD_SHIFT | KMOD_ALT | KMOD_GUI)) == (modifier_flags & flag_check); 
- } 
-   
- static int get_and_handle_message(MSG_* msg) { 
-     SDL_Event event; 
-     int dinput_key; 
-   
-     while (SDL_PollEvent(&event)) { 
-         switch (event.type) { 
-         case SDL_KEYDOWN: 
-         case SDL_KEYUP: 
-             if (event.key.keysym.sym == SDLK_RETURN) { 
-                 if (event.key.type == SDL_KEYDOWN) { 
-                     if ((event.key.keysym.mod & (KMOD_CTRL | KMOD_SHIFT | KMOD_ALT | KMOD_GUI))) { 
-                         // Ignore keydown of RETURN when used together with some modifier 
-                         return 0; 
-                     } 
-                 } else if (event.key.type == SDL_KEYUP) { 
-                     if (is_only_key_modifier(event.key.keysym.mod, KMOD_ALT)) { 
-                         SDL_SetWindowFullscreen(window, (SDL_GetWindowFlags(window) & SDL_WINDOW_FULLSCREEN_DESKTOP) ? 0 : SDL_WINDOW_FULLSCREEN_DESKTOP); 
-                     } 
-                 } 
-             } 
-   
-             // Map incoming SDL scancode to DirectInput DIK_* key code. 
-             // https://github.com/DanielGibson/Snippets/blob/master/sdl2_scancode_to_dinput.h 
-             dinput_key = sdlScanCodeToDirectInputKeyNum[event.key.keysym.scancode]; 
-             if (dinput_key == 0) { 
-                 LOG_WARN("unexpected scan code %s (%d)", SDL_GetScancodeName(event.key.keysym.scancode), event.key.keysym.scancode); 
-                 return 0; 
-             } 
-             // DInput expects high bit to be set if key is down 
-             // https://learn.microsoft.com/en-us/previous-versions/windows/desktop/ee418261(v=vs.85) 
-             directinput_key_state[dinput_key] = (event.type == SDL_KEYDOWN ? 0x80 : 0); 
-             break; 
-   
-         case SDL_WINDOWEVENT: 
-             switch (event.window.event) { 
-             case SDL_WINDOWEVENT_SIZE_CHANGED: 
-                 SDL_GetWindowSize(window, &window_width, &window_height); 
-                 update_viewport(); 
-                 sdl_window_scale.x = (float)render_width / vp_width; 
-                 sdl_window_scale.y = (float)render_height / vp_height; 
-                 break; 
-             } 
-             break; 
-   
-         case SDL_QUIT: 
-             msg->message = WM_QUIT; 
-             return 1; 
-         } 
-     } 
-     return 0; 
- } 
-   
- static void swap_window(void) { 
-     SDL_GL_SwapWindow(window); 
- } 
-   
- static void get_keyboard_state(unsigned int count, uint8_t* buffer) { 
-     memcpy(- buffer ,-  directinput_key_state ,-  count );
 
- } 
-   
- static int get_mouse_buttons(int* pButton1, int* pButton2) { 
-     int state = SDL_GetMouseState(NULL, NULL); 
-     *pButton1 = state & SDL_BUTTON_LMASK; 
-     *pButton2 = state & SDL_BUTTON_RMASK; 
-     return 0; 
- } 
-   
- static int get_mouse_position(int* pX, int* pY) { 
-     SDL_GetMouseState(pX, pY); 
-   
-     if (*pX < vp_x) { 
-         *pX = vp_x; 
-     } else if (*pX >= vp_x + vp_width) { 
-         *pX = vp_x + vp_width - 1; 
-     } 
-     if (*pY < vp_y) { 
-         *pY = vp_y; 
-     } else if (*pY >= vp_y + vp_height) { 
-         *pY = vp_y + vp_height - 1; 
-     } 
-     *pX -= vp_x; 
-     *pY -= vp_y; 
-     *pX *= sdl_window_scale.x; 
-     *pY *= sdl_window_scale.y; 
-   
- #if defined(DETHRACE_FIX_BUGS) 
-     // In hires mode (640x480), the menus are still rendered at (320x240), 
-     // so prescale the cursor coordinates accordingly. 
-     *pX *= gGraf_specs[gGraf_data_index].phys_width; 
-     *pX /= gGraf_specs[gReal_graf_data_index].phys_width; 
-     *pY *= gGraf_specs[gGraf_data_index].phys_height; 
-     *pY /= gGraf_specs[gReal_graf_data_index].phys_height; 
- #endif 
-     return 0; 
- } 
-   
- static void set_palette(PALETTEENTRY_* pal) { 
-     GLRenderer_SetPalette((uint8_t*)pal); 
- } 
-   
- int show_error_message(void* window, char* text, char* caption) { 
-     SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR, caption, text, window); 
-     return 0; 
- } 
-   
- void Harness_Platform_Init(tHarness_platform* platform) { 
-     platform->ProcessWindowMessages = get_and_handle_message; 
-     platform->Sleep = SDL_Delay; 
-     platform->GetTicks = SDL_GetTicks; 
-     platform->CreateWindowAndRenderer = create_window_and_renderer; 
-     platform->ShowCursor = SDL_ShowCursor; 
-     platform->SetWindowPos = set_window_pos; 
-     platform->SwapWindow = swap_window; 
-     platform->DestroyWindow = destroy_window; 
-     platform->GetKeyboardState = get_keyboard_state; 
-     platform->GetMousePosition = get_mouse_position; 
-     platform->GetMouseButtons = get_mouse_buttons; 
-     platform->DestroyWindow = destroy_window; 
-     platform->ShowErrorMessage = show_error_message; 
-   
-     platform->Renderer_BufferModel = GLRenderer_BufferModel; 
-     platform->Renderer_BufferMaterial = GLRenderer_BufferMaterial; 
-     platform->Renderer_BufferTexture = GLRenderer_BufferTexture; 
-     platform->Renderer_SetPalette = set_palette; 
-     platform->Renderer_FullScreenQuad = GLRenderer_FullScreenQuad; 
-     platform->Renderer_Model = GLRenderer_Model; 
-     platform->Renderer_ClearBuffers = GLRenderer_ClearBuffers; 
-     platform->Renderer_FlushBuffers = GLRenderer_FlushBuffers; 
-     platform->Renderer_BeginScene = GLRenderer_BeginScene; 
-     platform->Renderer_EndScene = GLRenderer_EndScene; 
-     platform->Renderer_SetViewport = GLRenderer_SetViewport; 
- } 
-