Files
commandergenius/project/jni/application/opentyrian/src/backgrnd.cpp

469 lines
11 KiB
C++

/*
* OpenTyrian Classic: A modern cross-platform port of Tyrian
* Copyright (C) 2007-2009 The OpenTyrian Development Team
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#include "opentyr.h"
#include "backgrnd.h"
#include "config.h"
#include "varz.h"
#include "video.h"
#include <assert.h>
/*Special Background 2 and Background 3*/
/*Back Pos 3*/
JE_word backPos, backPos2, backPos3;
JE_word backMove, backMove2, backMove3;
/*Main Maps*/
JE_word mapX, mapY, mapX2, mapX3, mapY2, mapY3;
JE_byte **mapYPos, **mapY2Pos, **mapY3Pos;
JE_word mapXPos, oldMapXOfs, mapXOfs, mapX2Ofs, mapX2Pos, mapX3Pos, oldMapX3Ofs, mapX3Ofs, tempMapXOfs;
intptr_t mapXbpPos, mapX2bpPos, mapX3bpPos;
JE_byte map1YDelay, map1YDelayMax, map2YDelay, map2YDelayMax;
JE_boolean anySmoothies;
JE_byte smoothie_data[9]; /* [1..9] */
void JE_darkenBackground( JE_word neat ) /* wild detail level */
{
Uint8 *s = (Uint8 *)VGAScreen->pixels; /* screen pointer, 8-bit specific */
int x, y;
s += 24;
for (y = 184; y; y--)
{
for (x = 264; x; x--)
{
*s = ((((*s & 0x0f) << 4) - (*s & 0x0f) + ((((x - neat - y) >> 2) + *(s-2) + (y == 184 ? 0 : *(s-(VGAScreen->pitch-1)))) & 0x0f)) >> 4) | (*s & 0xf0);
s++;
}
s += VGAScreen->pitch - 264;
}
}
void blit_background_row( SDL_Surface *surface, int x, int y, Uint8 **map )
{
assert(surface->format->BitsPerPixel == 8);
Uint8 *pixels = (Uint8 *)surface->pixels + (y * surface->pitch) + x,
*pixels_ll = (Uint8 *)surface->pixels, // lower limit
*pixels_ul = (Uint8 *)surface->pixels + (surface->h * surface->pitch); // upper limit
for (int y = 0; y < 28; y++)
{
// not drawing on screen yet; skip y
if ((pixels + (12 * 24)) < pixels_ll)
{
pixels += surface->pitch;
continue;
}
for (int tile = 0; tile < 12; tile++)
{
Uint8 *data = *(map + tile);
// no tile; skip tile
if (data == NULL)
{
pixels += 24;
continue;
}
data += y * 24;
for (int x = 24; x; x--)
{
if (pixels >= pixels_ul)
return;
if (pixels >= pixels_ll && *data != 0)
*pixels = *data;
pixels++;
data++;
}
}
pixels += surface->pitch - 12 * 24;
}
}
void blit_background_row_blend( SDL_Surface *surface, int x, int y, Uint8 **map )
{
assert(surface->format->BitsPerPixel == 8);
Uint8 *pixels = (Uint8 *)surface->pixels + (y * surface->pitch) + x,
*pixels_ll = (Uint8 *)surface->pixels, // lower limit
*pixels_ul = (Uint8 *)surface->pixels + (surface->h * surface->pitch); // upper limit
for (int y = 0; y < 28; y++)
{
// not drawing on screen yet; skip y
if ((pixels + (12 * 24)) < pixels_ll)
{
pixels += surface->pitch;
continue;
}
for (int tile = 0; tile < 12; tile++)
{
Uint8 *data = *(map + tile);
// no tile; skip tile
if (data == NULL)
{
pixels += 24;
continue;
}
data += y * 24;
for (int x = 24; x; x--)
{
if (pixels >= pixels_ul)
return;
if (pixels >= pixels_ll && *data != 0)
*pixels = (*data & 0xf0) | (((*pixels & 0x0f) + (*data & 0x0f)) / 2);
pixels++;
data++;
}
}
pixels += surface->pitch - 12 * 24;
}
}
void draw_background_1( SDL_Surface *surface )
{
SDL_FillRect(surface, NULL, 0);
Uint8 **map = (Uint8 **)mapYPos + mapXbpPos - 12;
for (int i = -1; i < 7; i++)
{
blit_background_row(surface, mapXPos, (i * 28) + backPos, map);
map += 14;
}
}
void draw_background_2( SDL_Surface *surface )
{
if (map2YDelayMax > 1 && backMove2 < 2)
backMove2 = (map2YDelay == 1) ? 1 : 0;
if (background2 != 0)
{
// water effect combines background 1 and 2 by syncronizing the x coordinate
int x = smoothies[1] ? mapXPos : mapX2Pos;
Uint8 **map = (Uint8 **)mapY2Pos + (smoothies[1] ? mapXbpPos : mapX2bpPos) - 12;
for (int i = -1; i < 7; i++)
{
blit_background_row(surface, x, (i * 28) + backPos2, map);
map += 14;
}
}
/*Set Movement of background*/
if (--map2YDelay == 0)
{
map2YDelay = map2YDelayMax;
backPos2 += backMove2;
if (backPos2 > 27)
{
backPos2 -= 28;
mapY2--;
mapY2Pos -= 14; /*Map Width*/
}
}
}
void draw_background_2_blend( SDL_Surface *surface )
{
if (map2YDelayMax > 1 && backMove2 < 2)
backMove2 = (map2YDelay == 1) ? 1 : 0;
Uint8 **map = (Uint8 **)mapY2Pos + mapX2bpPos - 12;
for (int i = -1; i < 7; i++)
{
blit_background_row_blend(surface, mapX2Pos, (i * 28) + backPos2, map);
map += 14;
}
/*Set Movement of background*/
if (--map2YDelay == 0)
{
map2YDelay = map2YDelayMax;
backPos2 += backMove2;
if (backPos2 > 27)
{
backPos2 -= 28;
mapY2--;
mapY2Pos -= 14; /*Map Width*/
}
}
}
void draw_background_3( SDL_Surface *surface )
{
/* Movement of background */
backPos3 += backMove3;
if (backPos3 > 27)
{
backPos3 -= 28;
mapY3--;
mapY3Pos -= 15; /*Map Width*/
}
Uint8 **map = (Uint8 **)mapY3Pos + mapX3bpPos - 12;
for (int i = -1; i < 7; i++)
{
blit_background_row(surface, mapX3Pos, (i * 28) + backPos3, map);
map += 15;
}
}
void JE_filterScreen( JE_shortint col, JE_shortint int_)
{
Uint8 *s = NULL; /* screen pointer, 8-bit specific */
int x, y;
unsigned int temp;
if (filterFade)
{
levelBrightness += levelBrightnessChg;
if ((filterFadeStart && levelBrightness < -14) || levelBrightness > 14)
{
levelBrightnessChg = -levelBrightnessChg;
filterFadeStart = false;
levelFilter = levelFilterNew;
}
if (!filterFadeStart && levelBrightness == 0)
{
filterFade = false;
levelBrightness = -99;
}
}
if (col != -99 && filtrationAvail)
{
s = (Uint8 *)VGAScreen->pixels;
s += 24;
col <<= 4;
for (y = 184; y; y--)
{
for (x = 264; x; x--)
{
*s = col | (*s & 0x0f);
s++;
}
s += VGAScreen->pitch - 264;
}
}
if (int_ != -99 && explosionTransparent)
{
s = (Uint8 *)VGAScreen->pixels;
s += 24;
for (y = 184; y; y--)
{
for (x = 264; x; x--)
{
temp = (*s & 0x0f) + int_;
*s = (*s & 0xf0) | (temp >= 0x1f ? 0 : (temp >= 0x0f ? 0x0f : temp));
s++;
}
s += VGAScreen->pitch - 264;
}
}
}
void JE_checkSmoothies( void )
{
anySmoothies = (processorType > 2 && (smoothies[1-1] || smoothies[2-1])) || (processorType > 1 && (smoothies[3-1] || smoothies[4-1] || smoothies[5-1]));
}
void lava_filter( SDL_Surface *dst, SDL_Surface *src )
{
assert(src->format->BitsPerPixel == 8 && dst->format->BitsPerPixel == 8);
/* we don't need to check for over-reading the pixel surfaces since we only
* read from the top 185+1 scanlines, and there should be 320 */
const int dst_pitch = dst->pitch;
Uint8 *dst_pixel = (Uint8 *)dst->pixels + (185 * dst_pitch);
const Uint8 * const dst_pixel_ll = (Uint8 *)dst->pixels; // lower limit
const int src_pitch = src->pitch;
const Uint8 *src_pixel = (Uint8 *)src->pixels + (185 * src->pitch);
const Uint8 * const src_pixel_ll = (Uint8 *)src->pixels; // lower limit
int w = 320 * 185 - 1;
for (int y = 185 - 1; y >= 0; --y)
{
dst_pixel -= (dst_pitch - 320); // in case pitch is not 320
src_pixel -= (src_pitch - 320); // in case pitch is not 320
for (int x = 320 - 1; x >= 0; x -= 8)
{
int waver = abs(((w >> 9) & 0x0f) - 8) - 1;
w -= 8;
for (int xi = 8 - 1; xi >= 0; --xi)
{
--dst_pixel;
--src_pixel;
// value is average value of source pixel (2x), destination pixel above, and destination pixel below (all with waver)
// hue is red
Uint8 value = 0;
if (src_pixel + waver >= src_pixel_ll)
value += (*(src_pixel + waver) & 0x0f) * 2;
value += *(dst_pixel + waver + dst_pitch) & 0x0f;
if (dst_pixel + waver - dst_pitch >= dst_pixel_ll)
value += *(dst_pixel + waver - dst_pitch) & 0x0f;
*dst_pixel = (value / 4) | 0x70;
}
}
}
}
void water_filter( SDL_Surface *dst, SDL_Surface *src )
{
assert(src->format->BitsPerPixel == 8 && dst->format->BitsPerPixel == 8);
Uint8 hue = smoothie_data[1] << 4;
/* we don't need to check for over-reading the pixel surfaces since we only
* read from the top 185+1 scanlines, and there should be 320 */
const int dst_pitch = dst->pitch;
Uint8 *dst_pixel = (Uint8 *)dst->pixels + (185 * dst_pitch);
const Uint8 *src_pixel = (Uint8 *)src->pixels + (185 * src->pitch);
int w = 320 * 185 - 1;
for (int y = 185 - 1; y >= 0; --y)
{
dst_pixel -= (dst_pitch - 320); // in case pitch is not 320
src_pixel -= (src->pitch - 320); // in case pitch is not 320
for (int x = 320 - 1; x >= 0; x -= 8)
{
int waver = abs(((w >> 10) & 0x07) - 4) - 1;
w -= 8;
for (int xi = 8 - 1; xi >= 0; --xi)
{
--dst_pixel;
--src_pixel;
// pixel is copied from source if not blue
// otherwise, value is average of value of source pixel and destination pixel below (with waver)
if ((*src_pixel & 0x30) == 0)
{
*dst_pixel = *src_pixel;
}
else
{
Uint8 value = *src_pixel & 0x0f;
value += *(dst_pixel + waver + dst_pitch) & 0x0f;
*dst_pixel = (value / 2) | hue;
}
}
}
}
}
void iced_blur_filter( SDL_Surface *dst, SDL_Surface *src )
{
assert(src->format->BitsPerPixel == 8 && dst->format->BitsPerPixel == 8);
Uint8 *dst_pixel = (Uint8 *)dst->pixels;
const Uint8 *src_pixel = (Uint8 *)src->pixels;
for (int y = 0; y < 184; ++y)
{
for (int x = 0; x < 320; ++x)
{
// value is average value of source pixel and destination pixel
// hue is icy blue
const Uint8 value = (*src_pixel & 0x0f) + (*dst_pixel & 0x0f);
*dst_pixel = (value / 2) | 0x80;
++dst_pixel;
++src_pixel;
}
dst_pixel += (dst->pitch - 320); // in case pitch is not 320
src_pixel += (src->pitch - 320); // in case pitch is not 320
}
}
void blur_filter( SDL_Surface *dst, SDL_Surface *src )
{
assert(src->format->BitsPerPixel == 8 && dst->format->BitsPerPixel == 8);
Uint8 *dst_pixel = (Uint8 *)dst->pixels;
const Uint8 *src_pixel = (Uint8 *)src->pixels;
for (int y = 0; y < 184; ++y)
{
for (int x = 0; x < 320; ++x)
{
// value is average value of source pixel and destination pixel
// hue is source pixel hue
const Uint8 value = (*src_pixel & 0x0f) + (*dst_pixel & 0x0f);
*dst_pixel = (value / 2) | (*src_pixel & 0xf0);
++dst_pixel;
++src_pixel;
}
dst_pixel += (dst->pitch - 320); // in case pitch is not 320
src_pixel += (src->pitch - 320); // in case pitch is not 320
}
}
// kate: tab-width 4; vim: set noet: