2
* OpenTyrian: A modern cross-platform port of Tyrian
3
* Copyright (C) 2007-2009 The OpenTyrian Development Team
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.
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.
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.
29
/*Special Background 2 and Background 3*/
32
JE_word backPos, backPos2, backPos3;
33
JE_word backMove, backMove2, backMove3;
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;
43
JE_boolean anySmoothies;
44
JE_byte smoothie_data[9]; /* [1..9] */
46
void JE_darkenBackground( JE_word neat ) /* wild detail level */
48
Uint8 *s = VGAScreen->pixels; /* screen pointer, 8-bit specific */
57
*s = ((((*s & 0x0f) << 4) - (*s & 0x0f) + ((((x - neat - y) >> 2) + *(s-2) + (y == 184 ? 0 : *(s-(VGAScreen->pitch-1)))) & 0x0f)) >> 4) | (*s & 0xf0);
60
s += VGAScreen->pitch - 264;
64
void blit_background_row( SDL_Surface *surface, int x, int y, Uint8 **map )
66
assert(surface->format->BitsPerPixel == 8);
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
72
for (int y = 0; y < 28; y++)
74
// not drawing on screen yet; skip y
75
if ((pixels + (12 * 24)) < pixels_ll)
77
pixels += surface->pitch;
81
for (int tile = 0; tile < 12; tile++)
83
Uint8 *data = *(map + tile);
94
for (int x = 24; x; x--)
96
if (pixels >= pixels_ul)
98
if (pixels >= pixels_ll && *data != 0)
106
pixels += surface->pitch - 12 * 24;
110
void blit_background_row_blend( SDL_Surface *surface, int x, int y, Uint8 **map )
112
assert(surface->format->BitsPerPixel == 8);
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
118
for (int y = 0; y < 28; y++)
120
// not drawing on screen yet; skip y
121
if ((pixels + (12 * 24)) < pixels_ll)
123
pixels += surface->pitch;
127
for (int tile = 0; tile < 12; tile++)
129
Uint8 *data = *(map + tile);
131
// no tile; skip tile
140
for (int x = 24; x; x--)
142
if (pixels >= pixels_ul)
144
if (pixels >= pixels_ll && *data != 0)
145
*pixels = (*data & 0xf0) | (((*pixels & 0x0f) + (*data & 0x0f)) / 2);
152
pixels += surface->pitch - 12 * 24;
156
void draw_background_1( SDL_Surface *surface )
158
SDL_FillRect(surface, NULL, 0);
160
Uint8 **map = (Uint8 **)mapYPos + mapXbpPos - 12;
162
for (int i = -1; i < 7; i++)
164
blit_background_row(surface, mapXPos, (i * 28) + backPos, map);
170
void draw_background_2( SDL_Surface *surface )
172
if (map2YDelayMax > 1 && backMove2 < 2)
173
backMove2 = (map2YDelay == 1) ? 1 : 0;
175
if (background2 != 0)
177
// water effect combines background 1 and 2 by syncronizing the x coordinate
178
int x = smoothies[1] ? mapXPos : mapX2Pos;
180
Uint8 **map = (Uint8 **)mapY2Pos + (smoothies[1] ? mapXbpPos : mapX2bpPos) - 12;
182
for (int i = -1; i < 7; i++)
184
blit_background_row(surface, x, (i * 28) + backPos2, map);
190
/*Set Movement of background*/
191
if (--map2YDelay == 0)
193
map2YDelay = map2YDelayMax;
195
backPos2 += backMove2;
201
mapY2Pos -= 14; /*Map Width*/
206
void draw_background_2_blend( SDL_Surface *surface )
208
if (map2YDelayMax > 1 && backMove2 < 2)
209
backMove2 = (map2YDelay == 1) ? 1 : 0;
211
Uint8 **map = (Uint8 **)mapY2Pos + mapX2bpPos - 12;
213
for (int i = -1; i < 7; i++)
215
blit_background_row_blend(surface, mapX2Pos, (i * 28) + backPos2, map);
220
/*Set Movement of background*/
221
if (--map2YDelay == 0)
223
map2YDelay = map2YDelayMax;
225
backPos2 += backMove2;
231
mapY2Pos -= 14; /*Map Width*/
236
void draw_background_3( SDL_Surface *surface )
238
/* Movement of background */
239
backPos3 += backMove3;
245
mapY3Pos -= 15; /*Map Width*/
248
Uint8 **map = (Uint8 **)mapY3Pos + mapX3bpPos - 12;
250
for (int i = -1; i < 7; i++)
252
blit_background_row(surface, mapX3Pos, (i * 28) + backPos3, map);
258
void JE_filterScreen( JE_shortint col, JE_shortint int_)
260
Uint8 *s = NULL; /* screen pointer, 8-bit specific */
266
levelBrightness += levelBrightnessChg;
267
if ((filterFadeStart && levelBrightness < -14) || levelBrightness > 14)
269
levelBrightnessChg = -levelBrightnessChg;
270
filterFadeStart = false;
271
levelFilter = levelFilterNew;
273
if (!filterFadeStart && levelBrightness == 0)
276
levelBrightness = -99;
280
if (col != -99 && filtrationAvail)
282
s = VGAScreen->pixels;
287
for (y = 184; y; y--)
289
for (x = 264; x; x--)
291
*s = col | (*s & 0x0f);
294
s += VGAScreen->pitch - 264;
298
if (int_ != -99 && explosionTransparent)
300
s = VGAScreen->pixels;
303
for (y = 184; y; y--)
305
for (x = 264; x; x--)
307
temp = (*s & 0x0f) + int_;
308
*s = (*s & 0xf0) | (temp >= 0x1f ? 0 : (temp >= 0x0f ? 0x0f : temp));
311
s += VGAScreen->pitch - 264;
316
void JE_checkSmoothies( void )
318
anySmoothies = (processorType > 2 && (smoothies[1-1] || smoothies[2-1])) || (processorType > 1 && (smoothies[3-1] || smoothies[4-1] || smoothies[5-1]));
321
void lava_filter( SDL_Surface *dst, SDL_Surface *src )
323
assert(src->format->BitsPerPixel == 8 && dst->format->BitsPerPixel == 8);
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 */
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
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
336
int w = 320 * 185 - 1;
338
for (int y = 185 - 1; y >= 0; --y)
340
dst_pixel -= (dst_pitch - 320); // in case pitch is not 320
341
src_pixel -= (src_pitch - 320); // in case pitch is not 320
343
for (int x = 320 - 1; x >= 0; x -= 8)
345
int waver = abs(((w >> 9) & 0x0f) - 8) - 1;
348
for (int xi = 8 - 1; xi >= 0; --xi)
353
// value is average value of source pixel (2x), destination pixel above, and destination pixel below (all with waver)
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;
363
*dst_pixel = (value / 4) | 0x70;
369
void water_filter( SDL_Surface *dst, SDL_Surface *src )
371
assert(src->format->BitsPerPixel == 8 && dst->format->BitsPerPixel == 8);
373
Uint8 hue = smoothie_data[1] << 4;
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 */
378
const int dst_pitch = dst->pitch;
379
Uint8 *dst_pixel = (Uint8 *)dst->pixels + (185 * dst_pitch);
381
const Uint8 *src_pixel = (Uint8 *)src->pixels + (185 * src->pitch);
383
int w = 320 * 185 - 1;
385
for (int y = 185 - 1; y >= 0; --y)
387
dst_pixel -= (dst_pitch - 320); // in case pitch is not 320
388
src_pixel -= (src->pitch - 320); // in case pitch is not 320
390
for (int x = 320 - 1; x >= 0; x -= 8)
392
int waver = abs(((w >> 10) & 0x07) - 4) - 1;
395
for (int xi = 8 - 1; xi >= 0; --xi)
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)
404
*dst_pixel = *src_pixel;
408
Uint8 value = *src_pixel & 0x0f;
409
value += *(dst_pixel + waver + dst_pitch) & 0x0f;
410
*dst_pixel = (value / 2) | hue;
417
void iced_blur_filter( SDL_Surface *dst, SDL_Surface *src )
419
assert(src->format->BitsPerPixel == 8 && dst->format->BitsPerPixel == 8);
421
Uint8 *dst_pixel = dst->pixels;
422
const Uint8 *src_pixel = src->pixels;
424
for (int y = 0; y < 184; ++y)
426
for (int x = 0; x < 320; ++x)
428
// value is average value of source pixel and destination pixel
431
const Uint8 value = (*src_pixel & 0x0f) + (*dst_pixel & 0x0f);
432
*dst_pixel = (value / 2) | 0x80;
438
dst_pixel += (dst->pitch - 320); // in case pitch is not 320
439
src_pixel += (src->pitch - 320); // in case pitch is not 320
443
void blur_filter( SDL_Surface *dst, SDL_Surface *src )
445
assert(src->format->BitsPerPixel == 8 && dst->format->BitsPerPixel == 8);
447
Uint8 *dst_pixel = dst->pixels;
448
const Uint8 *src_pixel = src->pixels;
450
for (int y = 0; y < 184; ++y)
452
for (int x = 0; x < 320; ++x)
454
// value is average value of source pixel and destination pixel
455
// hue is source pixel hue
457
const Uint8 value = (*src_pixel & 0x0f) + (*dst_pixel & 0x0f);
458
*dst_pixel = (value / 2) | (*src_pixel & 0xf0);
464
dst_pixel += (dst->pitch - 320); // in case pitch is not 320
465
src_pixel += (src->pitch - 320); // in case pitch is not 320
470
/* Background Starfield */
474
JE_word position; // relies on overflow wrap-around
478
#define MAX_STARS 100
479
#define STARFIELD_HUE 0x90
480
static StarfieldStar starfield_stars[MAX_STARS];
483
void initialize_starfield( void )
485
for (int i = MAX_STARS-1; i >= 0; --i)
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;
493
void update_and_draw_starfield( SDL_Surface* surface, int move_speed )
495
Uint8* p = (Uint8*)surface->pixels;
497
for (int i = MAX_STARS-1; i >= 0; --i)
499
StarfieldStar* star = &starfield_stars[i];
501
star->position += (star->speed + move_speed) * surface->pitch;
503
if (star->position < 177 * surface->pitch)
505
if (p[star->position] == 0)
507
p[star->position] = star->color;
510
// If star is bright enough, draw surrounding pixels
511
if (star->color - 4 >= STARFIELD_HUE)
513
if (p[star->position + 1] == 0)
514
p[star->position + 1] = star->color - 4;
516
if (star->position > 0 && p[star->position - 1] == 0)
517
p[star->position - 1] = star->color - 4;
519
if (p[star->position + surface->pitch] == 0)
520
p[star->position + surface->pitch] = star->color - 4;
522
if (star->position >= surface->pitch && p[star->position - surface->pitch] == 0)
523
p[star->position - surface->pitch] = star->color - 4;