[c] sdl

Viewer

  1. //
  2. // Copyright 2020 Electronic Arts Inc.
  3. //
  4. // TiberianDawn.DLL and RedAlert.dll and corresponding source code is free
  5. // software: you can redistribute it and/or modify it under the terms of
  6. // the GNU General Public License as published by the Free Software Foundation,
  7. // either version 3 of the License, or (at your option) any later version.
  8.  
  9. // TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed
  10. // in the hope that it will be useful, but with permitted additional restrictions
  11. // under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT
  12. // distributed with this program. You should have received a copy of the
  13. // GNU General Public License along with permitted additional restrictions
  14. // with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection
  15.  
  16. /***************************************************************************
  17.  **   C O N F I D E N T I A L --- W E S T W O O D   A S S O C I A T E S   **
  18.  ***************************************************************************
  19.  *                                                                         *
  20.  *                 Project Name : Westwood Win32 Library                   *
  21.  *                                                                         *
  22.  *                    File Name : DDRAW.CPP                                *
  23.  *                                                                         *
  24.  *                   Programmer : Philip W. Gorrow                         *
  25.  *                                                                         *
  26.  *                   Start Date : October 10, 1995                         *
  27.  *                                                                         *
  28.  *                  Last Update : October 10, 1995   []                    *
  29.  *                                                                         *
  30.  *-------------------------------------------------------------------------*
  31.  * Functions:                                                              *
  32.  * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
  33.  
  34. /*=========================================================================*/
  35. /* The following PRIVATE functions are in this file:                       */
  36. /*=========================================================================*/
  37.  
  38. /*= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =*/
  39.  
  40. #include "gbuffer.h"
  41. #include "palette.h"
  42. #include "video.h"
  43. #include "wwkeyboard.h"
  44. #include "wwmouse.h"
  45. #include "settings.h"
  46. #include "debugstring.h"
  47.  
  48. #include <SDL.h>
  49.  
  50. #ifndef SDL2
  51.  
  52. #include <SDL1/SDL2_backports.h>
  53.  
  54. //= Renderer stubs
  55.  
  56. #define SDL_InvalidParamError(x)          SDL_SetError("Parameter '%s' is invalid", (x))
  57.  
  58. int
  59. SDL_SetPaletteColors(SDL_Palette * palette, const SDL_Color * colors,
  60.                      int firstcolor, int ncolors)
  61. {
  62.     int status = 0;
  63.  
  64.     /* Verify the parameters */
  65.     if (!palette) {
  66.         return -1;
  67.     }
  68.     if (ncolors > (palette->ncolors - firstcolor)) {
  69.         ncolors = (palette->ncolors - firstcolor);
  70.         status = -1;
  71.     }
  72.  
  73.     if (colors != (palette->colors + firstcolor)) {
  74.         SDL_memcpy(palette->colors + firstcolor, colors,
  75.                    ncolors * sizeof(*colors));
  76.     }
  77.     //++palette->version;
  78.    // if (!palette->version) {
  79.         //palette->version = 1;
  80.     //}
  81.  
  82.     return status;
  83. }
  84.  
  85. inline SDL_Palette *
  86. SDL_AllocPalette(int ncolors)
  87. {
  88.         SDL_Palette *palette;
  89.  
  90.         /* Input validation */
  91.         if (ncolors < 1) {
  92.                 SDL_InvalidParamError("ncolors");
  93.         printf(" line %d in file %s\n", __LINE__, __FILE__);
  94.                 return NULL;
  95.         }
  96.  
  97.         palette = (SDL_Palette *)SDL_malloc(sizeof(*palette));
  98.         if (!palette) {
  99.                 SDL_OutOfMemory();
  100.                 return NULL;
  101.         }
  102.         palette->colors = (SDL_Color *)SDL_malloc(ncolors * sizeof(*palette->colors));
  103.         if (!palette->colors) {
  104.                 SDL_free(palette);
  105.                 return NULL;
  106.         }
  107.         palette->ncolors = ncolors;
  108.         SDL_memset(palette->colors, 0xFF, ncolors * sizeof(*palette->colors));
  109.         return palette;
  110. }
  111.  
  112. inline void
  113. SDL_FreePalette(SDL_Palette *palette)
  114. {
  115.         if (!palette) {
  116.                 SDL_InvalidParamError("palette");
  117.         printf(" line %d in file %s\n", __LINE__, __FILE__);
  118.                 return;
  119.         }
  120.         SDL_free(palette->colors);
  121.         SDL_free(palette);
  122. }
  123.  
  124. #else
  125. static SDL_Window* window;
  126. static SDL_Renderer* renderer;
  127. #endif
  128. static SDL_Palette* palette;
  129. static Uint32 pixel_format;
  130. static SDL_Rect render_dst;
  131.  
  132. static struct
  133. {
  134.     int GameW;
  135.     int GameH;
  136.     bool Clip;
  137.     float ScaleX{1.0f};
  138.     float ScaleY{1.0f};
  139.     void* Raw;
  140.     int W;
  141.     int H;
  142.     int HotX;
  143.     int HotY;
  144.     float X;
  145.     float Y;
  146.     SDL_Cursor* Pending;
  147.     SDL_Cursor* Current;
  148.     SDL_Surface* Surface;
  149. } hwcursor;
  150.  
  151. #define ARRAY_SIZE(x) int(sizeof(x) / sizeof(x[0]))
  152. #ifdef SDL2
  153. #define MAKEFORMAT(f)                                                                                                  \
  154.     {                                                                                                                  \
  155.         SDL_PIXELFORMAT_##f, #f                                                                                        \
  156.     }
  157. Uint32 SettingsPixelFormat()
  158. {
  159.     /*
  160.     ** Known good RGB formats for both the surface and texture.
  161.     */
  162.     static struct
  163.     {
  164.         Uint32 format;
  165.         std::string name;
  166.     } formats[] = {
  167.         MAKEFORMAT(ARGB8888),
  168.         MAKEFORMAT(RGBA8888),
  169.         MAKEFORMAT(ABGR8888),
  170.         MAKEFORMAT(BGRA8888),
  171.         MAKEFORMAT(RGB24),
  172.         MAKEFORMAT(BGR24),
  173.         MAKEFORMAT(RGB888),
  174.         MAKEFORMAT(BGR888),
  175.         MAKEFORMAT(RGB555),
  176.         MAKEFORMAT(BGR555),
  177.         MAKEFORMAT(RGB565),
  178.         MAKEFORMAT(BGR565),
  179.     };
  180.  
  181.     std::string str = Settings.Video.PixelFormat;
  182.  
  183.     for (auto& c : str) {
  184.         c = toupper(c);
  185.     }
  186.  
  187.     for (int i = 0; i < ARRAY_SIZE(formats); i++) {
  188.         if (str.compare(formats[i].name) == 0) {
  189.             return formats[i].format;
  190.         }
  191.     }
  192.  
  193.     return SDL_PIXELFORMAT_UNKNOWN;
  194. }
  195. #endif
  196. static void Update_HWCursor();
  197.  
  198. static void Update_HWCursor_Settings()
  199. {
  200.     /*
  201.     ** Update mouse scaling settings.
  202.     */
  203.  
  204. #ifdef SDL2   
  205.         int win_w, win_h;
  206.     SDL_GetRendererOutputSize(renderer, &win_w, &win_h);
  207. #else
  208.         int win_w = 640;
  209.     int win_h = 400;
  210. #endif 
  211.  
  212.     hwcursor.ScaleX = win_w / (float)hwcursor.GameW;
  213.     hwcursor.ScaleY = win_h / (float)hwcursor.GameH;
  214.  
  215.     /*
  216.     ** Update screen boxing settings.
  217.     */
  218.     float ar = (float)hwcursor.GameW / hwcursor.GameH;
  219.     if (Settings.Video.Boxing) {
  220.         render_dst.w = win_w;
  221.         render_dst.h = render_dst.w / ar;
  222.         if (render_dst.h > win_h) {
  223.             render_dst.h = win_h;
  224.             render_dst.w = render_dst.h * ar;
  225.         }
  226.         render_dst.x = (win_w - render_dst.w) / 2;
  227.         render_dst.y = (win_h - render_dst.h) / 2;
  228.     } else {
  229.         render_dst.w = win_w;
  230.         render_dst.h = win_h;
  231.         render_dst.x = 0;
  232.         render_dst.y = 0;
  233.     }
  234.  
  235.     /*
  236.     ** Ensure cursor clip is in the desired state.
  237.     */
  238.     Set_Video_Cursor_Clip(hwcursor.Clip);
  239.  
  240.     /*
  241.     ** Update visible cursor scaling.
  242.     */
  243.     Update_HWCursor();
  244. }
  245.  
  246. class SurfaceMonitorClassDummy : public SurfaceMonitorClass
  247. {
  248.  
  249. public:
  250.     SurfaceMonitorClassDummy()
  251.     {
  252.     }
  253.  
  254.     virtual void Restore_Surfaces()
  255.     {
  256.     }
  257.  
  258.     virtual void Set_Surface_Focus(bool in_focus)
  259.     {
  260.     }
  261.  
  262.     virtual void Release()
  263.     {
  264.     }
  265. };
  266.  
  267. SurfaceMonitorClassDummy AllSurfacesDummy;           // List of all direct draw surfaces
  268. SurfaceMonitorClass& AllSurfaces = AllSurfacesDummy; // List of all direct draw surfaces
  269.  
  270. /***********************************************************************************************
  271.  * Set_Video_Mode -- Initializes Direct Draw and sets the required Video Mode                  *
  272.  *                                                                                             *
  273.  * INPUT:           int width           - the width of the video mode in pixels                *
  274.  *                  int height          - the height of the video mode in pixels               *
  275.  *                  int bits_per_pixel  - the number of bits per pixel the video mode supports *
  276.  *                                                                                             *
  277.  * OUTPUT:     none                                                                            *
  278.  *                                                                                             *
  279.  * HISTORY:                                                                                    *
  280.  *   09/26/1995 PWG : Created.                                                                 *
  281.  *=============================================================================================*/
  282. bool Set_Video_Mode(int w, int h, int bits_per_pixel)
  283. {
  284.     SDL_Init(SDL_INIT_VIDEO);
  285.    //SDL_ShowCursor(SDL_DISABLE);
  286.  
  287.     int win_w = w;
  288.     int win_h = h;
  289.     int win_flags = 0;
  290.  
  291. #ifdef SDL2
  292.     Uint32 requested_pixel_format = SettingsPixelFormat();
  293.     if (!Settings.Video.Windowed) {
  294.         /*
  295.         ** Native fullscreen if no proper width and height set.
  296.         */
  297.         if (Settings.Video.Width < w || Settings.Video.Height < h) {
  298.             win_w = Settings.Video.Width = 0;
  299.             win_h = Settings.Video.Height = 0;
  300.             win_flags |= SDL_FULLSCREEN;
  301.         } else {
  302.             win_w = Settings.Video.Width;
  303.             win_h = Settings.Video.Height;
  304.             win_flags |= SDL_FULLSCREEN;
  305.         }
  306.     } else if (Settings.Video.WindowWidth > w || Settings.Video.WindowHeight > h) {
  307.         win_w = Settings.Video.WindowWidth;
  308.         win_h = Settings.Video.WindowHeight;
  309.     } else {
  310.         Settings.Video.WindowWidth = win_w;
  311.         Settings.Video.WindowHeight = win_h;
  312.     }
  313. #endif
  314.         if (bits_per_pixel == 0){
  315.         fprintf(stderr, "error: bits_per_pixel == 0: %s\n", SDL_GetError());
  316.                 return false;
  317.     }
  318. #ifndef SDL2
  319.     SDL_SetVideoMode(w, h, 8/*bits_per_pixel*/, SDL_HWSURFACE|SDL_HWPALETTE);
  320. #else
  321.     window =
  322.         SDL_CreateWindow("Vanilla Conquer", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, win_w, win_h, win_flags);
  323.  
  324.     if (window == nullptr) {
  325.         DBG_ERROR("SDL_CreateWindow failed: %s", SDL_GetError());
  326.         Reset_Video_Mode();
  327.         return false;
  328.     }
  329.  
  330.     DBG_INFO("Created SDL2 %s window in %dx%d", (win_flags ? "fullscreen" : "windowed"), win_w, win_h);
  331.  
  332.     
  333.     pixel_format = SDL_GetWindowPixelFormat(window);
  334.  
  335.     if (pixel_format == SDL_PIXELFORMAT_UNKNOWN || SDL_BITSPERPIXEL(pixel_format) < 16) {
  336.         DBG_ERROR("SDL2 window pixel format unsupported: %s (%d bpp)",
  337.                   SDL_GetPixelFormatName(pixel_format),
  338.                   SDL_BITSPERPIXEL(pixel_format));
  339.         Reset_Video_Mode();
  340.         return false;
  341.     }
  342.  
  343.     DBG_INFO("  pixel format: %s (%d bpp)", SDL_GetPixelFormatName(pixel_format), SDL_BITSPERPIXEL(pixel_format));
  344.     DBG_INFO("SDL2 drivers available: (user preference '%s')", Settings.Video.Driver.c_str());
  345.     int renderer_index = -1;
  346.     for (int i = 0; i < SDL_GetNumRenderDrivers(); i++) {
  347.         SDL_RendererInfo info;
  348.         if (SDL_GetRenderDriverInfo(i, &info) == 0) {
  349.             if (Settings.Video.Driver.compare(info.name) == 0) {
  350.                 renderer_index = i;
  351.             }
  352.  
  353.             DBG_INFO(" %s%s", info.name, (== renderer_index ? " (selected)" : ""));
  354.         }
  355.     }
  356.  
  357.     renderer = SDL_CreateRenderer(window, renderer_index, SDL_RENDERER_TARGETTEXTURE);
  358.     if (renderer == nullptr) {
  359.         DBG_ERROR("SDL_CreateRenderer failed: %s", SDL_GetError());
  360.         Reset_Video_Mode();
  361.         return false;
  362.     }
  363.  
  364.     SDL_RendererInfo info;
  365.     if (SDL_GetRendererInfo(renderer, &info) != 0) {
  366.         DBG_ERROR("SDL_GetRendererInfo failed: %s", SDL_GetError());
  367.         Reset_Video_Mode();
  368.         return false;
  369.     }
  370.  
  371.     DBG_INFO("Initialized SDL2 driver '%s'", info.name);
  372.     DBG_INFO("  flags:");
  373.     if (info.flags & SDL_RENDERER_SOFTWARE) {
  374.         DBG_INFO("    SDL_RENDERER_SOFTWARE");
  375.     }
  376.     if (info.flags & SDL_RENDERER_ACCELERATED) {
  377.         DBG_INFO("    SDL_RENDERER_ACCELERATED");
  378.     }
  379.     if (info.flags & SDL_RENDERER_PRESENTVSYNC) {
  380.         DBG_INFO("    SDL_RENDERER_PRESENT_VSYNC");
  381.     }
  382.     if (info.flags & SDL_RENDERER_TARGETTEXTURE) {
  383.         DBG_INFO("    SDL_RENDERER_TARGETTEXTURE");
  384.     }
  385.  
  386.     DBG_INFO("  max texture size: %dx%d", info.max_texture_width, info.max_texture_height);
  387.  
  388.     DBG_INFO("  %d texture formats supported: (user preference '%s')",
  389.              info.num_texture_formats,
  390.              SDL_GetPixelFormatName(requested_pixel_format));
  391.  
  392.     /*
  393.     ** Pick the first pixel format or the user requested one. It better be RGB.
  394.     */
  395.     pixel_format = SDL_PIXELFORMAT_UNKNOWN;
  396.     for (int i = 0; i < info.num_texture_formats; i++) {
  397.         if ((pixel_format == SDL_PIXELFORMAT_UNKNOWN && i == 0) || info.texture_formats[i] == requested_pixel_format) {
  398.             pixel_format = info.texture_formats[i];
  399.         }
  400.     }
  401.  
  402.     for (int i = 0; i < info.num_texture_formats; i++) {
  403.         DBG_INFO("    %s%s",
  404.                  SDL_GetPixelFormatName(info.texture_formats[i]),
  405.                  (pixel_format == info.texture_formats[i] ? " (selected)" : ""));
  406.     }
  407.  
  408.     /*
  409.     ** Set requested scaling algorithm.
  410.     */
  411.     if (!SDL_SetHintWithPriority(SDL_HINT_RENDER_SCALE_QUALITY, Settings.Video.Scaler.c_str(), SDL_HINT_OVERRIDE)) {
  412.         DBG_WARN("  scaler '%s' is unsupported");
  413.     } else {
  414.         DBG_INFO("  scaler set to '%s'", Settings.Video.Scaler.c_str());
  415.     }
  416. #endif
  417.     if (palette == nullptr) {
  418.         palette = SDL_AllocPalette(256);
  419.     }
  420.  
  421.     /*
  422.     ** Set mouse scaling options.
  423.     */
  424.     hwcursor.GameW = w;
  425.     hwcursor.GameH = h;
  426.     hwcursor.X = w / 2;
  427.     hwcursor.Y = h / 2;
  428.     Update_HWCursor_Settings();
  429.  
  430.     return true;
  431. }
  432.  
  433. void Toggle_Video_Fullscreen()
  434. {
  435.     Settings.Video.Windowed = !Settings.Video.Windowed;
  436. #ifdef SDL2
  437.     if (!Settings.Video.Windowed) {
  438.         if (Settings.Video.Width == 0 || Settings.Video.Height == 0) {
  439.             SDL_SetWindowFullscreen(window, SDL_WINDOW_FULLSCREEN_DESKTOP);
  440.         } else {
  441.             SDL_SetWindowSize(window, Settings.Video.Width, Settings.Video.Height);
  442.             SDL_SetWindowFullscreen(window, SDL_WINDOW_FULLSCREEN);
  443.         }
  444.     } else {
  445.         SDL_SetWindowFullscreen(window, 0);
  446.         SDL_SetWindowSize(window, Settings.Video.WindowWidth, Settings.Video.WindowHeight);
  447.     }
  448. #endif
  449.     Update_HWCursor_Settings();
  450. }
  451.  
  452. void Get_Video_Scale(float& x, float& y)
  453. {
  454.     x = hwcursor.ScaleX;
  455.     y = hwcursor.ScaleY;
  456. }
  457.  
  458. void Set_Video_Cursor_Clip(bool clipped)
  459. {
  460.     hwcursor.Clip = clipped;
  461. #ifdef SDL2
  462.     SDL_ShowCursor(0);
  463.     SDL_WM_GrabInput(SDL_GRAB_ON);
  464.  
  465.     if (window) {
  466.         int relative;
  467.  
  468.         if (Settings.Video.Windowed) {
  469.             SDL_SetWindowGrab(window, hwcursor.Clip ? SDL_TRUE : SDL_FALSE);
  470.             relative = SDL_SetRelativeMouseMode(Settings.Mouse.RawInput && hwcursor.Clip ? SDL_TRUE : SDL_FALSE);
  471.             /*
  472.             ** When grabbing with raw input, move in-game cursor where the real cursor was and vice versa.
  473.             */
  474.             if (Settings.Mouse.RawInput) {
  475.                 if (hwcursor.Clip) {
  476.                     int x, y;
  477.                     SDL_GetMouseState(&x, &y);
  478.                     hwcursor.X = x / hwcursor.ScaleX;
  479.                     hwcursor.Y = y / hwcursor.ScaleY;
  480.                 } else {
  481.                     SDL_WarpMouseInWindow(window, hwcursor.X * hwcursor.ScaleX, hwcursor.Y * hwcursor.ScaleY);
  482.                 }
  483.             }
  484.         } else {
  485.             SDL_SetWindowGrab(window, SDL_TRUE);
  486.             relative = SDL_SetRelativeMouseMode(Settings.Mouse.RawInput ? SDL_TRUE : SDL_FALSE);
  487.         }
  488.  
  489.         if (relative < 0) {
  490.             DBG_ERROR("Raw input not supported, disabling.");
  491.             Settings.Mouse.RawInput = false;
  492.         }      
  493.     }
  494. #endif
  495. }
  496.  
  497. void Move_Video_Mouse(int xrel, int yrel)
  498. {
  499.     if (hwcursor.Clip || !Settings.Video.Windowed) {
  500.         hwcursor.X += xrel * (Settings.Mouse.Sensitivity / 100.0f);
  501.         hwcursor.Y += yrel * (Settings.Mouse.Sensitivity / 100.0f);
  502.     }
  503.  
  504.     if (hwcursor.X >= hwcursor.GameW) {
  505.         hwcursor.X = hwcursor.GameW - 1;
  506.     } else if (hwcursor.X < 0) {
  507.         hwcursor.X = 0;
  508.     }
  509.  
  510.     if (hwcursor.Y >= hwcursor.GameH) {
  511.         hwcursor.Y = hwcursor.GameH - 1;
  512.     } else if (hwcursor.Y < 0) {
  513.         hwcursor.Y = 0;
  514.     }
  515. }
  516.  
  517. void Get_Video_Mouse(int& x, int& y)
  518. {
  519.     if (Settings.Mouse.RawInput && (hwcursor.Clip || !Settings.Video.Windowed)) {
  520.         x = hwcursor.X;
  521.         y = hwcursor.Y;
  522.     } else {
  523.         float scale_x, scale_y;
  524.         Get_Video_Scale(scale_x, scale_y);
  525.         SDL_GetMouseState(&x, &y);
  526.         x /= scale_x;
  527.         y /= scale_y;
  528.     }
  529. }
  530.  
  531. /***********************************************************************************************
  532.  * Reset_Video_Mode -- Resets video mode and deletes Direct Draw Object                        *
  533.  *                                                                                             *
  534.  * INPUT:             none                                                                            *
  535.  *                                                                                             *
  536.  * OUTPUT:     none                                                                            *
  537.  *                                                                                             *
  538.  * WARNINGS:                                                                                   *
  539.  *                                                                                             *
  540.  * HISTORY:                                                                                    *
  541.  *   09/26/1995 PWG : Created.                                                                 *
  542.  *=============================================================================================*/
  543. void Reset_Video_Mode(void)
  544. {
  545.     if (hwcursor.Pending) {
  546.         SDL_FreeCursor(hwcursor.Pending);
  547.         hwcursor.Pending = nullptr;
  548.     }
  549.  
  550.     if (hwcursor.Current) {
  551.         SDL_FreeCursor(hwcursor.Current);
  552.         hwcursor.Current = nullptr;
  553.     }
  554.  
  555.     if (hwcursor.Surface) {
  556.         SDL_FreeSurface(hwcursor.Surface);
  557.         hwcursor.Surface = nullptr;
  558.     }
  559. #ifdef SDL2
  560.     SDL_DestroyRenderer(renderer);
  561.     renderer = nullptr;
  562.        
  563.     SDL_DestroyWindow(window);
  564.     window = nullptr;
  565. #else
  566.     SDL_FreeSurface(windowSurface);
  567.     windowSurface = nullptr;
  568. #endif
  569.        
  570.     SDL_FreePalette(palette);
  571.     palette = nullptr;
  572.  
  573.  
  574. }
  575.  
  576. static void Update_HWCursor()
  577. {
  578.     float scale_x = 1.0f;
  579.     float scale_y = 1.0f;
  580.     int scaled_w = hwcursor.W;
  581.     int scaled_h = hwcursor.H;
  582.  
  583.     /*
  584.     ** Pre-scale cursor *only* if we are not emulating a hw cursor.
  585.     */
  586.     if (Settings.Video.HardwareCursor) {
  587.         scale_x = hwcursor.ScaleX;
  588.         scale_y = hwcursor.ScaleY;
  589.         scaled_w *= scale_x;
  590.         scaled_h *= scale_y;
  591.     }
  592.  
  593.     /*
  594.     ** Allocate or reallocate surface if it has the wrong size.
  595.     */
  596.     if (hwcursor.Surface == nullptr || hwcursor.Surface->!= scaled_w || hwcursor.Surface->!= scaled_h) {
  597.         if (hwcursor.Surface) {
  598.             SDL_FreeSurface(hwcursor.Surface);
  599.         }
  600.  
  601.         /*
  602.         ** Real HW cursor needs to be scaled up. Emulated can use original cursor data.
  603.         */
  604.         if (Settings.Video.HardwareCursor) {
  605.             hwcursor.Surface = SDL_CreateRGBSurfaceWithFormat(0, scaled_w, scaled_h, 8, SDL_PIXELFORMAT_INDEX8);
  606.         } else {
  607.             hwcursor.Surface =
  608.                 SDL_CreateRGBSurfaceFrom(hwcursor.Raw, hwcursor.W, hwcursor.H, 8, hwcursor.W, 0, 0, 0, 0);
  609.         }
  610. #ifdef SDL2
  611.         SDL_SetSurfacePalette(hwcursor.Surface, palette);
  612. #else      
  613.         SDL_SetColorKey(hwcursor.Surface, SDL_TRUE, 0);
  614. #endif         
  615.     }
  616.  
  617.     /*
  618.     ** Prepare HW cursor by scaling up and creating the SDL version.
  619.     */
  620.     if (Settings.Video.HardwareCursor) {
  621.         uint8_t* src = (uint8_t*)hwcursor.Raw;
  622.         uint8_t* dst = (uint8_t*)hwcursor.Surface->pixels;
  623.         int src_pitch = hwcursor.W;
  624.         int dst_pitch = hwcursor.Surface->pitch;
  625.  
  626.         for (int y = 0; y < scaled_h; y++) {
  627.             for (int x = 0; x < scaled_w; x++) {
  628.                 dst[dst_pitch * y + x] = src[src_pitch * (int)(/ scale_y) + (int)(/ scale_x)];
  629.             }
  630.         }
  631.  
  632.         if (hwcursor.Pending) {
  633.             SDL_FreeCursor(hwcursor.Pending);
  634.         }
  635.  
  636.         /*
  637.         ** Queue new cursor to be set during frame flip.
  638.         */
  639. #ifdef SDL2           
  640.         hwcursor.Pending =
  641.             SDL_CreateColorCursor(hwcursor.Surface, hwcursor.HotX * hwcursor.ScaleX, hwcursor.HotY * hwcursor.ScaleY);
  642. #endif                 
  643.     }
  644. }
  645.  
  646. void Set_Video_Cursor(void* cursor, int w, int h, int hotx, int hoty)
  647. {
  648.     hwcursor.Raw = cursor;
  649.     hwcursor.W = w;
  650.     hwcursor.H = h;
  651.     hwcursor.HotX = hotx;
  652.     hwcursor.HotY = hoty;
  653.  
  654.     Update_HWCursor();
  655. }
  656.  
  657. /***********************************************************************************************
  658.  * Get_Free_Video_Memory -- returns amount of free video memory                                *
  659.  *                                                                                             *
  660.  *                                                                                             *
  661.  *                                                                                             *
  662.  * INPUT:    Nothing                                                                           *
  663.  *                                                                                             *
  664.  * OUTPUT:   bytes of available video RAM                                                      *
  665.  *                                                                                             *
  666.  * WARNINGS: None                                                                              *
  667.  *                                                                                             *
  668.  * HISTORY:                                                                                    *
  669.  *    11/29/95 12:52PM ST : Created                                                            *
  670.  *=============================================================================================*/
  671. unsigned int Get_Free_Video_Memory(void)
  672. {
  673.     return 1000000000;
  674. }
  675.  
  676. /***********************************************************************************************
  677.  * Get_Video_Hardware_Caps -- returns bitmask of direct draw video hardware support            *
  678.  *                                                                                             *
  679.  *                                                                                             *
  680.  *                                                                                             *
  681.  * INPUT:    Nothing                                                                           *
  682.  *                                                                                             *
  683.  * OUTPUT:   hardware flags                                                                    *
  684.  *                                                                                             *
  685.  * WARNINGS: Must call Set_Video_Mode 1st to create the direct draw object                     *
  686.  *                                                                                             *
  687.  * HISTORY:                                                                                    *
  688.  *    1/12/96 9:14AM ST : Created                                                              *
  689.  *=============================================================================================*/
  690. unsigned Get_Video_Hardware_Capabilities(void)
  691. {
  692.     return VIDEO_BLITTER;
  693. }
  694.  
  695. /***********************************************************************************************
  696.  * Wait_Vert_Blank -- Waits for the start (leading edge) of a vertical blank                   *
  697.  *                                                                                             *
  698.  * INPUT:                                                                                      *
  699.  *                                                                                             *
  700.  * OUTPUT:                                                                                     *
  701.  *                                                                                             *
  702.  * WARNINGS:                                                                                   *
  703.  *                                                                                             *
  704.  * HISTORY:                                                                                    *
  705.  *=============================================================================================*/
  706. void Wait_Vert_Blank(void)
  707. {
  708. }
  709.  
  710. /***********************************************************************************************
  711.  * Set_Palette -- set a direct draw palette                                                    *
  712.  *                                                                                             *
  713.  *                                                                                             *
  714.  *                                                                                             *
  715.  * INPUT:    ptr to 768 rgb palette bytes                                                      *
  716.  *                                                                                             *
  717.  * OUTPUT:   Nothing                                                                           *
  718.  *                                                                                             *
  719.  * WARNINGS: None                                                                              *
  720.  *                                                                                             *
  721.  * HISTORY:                                                                                    *
  722.  *    10/11/95 3:33PM ST : Created                                                             *
  723.  *=============================================================================================*/
  724. void Set_DD_Palette(void* rpalette)
  725. {
  726.     SDL_Color colors[256];
  727.  
  728.     unsigned char* rcolors = (unsigned char*)rpalette;
  729.     for (int i = 0; i < 256; i++) {
  730.         colors[i].r = (unsigned char)rcolors[* 3] << 2;
  731.         colors[i].g = (unsigned char)rcolors[* 3 + 1] << 2;
  732.         colors[i].b = (unsigned char)rcolors[* 3 + 2] << 2;
  733.        // colors[i].a = 0xFF;
  734.     }
  735.  
  736.     /*
  737.     ** First color is transparent. This needs to be set so that hardware cursor has transparent
  738.     ** surroundings when converting from 8-bit to 32-bit.
  739.     */
  740.     //colors[0].a = 0;
  741.  
  742.     SDL_SetPaletteColors(palette, colors, 0, 256);
  743.  
  744.     //SDL_SetPalette(surface, SDL_LOGPAL, colors, 0, 256); 
  745.        
  746.  
  747.     /*
  748.     ** Cursor needs to be updated when palette changes.
  749.     */
  750.     Update_HWCursor();
  751. }
  752.  
  753. /***********************************************************************************************
  754.  * Wait_Blit -- waits for the DirectDraw blitter to become idle                                *
  755.  *                                                                                             *
  756.  *                                                                                             *
  757.  *                                                                                             *
  758.  * INPUT:    Nothing                                                                           *
  759.  *                                                                                             *
  760.  * OUTPUT:   Nothing                                                                           *
  761.  *                                                                                             *
  762.  * WARNINGS: None                                                                              *
  763.  *                                                                                             *
  764.  * HISTORY:                                                                                    *
  765.  *   07-25-95 03:53pm ST : Created                                                             *
  766.  *=============================================================================================*/
  767.  
  768. void Wait_Blit(void)
  769. {
  770. }
  771.  
  772. /***********************************************************************************************
  773.  * SMC::SurfaceMonitorClass -- constructor for surface monitor class                           *
  774.  *                                                                                             *
  775.  *                                                                                             *
  776.  *                                                                                             *
  777.  * INPUT:    Nothing                                                                           *
  778.  *                                                                                             *
  779.  * OUTPUT:   Nothing                                                                           *
  780.  *                                                                                             *
  781.  * WARNINGS: None                                                                              *
  782.  *                                                                                             *
  783.  * HISTORY:                                                                                    *
  784.  *    11/3/95 3:23PM ST : Created                                                              *
  785.  *=============================================================================================*/
  786.  
  787. SurfaceMonitorClass::SurfaceMonitorClass()
  788. {
  789.     SurfacesRestored = false;
  790. }
  791.  
  792. /*
  793. ** VideoSurfaceDDraw
  794. */
  795. class VideoSurfaceSDL2;
  796. static VideoSurfaceSDL2* frontSurface = nullptr;
  797.  
  798. class VideoSurfaceSDL2 : public VideoSurface
  799. {
  800. public:
  801.     VideoSurfaceSDL2(int w, int h, GBC_Enum flags)
  802.         : flags(flags)
  803.         , windowSurface(nullptr)
  804. #ifdef SDL2                   
  805.         , texture(nullptr)
  806. #endif     
  807.     {
  808.         surface = SDL_CreateRGBSurface(0, w, h, 8, 0, 0, 0, 0);
  809. #ifdef SDL2                   
  810.         SDL_SetSurfacePalette(surface, palette);      
  811. #else          
  812.                  //SDL_SetPalette(surface, SDL_LOGPAL, palette->colors, 0, 256);
  813. #endif
  814.         if (flags & GBC_VISIBLE) {
  815.               
  816. #ifdef SDL2                           
  817.                         windowSurface = SDL_CreateRGBSurfaceWithFormat(0, w, h, SDL_BITSPERPIXEL(pixel_format), pixel_format);
  818.                 texture = SDL_CreateTexture(renderer, windowSurface->format->format, SDL_TEXTUREACCESS_STREAMING, w, h);         
  819. #else
  820.                         windowSurface =SDL_CreateRGBSurfaceWithFormat(0, w, h, 16/*SDL_BITSPERPIXEL(pixel_format)*/, 3 /*pixel_format*/);
  821. #endif             
  822.            frontSurface = this;
  823.         }
  824.  
  825.     }
  826.  
  827.     virtual ~VideoSurfaceSDL2()
  828.     {
  829.         if (frontSurface == this) {
  830.             frontSurface = nullptr;
  831.         }
  832.  
  833.         SDL_FreeSurface(surface);
  834. #ifdef SDL2   
  835.         if (texture) {
  836.             SDL_DestroyTexture(texture);
  837.         }
  838. #endif
  839.         if (windowSurface) {
  840.             SDL_FreeSurface(windowSurface);
  841.         }
  842.     }
  843.  
  844.     virtual void* GetData() const
  845.     {
  846.         return surface->pixels;
  847.     }
  848.     virtual long GetPitch() const
  849.     {
  850.         return surface->pitch;
  851.     }
  852.     virtual bool IsAllocated() const
  853.     {
  854.         return false;
  855.     }
  856.  
  857.     virtual void AddAttachedSurface(VideoSurface* surface)
  858.     {
  859.     }
  860.  
  861.     virtual bool IsReadyToBlit()
  862.     {
  863.         return true;
  864.     }
  865.  
  866.     virtual bool LockWait()
  867.     {
  868.         return (SDL_LockSurface(surface) == 0);
  869.     }
  870.  
  871.     virtual bool Unlock()
  872.     {
  873.         SDL_UnlockSurface(surface);
  874.         return true;
  875.     }
  876.  
  877.     virtual void Blt(const Rect& destRect, VideoSurface* src, const Rect& srcRect, bool mask)
  878.     {
  879.         SDL_BlitSurface(((VideoSurfaceSDL2*)src)->surface, (SDL_Rect*)(&srcRect), surface, (SDL_Rect*)&destRect);
  880.     }
  881.  
  882.     virtual void FillRect(const Rect& rect, unsigned char color)
  883.     {
  884.         SDL_FillRect(surface, (SDL_Rect*)(&rect), color);
  885.     }
  886.  
  887.     void RenderSurface()
  888.     {
  889.         void* pixels;
  890.         int pitch;
  891.  
  892.         SDL_BlitSurface(surface, NULL, windowSurface, NULL);
  893. #ifdef SDL2
  894.         if (Settings.Video.HardwareCursor) {
  895.             /*
  896.             ** Swap cursor before a frame is drawn. This reduces flickering when it's done only once per frame.
  897.             */
  898.             if (hwcursor.Pending) {
  899.                 SDL_SetCursor(hwcursor.Pending);
  900.  
  901.                 if (hwcursor.Current) {
  902.                     SDL_FreeCursor(hwcursor.Current);
  903.                 }
  904.  
  905.                 hwcursor.Current = hwcursor.Pending;
  906.                 hwcursor.Pending = nullptr;
  907.             }
  908.  
  909.             /*
  910.             ** Update hardware cursor visibility.
  911.             */
  912.             SDL_ShowCursor(!Get_Mouse_State());
  913.         } else if (!Get_Mouse_State() && hwcursor.Surface != nullptr) {
  914.             /*
  915.             ** Draw software emulated cursor.
  916.             */
  917.             int x, y;
  918.             SDL_Rect dst;
  919.  
  920.             Get_Video_Mouse(x, y);
  921.  
  922.             dst.x = x - hwcursor.HotX;
  923.             dst.y = y - hwcursor.HotY;
  924.             dst.w = hwcursor.Surface->w;
  925.             dst.h = hwcursor.Surface->h;
  926.  
  927.             SDL_BlitSurface(hwcursor.Surface, nullptr, windowSurface, &dst);
  928.         }
  929.  
  930.         SDL_UpdateTexture(texture, NULL, windowSurface->pixels, windowSurface->pitch);
  931.         SDL_RenderClear(renderer);
  932.         SDL_RenderCopy(renderer, texture, NULL, &render_dst);
  933.         SDL_RenderPresent(renderer);
  934.                
  935. #else          
  936.         SDL_Flip(windowSurface);
  937. #endif         
  938.     }
  939.  
  940. private:
  941.     SDL_Surface* surface;
  942.     SDL_Surface* windowSurface;
  943. #ifdef SDL2   
  944.     SDL_Texture* texture;
  945. #endif 
  946.     GBC_Enum flags;
  947. };
  948.  
  949. void Video_Render_Frame()
  950. {
  951.     if (frontSurface) {
  952.         frontSurface->RenderSurface();
  953.     }
  954. }
  955.  
  956. /*
  957. ** Video
  958. */
  959.  
  960. Video::Video()
  961. {
  962. }
  963.  
  964. Video::~Video()
  965. {
  966. }
  967.  
  968. Video& Video::Shared()
  969. {
  970.     static Video video;
  971.     return video;
  972. }
  973.  
  974. VideoSurface* Video::CreateSurface(int w, int h, GBC_Enum flags)
  975. {
  976.     return new VideoSurfaceSDL2(w, h, flags);
  977. }
  978.  

Editor

You can edit this paste and save as new:


File Description
  • sdl
  • Paste Code
  • 05 Sep-2021
  • 34.28 Kb
You can Share it: