~ubuntu-branches/debian/stretch/opentyrian/stretch

« back to all changes in this revision

Viewing changes to src/sprite.c

  • Committer: Package Import Robot
  • Author(s): Etienne Millon
  • Date: 2015-03-31 08:48:54 UTC
  • Revision ID: package-import@ubuntu.com-20150331084854-f5a4uoz7uv3vopk6
Tags: upstream-2.1.20130907+dfsg
ImportĀ upstreamĀ versionĀ 2.1.20130907+dfsg

Show diffs side-by-side

added added

removed removed

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