Richard Boegli's CnC_Generals_Zero_Hour Fork WIP
This is documentation of Richard Boegil's Zero Hour Fork
 
Loading...
Searching...
No Matches
rlerle.h
Go to the documentation of this file.
1/*
2** Command & Conquer Generals Zero Hour(tm)
3** Copyright 2025 Electronic Arts Inc.
4**
5** This program is free software: you can redistribute it and/or modify
6** it under the terms of the GNU General Public License as published by
7** the Free Software Foundation, either version 3 of the License, or
8** (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, see <http://www.gnu.org/licenses/>.
17*/
18
19/***********************************************************************************************
20 *** C O N F I D E N T I A L --- W E S T W O O D S T U D I O S ***
21 ***********************************************************************************************
22 * *
23 * Project Name : Command & Conquer *
24 * *
25 * $Archive:: /Commando/Library/RLERLE.h $*
26 * *
27 * $Author:: Greg_h $*
28 * *
29 * $Modtime:: 7/22/97 11:37a $*
30 * *
31 * $Revision:: 1 $*
32 * *
33 *---------------------------------------------------------------------------------------------*
34 * Functions: *
35 * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
36
37#ifndef RLERLE_H
38#define RLERLE_H
39
40/*
41** This class holds the RLE enabled blitter object definitions. There is a blitter object
42** type for every kind of pixel operation required of RLE shapes. These are defined as
43** templates to support the different destination pixel formats.
44*/
45
46#include "blitter.h"
47#include <assert.h>
48#include <string.h>
49
50
51/*
52** This is a helper function that will skip N pixels in the RLE compressed source. This is
53** necessary for clipping purposes. The return value represents the number of transparent
54** pixels before actual pixel data starts when the RLE uncompression is resumed.
55*/
56inline int Skip_Leading_Pixels(unsigned char const * & sptr, int skipper)
57{
58 /*
59 ** Skip leading pixels as requested.
60 */
61 while (skipper > 0) {
62 if (*sptr++ == '\0') {
63 skipper -= *sptr++;
64 } else {
65 skipper--;
66 }
67 }
68
69 /*
70 ** Return with then number of leading transparent pixels in the pixel stream
71 ** after the end of the skip process. This value must be tracked since the pixel
72 ** skip process may have ended in the middle of a transparent pixel run.
73 */
74 return(-skipper);
75}
76
77
78/*
79** Blits with transparency checking and translation to destination pixel format.
80*/
81template<class T>
83 public:
84 RLEBlitTransXlat(T const * translator) : TranslateTable(translator) {assert(TranslateTable != NULL);}
85
86 virtual void Blit(void * dest, void const * source, int length, int leadskip=0) const
87 {
88 unsigned char const * sptr = (unsigned char const *)source;
89 T * dptr = (T *)dest;
90
91 /*
92 ** Skip any leading pixels as requested.
93 */
94 if (leadskip > 0) {
95 int transcount = Skip_Leading_Pixels(sptr, leadskip);
96 dptr += transcount;
97 length -= transcount;
98 }
99
100 /*
101 ** Uncompress and store the pixel stream until the length has been
102 ** exhausted.
103 */
104 while (length > 0) {
105 unsigned char value = *sptr++;
106 if (value == '\0') {
107 value = *sptr++;
108 length -= value;
109 dptr += value;
110 } else {
111 *dptr++ = TranslateTable[value];
112 length -= 1;
113 }
114 }
115 }
116
117 private:
118 T const * TranslateTable;
119};
120
121
122/*
123** This blits RLE compressed pixels by first remapping through a 256 byte table and then
124** translating the pixel to screen format.
125*/
126template<class T>
128 public:
129 RLEBlitTransRemapXlat(unsigned char const * remapper, T const * translator) : RemapTable(remapper), TranslateTable(translator) {assert(TranslateTable != NULL);assert(RemapTable != NULL);}
130
131 virtual void Blit(void * dest, void const * source, int length, int leadskip=0) const
132 {
133 unsigned char const * sptr = (unsigned char const *)source;
134 T * dptr = (T *)dest;
135
136 /*
137 ** Skip any leading pixels as requested.
138 */
139 if (leadskip > 0) {
140 int transcount = Skip_Leading_Pixels(sptr, leadskip);
141 dptr += transcount;
142 length -= transcount;
143 }
144
145 /*
146 ** Uncompress and store the pixel stream until the length has been
147 ** exhausted.
148 */
149 while (length > 0) {
150 unsigned char value = *sptr++;
151 if (value == '\0') {
152 value = *sptr++;
153 length -= value;
154 dptr += value;
155 } else {
156 *dptr++ = TranslateTable[RemapTable[value]];
157 length -= 1;
158 }
159 }
160 }
161
162 private:
163 unsigned char const * RemapTable;
164 T const * TranslateTable;
165};
166
167
168/*
169** This blits RLE compressed pixels by first remapping through a 256 byte table and then
170** translating the pixel to screen format. The remapping table is doubly indirected so that
171** it is possible to change the remapping table pointer without creating a separate blitter
172** object.
173*/
174template<class T>
176 public:
177 RLEBlitTransZRemapXlat(unsigned char const * const * remapper, T const * translator) : RemapTable(remapper), TranslateTable(translator) {assert(TranslateTable != NULL);assert(RemapTable != NULL);}
178
179 virtual void Blit(void * dest, void const * source, int length, int leadskip=0) const
180 {
181 unsigned char const * sptr = (unsigned char const *)source;
182 unsigned char const * remapper = *RemapTable;
183 T * dptr = (T *)dest;
184
185 /*
186 ** Skip any leading pixels as requested.
187 */
188 if (leadskip > 0) {
189 int transcount = Skip_Leading_Pixels(sptr, leadskip);
190 dptr += transcount;
191 length -= transcount;
192 }
193
194 /*
195 ** Uncompress and store the pixel stream until the length has been
196 ** exhausted.
197 */
198 while (length > 0) {
199 unsigned char value = *sptr++;
200 if (value == '\0') {
201 value = *sptr++;
202 length -= value;
203 dptr += value;
204 } else {
205 *dptr++ = TranslateTable[remapper[value]];
206 length -= 1;
207 }
208 }
209 }
210
211 private:
212 unsigned char const * const * RemapTable;
213 T const * TranslateTable;
214};
215
216
217/*
218** This will remap the destination pixels but under the control of the source pixels.
219** Where the source pixel is not transparent, the dest pixel is remapped. This algorithm
220** really only applies to lowcolor display.
221*/
222template<class T>
224 public:
225 RLEBlitTransRemapDest(T const * remap) : RemapTable(remap) {}
226
227 virtual void Blit(void * dest, void const * source, int length, int leadskip=0) const
228 {
229 unsigned char const * sptr = (unsigned char const *)source;
230 T * dptr = (T *)dest;
231
232 /*
233 ** Skip any leading pixels as requested.
234 */
235 if (leadskip > 0) {
236 int transcount = Skip_Leading_Pixels(sptr, leadskip);
237 dptr += transcount;
238 length -= transcount;
239 }
240
241 /*
242 ** Uncompress and store the pixel stream until the length has been
243 ** exhausted.
244 */
245 while (length > 0) {
246 unsigned char value = *sptr++;
247 if (value == '\0') {
248 value = *sptr++;
249 length -= value;
250 dptr += value;
251 } else {
252 *dptr = RemapTable[*dptr];
253 length -= 1;
254 dptr++;
255 }
256 }
257 }
258
259 private:
260 T const * RemapTable;
261};
262
263
264/*
265** Algorithmic darkening of hicolor pixels controlled by the source pixels. The source
266** pixels are examined only to determine if the destination pixel should be darkened.
267** If the source pixel is transparent, then the dest pixel is skipped. The darkening
268** algorithm works only for hicolor pixels.
269*/
270template<class T>
272 public:
273 RLEBlitTransDarken(T mask) : Mask(mask) {}
274
275 virtual void Blit(void * dest, void const * source, int length, int leadskip=0) const
276 {
277 unsigned char const * sptr = (unsigned char const *)source;
278 T * dptr = (T *)dest;
279
280 /*
281 ** Skip any leading pixels as requested.
282 */
283 if (leadskip > 0) {
284 int transcount = Skip_Leading_Pixels(sptr, leadskip);
285 dptr += transcount;
286 length -= transcount;
287 }
288
289 /*
290 ** Uncompress and store the pixel stream until the length has been
291 ** exhausted.
292 */
293 while (length > 0) {
294 unsigned char value = *sptr++;
295 if (value == '\0') {
296 value = *sptr++;
297 length -= value;
298 dptr += value;
299 } else {
300 *dptr = (T)((*dptr >> 1) & Mask);
301 length -= 1;
302 dptr++;
303 }
304 }
305 }
306
307 private:
308 T Mask;
309};
310
311
312/*
313** This blitter performs 50% translucency as it draws. It is commonly used for animation
314** effects and other stealth like images. It only works with hicolor pixels but is a good
315** candidate for optimization.
316*/
317template<class T>
319 public:
320 RLEBlitTransLucent50(T const * translator, T mask) : TranslateTable(translator), Mask(mask) {}
321
322 virtual void Blit(void * dest, void const * source, int length, int leadskip=0) const
323 {
324 unsigned char const * sptr = (unsigned char const *)source;
325 T * dptr = (T *)dest;
326
327 /*
328 ** Skip any leading pixels as requested.
329 */
330 if (leadskip > 0) {
331 int transcount = Skip_Leading_Pixels(sptr, leadskip);
332 dptr += transcount;
333 length -= transcount;
334 }
335
336 /*
337 ** Uncompress and store the pixel stream until the length has been
338 ** exhausted.
339 */
340 while (length > 0) {
341 unsigned char value = *sptr++;
342 if (value == '\0') {
343 value = *sptr++;
344 length -= value;
345 dptr += value;
346 } else {
347 *dptr = (T)((((*dptr) >> 1) & Mask) + ((TranslateTable[value] >> 1) & Mask));
348 length -= 1;
349 dptr++;
350 }
351 }
352 }
353
354 private:
355 T const * TranslateTable;
356 T Mask;
357};
358
359
360/*
361** This blitter performs 25% translucency as it draws. This effect is less than spectacular,
362** but there are some uses for it. It only works with hicolor pixels.
363*/
364template<class T>
366 public:
367 RLEBlitTransLucent25(T const * translator, T mask) : TranslateTable(translator), Mask(mask) {}
368
369 virtual void Blit(void * dest, void const * source, int length, int leadskip=0) const
370 {
371 unsigned char const * sptr = (unsigned char const *)source;
372 T * dptr = (T *)dest;
373
374 /*
375 ** Skip any leading pixels as requested.
376 */
377 if (leadskip > 0) {
378 int transcount = Skip_Leading_Pixels(sptr, leadskip);
379 dptr += transcount;
380 length -= transcount;
381 }
382
383 /*
384 ** Uncompress and store the pixel stream until the length has been
385 ** exhausted.
386 */
387 while (length > 0) {
388 unsigned char value = *sptr++;
389 if (value == '\0') {
390 value = *sptr++;
391 length -= value;
392 dptr += value;
393 } else {
394 T qsource = (T)(((TranslateTable[value] >> 2) & Mask));
395 T qdest = (T)(((*dptr) >> 2) & Mask);
396 *dptr++ = (T)(qdest + qsource + qsource + qsource);
397 length -= 1;
398 }
399 }
400 }
401
402 private:
403 T const * TranslateTable;
404 T Mask;
405};
406
407
408/*
409** This blitter performs 75% translucency as it draws. This is quite useful for explosions and
410** other gas animation effects. It only works with hicolor pixels and is a good candidate
411** for optimization.
412*/
413template<class T>
415 public:
416 RLEBlitTransLucent75(T const * translator, T mask) : TranslateTable(translator), Mask(mask) {}
417
418 virtual void Blit(void * dest, void const * source, int length, int leadskip=0) const
419 {
420 unsigned char const * sptr = (unsigned char const *)source;
421 T * dptr = (T *)dest;
422
423 /*
424 ** Skip any leading pixels as requested.
425 */
426 if (leadskip > 0) {
427 int transcount = Skip_Leading_Pixels(sptr, leadskip);
428 dptr += transcount;
429 length -= transcount;
430 }
431
432 /*
433 ** Uncompress and store the pixel stream until the length has been
434 ** exhausted.
435 */
436 while (length > 0) {
437 unsigned char value = *sptr++;
438 if (value == '\0') {
439 value = *sptr++;
440 length -= value;
441 dptr += value;
442 } else {
443 T qsource = (T)(((TranslateTable[value] >> 2) & Mask));
444 T qdest = (T)(((*dptr) >> 2) & Mask);
445 *dptr++ = (T)(qdest + qdest + qdest + qsource);
446 length -= 1;
447 }
448 }
449 }
450
451 private:
452 T const * TranslateTable;
453 T Mask;
454};
455
456
457#if defined(_MSC_VER)
458void RLEBlitTransZRemapXlat<unsigned short>::Blit(void * dest, void const * source, int len, int leadskip) const
459{
460 unsigned char const * remapper = *RemapTable;
461 unsigned short const * transtable = TranslateTable;
462
463 /*
464 ** Set up the working registers for the blit operation.
465 */
466 __asm {
467 mov ecx,[len]
468 mov edi,[dest]
469 mov esi,[source]
470 mov ebx,[remapper]
471 mov edx,[leadskip]
472 xor eax,eax
473 }
474
475 /*
476 ** Skip leading pixels by analyzing the RLE data until the entire
477 ** requested skip pixel count has been processed. This could result in
478 ** unprocessed transparent pixels if it ended up in the middle of
479 ** a transparent pixel run. This is handled in the next block.
480 */
481moreskip:
482 __asm {
483 test edx,edx
484 jle nomoreskip
485 dec edx
486 lodsb
487 test al,al
488 jnz moreskip
489 lodsb
490 sub edx,eax
491 inc edx
492 jmp moreskip
493 }
494nomoreskip:
495
496 /*
497 ** Handle any left over transparent pixels that would be part of
498 ** a transparent pixel run that occurs at the end of the leading
499 ** pixel skip process.
500 */
501 __asm {
502 neg edx
503 sub ecx,edx // Account for any left over transparent pixels
504 lea edi,[edi+edx*2]
505 mov edx,[transtable]
506 }
507
508 /*
509 ** Output the pixel data to the destination.
510 */
511moredata:
512 __asm {
513 xor eax,eax
514 or ecx,ecx
515 jle fini
516 lodsb
517 test al,al
518 jz transparent
519 mov al,[ebx+eax]
520 mov ax,[edx+eax*2]
521 dec ecx
522 stosw
523 jmp moredata
524 }
525
526 /*
527 ** A transparent pixel run just causes the destination pointer
528 ** and length count to be adjusted by the length of the run.
529 */
530transparent:
531 __asm {
532 lodsb
533 lea edi,[edi+eax*2]
534 sub ecx,eax
535 jmp moredata
536 }
537
538fini:;
539}
540
541
542void RLEBlitTransRemapXlat<unsigned short>::Blit(void * dest, void const * source, int len, int leadskip) const
543{
544 unsigned char const * remapper = RemapTable;
545 unsigned short const * transtable = TranslateTable;
546
547 /*
548 ** Set up the working registers for the blit operation.
549 */
550 __asm {
551 mov ecx,[len]
552 mov edi,[dest]
553 mov esi,[source]
554 mov ebx,[remapper]
555 mov edx,[leadskip]
556 xor eax,eax
557 }
558
559 /*
560 ** Skip leading pixels by analyzing the RLE data until the entire
561 ** requested skip pixel count has been processed. This could result in
562 ** unprocessed transparent pixels if it ended up in the middle of
563 ** a transparent pixel run. This is handled in the next block.
564 */
565moreskip:
566 __asm {
567 test edx,edx
568 jle nomoreskip
569 dec edx
570 lodsb
571 test al,al
572 jnz moreskip
573 lodsb
574 sub edx,eax
575 inc edx
576 jmp moreskip
577 }
578nomoreskip:
579
580 /*
581 ** Handle any left over transparent pixels that would be part of
582 ** a transparent pixel run that occurs at the end of the leading
583 ** pixel skip process.
584 */
585 __asm {
586 neg edx
587 sub ecx,edx // Account for any left over transparent pixels
588 lea edi,[edi+edx*2]
589 mov edx,[transtable]
590 }
591
592 /*
593 ** Output the pixel data to the destination.
594 */
595moredata:
596 __asm {
597 xor eax,eax
598 or ecx,ecx
599 jle fini
600 lodsb
601 test al,al
602 jz transparent
603 mov al,[ebx+eax]
604 mov ax,[edx+eax*2]
605 dec ecx
606 stosw
607 jmp moredata
608 }
609
610 /*
611 ** A transparent pixel run just causes the destination pointer
612 ** and length count to be adjusted by the length of the run.
613 */
614transparent:
615 __asm {
616 lodsb
617 lea edi,[edi+eax*2]
618 sub ecx,eax
619 jmp moredata
620 }
621
622fini:;
623}
624
625
626void RLEBlitTransXlat<unsigned short>::Blit(void * dest, void const * source, int len, int leadskip) const
627{
628 unsigned short const * transtable = TranslateTable;
629
630 /*
631 ** Set up the working registers for the blit operation.
632 */
633 __asm {
634 mov ecx,[len]
635 mov edi,[dest]
636 mov esi,[source]
637 mov ebx,[transtable]
638 mov edx,[leadskip]
639 xor eax,eax
640 }
641
642 /*
643 ** Skip leading pixels by analyzing the RLE data until the entire
644 ** requested skip pixel count has been processed. This could result in
645 ** unprocessed transparent pixels if it ended up in the middle of
646 ** a transparent pixel run. This is handled in the next block.
647 */
648moreskip:
649 __asm {
650 test edx,edx
651 jle nomoreskip
652 dec edx
653 lodsb
654 test al,al
655 jnz moreskip
656 lodsb
657 sub edx,eax
658 inc edx
659 jmp moreskip
660 }
661nomoreskip:
662
663 /*
664 ** Handle any left over transparent pixels that would be part of
665 ** a transparent pixel run that occurs at the end of the leading
666 ** pixel skip process.
667 */
668 __asm {
669 neg edx
670 sub ecx,edx // Account for any left over transparent pixels
671 lea edi,[edi+edx*2]
672 }
673
674 /*
675 ** Output the pixel data to the destination.
676 */
677moredata:
678 __asm {
679 xor eax,eax
680 or ecx,ecx
681 jle fini
682 lodsb
683 test al,al
684 jz transparent
685 mov ax,[ebx+eax*2]
686 dec ecx
687 stosw
688 jmp moredata
689 }
690
691 /*
692 ** A transparent pixel run just causes the destination pointer
693 ** and length count to be adjusted by the length of the run.
694 */
695transparent:
696 __asm {
697 lodsb
698 lea edi,[edi+eax*2]
699 sub ecx,eax
700 jmp moredata
701 }
702
703fini:;
704}
705
706#endif
707
708
709#endif
#define NULL
Definition BaseType.h:92
void const char * value
RLEBlitTransDarken(T mask)
Definition rlerle.h:273
virtual void Blit(void *dest, void const *source, int length, int leadskip=0) const
Definition rlerle.h:275
virtual void Blit(void *dest, void const *source, int length, int leadskip=0) const
Definition rlerle.h:369
RLEBlitTransLucent25(T const *translator, T mask)
Definition rlerle.h:367
RLEBlitTransLucent50(T const *translator, T mask)
Definition rlerle.h:320
virtual void Blit(void *dest, void const *source, int length, int leadskip=0) const
Definition rlerle.h:322
virtual void Blit(void *dest, void const *source, int length, int leadskip=0) const
Definition rlerle.h:418
RLEBlitTransLucent75(T const *translator, T mask)
Definition rlerle.h:416
RLEBlitTransRemapDest(T const *remap)
Definition rlerle.h:225
virtual void Blit(void *dest, void const *source, int length, int leadskip=0) const
Definition rlerle.h:227
RLEBlitTransRemapXlat(unsigned char const *remapper, T const *translator)
Definition rlerle.h:129
virtual void Blit(void *dest, void const *source, int length, int leadskip=0) const
Definition rlerle.h:131
RLEBlitTransXlat(T const *translator)
Definition rlerle.h:84
virtual void Blit(void *dest, void const *source, int length, int leadskip=0) const
Definition rlerle.h:86
RLEBlitTransZRemapXlat(unsigned char const *const *remapper, T const *translator)
Definition rlerle.h:177
virtual void Blit(void *dest, void const *source, int length, int leadskip=0) const
Definition rlerle.h:179
int Skip_Leading_Pixels(unsigned char const *&sptr, int skipper)
Definition rlerle.h:56
int test
Definition test6.cpp:32