workaround a problem with the harmattan gcc
[drnoksnes] / tile.cpp
1 /*
2  * Snes9x - Portable Super Nintendo Entertainment System (TM) emulator.
3  *
4  * (c) Copyright 1996 - 2001 Gary Henderson (gary.henderson@ntlworld.com) and
5  *                           Jerremy Koot (jkoot@snes9x.com)
6  *
7  * Super FX C emulator code 
8  * (c) Copyright 1997 - 1999 Ivar (ivar@snes9x.com) and
9  *                           Gary Henderson.
10  * Super FX assembler emulator code (c) Copyright 1998 zsKnight and _Demo_.
11  *
12  * DSP1 emulator code (c) Copyright 1998 Ivar, _Demo_ and Gary Henderson.
13  * C4 asm and some C emulation code (c) Copyright 2000 zsKnight and _Demo_.
14  * C4 C code (c) Copyright 2001 Gary Henderson (gary.henderson@ntlworld.com).
15  *
16  * DOS port code contains the works of other authors. See headers in
17  * individual files.
18  *
19  * Snes9x homepage: http://www.snes9x.com
20  *
21  * Permission to use, copy, modify and distribute Snes9x in both binary and
22  * source form, for non-commercial purposes, is hereby granted without fee,
23  * providing that this license information and copyright notice appear with
24  * all copies and any derived work.
25  *
26  * This software is provided 'as-is', without any express or implied
27  * warranty. In no event shall the authors be held liable for any damages
28  * arising from the use of this software.
29  *
30  * Snes9x is freeware for PERSONAL USE only. Commercial users should
31  * seek permission of the copyright holders first. Commercial use includes
32  * charging money for Snes9x or software derived from Snes9x.
33  *
34  * The copyright holders request that bug fixes and improvements to the code
35  * should be forwarded to them so everyone can benefit from the modifications
36  * in future versions.
37  *
38  * Super NES and Super Nintendo Entertainment System are trademarks of
39  * Nintendo Co., Limited and its subsidiary companies.
40  */
41 #include "snes9x.h"
42
43 #include "memmap.h"
44 #include "ppu.h"
45 #include "gfx.h"
46 #include "tile.h"
47
48 #define TILE_PREAMBLE \
49     uint8 *pCache; \
50 \
51     uint32 TileAddr = BG.TileAddress + ((Tile & 0x3ff) << BG.TileShift); \
52     if ((Tile & 0x1ff) >= 256) \
53         TileAddr += BG.NameSelect; \
54 \
55     TileAddr &= 0xffff; \
56 \
57     uint32 TileNumber; \
58     pCache = &BG.Buffer[(TileNumber = (TileAddr >> BG.TileShift)) << 6]; \
59 \
60     if (!BG.Buffered [TileNumber]) \
61         BG.Buffered[TileNumber] = ConvertTile (pCache, TileAddr); \
62 \
63     if (BG.Buffered [TileNumber] == BLANK_TILE) \
64         return; \
65 \
66     register uint32 l; \
67     if (BG.DirectColourMode) \
68     { \
69         if (IPPU.DirectColourMapsNeedRebuild) \
70             S9xBuildDirectColourMaps (); \
71         GFX.ScreenColors = DirectColourMaps [(Tile >> 10) & BG.PaletteMask]; \
72     } \
73     else \
74         GFX.ScreenColors = &IPPU.ScreenColors [(((Tile >> 10) & BG.PaletteMask) << BG.PaletteShift) + BG.StartPalette];
75
76 #define RENDER_TILE(NORMAL, FLIPPED, N) \
77     if (!(Tile & (V_FLIP | H_FLIP))) \
78     { \
79         bp = pCache + StartLine; \
80         for (l = LineCount; l != 0; l--, bp += 8, Offset += GFX.PPL) \
81         { \
82             if (*(uint32 *) bp) \
83                 NORMAL (Offset, bp); \
84             if (*(uint32 *) (bp + 4)) \
85                 NORMAL (Offset + N, bp + 4); \
86         } \
87     } \
88     else \
89     if (!(Tile & V_FLIP)) \
90     { \
91         bp = pCache + StartLine; \
92         for (l = LineCount; l != 0; l--, bp += 8, Offset += GFX.PPL) \
93         { \
94             if (*(uint32 *) (bp + 4)) \
95                 FLIPPED (Offset, bp + 4); \
96             if (*(uint32 *) bp) \
97                 FLIPPED (Offset + N, bp); \
98         } \
99     } \
100     else \
101     if (Tile & H_FLIP) \
102     { \
103         bp = pCache + 56 - StartLine; \
104         for (l = LineCount; l != 0; l--, bp -= 8, Offset += GFX.PPL) \
105         { \
106             if (*(uint32 *) (bp + 4)) \
107                 FLIPPED (Offset, bp + 4); \
108             if (*(uint32 *) bp) \
109                 FLIPPED (Offset + N, bp); \
110         } \
111     } \
112     else \
113     { \
114         bp = pCache + 56 - StartLine; \
115         for (l = LineCount; l != 0; l--, bp -= 8, Offset += GFX.PPL) \
116         { \
117             if (*(uint32 *) bp) \
118                 NORMAL (Offset, bp); \
119             if (*(uint32 *) (bp + 4)) \
120                 NORMAL (Offset + N, bp + 4); \
121         } \
122     }
123
124 #define TILE_CLIP_PREAMBLE \
125     uint32 dd; \
126     uint32 d1; \
127     uint32 d2; \
128 \
129     if (StartPixel < 4) \
130     { \
131         d1 = HeadMask [StartPixel]; \
132         if (StartPixel + Width < 4) \
133             d1 &= TailMask [StartPixel + Width]; \
134     } \
135     else \
136         d1 = 0; \
137 \
138     if (StartPixel + Width > 4) \
139     { \
140         if (StartPixel > 4) \
141             d2 = HeadMask [StartPixel - 4]; \
142         else \
143             d2 = 0xffffffff; \
144 \
145         d2 &= TailMask [(StartPixel + Width - 4)]; \
146     } \
147     else \
148         d2 = 0;
149
150
151 #define RENDER_CLIPPED_TILE(NORMAL, FLIPPED, N) \
152     if (!(Tile & (V_FLIP | H_FLIP))) \
153     { \
154         bp = pCache + StartLine; \
155         for (l = LineCount; l != 0; l--, bp += 8, Offset += GFX.PPL) \
156         { \
157             if ((dd = (*(uint32 *) bp) & d1)) \
158                 NORMAL (Offset, (uint8 *) &dd); \
159             if ((dd = (*(uint32 *) (bp + 4)) & d2)) \
160                 NORMAL (Offset + N, (uint8 *) &dd); \
161         } \
162     } \
163     else \
164     if (!(Tile & V_FLIP)) \
165     { \
166         bp = pCache + StartLine; \
167         SWAP_DWORD (d1); \
168         SWAP_DWORD (d2); \
169         for (l = LineCount; l != 0; l--, bp += 8, Offset += GFX.PPL) \
170         { \
171             if ((dd = *(uint32 *) (bp + 4) & d1)) \
172                 FLIPPED (Offset, (uint8 *) &dd); \
173             if ((dd = *(uint32 *) bp & d2)) \
174                 FLIPPED (Offset + N, (uint8 *) &dd); \
175         } \
176     } \
177     else \
178     if (Tile & H_FLIP) \
179     { \
180         bp = pCache + 56 - StartLine; \
181         SWAP_DWORD (d1); \
182         SWAP_DWORD (d2); \
183         for (l = LineCount; l != 0; l--, bp -= 8, Offset += GFX.PPL) \
184         { \
185             if ((dd = *(uint32 *) (bp + 4) & d1)) \
186                 FLIPPED (Offset, (uint8 *) &dd); \
187             if ((dd = *(uint32 *) bp & d2)) \
188                 FLIPPED (Offset + N, (uint8 *) &dd); \
189         } \
190     } \
191     else \
192     { \
193         bp = pCache + 56 - StartLine; \
194         for (l = LineCount; l != 0; l--, bp -= 8, Offset += GFX.PPL) \
195         { \
196             if ((dd = (*(uint32 *) bp) & d1)) \
197                 NORMAL (Offset, (uint8 *) &dd); \
198             if ((dd = (*(uint32 *) (bp + 4)) & d2)) \
199                 NORMAL (Offset + N, (uint8 *) &dd); \
200         } \
201     }
202
203 #define RENDER_TILE_LARGE(PIXEL, FUNCTION) \
204     if (!(Tile & (V_FLIP | H_FLIP))) \
205     { \
206         if ((pixel = *(pCache + StartLine + StartPixel))) \
207         { \
208             pixel = PIXEL; \
209             for (l = LineCount; l != 0; l--, sp += GFX.PPL, Depth += GFX.PPL) \
210             { \
211                 for (int z = Pixels - 1; z >= 0; z--) \
212                     if (GFX.Z1 > Depth [z]) \
213                     { \
214                         sp [z] = FUNCTION(sp + z, pixel); \
215                         Depth [z] = GFX.Z2; \
216                     }\
217             } \
218         } \
219     } \
220     else \
221     if (!(Tile & V_FLIP)) \
222     { \
223         StartPixel = 7 - StartPixel; \
224         if ((pixel = *(pCache + StartLine + StartPixel))) \
225         { \
226             pixel = PIXEL; \
227             for (l = LineCount; l != 0; l--, sp += GFX.PPL, Depth += GFX.PPL) \
228             { \
229                 for (int z = Pixels - 1; z >= 0; z--) \
230                     if (GFX.Z1 > Depth [z]) \
231                     { \
232                         sp [z] = FUNCTION(sp + z, pixel); \
233                         Depth [z] = GFX.Z2; \
234                     }\
235             } \
236         } \
237     } \
238     else \
239     if (Tile & H_FLIP) \
240     { \
241         StartPixel = 7 - StartPixel; \
242         if ((pixel = *(pCache + 56 - StartLine + StartPixel))) \
243         { \
244             pixel = PIXEL; \
245             for (l = LineCount; l != 0; l--, sp += GFX.PPL, Depth += GFX.PPL) \
246             { \
247                 for (int z = Pixels - 1; z >= 0; z--) \
248                     if (GFX.Z1 > Depth [z]) \
249                     { \
250                         sp [z] = FUNCTION(sp + z, pixel); \
251                         Depth [z] = GFX.Z2; \
252                     }\
253             } \
254         } \
255     } \
256     else \
257     { \
258         if ((pixel = *(pCache + 56 - StartLine + StartPixel))) \
259         { \
260             pixel = PIXEL; \
261             for (l = LineCount; l != 0; l--, sp += GFX.PPL, Depth += GFX.PPL) \
262             { \
263                 for (int z = Pixels - 1; z >= 0; z--) \
264                     if (GFX.Z1 > Depth [z]) \
265                     { \
266                         sp [z] = FUNCTION(sp + z, pixel); \
267                         Depth [z] = GFX.Z2; \
268                     }\
269             } \
270         } \
271     }
272         
273 #define RENDER_TILEHI(NORMAL, FLIPPED, N) \
274     if (!(Tile & (V_FLIP | H_FLIP))) \
275     { \
276         bp = pCache + StartLine; \
277         for (l = LineCount; l != 0; l--, bp += 8, Offset += GFX.PPL) \
278         { \
279             /*if (*(uint32 *) bp)*/if (((uint32)bp[0])|((uint32)bp[2])|((uint32)bp[4])|((uint32)bp[6])) \
280                 NORMAL (Offset, bp); \
281         } \
282     } \
283     else \
284     if (!(Tile & V_FLIP)) \
285     { \
286         bp = pCache + StartLine; \
287         for (l = LineCount; l != 0; l--, bp += 8, Offset += GFX.PPL) \
288         { \
289             /*if (*(uint32 *) (bp + 4))*/if (((uint32)bp[0])|((uint32)bp[2])|((uint32)bp[4])|((uint32)bp[6])) \
290                 FLIPPED (Offset, bp); \
291         } \
292     } \
293     else \
294     if (Tile & H_FLIP) \
295     { \
296         bp = pCache + 56 - StartLine; \
297         for (l = LineCount; l != 0; l--, bp -= 8, Offset += GFX.PPL) \
298         { \
299             /*if (*(uint32 *) (bp + 4))*/if (((uint32)bp[0])|((uint32)bp[2])|((uint32)bp[4])|((uint32)bp[6]))  \
300                 FLIPPED (Offset, bp); \
301         } \
302     } \
303     else \
304     { \
305         bp = pCache + 56 - StartLine; \
306         for (l = LineCount; l != 0; l--, bp -= 8, Offset += GFX.PPL) \
307         { \
308             /*if (*(uint32 *) bp)*/if (((uint32)bp[0])|((uint32)bp[2])|((uint32)bp[4])|((uint32)bp[6])) \
309                 NORMAL (Offset, bp); \
310         } \
311     }
312     
313     
314     
315 #define RENDER_CLIPPED_TILEHI(NORMAL, FLIPPED, N) \
316         d1=(d1&0xFF)|((d1&0xFF0000)>>8)|((d2&0xFF)<<16)|((d2&0xFF0000)<<8);\
317     if (!(Tile & (V_FLIP | H_FLIP))) \
318     { \
319         bp = pCache + StartLine; \
320         for (l = LineCount; l != 0; l--, bp += 8, Offset += GFX.PPL) \
321         { \
322             /*if ((dd = (*(uint32 *) bp) & d1))*/if ((dd = (((((uint32)bp[6])<<24)|(((uint32)bp[4])<<16)|(((uint32)bp[2])<<8)|((uint32)bp[0]))&d1))) \
323                 NORMAL (Offset, (uint8 *) &dd); \
324         } \
325     } \
326     else \
327     if (!(Tile & V_FLIP)) \
328     { \
329         bp = pCache + StartLine; \
330         SWAP_DWORD (d1); \
331         /*SWAP_DWORD (d2);*/ \
332         for (l = LineCount; l != 0; l--, bp += 8, Offset += GFX.PPL) \
333         { \
334             /*if ((dd = *(uint32 *) (bp + 4) & d1))*/if ((dd = (((((uint32)bp[6])<<24)|(((uint32)bp[4])<<16)|(((uint32)bp[2])<<8)|((uint32)bp[0]))&d1))) \
335                 FLIPPED (Offset, (uint8 *) &dd); \
336         } \
337     } \
338     else \
339     if (Tile & H_FLIP) \
340     { \
341         bp = pCache + 56 - StartLine; \
342         SWAP_DWORD (d1); \
343         /*SWAP_DWORD (d2);*/ \
344         for (l = LineCount; l != 0; l--, bp -= 8, Offset += GFX.PPL) \
345         { \
346             /*if ((dd = *(uint32 *) (bp + 4) & d1))*/if ((dd = (((((uint32)bp[6])<<24)|(((uint32)bp[4])<<16)|(((uint32)bp[2])<<8)|((uint32)bp[0]))&d1))) \
347                 FLIPPED (Offset, (uint8 *) &dd); \
348         } \
349     } \
350     else \
351     { \
352         bp = pCache + 56 - StartLine; \
353         for (l = LineCount; l != 0; l--, bp -= 8, Offset += GFX.PPL) \
354         { \
355             /*if ((dd = (*(uint32 *) bp) & d1))*/ if ((dd = (((((uint32)bp[6])<<24)|(((uint32)bp[4])<<16)|(((uint32)bp[2])<<8)|((uint32)bp[0]))&d1))) \
356                 NORMAL (Offset, (uint8 *) &dd); \
357         } \
358     }
359
360 #define PLOT_PIXEL(screen, pixel) (pixel)
361
362 extern uint32 HeadMask [4];
363 extern uint32 TailMask [5];
364
365 uint8 ConvertTile (uint8 *pCache, uint32 TileAddr)
366 {
367     register uint8 *tp = &Memory.VRAM[TileAddr];
368     uint32 *p = (uint32 *) pCache;
369     uint32 non_zero = 0;
370     uint8 line;
371         uint32 p1;
372         uint32 p2;
373         register uint8 pix;
374
375     switch (BG.BitShift)
376     {
377     case 8:
378         for (line = 8; line != 0; line--, tp += 2)
379         {
380             p1 = p2 = 0;
381             if ((pix = *(tp + 0)))
382             {
383                 p1 |= odd_high[0][pix >> 4];
384                 p2 |= odd_low[0][pix & 0xf];
385             }
386             if ((pix = *(tp + 1)))
387             {
388                 p1 |= even_high[0][pix >> 4];
389                 p2 |= even_low[0][pix & 0xf];
390             }
391             if ((pix = *(tp + 16)))
392             {
393                 p1 |= odd_high[1][pix >> 4];
394                 p2 |= odd_low[1][pix & 0xf];
395             }
396             if ((pix = *(tp + 17)))
397             {
398                 p1 |= even_high[1][pix >> 4];
399                 p2 |= even_low[1][pix & 0xf];
400             }
401             if ((pix = *(tp + 32)))
402             {
403                 p1 |= odd_high[2][pix >> 4];
404                 p2 |= odd_low[2][pix & 0xf];
405             }
406             if ((pix = *(tp + 33)))
407             {
408                 p1 |= even_high[2][pix >> 4];
409                 p2 |= even_low[2][pix & 0xf];
410             }
411             if ((pix = *(tp + 48)))
412             {
413                 p1 |= odd_high[3][pix >> 4];
414                 p2 |= odd_low[3][pix & 0xf];
415             }
416             if ((pix = *(tp + 49)))
417             {
418                 p1 |= even_high[3][pix >> 4];
419                 p2 |= even_low[3][pix & 0xf];
420             }
421             *p++ = p1;
422             *p++ = p2;
423             non_zero |= p1 | p2;
424         }
425         break;
426
427     case 4:
428         for (line = 8; line != 0; line--, tp += 2)
429         {
430             p1 = p2 = 0;
431             if ((pix = *(tp + 0)))
432             {
433                 p1 |= odd_high[0][pix >> 4];
434                 p2 |= odd_low[0][pix & 0xf];
435             }
436             if ((pix = *(tp + 1)))
437             {
438                 p1 |= even_high[0][pix >> 4];
439                 p2 |= even_low[0][pix & 0xf];
440             }
441             if ((pix = *(tp + 16)))
442             {
443                 p1 |= odd_high[1][pix >> 4];
444                 p2 |= odd_low[1][pix & 0xf];
445             }
446             if ((pix = *(tp + 17)))
447             {
448                 p1 |= even_high[1][pix >> 4];
449                 p2 |= even_low[1][pix & 0xf];
450             }
451             *p++ = p1;
452             *p++ = p2;
453             non_zero |= p1 | p2;
454         }
455         break;
456
457     case 2:
458         for (line = 8; line != 0; line--, tp += 2)
459         {
460             p1 = p2 = 0;
461             if ((pix = *(tp + 0)))
462             {
463                 p1 |= odd_high[0][pix >> 4];
464                 p2 |= odd_low[0][pix & 0xf];
465             }
466             if ((pix = *(tp + 1)))
467             {
468                 p1 |= even_high[0][pix >> 4];
469                 p2 |= even_low[0][pix & 0xf];
470             }
471             *p++ = p1;
472             *p++ = p2;
473             non_zero |= p1 | p2;
474         }
475         break;
476     }
477     return (non_zero ? TRUE : BLANK_TILE);
478 }
479
480 inline void WRITE_4PIXELSHI16 (tile_offset_t Offset, uint8 *Pixels)
481 {
482     uint32 Pixel;
483     uint16 *Screen = (uint16 *) GFX.S + Offset;
484     uint8  *Depth = GFX.DB + Offset;
485
486 #define FN(N) \
487     if (GFX.Z1 > Depth [N] && (Pixel = Pixels[2*N])) \
488     { \
489         Screen [N] = GFX.ScreenColors [Pixel]; \
490         Depth [N] = GFX.Z2; \
491     }
492
493     FN(0)
494     FN(1)
495     FN(2)
496     FN(3)
497 #undef FN
498 }
499
500 inline void WRITE_4PIXELSHI16_FLIPPED (tile_offset_t Offset, uint8 *Pixels)
501 {
502     uint32 Pixel;
503     uint16 *Screen = (uint16 *) GFX.S + Offset;
504     uint8  *Depth = GFX.DB + Offset;
505
506 #define FN(N) \
507     if (GFX.Z1 > Depth [N] && (Pixel = Pixels[6 - 2*N])) \
508     { \
509         Screen [N] = GFX.ScreenColors [Pixel]; \
510         Depth [N] = GFX.Z2; \
511     }
512
513     FN(0)
514     FN(1)
515     FN(2)
516     FN(3)
517 #undef FN
518 }
519
520 STATIC INLINE void WRITE_4PIXELS16 (tile_offset_t Offset, uint8 *Pixels)
521 {
522     register uint32 Pixel;
523     uint16 *Screen = (uint16 *) GFX.S + Offset;
524     uint8  *Depth = GFX.DB + Offset;
525
526 #define FN(N) \
527     if (GFX.Z1 > Depth [N] && (Pixel = Pixels[N])) \
528     { \
529         Screen [N] = GFX.ScreenColors [Pixel]; \
530         Depth [N] = GFX.Z2; \
531     }
532
533     FN(0)
534     FN(1)
535     FN(2)
536     FN(3)
537 #undef FN
538 }
539
540 STATIC INLINE void WRITE_4PIXELS16_FLIPPED (tile_offset_t Offset, uint8 *Pixels)
541 {
542     register uint32 Pixel;
543     uint16 *Screen = (uint16 *) GFX.S + Offset;
544     uint8  *Depth = GFX.DB + Offset;
545
546 #define FN(N) \
547     if (GFX.Z1 > Depth [N] && (Pixel = Pixels[3 - N])) \
548     { \
549         Screen [N] = GFX.ScreenColors [Pixel]; \
550         Depth [N] = GFX.Z2; \
551     }
552
553     FN(0)
554     FN(1)
555     FN(2)
556     FN(3)
557 #undef FN
558 }
559
560 void DrawTile16 (uint32 Tile, tile_offset_t Offset, uint32 StartLine,
561                  uint32 LineCount)
562 {
563     TILE_PREAMBLE
564     register uint8 *bp;
565
566     RENDER_TILE(WRITE_4PIXELS16, WRITE_4PIXELS16_FLIPPED, 4)
567 }
568
569 void DrawClippedTile16 (uint32 Tile, tile_offset_t Offset,
570                         uint32 StartPixel, uint32 Width,
571                         uint32 StartLine, uint32 LineCount)
572 {
573     TILE_PREAMBLE
574     register uint8 *bp;
575
576     TILE_CLIP_PREAMBLE
577     RENDER_CLIPPED_TILE(WRITE_4PIXELS16, WRITE_4PIXELS16_FLIPPED, 4)
578 }
579
580 void DrawLargePixel16 (uint32 Tile, tile_offset_t Offset,
581                        uint32 StartPixel, uint32 Pixels,
582                        uint32 StartLine, uint32 LineCount)
583 {
584     TILE_PREAMBLE
585
586     register uint16 *sp = (uint16 *) GFX.S + Offset;
587     uint8  *Depth = GFX.DB + Offset;
588     uint16 pixel;
589
590     RENDER_TILE_LARGE (GFX.ScreenColors [pixel], PLOT_PIXEL)
591 }
592
593 STATIC INLINE void WRITE_4PIXELS16_ADD (tile_offset_t Offset, uint8 *Pixels)
594 {
595     register uint32 Pixel;
596     uint16 *Screen = (uint16 *) GFX.S + Offset;
597     uint8  *Depth = GFX.ZBuffer + Offset;
598     uint8  *SubDepth = GFX.SubZBuffer + Offset;
599
600 #define FN(N) \
601     if (GFX.Z1 > Depth [N] && (Pixel = Pixels[N])) \
602     { \
603         if (SubDepth [N]) \
604         { \
605             if (SubDepth [N] != 1) \
606                 Screen [N] = COLOR_ADD (GFX.ScreenColors [Pixel], \
607                                         Screen [GFX.Delta + N]); \
608             else \
609                 Screen [N] = COLOR_ADD (GFX.ScreenColors [Pixel], \
610                                         GFX.FixedColour); \
611         } \
612         else \
613             Screen [N] = GFX.ScreenColors [Pixel]; \
614         Depth [N] = GFX.Z2; \
615     }
616
617     FN(0)
618     FN(1)
619     FN(2)
620     FN(3)
621
622 #undef FN
623 }
624
625 STATIC INLINE void WRITE_4PIXELS16_FLIPPED_ADD (tile_offset_t Offset, uint8 *Pixels)
626 {
627     register uint32 Pixel;
628     uint16 *Screen = (uint16 *) GFX.S + Offset;
629     uint8  *Depth = GFX.ZBuffer + Offset;
630     uint8  *SubDepth = GFX.SubZBuffer + Offset;
631
632 #define FN(N) \
633     if (GFX.Z1 > Depth [N] && (Pixel = Pixels[3 - N])) \
634     { \
635         if (SubDepth [N]) \
636         { \
637             if (SubDepth [N] != 1) \
638                 Screen [N] = COLOR_ADD (GFX.ScreenColors [Pixel], \
639                                         Screen [GFX.Delta + N]); \
640             else \
641                 Screen [N] = COLOR_ADD (GFX.ScreenColors [Pixel], \
642                                         GFX.FixedColour); \
643         } \
644         else \
645             Screen [N] = GFX.ScreenColors [Pixel]; \
646         Depth [N] = GFX.Z2; \
647     }
648
649     FN(0)
650     FN(1)
651     FN(2)
652     FN(3)
653
654 #undef FN
655 }
656
657 STATIC INLINE void WRITE_4PIXELS16_ADD1_2 (tile_offset_t Offset, uint8 *Pixels)
658 {
659     register uint32 Pixel;
660     uint16 *Screen = (uint16 *) GFX.S + Offset;
661     uint8  *Depth = GFX.ZBuffer + Offset;
662     uint8  *SubDepth = GFX.SubZBuffer + Offset;
663
664 #define FN(N) \
665     if (GFX.Z1 > Depth [N] && (Pixel = Pixels[N])) \
666     { \
667         if (SubDepth [N]) \
668         { \
669             if (SubDepth [N] != 1) \
670                 Screen [N] = (uint16) (COLOR_ADD1_2 (GFX.ScreenColors [Pixel], \
671                                                      Screen [GFX.Delta + N])); \
672             else \
673                 Screen [N] = COLOR_ADD (GFX.ScreenColors [Pixel], \
674                                         GFX.FixedColour); \
675         } \
676         else \
677             Screen [N] = GFX.ScreenColors [Pixel]; \
678         Depth [N] = GFX.Z2; \
679     }
680
681     FN(0)
682     FN(1)
683     FN(2)
684     FN(3)
685
686 #undef FN
687 }
688
689 STATIC INLINE void WRITE_4PIXELS16_FLIPPED_ADD1_2 (tile_offset_t Offset, uint8 *Pixels)
690 {
691     register uint32 Pixel;
692     uint16 *Screen = (uint16 *) GFX.S + Offset;
693     uint8  *Depth = GFX.ZBuffer + Offset;
694     uint8  *SubDepth = GFX.SubZBuffer + Offset;
695
696 #define FN(N) \
697     if (GFX.Z1 > Depth [N] && (Pixel = Pixels[3 - N])) \
698     { \
699         if (SubDepth [N]) \
700         { \
701             if (SubDepth [N] != 1) \
702                 Screen [N] = (uint16) (COLOR_ADD1_2 (GFX.ScreenColors [Pixel], \
703                                                      Screen [GFX.Delta + N])); \
704             else \
705                 Screen [N] = COLOR_ADD (GFX.ScreenColors [Pixel], \
706                                         GFX.FixedColour); \
707         } \
708         else \
709             Screen [N] = GFX.ScreenColors [Pixel]; \
710         Depth [N] = GFX.Z2; \
711     }
712
713     FN(0)
714     FN(1)
715     FN(2)
716     FN(3)
717
718 #undef FN
719 }
720
721 STATIC INLINE void WRITE_4PIXELS16_SUB (tile_offset_t Offset, uint8 *Pixels)
722 {
723     register uint32 Pixel;
724     uint16 *Screen = (uint16 *) GFX.S + Offset;
725     uint8  *Depth = GFX.ZBuffer + Offset;
726     uint8  *SubDepth = GFX.SubZBuffer + Offset;
727
728 #define FN(N) \
729     if (GFX.Z1 > Depth [N] && (Pixel = Pixels[N])) \
730     { \
731         if (SubDepth [N]) \
732         { \
733             if (SubDepth [N] != 1) \
734                 Screen [N] = (uint16) COLOR_SUB (GFX.ScreenColors [Pixel], \
735                                         Screen [GFX.Delta + N]); \
736             else \
737                 Screen [N] = (uint16) COLOR_SUB (GFX.ScreenColors [Pixel], \
738                                         GFX.FixedColour); \
739         } \
740         else \
741             Screen [N] = GFX.ScreenColors [Pixel]; \
742         Depth [N] = GFX.Z2; \
743     }
744
745     FN(0)
746     FN(1)
747     FN(2)
748     FN(3)
749
750 #undef FN
751 }
752
753 STATIC INLINE void WRITE_4PIXELS16_FLIPPED_SUB (tile_offset_t Offset, uint8 *Pixels)
754 {
755     register uint32 Pixel;
756     uint16 *Screen = (uint16 *) GFX.S + Offset;
757     uint8  *Depth = GFX.ZBuffer + Offset;
758     uint8  *SubDepth = GFX.SubZBuffer + Offset;
759
760 #define FN(N) \
761     if (GFX.Z1 > Depth [N] && (Pixel = Pixels[3 - N])) \
762     { \
763         if (SubDepth [N]) \
764         { \
765             if (SubDepth [N] != 1) \
766                 Screen [N] = (uint16) COLOR_SUB (GFX.ScreenColors [Pixel], \
767                                         Screen [GFX.Delta + N]); \
768             else \
769                 Screen [N] = (uint16) COLOR_SUB (GFX.ScreenColors [Pixel], \
770                                         GFX.FixedColour); \
771         } \
772         else \
773             Screen [N] = GFX.ScreenColors [Pixel]; \
774         Depth [N] = GFX.Z2; \
775     }
776
777     FN(0)
778     FN(1)
779     FN(2)
780     FN(3)
781
782 #undef FN
783 }
784
785 STATIC INLINE void WRITE_4PIXELS16_SUB1_2 (tile_offset_t Offset, uint8 *Pixels)
786 {
787     register uint32 Pixel;
788     uint16 *Screen = (uint16 *) GFX.S + Offset;
789     uint8  *Depth = GFX.ZBuffer + Offset;
790     uint8  *SubDepth = GFX.SubZBuffer + Offset;
791
792 #define FN(N) \
793     if (GFX.Z1 > Depth [N] && (Pixel = Pixels[N])) \
794     { \
795         if (SubDepth [N]) \
796         { \
797             if (SubDepth [N] != 1) \
798                 Screen [N] = (uint16) COLOR_SUB1_2 (GFX.ScreenColors [Pixel], \
799                                            Screen [GFX.Delta + N]); \
800             else \
801                 Screen [N] = (uint16) COLOR_SUB (GFX.ScreenColors [Pixel], \
802                                         GFX.FixedColour); \
803         } \
804         else \
805             Screen [N] = GFX.ScreenColors [Pixel]; \
806         Depth [N] = GFX.Z2; \
807     }
808
809     FN(0)
810     FN(1)
811     FN(2)
812     FN(3)
813
814 #undef FN
815 }
816
817 STATIC INLINE void WRITE_4PIXELS16_FLIPPED_SUB1_2 (tile_offset_t Offset, uint8 *Pixels)
818 {
819     register uint32 Pixel;
820     uint16 *Screen = (uint16 *) GFX.S + Offset;
821     uint8  *Depth = GFX.ZBuffer + Offset;
822     uint8  *SubDepth = GFX.SubZBuffer + Offset;
823
824 #define FN(N) \
825     if (GFX.Z1 > Depth [N] && (Pixel = Pixels[3 - N])) \
826     { \
827         if (SubDepth [N]) \
828         { \
829             if (SubDepth [N] != 1) \
830                 Screen [N] = (uint16) COLOR_SUB1_2 (GFX.ScreenColors [Pixel], \
831                                            Screen [GFX.Delta + N]); \
832             else \
833                 Screen [N] = (uint16) COLOR_SUB (GFX.ScreenColors [Pixel], \
834                                         GFX.FixedColour); \
835         } \
836         else \
837             Screen [N] = GFX.ScreenColors [Pixel]; \
838         Depth [N] = GFX.Z2; \
839     }
840
841     FN(0)
842     FN(1)
843     FN(2)
844     FN(3)
845
846 #undef FN
847 }
848
849
850 void DrawTile16Add (uint32 Tile, tile_offset_t Offset, uint32 StartLine,
851                     uint32 LineCount)
852 {
853     TILE_PREAMBLE
854     register uint8 *bp;
855
856     RENDER_TILE(WRITE_4PIXELS16_ADD, WRITE_4PIXELS16_FLIPPED_ADD, 4)
857 }
858
859 void DrawClippedTile16Add (uint32 Tile, tile_offset_t Offset,
860                            uint32 StartPixel, uint32 Width,
861                            uint32 StartLine, uint32 LineCount)
862 {
863     TILE_PREAMBLE
864     register uint8 *bp;
865
866     TILE_CLIP_PREAMBLE
867     RENDER_CLIPPED_TILE(WRITE_4PIXELS16_ADD, WRITE_4PIXELS16_FLIPPED_ADD, 4)
868 }
869
870 void DrawTile16Add1_2 (uint32 Tile, tile_offset_t Offset, uint32 StartLine,
871                        uint32 LineCount)
872 {
873     TILE_PREAMBLE
874     register uint8 *bp;
875
876     RENDER_TILE(WRITE_4PIXELS16_ADD1_2, WRITE_4PIXELS16_FLIPPED_ADD1_2, 4)
877 }
878
879 void DrawClippedTile16Add1_2 (uint32 Tile, tile_offset_t Offset,
880                               uint32 StartPixel, uint32 Width,
881                               uint32 StartLine, uint32 LineCount)
882 {
883     TILE_PREAMBLE
884     register uint8 *bp;
885
886     TILE_CLIP_PREAMBLE
887     RENDER_CLIPPED_TILE(WRITE_4PIXELS16_ADD1_2, WRITE_4PIXELS16_FLIPPED_ADD1_2, 4)
888 }
889
890 void DrawTile16Sub (uint32 Tile, tile_offset_t Offset, uint32 StartLine,
891                     uint32 LineCount)
892 {
893     TILE_PREAMBLE
894     register uint8 *bp;
895
896     RENDER_TILE(WRITE_4PIXELS16_SUB, WRITE_4PIXELS16_FLIPPED_SUB, 4)
897 }
898
899 void DrawClippedTile16Sub (uint32 Tile, tile_offset_t Offset,
900                            uint32 StartPixel, uint32 Width,
901                            uint32 StartLine, uint32 LineCount)
902 {
903     TILE_PREAMBLE
904     register uint8 *bp;
905
906     TILE_CLIP_PREAMBLE
907     RENDER_CLIPPED_TILE(WRITE_4PIXELS16_SUB, WRITE_4PIXELS16_FLIPPED_SUB, 4)
908 }
909
910 void DrawTile16Sub1_2 (uint32 Tile, tile_offset_t Offset, uint32 StartLine,
911                        uint32 LineCount)
912 {
913     TILE_PREAMBLE
914     register uint8 *bp;
915
916     RENDER_TILE(WRITE_4PIXELS16_SUB1_2, WRITE_4PIXELS16_FLIPPED_SUB1_2, 4)
917 }
918
919 void DrawClippedTile16Sub1_2 (uint32 Tile, tile_offset_t Offset,
920                               uint32 StartPixel, uint32 Width,
921                               uint32 StartLine, uint32 LineCount)
922 {
923     TILE_PREAMBLE
924     register uint8 *bp;
925
926     TILE_CLIP_PREAMBLE
927     RENDER_CLIPPED_TILE(WRITE_4PIXELS16_SUB1_2, WRITE_4PIXELS16_FLIPPED_SUB1_2, 4)
928 }
929
930 STATIC INLINE void WRITE_4PIXELS16_ADDF1_2 (tile_offset_t Offset, uint8 *Pixels)
931 {
932     register uint32 Pixel;
933     uint16 *Screen = (uint16 *) GFX.S + Offset;
934     uint8  *Depth = GFX.ZBuffer + Offset;
935     uint8  *SubDepth = GFX.SubZBuffer + Offset;
936
937 #define FN(N) \
938     if (GFX.Z1 > Depth [N] && (Pixel = Pixels[N])) \
939     { \
940         if (SubDepth [N] == 1) \
941             Screen [N] = (uint16) (COLOR_ADD1_2 (GFX.ScreenColors [Pixel], \
942                                                  GFX.FixedColour)); \
943         else \
944             Screen [N] = GFX.ScreenColors [Pixel];\
945         Depth [N] = GFX.Z2; \
946     }
947
948     FN(0)
949     FN(1)
950     FN(2)
951     FN(3)
952
953 #undef FN
954 }
955
956 STATIC INLINE void WRITE_4PIXELS16_FLIPPED_ADDF1_2 (tile_offset_t Offset, uint8 *Pixels)
957 {
958     register uint32 Pixel;
959     uint16 *Screen = (uint16 *) GFX.S + Offset;
960     uint8  *Depth = GFX.ZBuffer + Offset;
961     uint8  *SubDepth = GFX.SubZBuffer + Offset;
962
963 #define FN(N) \
964     if (GFX.Z1 > Depth [N] && (Pixel = Pixels[3 - N])) \
965     { \
966         if (SubDepth [N] == 1) \
967             Screen [N] = (uint16) (COLOR_ADD1_2 (GFX.ScreenColors [Pixel], \
968                                                  GFX.FixedColour)); \
969         else \
970             Screen [N] = GFX.ScreenColors [Pixel];\
971         Depth [N] = GFX.Z2; \
972     }
973
974     FN(0)
975     FN(1)
976     FN(2)
977     FN(3)
978
979 #undef FN
980 }
981
982 STATIC INLINE void WRITE_4PIXELS16_SUBF1_2 (tile_offset_t Offset, uint8 *Pixels)
983 {
984     register uint32 Pixel;
985     uint16 *Screen = (uint16 *) GFX.S + Offset;
986     uint8  *Depth = GFX.ZBuffer + Offset;
987     uint8  *SubDepth = GFX.SubZBuffer + Offset;
988
989 #define FN(N) \
990     if (GFX.Z1 > Depth [N] && (Pixel = Pixels[N])) \
991     { \
992         if (SubDepth [N] == 1) \
993             Screen [N] = (uint16) COLOR_SUB1_2 (GFX.ScreenColors [Pixel], \
994                                                 GFX.FixedColour); \
995         else \
996             Screen [N] = GFX.ScreenColors [Pixel]; \
997         Depth [N] = GFX.Z2; \
998     }
999
1000     FN(0)
1001     FN(1)
1002     FN(2)
1003     FN(3)
1004
1005 #undef FN
1006 }
1007
1008 STATIC INLINE void WRITE_4PIXELS16_FLIPPED_SUBF1_2 (tile_offset_t Offset, uint8 *Pixels)
1009 {
1010     register uint32 Pixel;
1011     uint16 *Screen = (uint16 *) GFX.S + Offset;
1012     uint8  *Depth = GFX.ZBuffer + Offset;
1013     uint8  *SubDepth = GFX.SubZBuffer + Offset;
1014
1015 #define FN(N) \
1016     if (GFX.Z1 > Depth [N] && (Pixel = Pixels[3 - N])) \
1017     { \
1018         if (SubDepth [N] == 1) \
1019             Screen [N] = (uint16) COLOR_SUB1_2 (GFX.ScreenColors [Pixel], \
1020                                                 GFX.FixedColour); \
1021         else \
1022             Screen [N] = GFX.ScreenColors [Pixel]; \
1023         Depth [N] = GFX.Z2; \
1024     }
1025
1026     FN(0)
1027     FN(1)
1028     FN(2)
1029     FN(3)
1030
1031 #undef FN
1032 }
1033
1034 void DrawTile16FixedAdd1_2 (uint32 Tile, tile_offset_t Offset, uint32 StartLine,
1035                             uint32 LineCount)
1036 {
1037     TILE_PREAMBLE
1038     register uint8 *bp;
1039
1040     RENDER_TILE(WRITE_4PIXELS16_ADDF1_2, WRITE_4PIXELS16_FLIPPED_ADDF1_2, 4)
1041 }
1042
1043 void DrawClippedTile16FixedAdd1_2 (uint32 Tile, tile_offset_t Offset,
1044                                    uint32 StartPixel, uint32 Width,
1045                                    uint32 StartLine, uint32 LineCount)
1046 {
1047     TILE_PREAMBLE
1048     register uint8 *bp;
1049
1050     TILE_CLIP_PREAMBLE
1051     RENDER_CLIPPED_TILE(WRITE_4PIXELS16_ADDF1_2, 
1052                         WRITE_4PIXELS16_FLIPPED_ADDF1_2, 4)
1053 }
1054
1055 void DrawTile16FixedSub1_2 (uint32 Tile, tile_offset_t Offset, uint32 StartLine,
1056                             uint32 LineCount)
1057 {
1058     TILE_PREAMBLE
1059     register uint8 *bp;
1060
1061     RENDER_TILE(WRITE_4PIXELS16_SUBF1_2, WRITE_4PIXELS16_FLIPPED_SUBF1_2, 4)
1062 }
1063
1064 void DrawClippedTile16FixedSub1_2 (uint32 Tile, tile_offset_t Offset,
1065                                    uint32 StartPixel, uint32 Width,
1066                                    uint32 StartLine, uint32 LineCount)
1067 {
1068     TILE_PREAMBLE
1069     register uint8 *bp;
1070
1071     TILE_CLIP_PREAMBLE
1072     RENDER_CLIPPED_TILE(WRITE_4PIXELS16_SUBF1_2, 
1073                         WRITE_4PIXELS16_FLIPPED_SUBF1_2, 4)
1074 }
1075
1076 void DrawLargePixel16Add (uint32 Tile, tile_offset_t Offset,
1077                           uint32 StartPixel, uint32 Pixels,
1078                           uint32 StartLine, uint32 LineCount)
1079 {
1080     TILE_PREAMBLE
1081
1082     register uint16 *sp = (uint16 *) GFX.S + Offset;
1083     uint8  *Depth = GFX.ZBuffer + Offset;
1084     register uint16 pixel;
1085
1086 #define LARGE_ADD_PIXEL(s, p) \
1087 (Depth [z + GFX.DepthDelta] ? (Depth [z + GFX.DepthDelta] != 1 ? \
1088                                COLOR_ADD (p, *(s + GFX.Delta))    : \
1089                                COLOR_ADD (p, GFX.FixedColour)) \
1090                             : p)
1091                               
1092     RENDER_TILE_LARGE (GFX.ScreenColors [pixel], LARGE_ADD_PIXEL)
1093 }
1094
1095 void DrawLargePixel16Add1_2 (uint32 Tile, tile_offset_t Offset,
1096                              uint32 StartPixel, uint32 Pixels,
1097                              uint32 StartLine, uint32 LineCount)
1098 {
1099     TILE_PREAMBLE
1100
1101     register uint16 *sp = (uint16 *) GFX.S + Offset;
1102     uint8  *Depth = GFX.ZBuffer + Offset;
1103     register uint16 pixel;
1104
1105 #define LARGE_ADD_PIXEL1_2(s, p) \
1106 ((uint16) (Depth [z + GFX.DepthDelta] ? (Depth [z + GFX.DepthDelta] != 1 ? \
1107                                COLOR_ADD1_2 (p, *(s + GFX.Delta))    : \
1108                                COLOR_ADD (p, GFX.FixedColour)) \
1109                             : p))
1110                               
1111     RENDER_TILE_LARGE (GFX.ScreenColors [pixel], LARGE_ADD_PIXEL1_2)
1112 }
1113
1114 void DrawLargePixel16Sub (uint32 Tile, tile_offset_t Offset,
1115                           uint32 StartPixel, uint32 Pixels,
1116                           uint32 StartLine, uint32 LineCount)
1117 {
1118     TILE_PREAMBLE
1119
1120     register uint16 *sp = (uint16 *) GFX.S + Offset;
1121     uint8  *Depth = GFX.ZBuffer + Offset;
1122     register uint16 pixel;
1123
1124 #define LARGE_SUB_PIXEL(s, p) \
1125 (Depth [z + GFX.DepthDelta] ? (Depth [z + GFX.DepthDelta] != 1 ? \
1126                                COLOR_SUB (p, *(s + GFX.Delta))    : \
1127                                COLOR_SUB (p, GFX.FixedColour)) \
1128                             : p)
1129                               
1130     RENDER_TILE_LARGE (GFX.ScreenColors [pixel], LARGE_SUB_PIXEL)
1131 }
1132
1133 void DrawLargePixel16Sub1_2 (uint32 Tile, tile_offset_t Offset,
1134                              uint32 StartPixel, uint32 Pixels,
1135                              uint32 StartLine, uint32 LineCount)
1136 {
1137     TILE_PREAMBLE
1138
1139     register uint16 *sp = (uint16 *) GFX.S + Offset;
1140     uint8  *Depth = GFX.ZBuffer + Offset;
1141     uint16 pixel;
1142
1143 #define LARGE_SUB_PIXEL1_2(s, p) \
1144 (Depth [z + GFX.DepthDelta] ? (Depth [z + GFX.DepthDelta] != 1 ? \
1145                                COLOR_SUB1_2 (p, *(s + GFX.Delta))    : \
1146                                COLOR_SUB (p, GFX.FixedColour)) \
1147                             : p)
1148                               
1149     RENDER_TILE_LARGE (GFX.ScreenColors [pixel], LARGE_SUB_PIXEL1_2)
1150 }
1151
1152 void DrawHiResTile16 (uint32 Tile, tile_offset_t Offset, uint32 StartLine,
1153                  uint32 LineCount)
1154 {
1155     TILE_PREAMBLE
1156     register uint8 *bp;
1157
1158     RENDER_TILEHI(WRITE_4PIXELSHI16, WRITE_4PIXELSHI16_FLIPPED, 4)
1159 }
1160
1161 void DrawHiResClippedTile16 (uint32 Tile, tile_offset_t Offset,
1162                           uint32 StartPixel, uint32 Width,
1163                         uint32 StartLine, uint32 LineCount)
1164 {
1165     TILE_PREAMBLE
1166     register uint8 *bp;
1167
1168     TILE_CLIP_PREAMBLE
1169     RENDER_CLIPPED_TILEHI(WRITE_4PIXELSHI16, WRITE_4PIXELSHI16_FLIPPED, 4)
1170 }
1171