Subversion Repositories Games.Rick Dangerous

Rev

Rev 7 | Blame | Compare with Previous | Last modification | View Log | Download | RSS feed

  1. /*
  2.  * src/sysvid.c
  3.  *
  4.  * Copyright (C) 1998-2002 BigOrno (bigorno@bigorno.net). All rights reserved.
  5.  *
  6.  * The use and distribution terms for this software are contained in the file
  7.  * named README, which can be found in the root of this distribution. By
  8.  * using this software in any fashion, you are agreeing to be bound by the
  9.  * terms of this license.
  10.  *
  11.  * You must not remove this notice, or any other, from this software.
  12.  */
  13.  
  14. #include <stdlib.h> // malloc
  15. #include <string.h> // memset
  16. #include <stdbool.h> // bool
  17.  
  18. #include <SDL2/SDL.h>
  19.  
  20. #include "system.h"
  21. #include "game.h"
  22. #include "img.h"
  23.  
  24. #define SCALE_FACTOR 4
  25.  
  26. U8 sysvid_fb[320 * 200]; // the framebuffer for this game is really 320x200
  27. U8 want_fullscreen = FALSE;// TRUE;
  28. U8 want_filter = TRUE;
  29. U8 recreate_screen = FALSE;
  30.  
  31. static SDL_Window *window;
  32. static SDL_Renderer *renderer;
  33. static SDL_Texture *screen_texture;
  34.  
  35.  
  36. // XBRZ scaler
  37. void xbrz_scale (size_t factor, const uint32_t *src, uint32_t *trg, int srcWidth, int srcHeight, bool has_alpha_channel);
  38. void nearest_neighbor_scale (const uint32_t *src, int srcWidth, int srcHeight, uint32_t *trg, int trgWidth, int trgHeight);
  39.  
  40.  
  41. // Initialise video
  42. void sysvid_init (void)
  43. {
  44.    // SDL init
  45.    if (SDL_Init (SDL_INIT_VIDEO | SDL_INIT_TIMER) < 0)
  46.       sys_panic ("Fatal error: could not initialize SDL.\n");
  47.  
  48.    // create game window
  49.    window = SDL_CreateWindow ("Rick Dangerous",
  50.                               SDL_WINDOWPOS_UNDEFINED, // x
  51.                               SDL_WINDOWPOS_UNDEFINED, // y
  52.                               (want_fullscreen ? 0 : 1024), // let system assign width in fullscreen mode
  53.                               (want_fullscreen ? 0 : 768), // let system assign height in fullscreen mode
  54.                               (want_fullscreen ? SDL_WINDOW_FULLSCREEN_DESKTOP : 0));
  55.    if (window == NULL)
  56.       sys_panic ("Fatal error: SDL can not create game window.\n");
  57.  
  58.    // create renderer
  59.    renderer = SDL_CreateRenderer (window, -1, 0);
  60.    if (renderer == NULL)
  61.       sys_panic ("Fatal error: SDL can not create renderer\n");
  62.  
  63.    // amke the scaled rendering look smoother
  64.    SDL_RenderSetLogicalSize (renderer, 320 * SCALE_FACTOR, 200 * SCALE_FACTOR);
  65.  
  66.    // create a texture that will cover the whole window
  67.    screen_texture = SDL_CreateTexture (renderer, SDL_PIXELFORMAT_ARGB8888, SDL_TEXTUREACCESS_STREAMING, 320 * SCALE_FACTOR, 200 * SCALE_FACTOR);
  68.    if (screen_texture == NULL)
  69.       sys_panic ("Fatal error: SDL can not create rendering surface\n");
  70.  
  71.    // clear the screen to black
  72.    sysvid_clear ();
  73. }
  74.  
  75.  
  76. // Shutdown video
  77. void sysvid_shutdown (void)
  78. {
  79.    // SDL quit
  80.    SDL_Quit ();
  81. }
  82.  
  83.  
  84. // Clear screen
  85. void sysvid_clear (void)
  86. {
  87.    SDL_SetRenderDrawColor (renderer, 0, 0, 0, 255);
  88.    SDL_RenderClear (renderer);
  89.    SDL_RenderPresent (renderer);
  90.  
  91.    memset (sysvid_fb, 0, sizeof (sysvid_fb));
  92. }
  93.  
  94.  
  95. // Update screen
  96. void sysvid_paint (rect_t *rects)
  97. {
  98.    static uint8_t screen_pixels[320 * 200 * 4];
  99.    static uint8_t upscaled_pixels[320 * SCALE_FACTOR * 200 * SCALE_FACTOR * 4];
  100.    static rect_t rect_whole = {0, 0, 320, 200, NULL}; // framebuffer coordinates. The framebuffer is 320x200.
  101.    static U8 palette[16][3] =
  102.    {
  103.       {0x00, 0x00, 0x00},
  104.       {0xd8, 0x00, 0x00},
  105.       {0xb0, 0x6c, 0x68},
  106.       {0xf8, 0x90, 0x68},
  107.       {0x20, 0x24, 0x20},
  108.       {0x00, 0x48, 0xb0},
  109.       {0x00, 0x6c, 0xd8},
  110.       {0x20, 0x48, 0x00},
  111.       {0x48, 0x6c, 0x20},
  112.       {0x48, 0x24, 0x00},
  113.       {0x90, 0x48, 0x00},
  114.       {0xd8, 0x6c, 0x00},
  115.       {0x48, 0x48, 0x48},
  116.       {0x68, 0x6c, 0x68},
  117.       {0x90, 0x90, 0x90},
  118.       {0xb0, 0xb4, 0xb0}
  119.    };
  120.    U16 x, y;
  121.    U8 *p, *q, *p0, *q0;
  122.  
  123.    if (rects == NULL)
  124.       return;
  125.  
  126.    if (recreate_screen)
  127.    {
  128.       recreate_screen = FALSE;
  129.       SDL_SetWindowFullscreen (window, (want_fullscreen ? SDL_WINDOW_FULLSCREEN_DESKTOP : 0));
  130.       sysvid_paint (&rect_whole);
  131.    }
  132.  
  133.    // expand what's in the 320x200x1 frame buffer to the 320x200x4 SDL texture buffer
  134.    while (rects)
  135.    {
  136.       p0 = &sysvid_fb[rects->y * 320 + rects->x];
  137.       q0 = &screen_pixels[(rects->y * 320 + rects->x) * 4];
  138.  
  139.       for (y = rects->y; y < rects->y + rects->height; y++)
  140.       {
  141.          p = p0;
  142.          q = q0;
  143.  
  144.          for (x = rects->x; x < rects->x + rects->width; x++)
  145.          {
  146.             *(q + 0) = palette[*p][2]; // blue
  147.             *(q + 1) = palette[*p][1]; // green
  148.             *(q + 2) = palette[*p][0]; // red
  149.             *(q + 3) = 0; // alpha
  150.  
  151.             q += 4;
  152.             p++;
  153.          }
  154.  
  155.          q0 += 320 * 4;
  156.          p0 += 320;
  157.       }
  158.      
  159.       rects = rects->next;
  160.    }
  161.  
  162.    // now upscale with a little bit of magic
  163.    if (want_filter)
  164.       xbrz_scale (SCALE_FACTOR, (uint32_t *) screen_pixels, (uint32_t *) upscaled_pixels, 320, 200, false);
  165.    else
  166.       nearest_neighbor_scale ((uint32_t *) screen_pixels, 320, 200, (uint32_t *) upscaled_pixels, 320 * SCALE_FACTOR, 200 * SCALE_FACTOR);
  167.  
  168.    SDL_UpdateTexture (screen_texture, NULL, upscaled_pixels, 320 * SCALE_FACTOR * 4);
  169.    SDL_RenderClear (renderer);
  170.    SDL_RenderCopy (renderer, screen_texture, NULL, NULL);
  171.    SDL_RenderPresent (renderer);
  172. }
  173.