Richard Boegli's CnC_Generals_Zero_Hour Fork WIP
This is documentation of Richard Boegil's Zero Hour Fork
 
Loading...
Searching...
No Matches
blitblit.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/blitblit.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 BLITBLIT_H
38#define BLITBLIT_H
39
40
41/*
42** This module contains the pixel-pushing blitter objects. These objects only
43** serve one purpose. That is, to move pixels from one location to another. These
44** are prime candidates for optimization since they are called frequently and
45** loop greatly.
46**
47** The large variety of blitter objects is necessary because there is a rich
48** set of pixel operations required by the game engine. Complicating this is that
49** the game engine must support both 16 bit and 8 bit pixel formats. Some of these
50** blitter objects are templates (this reduces the need for both 8 and 16 bit
51** counterparts if the algorithm is constant between pixel formats). Also note
52** that there are some assembly implementations where it seems appropriate.
53**
54** If the blitter object has "Xlat" in the name, then this means that the source
55** pixel is 8 bit and the destination pixel is 16 bit (probably). This hybrid system
56** allows the game artwork to be shared between the two pixel format displays. To
57** accomplish this, a translation table is supplied to the blit operation so that
58** the 8 bit pixel can be converted into the appropriate 16 bit destination pixel.
59** If the destination surface is also 8 bit, then the translation table converts
60** the pixel to the logical palette color index appropriate for the display.
61*/
62
63
64#include "blitter.h"
65#include <assert.h>
66#include <string.h>
67
68
69/*
70** Blits without translation and source and dest are same pixel format. Note that
71** this uses the memcpy and memmove routines. The C library has optimized these for
72** maximum performance. This includes alignment issues and performing REP MOVSD
73** instruction. This might be further optimized by using MMX instructions. However,
74** this blitter process is not often required by the game.
75*/
76template<class T>
77class BlitPlain : public Blitter {
78 public:
79 virtual void BlitForward(void * dest, void const * source, int length) const {memcpy(dest, source, length*sizeof(T));}
80 virtual void BlitBackward(void * dest, void const * source, int length) const {memmove(dest, source, length*sizeof(T));}
81};
82
83
84/*
85** Blits with transparency checking when and source and dest are same pixel format.
86** This process is not often used.
87*/
88template<class T>
89class BlitTrans : public Blitter {
90 public:
91 virtual void BlitForward(void * dest, void const * source, int len) const
92 {
93 for (int index = 0; index < len; index++) {
94 T color = *(T const *)source;
95 source = ((T *)source) + 1;
96 if (color != 0) *((T *)dest) = color;
97 dest = ((T *)dest) + 1;
98 }
99 }
100
101 /*
102 ** The backward moving method will probably never be called in actual practice.
103 ** Implement in terms of the forward copying method until the need for this
104 ** version arrises.
105 */
106 virtual void BlitBackward(void * dest, void const * source, int length) const {BlitForward(dest, source, length);}
107};
108
109
110/*
111** Blits when source 8 bits and dest is T. This process is typically used
112** when loading screen bitmaps or perform other non-transparent image blitting.
113** It is used fairly frequently and is a good candidate for optimization.
114*/
115template<class T>
116class BlitPlainXlat : public Blitter {
117 public:
118 BlitPlainXlat(T const * translator) : TranslateTable(translator) {assert(TranslateTable != NULL);}
119 virtual void BlitForward(void * dest, void const * source, int len) const
120 {
121 for (int index = 0; index < len; index++) {
122 unsigned char color = *(unsigned char const *)source;
123 source = ((unsigned char const *)source)+1;
124 *((T *)dest) = TranslateTable[color];
125 dest = ((T *)dest) + 1;
126 }
127 }
128
129 /*
130 ** The backward moving method will probably never be called in actual practice.
131 ** Implement in terms of the forward copying method until the need for this
132 ** version arrises.
133 */
134 virtual void BlitBackward(void * dest, void const * source, int length) const {BlitForward(dest, source, length);}
135
136 private:
137 T const * TranslateTable;
138};
139
140
141/*
142** Blits with source 8 bit with transparency and dest is T. This process is used
143** frequently by trees and other terrain objects. It is a good candidate for
144** optimization.
145*/
146template<class T>
147class BlitTransXlat : public Blitter {
148 public:
149 BlitTransXlat(T const * translator) : TranslateTable(translator) {assert(TranslateTable != NULL);}
150 virtual void BlitForward(void * dest, void const * source, int len) const
151 {
152 for (int index = 0; index < len; index++) {
153 unsigned char color = *(unsigned char const *)source;
154 source = ((unsigned char const *)source)+1;
155 if (color != 0) {
156 *((T *)dest) = TranslateTable[color];
157 }
158 dest = ((T *)dest) + 1;
159 }
160 }
161
162 /*
163 ** The backward moving method will probably never be called in actual practice.
164 ** Implement in terms of the forward copying method until the need for this
165 ** version arrises.
166 */
167 virtual void BlitBackward(void * dest, void const * source, int length) const {BlitForward(dest, source, length);}
168
169 private:
170 T const * TranslateTable;
171};
172
173
174/*
175** Blits with source 8 bit, transparency check, then translate to pixel format T. This
176** is occasionally used to render special remapping effects. Since the remap table is
177** not doubly indirected, it is fixed to only using the remap table specified in the
178** constructor. As such, it has limited value.
179*/
180template<class T>
182 public:
183 BlitTransRemapXlat(unsigned char const * remapper, T const * translator) : RemapTable(remapper), TranslateTable(translator) {assert(RemapTable != NULL);assert(TranslateTable != NULL);}
184 virtual void BlitForward(void * dest, void const * source, int length) const
185 {
186 for (int index = 0; index < length; index++) {
187 unsigned char color = *(unsigned char const *)source;
188 source = ((unsigned char const *)source)+1;
189 if (color != 0) {
190 *((T *)dest) = TranslateTable[RemapTable[color]];
191 }
192 dest = ((T *)dest) + 1;
193 }
194 }
195
196 /*
197 ** The backward moving method will probably never be called in actual practice.
198 ** Implement in terms of the forward copying method until the need for this
199 ** version arrises.
200 */
201 virtual void BlitBackward(void * dest, void const * source, int length) const {BlitForward(dest, source, length);}
202
203 private:
204 unsigned char const * RemapTable;
205 T const * TranslateTable;
206};
207
208
209/*
210** Blits with source 8 bit with transparency then remap and dest is T. This is probably
211** the most used blitter process. Units, infantry, buildings, and aircraft use this for
212** their normal drawing needs. If any blitter process is to be optimized, this would be
213** the one. Take note that the remapper table is doubly indirected. This allows a single
214** blitter object to dynamically use alternate remap tables.
215*/
216template<class T>
218 public:
219 BlitTransZRemapXlat(unsigned char const * const * remapper, T const * translator) : RemapTable(remapper), TranslateTable(translator) {assert(RemapTable != NULL);assert(TranslateTable != NULL);}
220 virtual void BlitForward(void * dest, void const * source, int length) const
221 {
222 unsigned char const * rtable = *RemapTable;
223 for (int index = 0; index < length; index++) {
224 unsigned char color = *(unsigned char const *)source;
225 source = ((unsigned char const *)source)+1;
226 if (color != 0) {
227 *((T *)dest) = TranslateTable[rtable[color]];
228 }
229 dest = ((T *)dest) + 1;
230 }
231 }
232
233 /*
234 ** The backward moving method will probably never be called in actual practice.
235 ** Implement in terms of the forward copying method until the need for this
236 ** version arrises.
237 */
238 virtual void BlitBackward(void * dest, void const * source, int length) const {BlitForward(dest, source, length);}
239
240 private:
241 unsigned char const * const * RemapTable;
242 T const * TranslateTable;
243};
244
245
246/*
247** Algorithmic darkening of hicolor pixels controlled by the source pixels. The source
248** pixels are examined only to determine if the destination pixel should be darkened.
249** If the source pixel is transparent, then the dest pixel is skipped. The darkening
250** algorithm works only for hicolor pixels.
251*/
252template<class T>
253class BlitTransDarken : public Blitter {
254 public:
255 BlitTransDarken(T mask) : Mask(mask) {}
256 virtual void BlitForward(void * dest, void const * source, int length) const
257 {
258 for (int index = 0; index < length; index++) {
259 unsigned char color = *(unsigned char const *)source;
260 source = ((unsigned char const *)source)+1;
261 if (color != 0) {
262 *((T *)dest) = (T)((((*(T *)dest) >> 1) & Mask));
263 }
264 dest = ((T *)dest) + 1;
265 }
266 }
267
268 /*
269 ** The backward moving method will probably never be called in actual practice.
270 ** Implement in terms of the forward copying method until the need for this
271 ** version arrises.
272 */
273 virtual void BlitBackward(void * dest, void const * source, int length) const {BlitForward(dest, source, length);}
274
275 private:
276 T Mask;
277};
278
279
280/*
281** This will remap the destination pixels but under the control of the source pixels.
282** Where the source pixel is not transparent, the dest pixel is remapped. This algorithm
283** really only applies to lowcolor display.
284*/
285template<class T>
287 public:
288 BlitTransRemapDest(T const * remap) : RemapTable(remap) {}
289 virtual void BlitForward(void * dest, void const * source, int length) const
290 {
291 for (int index = 0; index < length; index++) {
292 unsigned char color = *(unsigned char const *)source;
293 source = ((unsigned char const *)source)+1;
294 if (color != 0) {
295 *((T *)dest) = RemapTable[*((T *)dest)];
296 }
297 dest = ((T *)dest) + 1;
298 }
299 }
300
301 /*
302 ** The backward moving method will probably never be called in actual practice.
303 ** Implement in terms of the forward copying method until the need for this
304 ** version arrises.
305 */
306 virtual void BlitBackward(void * dest, void const * source, int length) const {BlitForward(dest, source, length);}
307
308 private:
309 T const * RemapTable;
310};
311
312
313/*
314** This is similar to BlitTransDarken but instead of examining the source to determine what
315** pixels should be darkened, every destination pixel is darkened. This means that the source
316** pointer is unused.
317*/
318template<class T>
319class BlitDarken : public Blitter {
320 public:
321 BlitDarken(T mask) : Mask(mask) {}
322 virtual void BlitForward(void * dest, void const * , int length) const
323 {
324 for (int index = 0; index < length; index++) {
325 *((T *)dest) = (T)(((*(T *)dest) >> 1) & Mask);
326 dest = ((T *)dest) + 1;
327 }
328 }
329
330 /*
331 ** The backward moving method will probably never be called in actual practice.
332 ** Implement in terms of the forward copying method until the need for this
333 ** version arrises.
334 */
335 virtual void BlitBackward(void * dest, void const * source, int length) const {BlitForward(dest, source, length);}
336
337 private:
338 T Mask;
339};
340
341
342/*
343** This blitter performs 50% translucency as it draws. It is commonly used for animation
344** effects and other stealth like images. It only works with hicolor pixels but is a good
345** candidate for optimization.
346*/
347template<class T>
349 public:
350 BlitTransLucent50(T const * translator, T mask) : TranslateTable(translator), Mask(mask) {assert(TranslateTable != NULL);}
351 virtual void BlitForward(void * dest, void const * source, int length) const
352 {
353 for (int index = 0; index < length; index++) {
354 unsigned char color = *(unsigned char const *)source;
355 source = ((unsigned char *)source) + 1;
356 if (color != 0) {
357 *((T *)dest) = (T)((((*(T *)dest) >> 1) & Mask) + ((TranslateTable[color] >> 1) & Mask));
358 }
359 dest = ((T *)dest) + 1;
360 }
361 }
362
363 /*
364 ** The backward moving method will probably never be called in actual practice.
365 ** Implement in terms of the forward copying method until the need for this
366 ** version arrises.
367 */
368 virtual void BlitBackward(void * dest, void const * source, int length) const {BlitForward(dest, source, length);}
369
370 private:
371 T const * TranslateTable;
372 T Mask;
373};
374
375
376/*
377** This blitter performs 25% translucency as it draws. This effect is less than spectacular,
378** but there are some uses for it. It only works with hicolor pixels.
379*/
380template<class T>
382 public:
383 BlitTransLucent25(T const * translator, T mask) : TranslateTable(translator), Mask(mask) {assert(TranslateTable != NULL);}
384 virtual void BlitForward(void * dest, void const * source, int length) const
385 {
386 for (int index = 0; index < length; index++) {
387 unsigned char color = *(unsigned char const *)source;
388 source = ((unsigned char *)source) + 1;
389 if (color != 0) {
390 T qsource = (T)(((TranslateTable[color] >> 2) & Mask));
391 T qdest = (T)((((*(T *)dest) >> 2) & Mask));
392 *((T *)dest) = (T)(qdest + qsource + qsource + qsource);
393 }
394 dest = ((T *)dest) + 1;
395 }
396 }
397
398 /*
399 ** The backward moving method will probably never be called in actual practice.
400 ** Implement in terms of the forward copying method until the need for this
401 ** version arrises.
402 */
403 virtual void BlitBackward(void * dest, void const * source, int length) const {BlitForward(dest, source, length);}
404
405 private:
406 T const * TranslateTable;
407 T Mask;
408};
409
410
411/*
412** This blitter performs 75% translucency as it draws. This is quite useful for explosions and
413** other gas animation effects. It only works with hicolor pixels and is a good candidate
414** for optimization.
415*/
416template<class T>
418 public:
419 BlitTransLucent75(T const * translator, T mask) : TranslateTable(translator), Mask(mask) {assert(TranslateTable != NULL);}
420 virtual void BlitForward(void * dest, void const * source, int length) const
421 {
422 for (int index = 0; index < length; index++) {
423 unsigned char color = *(unsigned char const *)source;
424 source = ((unsigned char *)source) + 1;
425 if (color != 0) {
426 T qsource = (T)(((TranslateTable[color] >> 2) & Mask));
427 T qdest = (T)(((*(T *)dest) >> 2) & Mask);
428 *((T *)dest) = (T)(qdest + qdest + qdest + qsource);
429 }
430 dest = ((T *)dest) + 1;
431 }
432 }
433
434 /*
435 ** The backward moving method will probably never be called in actual practice.
436 ** Implement in terms of the forward copying method until the need for this
437 ** version arrises.
438 */
439 virtual void BlitBackward(void * dest, void const * source, int length) const {BlitForward(dest, source, length);}
440
441 private:
442 T const * TranslateTable;
443 T Mask;
444};
445
446
447/*
448** Assembly versions of some of the templated blitter object functions. Borland and
449** Visual C++ support a compatible inline-assembly formats. However, Borland compiler
450** does not allow inline-assembly to be part of an inline function -- go figure.
451** It will still compile, it just generates warning messages.
452*/
453#if defined(_MSC_VER)
454
455inline void BlitTrans<unsigned char>::BlitForward(void * dest, void const * source, int len) const
456{
457 __asm {
458 mov esi,[source]
459 mov edi,[dest]
460 mov ecx,[len]
461 dec edi
462 inc ecx
463 }
464again:
465 __asm {
466 dec ecx
467 jz fini
468 mov al,[esi]
469 inc edi
470 inc esi
471 test al,al
472 jz again
473 mov [edi],al
474 jmp again
475 }
476fini:;
477}
478
479
480inline void BlitTransXlat<unsigned short>::BlitForward(void * dest, void const * source, int len) const
481{
482 unsigned short const * xlator = TranslateTable;
483
484 __asm {
485 mov ebx,[xlator]
486 mov ecx,[len]
487 inc ecx
488 mov edi,[dest]
489 sub edi,2
490 mov esi,[source]
491 xor eax,eax
492 }
493again:
494 __asm {
495 dec ecx
496 jz over
497 add edi,2
498 mov al,[esi]
499 inc esi
500 or al,al
501 jz again
502 mov dx,[ebx+eax*2]
503 mov [edi],dx
504 jmp again
505 }
506over:;
507}
508
509
510inline void BlitTransRemapXlat<unsigned short>::BlitForward(void * dest, void const * source, int len) const
511{
512 unsigned short const * translator = TranslateTable;
513 unsigned char const * remapper = RemapTable;
514
515 __asm {
516 mov ecx,[len]
517 mov edi,[dest]
518 sub edi,2
519 mov esi,[source]
520 mov ebx,[remapper]
521 mov edx,[translator]
522 xor eax,eax
523 }
524
525 /*
526 ** This block is 11 cycles per pixel, if not transparent, and 5
527 ** cycles per pixel, if transparent.
528 */
529again:
530 __asm {
531 dec ecx
532 jz over
533 add edi,2
534 xor eax,eax
535 lodsb
536 or al,al
537 jz again
538 mov al,[ebx+eax] // First remap step (8 bit to 8 bit).
539 mov ax,[edx+eax*2] // Second remap step (8 bit to 16 bit).
540 mov [edi],ax
541 jmp again
542 }
543over:;
544}
545
546
547inline void BlitTransZRemapXlat<unsigned short>::BlitForward(void * dest, void const * source, int len) const
548{
549 unsigned short const * translator = TranslateTable;
550 unsigned char const * remapper = *RemapTable;
551
552 __asm {
553 mov ecx,[len]
554 mov edi,[dest]
555 sub edi,2
556 mov esi,[source]
557 mov ebx,[remapper]
558 mov edx,[translator]
559 xor eax,eax
560 }
561
562 /*
563 ** This block is 11 cycles per pixel, if not transparent, and 5
564 ** cycles per pixel, if transparent.
565 */
566again:
567 __asm {
568 dec ecx
569 jz over
570 add edi,2
571 xor eax,eax
572 lodsb
573 or al,al
574 jz again
575 mov al,[ebx+eax] // First remap step (8 bit to 8 bit).
576 mov ax,[edx+eax*2] // Second remap step (8 bit to 16 bit).
577 mov [edi],ax
578 jmp again
579 }
580over:;
581}
582
583
584inline void BlitPlainXlat<unsigned short>::BlitForward(void * dest, void const * source, int len) const
585{
586 unsigned short const * remapper = TranslateTable;
587 __asm {
588 mov ebx,[remapper]
589 mov ecx,[len]
590 mov esi,[source]
591 mov edi,[dest]
592 sub edi,2
593 }
594again:
595 /*
596 ** This block processes pixels at 7 clocks per pixel.
597 */
598 __asm {
599 xor eax,eax
600 add edi,2
601 mov al,[esi]
602 inc esi
603 mov ax,[ebx+eax*2]
604 mov [edi],ax
605 dec ecx
606 jnz again
607 }
608}
609
610
611#endif
612
613
614#endif
#define NULL
Definition BaseType.h:92
void add(float *sum, float *addend)
virtual void BlitForward(void *dest, void const *, int length) const
Definition blitblit.h:322
virtual void BlitBackward(void *dest, void const *source, int length) const
Definition blitblit.h:335
BlitDarken(T mask)
Definition blitblit.h:321
virtual void BlitForward(void *dest, void const *source, int length) const
Definition blitblit.h:79
virtual void BlitBackward(void *dest, void const *source, int length) const
Definition blitblit.h:80
BlitPlainXlat(T const *translator)
Definition blitblit.h:118
virtual void BlitBackward(void *dest, void const *source, int length) const
Definition blitblit.h:134
virtual void BlitForward(void *dest, void const *source, int len) const
Definition blitblit.h:119
virtual void BlitBackward(void *dest, void const *source, int length) const
Definition blitblit.h:273
virtual void BlitForward(void *dest, void const *source, int length) const
Definition blitblit.h:256
BlitTransDarken(T mask)
Definition blitblit.h:255
virtual void BlitForward(void *dest, void const *source, int len) const
Definition blitblit.h:91
virtual void BlitBackward(void *dest, void const *source, int length) const
Definition blitblit.h:106
virtual void BlitBackward(void *dest, void const *source, int length) const
Definition blitblit.h:403
virtual void BlitForward(void *dest, void const *source, int length) const
Definition blitblit.h:384
BlitTransLucent25(T const *translator, T mask)
Definition blitblit.h:383
BlitTransLucent50(T const *translator, T mask)
Definition blitblit.h:350
virtual void BlitBackward(void *dest, void const *source, int length) const
Definition blitblit.h:368
virtual void BlitForward(void *dest, void const *source, int length) const
Definition blitblit.h:351
virtual void BlitBackward(void *dest, void const *source, int length) const
Definition blitblit.h:439
BlitTransLucent75(T const *translator, T mask)
Definition blitblit.h:419
virtual void BlitForward(void *dest, void const *source, int length) const
Definition blitblit.h:420
virtual void BlitForward(void *dest, void const *source, int length) const
Definition blitblit.h:289
BlitTransRemapDest(T const *remap)
Definition blitblit.h:288
virtual void BlitBackward(void *dest, void const *source, int length) const
Definition blitblit.h:306
BlitTransRemapXlat(unsigned char const *remapper, T const *translator)
Definition blitblit.h:183
virtual void BlitForward(void *dest, void const *source, int length) const
Definition blitblit.h:184
virtual void BlitBackward(void *dest, void const *source, int length) const
Definition blitblit.h:201
virtual void BlitForward(void *dest, void const *source, int len) const
Definition blitblit.h:150
BlitTransXlat(T const *translator)
Definition blitblit.h:149
virtual void BlitBackward(void *dest, void const *source, int length) const
Definition blitblit.h:167
BlitTransZRemapXlat(unsigned char const *const *remapper, T const *translator)
Definition blitblit.h:219
virtual void BlitForward(void *dest, void const *source, int length) const
Definition blitblit.h:220
virtual void BlitBackward(void *dest, void const *source, int length) const
Definition blitblit.h:238
int test
Definition test6.cpp:32