Subversion Repositories Kolibri OS

Rev

Blame | Last modification | View Log | RSS feed

  1. /*
  2.  * OpenTyrian: A modern cross-platform port of Tyrian
  3.  * Copyright (C) 2007-2009  The OpenTyrian Development Team
  4.  *
  5.  * This program is free software; you can redistribute it and/or
  6.  * modify it under the terms of the GNU General Public License
  7.  * as published by the Free Software Foundation; either version 2
  8.  * of the License, or (at your option) any later version.
  9.  *
  10.  * This program is distributed in the hope that it will be useful,
  11.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  12.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  13.  * GNU General Public License for more details.
  14.  *
  15.  * You should have received a copy of the GNU General Public License
  16.  * along with this program; if not, write to the Free Software
  17.  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
  18.  */
  19. #include "sprite.h"
  20.  
  21. #include "file.h"
  22. #include "opentyr.h"
  23. #include "video.h"
  24.  
  25. #include <assert.h>
  26. #include <ctype.h>
  27.  
  28. Sprite_array sprite_table[SPRITE_TABLES_MAX];
  29.  
  30. Sprite2_array eShapes[6];
  31. Sprite2_array shapesC1, shapes6, shapes9, shapesW2;
  32.  
  33. void load_sprites_file( unsigned int table, const char *filename )
  34. {
  35.         free_sprites(table);
  36.        
  37.         FILE *f = dir_fopen_die(data_dir(), filename, "rb");
  38.        
  39.         load_sprites(table, f);
  40.        
  41.         fclose(f);
  42. }
  43.  
  44. void load_sprites( unsigned int table, FILE *f )
  45. {
  46.         free_sprites(table);
  47.        
  48.         Uint16 temp;
  49.         efread(&temp, sizeof(Uint16), 1, f);
  50.        
  51.         sprite_table[table].count = temp;
  52.        
  53.         assert(sprite_table[table].count <= SPRITES_PER_TABLE_MAX);
  54.        
  55.         for (unsigned int i = 0; i < sprite_table[table].count; ++i)
  56.         {
  57.                 Sprite * const cur_sprite = sprite(table, i);
  58.                
  59.                 if (!getc(f)) // sprite is empty
  60.                         continue;
  61.                
  62.                 efread(&cur_sprite->width,  sizeof(Uint16), 1, f);
  63.                 efread(&cur_sprite->height, sizeof(Uint16), 1, f);
  64.                 efread(&cur_sprite->size,   sizeof(Uint16), 1, f);
  65.                
  66.                 cur_sprite->data = malloc(cur_sprite->size);
  67.                
  68.                 efread(cur_sprite->data, sizeof(Uint8), cur_sprite->size, f);
  69.         }
  70. }
  71.  
  72. void free_sprites( unsigned int table )
  73. {
  74.         for (unsigned int i = 0; i < sprite_table[table].count; ++i)
  75.         {
  76.                 Sprite * const cur_sprite = sprite(table, i);
  77.                
  78.                 cur_sprite->width  = 0;
  79.                 cur_sprite->height = 0;
  80.                 cur_sprite->size   = 0;
  81.                
  82.                 free(cur_sprite->data);
  83.                 cur_sprite->data = NULL;
  84.         }
  85.        
  86.         sprite_table[table].count = 0;
  87. }
  88.  
  89. // does not clip on left or right edges of surface
  90. void blit_sprite( SDL_Surface *surface, int x, int y, unsigned int table, unsigned int index )
  91. {
  92.         if (index >= sprite_table[table].count || !sprite_exists(table, index))
  93.         {
  94.                 assert(false);
  95.                 return;
  96.         }
  97.        
  98.         const Sprite * const cur_sprite = sprite(table, index);
  99.        
  100.         const Uint8 *data = cur_sprite->data;
  101.         const Uint8 * const data_ul = data + cur_sprite->size;
  102.        
  103.         const unsigned int width = cur_sprite->width;
  104.         unsigned int x_offset = 0;
  105.        
  106.         assert(surface->format->BitsPerPixel == 8);
  107.         Uint8 *             pixels =    (Uint8 *)surface->pixels + (y * surface->pitch) + x;
  108.         const Uint8 * const pixels_ll = (Uint8 *)surface->pixels,  // lower limit
  109.                     * const pixels_ul = (Uint8 *)surface->pixels + (surface->h * surface->pitch);  // upper limit
  110.        
  111.         for (; data < data_ul; ++data)
  112.         {
  113.                 switch (*data)
  114.                 {
  115.                 case 255:  // transparent pixels
  116.                         data++;  // next byte tells how many
  117.                         pixels += *data;
  118.                         x_offset += *data;
  119.                         break;
  120.                        
  121.                 case 254:  // next pixel row
  122.                         pixels += width - x_offset;
  123.                         x_offset = width;
  124.                         break;
  125.                        
  126.                 case 253:  // 1 transparent pixel
  127.                         pixels++;
  128.                         x_offset++;
  129.                         break;
  130.                        
  131.                 default:  // set a pixel
  132.                         if (pixels >= pixels_ul)
  133.                                 return;
  134.                         if (pixels >= pixels_ll)
  135.                                 *pixels = *data;
  136.                        
  137.                         pixels++;
  138.                         x_offset++;
  139.                         break;
  140.                 }
  141.                 if (x_offset >= width)
  142.                 {
  143.                         pixels += surface->pitch - x_offset;
  144.                         x_offset = 0;
  145.                 }
  146.         }
  147. }
  148.  
  149. // does not clip on left or right edges of surface
  150. void blit_sprite_blend( SDL_Surface *surface, int x, int y, unsigned int table, unsigned int index )
  151. {
  152.         if (index >= sprite_table[table].count || !sprite_exists(table, index))
  153.         {
  154.                 assert(false);
  155.                 return;
  156.         }
  157.        
  158.         const Sprite * const cur_sprite = sprite(table, index);
  159.        
  160.         const Uint8 *data = cur_sprite->data;
  161.         const Uint8 * const data_ul = data + cur_sprite->size;
  162.        
  163.         const unsigned int width = cur_sprite->width;
  164.         unsigned int x_offset = 0;
  165.        
  166.         assert(surface->format->BitsPerPixel == 8);
  167.         Uint8 *             pixels =    (Uint8 *)surface->pixels + (y * surface->pitch) + x;
  168.         const Uint8 * const pixels_ll = (Uint8 *)surface->pixels,  // lower limit
  169.                     * const pixels_ul = (Uint8 *)surface->pixels + (surface->h * surface->pitch);  // upper limit
  170.        
  171.         for (; data < data_ul; ++data)
  172.         {
  173.                 switch (*data)
  174.                 {
  175.                 case 255:  // transparent pixels
  176.                         data++;  // next byte tells how many
  177.                         pixels += *data;
  178.                         x_offset += *data;
  179.                         break;
  180.                        
  181.                 case 254:  // next pixel row
  182.                         pixels += width - x_offset;
  183.                         x_offset = width;
  184.                         break;
  185.                        
  186.                 case 253:  // 1 transparent pixel
  187.                         pixels++;
  188.                         x_offset++;
  189.                         break;
  190.                        
  191.                 default:  // set a pixel
  192.                         if (pixels >= pixels_ul)
  193.                                 return;
  194.                         if (pixels >= pixels_ll)
  195.                                 *pixels = (*data & 0xf0) | (((*pixels & 0x0f) + (*data & 0x0f)) / 2);
  196.                        
  197.                         pixels++;
  198.                         x_offset++;
  199.                         break;
  200.                 }
  201.                 if (x_offset >= width)
  202.                 {
  203.                         pixels += surface->pitch - x_offset;
  204.                         x_offset = 0;
  205.                 }
  206.         }
  207. }
  208.  
  209. // does not clip on left or right edges of surface
  210. // unsafe because it doesn't check that value won't overflow into hue
  211. // we can replace it when we know that we don't rely on that 'feature'
  212. void blit_sprite_hv_unsafe( SDL_Surface *surface, int x, int y, unsigned int table, unsigned int index, Uint8 hue, Sint8 value )
  213. {
  214.         if (index >= sprite_table[table].count || !sprite_exists(table, index))
  215.         {
  216.                 assert(false);
  217.                 return;
  218.         }
  219.        
  220.         hue <<= 4;
  221.        
  222.         const Sprite * const cur_sprite = sprite(table, index);
  223.        
  224.         const Uint8 *data = cur_sprite->data;
  225.         const Uint8 * const data_ul = data + cur_sprite->size;
  226.        
  227.         const unsigned int width = cur_sprite->width;
  228.         unsigned int x_offset = 0;
  229.        
  230.         assert(surface->format->BitsPerPixel == 8);
  231.         Uint8 *             pixels =    (Uint8 *)surface->pixels + (y * surface->pitch) + x;
  232.         const Uint8 * const pixels_ll = (Uint8 *)surface->pixels,  // lower limit
  233.                     * const pixels_ul = (Uint8 *)surface->pixels + (surface->h * surface->pitch);  // upper limit
  234.        
  235.         for (; data < data_ul; ++data)
  236.         {
  237.                 switch (*data)
  238.                 {
  239.                 case 255:  // transparent pixels
  240.                         data++;  // next byte tells how many
  241.                         pixels += *data;
  242.                         x_offset += *data;
  243.                         break;
  244.                        
  245.                 case 254:  // next pixel row
  246.                         pixels += width - x_offset;
  247.                         x_offset = width;
  248.                         break;
  249.                        
  250.                 case 253:  // 1 transparent pixel
  251.                         pixels++;
  252.                         x_offset++;
  253.                         break;
  254.                        
  255.                 default:  // set a pixel
  256.                         if (pixels >= pixels_ul)
  257.                                 return;
  258.                         if (pixels >= pixels_ll)
  259.                                 *pixels = hue | ((*data & 0x0f) + value);
  260.                        
  261.                         pixels++;
  262.                         x_offset++;
  263.                         break;
  264.                 }
  265.                 if (x_offset >= width)
  266.                 {
  267.                         pixels += surface->pitch - x_offset;
  268.                         x_offset = 0;
  269.                 }
  270.         }
  271. }
  272.  
  273. // does not clip on left or right edges of surface
  274. void blit_sprite_hv( SDL_Surface *surface, int x, int y, unsigned int table, unsigned int index, Uint8 hue, Sint8 value )
  275. {
  276.         if (index >= sprite_table[table].count || !sprite_exists(table, index))
  277.         {
  278.                 assert(false);
  279.                 return;
  280.         }
  281.        
  282.         hue <<= 4;
  283.        
  284.         const Sprite * const cur_sprite = sprite(table, index);
  285.        
  286.         const Uint8 *data = cur_sprite->data;
  287.         const Uint8 * const data_ul = data + cur_sprite->size;
  288.        
  289.         const unsigned int width = cur_sprite->width;
  290.         unsigned int x_offset = 0;
  291.        
  292.         assert(surface->format->BitsPerPixel == 8);
  293.         Uint8 *             pixels =    (Uint8 *)surface->pixels + (y * surface->pitch) + x;
  294.         const Uint8 * const pixels_ll = (Uint8 *)surface->pixels,  // lower limit
  295.                     * const pixels_ul = (Uint8 *)surface->pixels + (surface->h * surface->pitch);  // upper limit
  296.        
  297.         for (; data < data_ul; ++data)
  298.         {
  299.                 switch (*data)
  300.                 {
  301.                 case 255:  // transparent pixels
  302.                         data++;  // next byte tells how many
  303.                         pixels += *data;
  304.                         x_offset += *data;
  305.                         break;
  306.                        
  307.                 case 254:  // next pixel row
  308.                         pixels += width - x_offset;
  309.                         x_offset = width;
  310.                         break;
  311.                        
  312.                 case 253:  // 1 transparent pixel
  313.                         pixels++;
  314.                         x_offset++;
  315.                         break;
  316.                        
  317.                 default:  // set a pixel
  318.                         if (pixels >= pixels_ul)
  319.                                 return;
  320.                         if (pixels >= pixels_ll)
  321.                         {
  322.                                 Uint8 temp_value = (*data & 0x0f) + value;
  323.                                 if (temp_value > 0xf)
  324.                                         temp_value = (temp_value >= 0x1f) ? 0x0 : 0xf;
  325.                                
  326.                                 *pixels = hue | temp_value;
  327.                         }
  328.                        
  329.                         pixels++;
  330.                         x_offset++;
  331.                         break;
  332.                 }
  333.                 if (x_offset >= width)
  334.                 {
  335.                         pixels += surface->pitch - x_offset;
  336.                         x_offset = 0;
  337.                 }
  338.         }
  339. }
  340.  
  341. // does not clip on left or right edges of surface
  342. void blit_sprite_hv_blend( SDL_Surface *surface, int x, int y, unsigned int table, unsigned int index, Uint8 hue, Sint8 value )
  343. {
  344.         if (index >= sprite_table[table].count || !sprite_exists(table, index))
  345.         {
  346.                 assert(false);
  347.                 return;
  348.         }
  349.        
  350.         hue <<= 4;
  351.        
  352.         const Sprite * const cur_sprite = sprite(table, index);
  353.        
  354.         const Uint8 *data = cur_sprite->data;
  355.         const Uint8 * const data_ul = data + cur_sprite->size;
  356.        
  357.         const unsigned int width = cur_sprite->width;
  358.         unsigned int x_offset = 0;
  359.        
  360.         assert(surface->format->BitsPerPixel == 8);
  361.         Uint8 *             pixels =    (Uint8 *)surface->pixels + (y * surface->pitch) + x;
  362.         const Uint8 * const pixels_ll = (Uint8 *)surface->pixels,  // lower limit
  363.                     * const pixels_ul = (Uint8 *)surface->pixels + (surface->h * surface->pitch);  // upper limit
  364.        
  365.         for (; data < data_ul; ++data)
  366.         {
  367.                 switch (*data)
  368.                 {
  369.                 case 255:  // transparent pixels
  370.                         data++;  // next byte tells how many
  371.                         pixels += *data;
  372.                         x_offset += *data;
  373.                         break;
  374.                        
  375.                 case 254:  // next pixel row
  376.                         pixels += width - x_offset;
  377.                         x_offset = width;
  378.                         break;
  379.                        
  380.                 case 253:  // 1 transparent pixel
  381.                         pixels++;
  382.                         x_offset++;
  383.                         break;
  384.                        
  385.                 default:  // set a pixel
  386.                         if (pixels >= pixels_ul)
  387.                                 return;
  388.                         if (pixels >= pixels_ll)
  389.                         {
  390.                                 Uint8 temp_value = (*data & 0x0f) + value;
  391.                                 if (temp_value > 0xf)
  392.                                         temp_value = (temp_value >= 0x1f) ? 0x0 : 0xf;
  393.                                
  394.                                 *pixels = hue | (((*pixels & 0x0f) + temp_value) / 2);
  395.                         }
  396.                        
  397.                         pixels++;
  398.                         x_offset++;
  399.                         break;
  400.                 }
  401.                 if (x_offset >= width)
  402.                 {
  403.                         pixels += surface->pitch - x_offset;
  404.                         x_offset = 0;
  405.                 }
  406.         }
  407. }
  408.  
  409. // does not clip on left or right edges of surface
  410. void blit_sprite_dark( SDL_Surface *surface, int x, int y, unsigned int table, unsigned int index, bool black )
  411. {
  412.         if (index >= sprite_table[table].count || !sprite_exists(table, index))
  413.         {
  414.                 assert(false);
  415.                 return;
  416.         }
  417.        
  418.         const Sprite * const cur_sprite = sprite(table, index);
  419.        
  420.         const Uint8 *data = cur_sprite->data;
  421.         const Uint8 * const data_ul = data + cur_sprite->size;
  422.        
  423.         const unsigned int width = cur_sprite->width;
  424.         unsigned int x_offset = 0;
  425.        
  426.         assert(surface->format->BitsPerPixel == 8);
  427.         Uint8 *             pixels =    (Uint8 *)surface->pixels + (y * surface->pitch) + x;
  428.         const Uint8 * const pixels_ll = (Uint8 *)surface->pixels,  // lower limit
  429.                     * const pixels_ul = (Uint8 *)surface->pixels + (surface->h * surface->pitch);  // upper limit
  430.        
  431.         for (; data < data_ul; ++data)
  432.         {
  433.                 switch (*data)
  434.                 {
  435.                 case 255:  // transparent pixels
  436.                         data++;  // next byte tells how many
  437.                         pixels += *data;
  438.                         x_offset += *data;
  439.                         break;
  440.                        
  441.                 case 254:  // next pixel row
  442.                         pixels += width - x_offset;
  443.                         x_offset = width;
  444.                         break;
  445.                        
  446.                 case 253:  // 1 transparent pixel
  447.                         pixels++;
  448.                         x_offset++;
  449.                         break;
  450.                        
  451.                 default:  // set a pixel
  452.                         if (pixels >= pixels_ul)
  453.                                 return;
  454.                         if (pixels >= pixels_ll)
  455.                                 *pixels = black ? 0x00 : ((*pixels & 0xf0) | ((*pixels & 0x0f) / 2));
  456.                        
  457.                         pixels++;
  458.                         x_offset++;
  459.                         break;
  460.                 }
  461.                 if (x_offset >= width)
  462.                 {
  463.                         pixels += surface->pitch - x_offset;
  464.                         x_offset = 0;
  465.                 }
  466.         }
  467. }
  468.  
  469.  
  470. void JE_loadCompShapes( Sprite2_array *sprite2s, char s )
  471. {
  472.         char buffer[20];
  473.         snprintf(buffer, sizeof(buffer), "newsh%c.shp", tolower((unsigned char)s));
  474.        
  475.         FILE *f = dir_fopen_die(data_dir(), buffer, "rb");
  476.        
  477.         sprite2s->size = ftell_eof(f);
  478.        
  479.         JE_loadCompShapesB(sprite2s, f);
  480.        
  481.         fclose(f);
  482. }
  483.  
  484. void JE_loadCompShapesB( Sprite2_array *sprite2s, FILE *f )
  485. {
  486.         free_sprite2s(sprite2s);
  487.        
  488.         sprite2s->data = malloc(sizeof(Uint8) * sprite2s->size);
  489.         efread(sprite2s->data, sizeof(Uint8), sprite2s->size, f);
  490. }
  491.  
  492. void free_sprite2s( Sprite2_array *sprite2s )
  493. {
  494.         free(sprite2s->data);
  495.         sprite2s->data = NULL;
  496. }
  497.  
  498. // does not clip on left or right edges of surface
  499. void blit_sprite2( SDL_Surface *surface, int x, int y, Sprite2_array sprite2s, unsigned int index )
  500. {
  501.         assert(surface->format->BitsPerPixel == 8);
  502.         Uint8 *             pixels =    (Uint8 *)surface->pixels + (y * surface->pitch) + x;
  503.         const Uint8 * const pixels_ll = (Uint8 *)surface->pixels,  // lower limit
  504.                     * const pixels_ul = (Uint8 *)surface->pixels + (surface->h * surface->pitch);  // upper limit
  505.        
  506.         const Uint8 *data = sprite2s.data + SDL_SwapLE16(((Uint16 *)sprite2s.data)[index - 1]);
  507.        
  508.         for (; *data != 0x0f; ++data)
  509.         {
  510.                 pixels += *data & 0x0f;                   // second nibble: transparent pixel count
  511.                 unsigned int count = (*data & 0xf0) >> 4; // first nibble: opaque pixel count
  512.                
  513.                 if (count == 0) // move to next pixel row
  514.                 {
  515.                         pixels += VGAScreen->pitch - 12;
  516.                 }
  517.                 else
  518.                 {
  519.                         while (count--)
  520.                         {
  521.                                 ++data;
  522.                                
  523.                                 if (pixels >= pixels_ul)
  524.                                         return;
  525.                                 if (pixels >= pixels_ll)
  526.                                         *pixels = *data;
  527.                                
  528.                                 ++pixels;
  529.                         }
  530.                 }
  531.         }
  532. }
  533.  
  534. // does not clip on left or right edges of surface
  535. void blit_sprite2_blend( SDL_Surface *surface,  int x, int y, Sprite2_array sprite2s, unsigned int index )
  536. {
  537.         assert(surface->format->BitsPerPixel == 8);
  538.         Uint8 *             pixels =    (Uint8 *)surface->pixels + (y * surface->pitch) + x;
  539.         const Uint8 * const pixels_ll = (Uint8 *)surface->pixels,  // lower limit
  540.                     * const pixels_ul = (Uint8 *)surface->pixels + (surface->h * surface->pitch);  // upper limit
  541.        
  542.         const Uint8 *data = sprite2s.data + SDL_SwapLE16(((Uint16 *)sprite2s.data)[index - 1]);
  543.        
  544.         for (; *data != 0x0f; ++data)
  545.         {
  546.                 pixels += *data & 0x0f;                   // second nibble: transparent pixel count
  547.                 unsigned int count = (*data & 0xf0) >> 4; // first nibble: opaque pixel count
  548.                
  549.                 if (count == 0) // move to next pixel row
  550.                 {
  551.                         pixels += VGAScreen->pitch - 12;
  552.                 }
  553.                 else
  554.                 {
  555.                         while (count--)
  556.                         {
  557.                                 ++data;
  558.                                
  559.                                 if (pixels >= pixels_ul)
  560.                                         return;
  561.                                 if (pixels >= pixels_ll)
  562.                                         *pixels = (((*data & 0x0f) + (*pixels & 0x0f)) / 2) | (*data & 0xf0);
  563.                                
  564.                                 ++pixels;
  565.                         }
  566.                 }
  567.         }
  568. }
  569.  
  570. // does not clip on left or right edges of surface
  571. void blit_sprite2_darken( SDL_Surface *surface, int x, int y, Sprite2_array sprite2s, unsigned int index )
  572. {
  573.         assert(surface->format->BitsPerPixel == 8);
  574.         Uint8 *             pixels =    (Uint8 *)surface->pixels + (y * surface->pitch) + x;
  575.         const Uint8 * const pixels_ll = (Uint8 *)surface->pixels,  // lower limit
  576.                     * const pixels_ul = (Uint8 *)surface->pixels + (surface->h * surface->pitch);  // upper limit
  577.        
  578.         const Uint8 *data = sprite2s.data + SDL_SwapLE16(((Uint16 *)sprite2s.data)[index - 1]);
  579.        
  580.         for (; *data != 0x0f; ++data)
  581.         {
  582.                 pixels += *data & 0x0f;                   // second nibble: transparent pixel count
  583.                 unsigned int count = (*data & 0xf0) >> 4; // first nibble: opaque pixel count
  584.                
  585.                 if (count == 0) // move to next pixel row
  586.                 {
  587.                         pixels += VGAScreen->pitch - 12;
  588.                 }
  589.                 else
  590.                 {
  591.                         while (count--)
  592.                         {
  593.                                 ++data;
  594.                                
  595.                                 if (pixels >= pixels_ul)
  596.                                         return;
  597.                                 if (pixels >= pixels_ll)
  598.                                         *pixels = ((*pixels & 0x0f) / 2) + (*pixels & 0xf0);
  599.                                
  600.                                 ++pixels;
  601.                         }
  602.                 }
  603.         }
  604. }
  605.  
  606. // does not clip on left or right edges of surface
  607. void blit_sprite2_filter( SDL_Surface *surface, int x, int y, Sprite2_array sprite2s, unsigned int index, Uint8 filter )
  608. {
  609.         assert(surface->format->BitsPerPixel == 8);
  610.         Uint8 *             pixels =    (Uint8 *)surface->pixels + (y * surface->pitch) + x;
  611.         const Uint8 * const pixels_ll = (Uint8 *)surface->pixels,  // lower limit
  612.                     * const pixels_ul = (Uint8 *)surface->pixels + (surface->h * surface->pitch);  // upper limit
  613.        
  614.         const Uint8 *data = sprite2s.data + SDL_SwapLE16(((Uint16 *)sprite2s.data)[index - 1]);
  615.        
  616.         for (; *data != 0x0f; ++data)
  617.         {
  618.                 pixels += *data & 0x0f;                   // second nibble: transparent pixel count
  619.                 unsigned int count = (*data & 0xf0) >> 4; // first nibble: opaque pixel count
  620.                
  621.                 if (count == 0) // move to next pixel row
  622.                 {
  623.                         pixels += VGAScreen->pitch - 12;
  624.                 }
  625.                 else
  626.                 {
  627.                         while (count--)
  628.                         {
  629.                                 ++data;
  630.                                
  631.                                 if (pixels >= pixels_ul)
  632.                                         return;
  633.                                 if (pixels >= pixels_ll)
  634.                                         *pixels = filter | (*data & 0x0f);
  635.                                
  636.                                 ++pixels;
  637.                         }
  638.                 }
  639.         }
  640. }
  641.  
  642. // does not clip on left or right edges of surface
  643. void blit_sprite2x2( SDL_Surface *surface, int x, int y, Sprite2_array sprite2s, unsigned int index )
  644. {
  645.         blit_sprite2(surface, x,      y,      sprite2s, index);
  646.         blit_sprite2(surface, x + 12, y,      sprite2s, index + 1);
  647.         blit_sprite2(surface, x,      y + 14, sprite2s, index + 19);
  648.         blit_sprite2(surface, x + 12, y + 14, sprite2s, index + 20);
  649. }
  650.  
  651. // does not clip on left or right edges of surface
  652. void blit_sprite2x2_blend( SDL_Surface *surface, int x, int y, Sprite2_array sprite2s, unsigned int index )
  653. {
  654.         blit_sprite2_blend(surface, x,      y,      sprite2s, index);
  655.         blit_sprite2_blend(surface, x + 12, y,      sprite2s, index + 1);
  656.         blit_sprite2_blend(surface, x,      y + 14, sprite2s, index + 19);
  657.         blit_sprite2_blend(surface, x + 12, y + 14, sprite2s, index + 20);
  658. }
  659.  
  660. // does not clip on left or right edges of surface
  661. void blit_sprite2x2_darken( SDL_Surface *surface, int x, int y, Sprite2_array sprite2s, unsigned int index )
  662. {
  663.         blit_sprite2_darken(surface, x,      y,      sprite2s, index);
  664.         blit_sprite2_darken(surface, x + 12, y,      sprite2s, index + 1);
  665.         blit_sprite2_darken(surface, x,      y + 14, sprite2s, index + 19);
  666.         blit_sprite2_darken(surface, x + 12, y + 14, sprite2s, index + 20);
  667. }
  668.  
  669.  
  670. void JE_loadMainShapeTables( const char *shpfile )
  671. {
  672.         enum { SHP_NUM = 12 };
  673.        
  674.         FILE *f = dir_fopen_die(data_dir(), shpfile, "rb");
  675.        
  676.         JE_word shpNumb;
  677.         JE_longint shpPos[SHP_NUM + 1]; // +1 for storing file length
  678.        
  679.         efread(&shpNumb, sizeof(JE_word), 1, f);
  680.         assert(shpNumb + 1u == COUNTOF(shpPos));
  681.        
  682.         for (unsigned int i = 0; i < shpNumb; ++i)
  683.                 efread(&shpPos[i], sizeof(JE_longint), 1, f);
  684.        
  685.         fseek(f, 0, SEEK_END);
  686.         for (unsigned int i = shpNumb; i < COUNTOF(shpPos); ++i)
  687.                 shpPos[i] = ftell(f);
  688.        
  689.         int i;
  690.         // fonts, interface, option sprites
  691.         for (i = 0; i < 7; i++)
  692.         {
  693.                 fseek(f, shpPos[i], SEEK_SET);
  694.                 load_sprites(i, f);
  695.         }
  696.        
  697.         // player shot sprites
  698.         shapesC1.size = shpPos[i + 1] - shpPos[i];
  699.         JE_loadCompShapesB(&shapesC1, f);
  700.         i++;
  701.        
  702.         // player ship sprites
  703.         shapes9.size = shpPos[i + 1] - shpPos[i];
  704.         JE_loadCompShapesB(&shapes9 , f);
  705.         i++;
  706.        
  707.         // power-up sprites
  708.         eShapes[5].size = shpPos[i + 1] - shpPos[i];
  709.         JE_loadCompShapesB(&eShapes[5], f);
  710.         i++;
  711.        
  712.         // coins, datacubes, etc sprites
  713.         eShapes[4].size = shpPos[i + 1] - shpPos[i];
  714.         JE_loadCompShapesB(&eShapes[4], f);
  715.         i++;
  716.        
  717.         // more player shot sprites
  718.         shapesW2.size = shpPos[i + 1] - shpPos[i];
  719.         JE_loadCompShapesB(&shapesW2, f);
  720.        
  721.         fclose(f);
  722. }
  723.  
  724. void free_main_shape_tables( void )
  725. {
  726.         for (uint i = 0; i < COUNTOF(sprite_table); ++i)
  727.                 free_sprites(i);
  728.        
  729.         free_sprite2s(&shapesC1);
  730.         free_sprite2s(&shapes9);
  731.         free_sprite2s(&eShapes[5]);
  732.         free_sprite2s(&eShapes[4]);
  733.         free_sprite2s(&shapesW2);
  734. }
  735.