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 "backgrnd.h"
  20.  
  21. #include "config.h"
  22. #include "mtrand.h"
  23. #include "opentyr.h"
  24. #include "varz.h"
  25. #include "video.h"
  26.  
  27. #include <assert.h>
  28.  
  29. /*Special Background 2 and Background 3*/
  30.  
  31. /*Back Pos 3*/
  32. JE_word backPos, backPos2, backPos3;
  33. JE_word backMove, backMove2, backMove3;
  34.  
  35. /*Main Maps*/
  36. JE_word mapX, mapY, mapX2, mapX3, mapY2, mapY3;
  37. JE_byte **mapYPos, **mapY2Pos, **mapY3Pos;
  38. JE_word mapXPos, oldMapXOfs, mapXOfs, mapX2Ofs, mapX2Pos, mapX3Pos, oldMapX3Ofs, mapX3Ofs, tempMapXOfs;
  39. intptr_t mapXbpPos, mapX2bpPos, mapX3bpPos;
  40. JE_byte map1YDelay, map1YDelayMax, map2YDelay, map2YDelayMax;
  41.  
  42.  
  43. JE_boolean  anySmoothies;
  44. JE_byte     smoothie_data[9]; /* [1..9] */
  45.  
  46. void JE_darkenBackground( JE_word neat )  /* wild detail level */
  47. {
  48.         Uint8 *s = VGAScreen->pixels; /* screen pointer, 8-bit specific */
  49.         int x, y;
  50.        
  51.         s += 24;
  52.        
  53.         for (y = 184; y; y--)
  54.         {
  55.                 for (x = 264; x; x--)
  56.                 {
  57.                         *s = ((((*s & 0x0f) << 4) - (*s & 0x0f) + ((((x - neat - y) >> 2) + *(s-2) + (y == 184 ? 0 : *(s-(VGAScreen->pitch-1)))) & 0x0f)) >> 4) | (*s & 0xf0);
  58.                         s++;
  59.                 }
  60.                 s += VGAScreen->pitch - 264;
  61.         }
  62. }
  63.  
  64. void blit_background_row( SDL_Surface *surface, int x, int y, Uint8 **map )
  65. {
  66.         assert(surface->format->BitsPerPixel == 8);
  67.        
  68.         Uint8 *pixels = (Uint8 *)surface->pixels + (y * surface->pitch) + x,
  69.               *pixels_ll = (Uint8 *)surface->pixels,  // lower limit
  70.               *pixels_ul = (Uint8 *)surface->pixels + (surface->h * surface->pitch);  // upper limit
  71.        
  72.         for (int y = 0; y < 28; y++)
  73.         {
  74.                 // not drawing on screen yet; skip y
  75.                 if ((pixels + (12 * 24)) < pixels_ll)
  76.                 {
  77.                         pixels += surface->pitch;
  78.                         continue;
  79.                 }
  80.                
  81.                 for (int tile = 0; tile < 12; tile++)
  82.                 {
  83.                         Uint8 *data = *(map + tile);
  84.                        
  85.                         // no tile; skip tile
  86.                         if (data == NULL)
  87.                         {
  88.                                 pixels += 24;
  89.                                 continue;
  90.                         }
  91.                        
  92.                         data += y * 24;
  93.                        
  94.                         for (int x = 24; x; x--)
  95.                         {
  96.                                 if (pixels >= pixels_ul)
  97.                                         return;
  98.                                 if (pixels >= pixels_ll && *data != 0)
  99.                                         *pixels = *data;
  100.                                
  101.                                 pixels++;
  102.                                 data++;
  103.                         }
  104.                 }
  105.                
  106.                 pixels += surface->pitch - 12 * 24;
  107.         }
  108. }
  109.  
  110. void blit_background_row_blend( SDL_Surface *surface, int x, int y, Uint8 **map )
  111. {
  112.         assert(surface->format->BitsPerPixel == 8);
  113.        
  114.         Uint8 *pixels = (Uint8 *)surface->pixels + (y * surface->pitch) + x,
  115.               *pixels_ll = (Uint8 *)surface->pixels,  // lower limit
  116.               *pixels_ul = (Uint8 *)surface->pixels + (surface->h * surface->pitch);  // upper limit
  117.        
  118.         for (int y = 0; y < 28; y++)
  119.         {
  120.                 // not drawing on screen yet; skip y
  121.                 if ((pixels + (12 * 24)) < pixels_ll)
  122.                 {
  123.                         pixels += surface->pitch;
  124.                         continue;
  125.                 }
  126.                
  127.                 for (int tile = 0; tile < 12; tile++)
  128.                 {
  129.                         Uint8 *data = *(map + tile);
  130.                        
  131.                         // no tile; skip tile
  132.                         if (data == NULL)
  133.                         {
  134.                                 pixels += 24;
  135.                                 continue;
  136.                         }
  137.                        
  138.                         data += y * 24;
  139.                        
  140.                         for (int x = 24; x; x--)
  141.                         {
  142.                                 if (pixels >= pixels_ul)
  143.                                         return;
  144.                                 if (pixels >= pixels_ll && *data != 0)
  145.                                         *pixels = (*data & 0xf0) | (((*pixels & 0x0f) + (*data & 0x0f)) / 2);
  146.                                
  147.                                 pixels++;
  148.                                 data++;
  149.                         }
  150.                 }
  151.                
  152.                 pixels += surface->pitch - 12 * 24;
  153.         }
  154. }
  155.  
  156. void draw_background_1( SDL_Surface *surface )
  157. {
  158.         SDL_FillRect(surface, NULL, 0);
  159.        
  160.         Uint8 **map = (Uint8 **)mapYPos + mapXbpPos - 12;
  161.        
  162.         for (int i = -1; i < 7; i++)
  163.         {
  164.                 blit_background_row(surface, mapXPos, (i * 28) + backPos, map);
  165.                
  166.                 map += 14;
  167.         }
  168. }
  169.  
  170. void draw_background_2( SDL_Surface *surface )
  171. {
  172.         if (map2YDelayMax > 1 && backMove2 < 2)
  173.                 backMove2 = (map2YDelay == 1) ? 1 : 0;
  174.        
  175.         if (background2 != 0)
  176.         {
  177.                 // water effect combines background 1 and 2 by syncronizing the x coordinate
  178.                 int x = smoothies[1] ? mapXPos : mapX2Pos;
  179.                
  180.                 Uint8 **map = (Uint8 **)mapY2Pos + (smoothies[1] ? mapXbpPos : mapX2bpPos) - 12;
  181.                
  182.                 for (int i = -1; i < 7; i++)
  183.                 {
  184.                         blit_background_row(surface, x, (i * 28) + backPos2, map);
  185.                        
  186.                         map += 14;
  187.                 }
  188.         }
  189.        
  190.         /*Set Movement of background*/
  191.         if (--map2YDelay == 0)
  192.         {
  193.                 map2YDelay = map2YDelayMax;
  194.                
  195.                 backPos2 += backMove2;
  196.                
  197.                 if (backPos2 >  27)
  198.                 {
  199.                         backPos2 -= 28;
  200.                         mapY2--;
  201.                         mapY2Pos -= 14;  /*Map Width*/
  202.                 }
  203.         }
  204. }
  205.  
  206. void draw_background_2_blend( SDL_Surface *surface )
  207. {
  208.         if (map2YDelayMax > 1 && backMove2 < 2)
  209.                 backMove2 = (map2YDelay == 1) ? 1 : 0;
  210.        
  211.         Uint8 **map = (Uint8 **)mapY2Pos + mapX2bpPos - 12;
  212.        
  213.         for (int i = -1; i < 7; i++)
  214.         {
  215.                 blit_background_row_blend(surface, mapX2Pos, (i * 28) + backPos2, map);
  216.                
  217.                 map += 14;
  218.         }
  219.        
  220.         /*Set Movement of background*/
  221.         if (--map2YDelay == 0)
  222.         {
  223.                 map2YDelay = map2YDelayMax;
  224.                
  225.                 backPos2 += backMove2;
  226.                
  227.                 if (backPos2 >  27)
  228.                 {
  229.                         backPos2 -= 28;
  230.                         mapY2--;
  231.                         mapY2Pos -= 14;  /*Map Width*/
  232.                 }
  233.         }
  234. }
  235.  
  236. void draw_background_3( SDL_Surface *surface )
  237. {
  238.         /* Movement of background */
  239.         backPos3 += backMove3;
  240.        
  241.         if (backPos3 > 27)
  242.         {
  243.                 backPos3 -= 28;
  244.                 mapY3--;
  245.                 mapY3Pos -= 15;   /*Map Width*/
  246.         }
  247.        
  248.         Uint8 **map = (Uint8 **)mapY3Pos + mapX3bpPos - 12;
  249.        
  250.         for (int i = -1; i < 7; i++)
  251.         {
  252.                 blit_background_row(surface, mapX3Pos, (i * 28) + backPos3, map);
  253.                
  254.                 map += 15;
  255.         }
  256. }
  257.  
  258. void JE_filterScreen( JE_shortint col, JE_shortint int_)
  259. {
  260.         Uint8 *s = NULL; /* screen pointer, 8-bit specific */
  261.         int x, y;
  262.         unsigned int temp;
  263.        
  264.         if (filterFade)
  265.         {
  266.                 levelBrightness += levelBrightnessChg;
  267.                 if ((filterFadeStart && levelBrightness < -14) || levelBrightness > 14)
  268.                 {
  269.                         levelBrightnessChg = -levelBrightnessChg;
  270.                         filterFadeStart = false;
  271.                         levelFilter = levelFilterNew;
  272.                 }
  273.                 if (!filterFadeStart && levelBrightness == 0)
  274.                 {
  275.                         filterFade = false;
  276.                         levelBrightness = -99;
  277.                 }
  278.         }
  279.        
  280.         if (col != -99 && filtrationAvail)
  281.         {
  282.                 s = VGAScreen->pixels;
  283.                 s += 24;
  284.                
  285.                 col <<= 4;
  286.                
  287.                 for (y = 184; y; y--)
  288.                 {
  289.                         for (x = 264; x; x--)
  290.                         {
  291.                                 *s = col | (*s & 0x0f);
  292.                                 s++;
  293.                         }
  294.                         s += VGAScreen->pitch - 264;
  295.                 }
  296.         }
  297.        
  298.         if (int_ != -99 && explosionTransparent)
  299.         {
  300.                 s = VGAScreen->pixels;
  301.                 s += 24;
  302.                
  303.                 for (y = 184; y; y--)
  304.                 {
  305.                         for (x = 264; x; x--)
  306.                         {
  307.                                 temp = (*s & 0x0f) + int_;
  308.                                 *s = (*s & 0xf0) | (temp >= 0x1f ? 0 : (temp >= 0x0f ? 0x0f : temp));
  309.                                 s++;
  310.                         }
  311.                         s += VGAScreen->pitch - 264;
  312.                 }
  313.         }
  314. }
  315.  
  316. void JE_checkSmoothies( void )
  317. {
  318.         anySmoothies = (processorType > 2 && (smoothies[1-1] || smoothies[2-1])) || (processorType > 1 && (smoothies[3-1] || smoothies[4-1] || smoothies[5-1]));
  319. }
  320.  
  321. void lava_filter( SDL_Surface *dst, SDL_Surface *src )
  322. {
  323.         assert(src->format->BitsPerPixel == 8 && dst->format->BitsPerPixel == 8);
  324.        
  325.         /* we don't need to check for over-reading the pixel surfaces since we only
  326.          * read from the top 185+1 scanlines, and there should be 320 */
  327.        
  328.         const int dst_pitch = dst->pitch;
  329.         Uint8 *dst_pixel = (Uint8 *)dst->pixels + (185 * dst_pitch);
  330.         const Uint8 * const dst_pixel_ll = (Uint8 *)dst->pixels;  // lower limit
  331.        
  332.         const int src_pitch = src->pitch;
  333.         const Uint8 *src_pixel = (Uint8 *)src->pixels + (185 * src->pitch);
  334.         const Uint8 * const src_pixel_ll = (Uint8 *)src->pixels;  // lower limit
  335.        
  336.         int w = 320 * 185 - 1;
  337.        
  338.         for (int y = 185 - 1; y >= 0; --y)
  339.         {
  340.                 dst_pixel -= (dst_pitch - 320);  // in case pitch is not 320
  341.                 src_pixel -= (src_pitch - 320);  // in case pitch is not 320
  342.                
  343.                 for (int x = 320 - 1; x >= 0; x -= 8)
  344.                 {
  345.                         int waver = abs(((w >> 9) & 0x0f) - 8) - 1;
  346.                         w -= 8;
  347.                        
  348.                         for (int xi = 8 - 1; xi >= 0; --xi)
  349.                         {
  350.                                 --dst_pixel;
  351.                                 --src_pixel;
  352.                                
  353.                                 // value is average value of source pixel (2x), destination pixel above, and destination pixel below (all with waver)
  354.                                 // hue is red
  355.                                 Uint8 value = 0;
  356.                                
  357.                                 if (src_pixel + waver >= src_pixel_ll)
  358.                                         value += (*(src_pixel + waver) & 0x0f) * 2;
  359.                                 value += *(dst_pixel + waver + dst_pitch) & 0x0f;
  360.                                 if (dst_pixel + waver - dst_pitch >= dst_pixel_ll)
  361.                                         value += *(dst_pixel + waver - dst_pitch) & 0x0f;
  362.                                
  363.                                 *dst_pixel = (value / 4) | 0x70;
  364.                         }
  365.                 }
  366.         }
  367. }
  368.  
  369. void water_filter( SDL_Surface *dst, SDL_Surface *src )
  370. {
  371.         assert(src->format->BitsPerPixel == 8 && dst->format->BitsPerPixel == 8);
  372.        
  373.         Uint8 hue = smoothie_data[1] << 4;
  374.        
  375.         /* we don't need to check for over-reading the pixel surfaces since we only
  376.          * read from the top 185+1 scanlines, and there should be 320 */
  377.        
  378.         const int dst_pitch = dst->pitch;
  379.         Uint8 *dst_pixel = (Uint8 *)dst->pixels + (185 * dst_pitch);
  380.        
  381.         const Uint8 *src_pixel = (Uint8 *)src->pixels + (185 * src->pitch);
  382.        
  383.         int w = 320 * 185 - 1;
  384.        
  385.         for (int y = 185 - 1; y >= 0; --y)
  386.         {
  387.                 dst_pixel -= (dst_pitch - 320);  // in case pitch is not 320
  388.                 src_pixel -= (src->pitch - 320);  // in case pitch is not 320
  389.                
  390.                 for (int x = 320 - 1; x >= 0; x -= 8)
  391.                 {
  392.                         int waver = abs(((w >> 10) & 0x07) - 4) - 1;
  393.                         w -= 8;
  394.                        
  395.                         for (int xi = 8 - 1; xi >= 0; --xi)
  396.                         {
  397.                                 --dst_pixel;
  398.                                 --src_pixel;
  399.                                
  400.                                 // pixel is copied from source if not blue
  401.                                 // otherwise, value is average of value of source pixel and destination pixel below (with waver)
  402.                                 if ((*src_pixel & 0x30) == 0)
  403.                                 {
  404.                                         *dst_pixel = *src_pixel;
  405.                                 }
  406.                                 else
  407.                                 {
  408.                                         Uint8 value = *src_pixel & 0x0f;
  409.                                         value += *(dst_pixel + waver + dst_pitch) & 0x0f;
  410.                                         *dst_pixel = (value / 2) | hue;
  411.                                 }
  412.                         }
  413.                 }
  414.         }
  415. }
  416.  
  417. void iced_blur_filter( SDL_Surface *dst, SDL_Surface *src )
  418. {
  419.         assert(src->format->BitsPerPixel == 8 && dst->format->BitsPerPixel == 8);
  420.        
  421.         Uint8 *dst_pixel = dst->pixels;
  422.         const Uint8 *src_pixel = src->pixels;
  423.        
  424.         for (int y = 0; y < 184; ++y)
  425.         {
  426.                 for (int x = 0; x < 320; ++x)
  427.                 {
  428.                         // value is average value of source pixel and destination pixel
  429.                         // hue is icy blue
  430.                        
  431.                         const Uint8 value = (*src_pixel & 0x0f) + (*dst_pixel & 0x0f);
  432.                         *dst_pixel = (value / 2) | 0x80;
  433.                        
  434.                         ++dst_pixel;
  435.                         ++src_pixel;
  436.                 }
  437.                
  438.                 dst_pixel += (dst->pitch - 320);  // in case pitch is not 320
  439.                 src_pixel += (src->pitch - 320);  // in case pitch is not 320
  440.         }
  441. }
  442.  
  443. void blur_filter( SDL_Surface *dst, SDL_Surface *src )
  444. {
  445.         assert(src->format->BitsPerPixel == 8 && dst->format->BitsPerPixel == 8);
  446.        
  447.         Uint8 *dst_pixel = dst->pixels;
  448.         const Uint8 *src_pixel = src->pixels;
  449.        
  450.         for (int y = 0; y < 184; ++y)
  451.         {
  452.                 for (int x = 0; x < 320; ++x)
  453.                 {
  454.                         // value is average value of source pixel and destination pixel
  455.                         // hue is source pixel hue
  456.                        
  457.                         const Uint8 value = (*src_pixel & 0x0f) + (*dst_pixel & 0x0f);
  458.                         *dst_pixel = (value / 2) | (*src_pixel & 0xf0);
  459.                        
  460.                         ++dst_pixel;
  461.                         ++src_pixel;
  462.                 }
  463.                
  464.                 dst_pixel += (dst->pitch - 320);  // in case pitch is not 320
  465.                 src_pixel += (src->pitch - 320);  // in case pitch is not 320
  466.         }
  467. }
  468.  
  469.  
  470. /* Background Starfield */
  471. typedef struct
  472. {
  473.         Uint8 color;
  474.         JE_word position; // relies on overflow wrap-around
  475.         int speed;
  476. } StarfieldStar;
  477.  
  478. #define MAX_STARS 100
  479. #define STARFIELD_HUE 0x90
  480. static StarfieldStar starfield_stars[MAX_STARS];
  481. int starfield_speed;
  482.  
  483. void initialize_starfield( void )
  484. {
  485.         for (int i = MAX_STARS-1; i >= 0; --i)
  486.         {
  487.                 starfield_stars[i].position = mt_rand() % 320 + mt_rand() % 200 * VGAScreen->pitch;
  488.                 starfield_stars[i].speed = mt_rand() % 3 + 2;
  489.                 starfield_stars[i].color = mt_rand() % 16 + STARFIELD_HUE;
  490.         }
  491. }
  492.  
  493. void update_and_draw_starfield( SDL_Surface* surface, int move_speed )
  494. {
  495.         Uint8* p = (Uint8*)surface->pixels;
  496.  
  497.         for (int i = MAX_STARS-1; i >= 0; --i)
  498.         {
  499.                 StarfieldStar* star = &starfield_stars[i];
  500.  
  501.                 star->position += (star->speed + move_speed) * surface->pitch;
  502.  
  503.                 if (star->position < 177 * surface->pitch)
  504.                 {
  505.                         if (p[star->position] == 0)
  506.                         {
  507.                                 p[star->position] = star->color;
  508.                         }
  509.  
  510.                         // If star is bright enough, draw surrounding pixels
  511.                         if (star->color - 4 >= STARFIELD_HUE)
  512.                         {
  513.                                 if (p[star->position + 1] == 0)
  514.                                         p[star->position + 1] = star->color - 4;
  515.  
  516.                                 if (star->position > 0 && p[star->position - 1] == 0)
  517.                                         p[star->position - 1] = star->color - 4;
  518.  
  519.                                 if (p[star->position + surface->pitch] == 0)
  520.                                         p[star->position + surface->pitch] = star->color - 4;
  521.  
  522.                                 if (star->position >= surface->pitch && p[star->position - surface->pitch] == 0)
  523.                                         p[star->position - surface->pitch] = star->color - 4;
  524.                         }
  525.                 }
  526.         }
  527. }
  528.