Subversion Repositories Games.Descent

Rev

Blame | Last modification | View Log | Download | RSS feed

  1. /*
  2.  * Portions of this file are copyright Rebirth contributors and licensed as
  3.  * described in COPYING.txt.
  4.  * Portions of this file are copyright Parallax Software and licensed
  5.  * according to the Parallax license below.
  6.  * See COPYING.txt for license details.
  7.  
  8. THE COMPUTER CODE CONTAINED HEREIN IS THE SOLE PROPERTY OF PARALLAX
  9. SOFTWARE CORPORATION ("PARALLAX").  PARALLAX, IN DISTRIBUTING THE CODE TO
  10. END-USERS, AND SUBJECT TO ALL OF THE TERMS AND CONDITIONS HEREIN, GRANTS A
  11. ROYALTY-FREE, PERPETUAL LICENSE TO SUCH END-USERS FOR USE BY SUCH END-USERS
  12. IN USING, DISPLAYING,  AND CREATING DERIVATIVE WORKS THEREOF, SO LONG AS
  13. SUCH USE, DISPLAY OR CREATION IS FOR NON-COMMERCIAL, ROYALTY OR REVENUE
  14. FREE PURPOSES.  IN NO EVENT SHALL THE END-USER USE THE COMPUTER CODE
  15. CONTAINED HEREIN FOR REVENUE-BEARING PURPOSES.  THE END-USER UNDERSTANDS
  16. AND AGREES TO THE TERMS HEREIN AND ACCEPTS THE SAME BY USE OF THIS FILE.
  17. COPYRIGHT 1993-1998 PARALLAX SOFTWARE CORPORATION.  ALL RIGHTS RESERVED.
  18. */
  19.  
  20. /*
  21.  *
  22.  * Graphical routines for setting the palette
  23.  *
  24.  */
  25.  
  26. #include <algorithm>
  27. #include <stdlib.h>
  28. #include <stdio.h>
  29. #include <string.h>
  30.  
  31. #include "physfsx.h"
  32. #include "pstypes.h"
  33. #include "u_mem.h"
  34. #include "gr.h"
  35. #include "grdef.h"
  36. #include "dxxerror.h"
  37. #include "maths.h"
  38. #include "palette.h"
  39.  
  40. #include "dxxsconf.h"
  41. #include "dsx-ns.h"
  42. #include "compiler-range_for.h"
  43. #include <array>
  44.  
  45. namespace dcx {
  46.  
  47. #define SQUARE(x) ((x)*(x))
  48.  
  49. #define MAX_COMPUTED_COLORS     32
  50.  
  51. static unsigned Num_computed_colors;
  52.  
  53. struct color_record {
  54.         ubyte   r,g,b;
  55.         color_palette_index color_num;
  56. };
  57.  
  58. static std::array<color_record, MAX_COMPUTED_COLORS> Computed_colors;
  59.  
  60. palette_array_t gr_palette;
  61. palette_array_t gr_current_pal;
  62. gft_array1 gr_fade_table;
  63.  
  64. ubyte gr_palette_gamma = 0;
  65. int gr_palette_gamma_param = 0;
  66.  
  67. void copy_bound_palette(palette_array_t &d, const palette_array_t &s)
  68. {
  69.         auto a = [](rgb_t c) {
  70.                 const ubyte bound = 63;
  71.                 c.r = std::min(c.r, bound);
  72.                 c.g = std::min(c.g, bound);
  73.                 c.b = std::min(c.b, bound);
  74.                 return c;
  75.         };
  76.         std::transform(s.begin(), s.end(), d.begin(), a);
  77. }
  78.  
  79. }
  80.  
  81. namespace dcx {
  82.  
  83. static void diminish_entry(rgb_t &c)
  84. {
  85.         c.r >>= 2;
  86.         c.g >>= 2;
  87.         c.b >>= 2;
  88. }
  89.  
  90. void diminish_palette(palette_array_t &palette)
  91. {
  92.         range_for (rgb_t &c, palette)
  93.                 diminish_entry(c);
  94. }
  95.  
  96. void gr_palette_set_gamma( int gamma )
  97. {
  98.         if ( gamma < 0 ) gamma = 0;
  99.         if ( gamma > 16 ) gamma = 16;      //was 8
  100.  
  101.         if (gr_palette_gamma_param != gamma )   {
  102.                 gr_palette_gamma_param = gamma;
  103.                 gr_palette_gamma = gamma;
  104.                 gr_palette_load( gr_palette );
  105.         }
  106. }
  107.  
  108. int gr_palette_get_gamma()
  109. {
  110.         return gr_palette_gamma_param;
  111. }
  112.  
  113. }
  114.  
  115. namespace dsx {
  116.  
  117. #if defined(DXX_BUILD_DESCENT_I)
  118. void copy_diminish_palette(palette_array_t &palette, const uint8_t *p)
  119. {
  120.         range_for (auto &i, palette)
  121.         {
  122.                 i.r = *p++ >> 2;
  123.                 i.g = *p++ >> 2;
  124.                 i.b = *p++ >> 2;
  125.         }
  126. }
  127. #endif
  128.  
  129. #if defined(DXX_BUILD_DESCENT_II)
  130. void gr_copy_palette(palette_array_t &gr_palette, const palette_array_t &pal)
  131. {
  132.         gr_palette = pal;
  133.  
  134.                 Num_computed_colors = 0;
  135. }
  136. #endif
  137.  
  138. void gr_use_palette_table(const char * filename )
  139. {
  140.         int fsize;
  141.  
  142.         auto fp = PHYSFSX_openReadBuffered(filename);
  143. #if defined(DXX_BUILD_DESCENT_I)
  144. #define FAILURE_FORMAT  "Can't open palette file <%s>"
  145. #elif defined(DXX_BUILD_DESCENT_II)
  146. #define FAILURE_FORMAT  "Can open neither palette file <%s> nor default palette file <" DEFAULT_LEVEL_PALETTE ">"
  147.         // the following is a hack to enable the loading of d2 levels
  148.         // even if only the d2 mac shareware datafiles are present.
  149.         // However, if the pig file is present but the palette file isn't,
  150.         // the textures in the level will look wierd...
  151.         if (!fp)
  152.                 fp = PHYSFSX_openReadBuffered( DEFAULT_LEVEL_PALETTE );
  153. #endif
  154.         if (!fp)
  155.                 Error(FAILURE_FORMAT,
  156.                       filename);
  157.  
  158.         fsize   = PHYSFS_fileLength( fp );
  159.         Assert( fsize == 9472 );
  160.         (void)fsize;
  161.         PHYSFS_read( fp, &gr_palette[0], sizeof(gr_palette[0]), gr_palette.size() );
  162.         PHYSFS_read( fp, gr_fade_table, 256*34, 1 );
  163.         fp.reset();
  164.  
  165.         // This is the TRANSPARENCY COLOR
  166.         range_for (auto &i, gr_fade_table)
  167.                 i[255] = 255;
  168. #if defined(DXX_BUILD_DESCENT_II)
  169.         Num_computed_colors = 0;        //      Flush palette cache.
  170. // swap colors 0 and 255 of the palette along with fade table entries
  171.  
  172. #ifdef SWAP_0_255
  173.         for (i = 0; i < 3; i++) {
  174.                 ubyte c;
  175.                 c = gr_palette[i];
  176.                 gr_palette[i] = gr_palette[765+i];
  177.                 gr_palette[765+i] = c;
  178.         }
  179.  
  180.         for (i = 0; i < GR_FADE_LEVELS * 256; i++) {
  181.                 if (gr_fade_table[i] == 0)
  182.                         gr_fade_table[i] = 255;
  183.         }
  184.         for (i=0; i<GR_FADE_LEVELS; i++)
  185.                 gr_fade_table[i*256] = TRANSPARENCY_COLOR;
  186. #endif
  187. #endif
  188. }
  189.  
  190. }
  191.  
  192. namespace dcx {
  193.  
  194. //      Add a computed color (by gr_find_closest_color) to list of computed colors in Computed_colors.
  195. //      If list wasn't full already, increment Num_computed_colors.
  196. //      If was full, replace a random one.
  197. static void add_computed_color(int r, int g, int b, color_t color_num)
  198. {
  199.         int     add_index;
  200.  
  201.         if (Num_computed_colors < MAX_COMPUTED_COLORS) {
  202.                 add_index = Num_computed_colors;
  203.                 Num_computed_colors++;
  204.         } else
  205.                 add_index = (d_rand() * MAX_COMPUTED_COLORS) >> 15;
  206.  
  207.         Computed_colors[add_index].r = r;
  208.         Computed_colors[add_index].g = g;
  209.         Computed_colors[add_index].b = b;
  210.         Computed_colors[add_index].color_num = color_num;
  211. }
  212.  
  213. void init_computed_colors(void)
  214. {
  215.         range_for (auto &i, Computed_colors)
  216.                 i.r = 255;              //      Make impossible to match.
  217. }
  218.  
  219. color_palette_index gr_find_closest_color(const int r, const int g, const int b)
  220. {
  221.         int j;
  222.         int best_value, value;
  223.  
  224.         if (Num_computed_colors == 0)
  225.                 init_computed_colors();
  226.  
  227.         //      If we've already computed this color, return it!
  228.         for (unsigned i=0; i<Num_computed_colors; i++)
  229.         {
  230.                 auto &c = Computed_colors[i];
  231.                 if (r == c.r && g == c.g && b == c.b)
  232.                 {
  233.                         const auto color_num = c.color_num;
  234.                                         if (i > 4) {
  235.                                                 std::swap(Computed_colors[i-1], c);
  236.                                         }
  237.                                         return color_num;
  238.                                 }
  239.         }
  240.  
  241. //      r &= 63;
  242. //      g &= 63;
  243. //      b &= 63;
  244.  
  245.         best_value = SQUARE(r-gr_palette[0].r)+SQUARE(g-gr_palette[0].g)+SQUARE(b-gr_palette[0].b);
  246.         color_palette_index best_index = 0;
  247.         if (best_value==0) {
  248.                 add_computed_color(r, g, b, best_index);
  249.                 return best_index;
  250.         }
  251.         j=0;
  252.         // only go to 255, 'cause we dont want to check the transparent color.
  253.         for (color_palette_index i{1}; i < 254; ++i)
  254.         {
  255.                 ++j;
  256.                 value = SQUARE(r-gr_palette[j].r)+SQUARE(g-gr_palette[j].g)+SQUARE(b-gr_palette[j].b);
  257.                 if ( value < best_value )       {
  258.                         if (value==0) {
  259.                                 add_computed_color(r, g, b, i);
  260.                                 return i;
  261.                         }
  262.                         best_value = value;
  263.                         best_index = i;
  264.                 }
  265.         }
  266.         add_computed_color(r, g, b, best_index);
  267.         return best_index;
  268. }
  269.  
  270. color_palette_index gr_find_closest_color_15bpp( int rgb )
  271. {
  272.         return gr_find_closest_color( ((rgb>>10)&31)*2, ((rgb>>5)&31)*2, (rgb&31)*2 );
  273. }
  274.  
  275.  
  276. color_palette_index gr_find_closest_color_current( int r, int g, int b )
  277. {
  278.         int j;
  279.         int best_value, value;
  280.  
  281. //      r &= 63;
  282. //      g &= 63;
  283. //      b &= 63;
  284.  
  285.         best_value = SQUARE(r-gr_current_pal[0].r)+SQUARE(g-gr_current_pal[0].g)+SQUARE(b-gr_current_pal[0].b);
  286.         color_t best_index = 0;
  287.         if (best_value==0)
  288.                 return best_index;
  289.  
  290.         j=0;
  291.         // only go to 255, 'cause we dont want to check the transparent color.
  292.         for (color_t i=1; i < 254; i++ )        {
  293.                 ++j;
  294.                 value = SQUARE(r-gr_current_pal[j].r)+SQUARE(g-gr_current_pal[j].g)+SQUARE(b-gr_current_pal[j].b);
  295.                 if ( value < best_value )       {
  296.                         if (value==0)
  297.                                 return i;
  298.                         best_value = value;
  299.                         best_index = i;
  300.                 }
  301.         }
  302.         return best_index;
  303. }
  304.  
  305. }
  306.