reorg gfx & tile code
[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 "display.h"
46 #include "gfx.h"
47 #include "tile.h"
48
49 #ifdef USE_GLIDE
50 #include "3d.h"
51 #endif
52
53 #define TILE_PREAMBLE \
54     uint8 *pCache; \
55 \
56     uint32 TileAddr = BG.TileAddress + ((Tile & 0x3ff) << BG.TileShift); \
57     if ((Tile & 0x1ff) >= 256) \
58         TileAddr += BG.NameSelect; \
59 \
60     TileAddr &= 0xffff; \
61 \
62     uint32 TileNumber; \
63     pCache = &BG.Buffer[(TileNumber = (TileAddr >> BG.TileShift)) << 6]; \
64 \
65     if (!BG.Buffered [TileNumber]) \
66         BG.Buffered[TileNumber] = ConvertTile (pCache, TileAddr); \
67 \
68     if (BG.Buffered [TileNumber] == BLANK_TILE) \
69         return; \
70 \
71     register uint32 l; \
72     if (BG.DirectColourMode) \
73     { \
74         if (IPPU.DirectColourMapsNeedRebuild) \
75             S9xBuildDirectColourMaps (); \
76         GFX.ScreenColors = DirectColourMaps [(Tile >> 10) & BG.PaletteMask]; \
77     } \
78     else \
79         GFX.ScreenColors = &IPPU.ScreenColors [(((Tile >> 10) & BG.PaletteMask) << BG.PaletteShift) + BG.StartPalette];
80
81 #define RENDER_TILE(NORMAL, FLIPPED, N) \
82     if (!(Tile & (V_FLIP | H_FLIP))) \
83     { \
84         bp = pCache + StartLine; \
85         for (l = LineCount; l != 0; l--, bp += 8, Offset += GFX.PPL) \
86         { \
87             if (*(uint32 *) bp) \
88                 NORMAL (Offset, bp); \
89             if (*(uint32 *) (bp + 4)) \
90                 NORMAL (Offset + N, bp + 4); \
91         } \
92     } \
93     else \
94     if (!(Tile & V_FLIP)) \
95     { \
96         bp = pCache + StartLine; \
97         for (l = LineCount; l != 0; l--, bp += 8, Offset += GFX.PPL) \
98         { \
99             if (*(uint32 *) (bp + 4)) \
100                 FLIPPED (Offset, bp + 4); \
101             if (*(uint32 *) bp) \
102                 FLIPPED (Offset + N, bp); \
103         } \
104     } \
105     else \
106     if (Tile & H_FLIP) \
107     { \
108         bp = pCache + 56 - StartLine; \
109         for (l = LineCount; l != 0; l--, bp -= 8, Offset += GFX.PPL) \
110         { \
111             if (*(uint32 *) (bp + 4)) \
112                 FLIPPED (Offset, bp + 4); \
113             if (*(uint32 *) bp) \
114                 FLIPPED (Offset + N, bp); \
115         } \
116     } \
117     else \
118     { \
119         bp = pCache + 56 - StartLine; \
120         for (l = LineCount; l != 0; l--, bp -= 8, Offset += GFX.PPL) \
121         { \
122             if (*(uint32 *) bp) \
123                 NORMAL (Offset, bp); \
124             if (*(uint32 *) (bp + 4)) \
125                 NORMAL (Offset + N, bp + 4); \
126         } \
127     }
128
129 #define TILE_CLIP_PREAMBLE \
130     uint32 dd; \
131     uint32 d1; \
132     uint32 d2; \
133 \
134     if (StartPixel < 4) \
135     { \
136         d1 = HeadMask [StartPixel]; \
137         if (StartPixel + Width < 4) \
138             d1 &= TailMask [StartPixel + Width]; \
139     } \
140     else \
141         d1 = 0; \
142 \
143     if (StartPixel + Width > 4) \
144     { \
145         if (StartPixel > 4) \
146             d2 = HeadMask [StartPixel - 4]; \
147         else \
148             d2 = 0xffffffff; \
149 \
150         d2 &= TailMask [(StartPixel + Width - 4)]; \
151     } \
152     else \
153         d2 = 0;
154
155
156 #define RENDER_CLIPPED_TILE(NORMAL, FLIPPED, N) \
157     if (!(Tile & (V_FLIP | H_FLIP))) \
158     { \
159         bp = pCache + StartLine; \
160         for (l = LineCount; l != 0; l--, bp += 8, Offset += GFX.PPL) \
161         { \
162             if ((dd = (*(uint32 *) bp) & d1)) \
163                 NORMAL (Offset, (uint8 *) &dd); \
164             if ((dd = (*(uint32 *) (bp + 4)) & d2)) \
165                 NORMAL (Offset + N, (uint8 *) &dd); \
166         } \
167     } \
168     else \
169     if (!(Tile & V_FLIP)) \
170     { \
171         bp = pCache + StartLine; \
172         SWAP_DWORD (d1); \
173         SWAP_DWORD (d2); \
174         for (l = LineCount; l != 0; l--, bp += 8, Offset += GFX.PPL) \
175         { \
176             if ((dd = *(uint32 *) (bp + 4) & d1)) \
177                 FLIPPED (Offset, (uint8 *) &dd); \
178             if ((dd = *(uint32 *) bp & d2)) \
179                 FLIPPED (Offset + N, (uint8 *) &dd); \
180         } \
181     } \
182     else \
183     if (Tile & H_FLIP) \
184     { \
185         bp = pCache + 56 - StartLine; \
186         SWAP_DWORD (d1); \
187         SWAP_DWORD (d2); \
188         for (l = LineCount; l != 0; l--, bp -= 8, Offset += GFX.PPL) \
189         { \
190             if ((dd = *(uint32 *) (bp + 4) & d1)) \
191                 FLIPPED (Offset, (uint8 *) &dd); \
192             if ((dd = *(uint32 *) bp & d2)) \
193                 FLIPPED (Offset + N, (uint8 *) &dd); \
194         } \
195     } \
196     else \
197     { \
198         bp = pCache + 56 - StartLine; \
199         for (l = LineCount; l != 0; l--, bp -= 8, Offset += GFX.PPL) \
200         { \
201             if ((dd = (*(uint32 *) bp) & d1)) \
202                 NORMAL (Offset, (uint8 *) &dd); \
203             if ((dd = (*(uint32 *) (bp + 4)) & d2)) \
204                 NORMAL (Offset + N, (uint8 *) &dd); \
205         } \
206     }
207
208 #define RENDER_TILE_LARGE(PIXEL, FUNCTION) \
209     if (!(Tile & (V_FLIP | H_FLIP))) \
210     { \
211         if ((pixel = *(pCache + StartLine + StartPixel))) \
212         { \
213             pixel = PIXEL; \
214             for (l = LineCount; l != 0; l--, sp += GFX.PPL, Depth += GFX.PPL) \
215             { \
216                 for (int z = Pixels - 1; z >= 0; z--) \
217                     if (GFX.Z1 > Depth [z]) \
218                     { \
219                         sp [z] = FUNCTION(sp + z, pixel); \
220                         Depth [z] = GFX.Z2; \
221                     }\
222             } \
223         } \
224     } \
225     else \
226     if (!(Tile & V_FLIP)) \
227     { \
228         StartPixel = 7 - StartPixel; \
229         if ((pixel = *(pCache + StartLine + StartPixel))) \
230         { \
231             pixel = PIXEL; \
232             for (l = LineCount; l != 0; l--, sp += GFX.PPL, Depth += GFX.PPL) \
233             { \
234                 for (int z = Pixels - 1; z >= 0; z--) \
235                     if (GFX.Z1 > Depth [z]) \
236                     { \
237                         sp [z] = FUNCTION(sp + z, pixel); \
238                         Depth [z] = GFX.Z2; \
239                     }\
240             } \
241         } \
242     } \
243     else \
244     if (Tile & H_FLIP) \
245     { \
246         StartPixel = 7 - StartPixel; \
247         if ((pixel = *(pCache + 56 - StartLine + StartPixel))) \
248         { \
249             pixel = PIXEL; \
250             for (l = LineCount; l != 0; l--, sp += GFX.PPL, Depth += GFX.PPL) \
251             { \
252                 for (int z = Pixels - 1; z >= 0; z--) \
253                     if (GFX.Z1 > Depth [z]) \
254                     { \
255                         sp [z] = FUNCTION(sp + z, pixel); \
256                         Depth [z] = GFX.Z2; \
257                     }\
258             } \
259         } \
260     } \
261     else \
262     { \
263         if ((pixel = *(pCache + 56 - StartLine + StartPixel))) \
264         { \
265             pixel = PIXEL; \
266             for (l = LineCount; l != 0; l--, sp += GFX.PPL, Depth += GFX.PPL) \
267             { \
268                 for (int z = Pixels - 1; z >= 0; z--) \
269                     if (GFX.Z1 > Depth [z]) \
270                     { \
271                         sp [z] = FUNCTION(sp + z, pixel); \
272                         Depth [z] = GFX.Z2; \
273                     }\
274             } \
275         } \
276     }
277         
278 #define RENDER_TILEHI(NORMAL, FLIPPED, N) \
279     if (!(Tile & (V_FLIP | H_FLIP))) \
280     { \
281         bp = pCache + StartLine; \
282         for (l = LineCount; l != 0; l--, bp += 8, Offset += GFX.PPL) \
283         { \
284             /*if (*(uint32 *) bp)*/if (((uint32)bp[0])|((uint32)bp[2])|((uint32)bp[4])|((uint32)bp[6])) \
285                 NORMAL (Offset, bp); \
286         } \
287     } \
288     else \
289     if (!(Tile & V_FLIP)) \
290     { \
291         bp = pCache + StartLine; \
292         for (l = LineCount; l != 0; l--, bp += 8, Offset += GFX.PPL) \
293         { \
294             /*if (*(uint32 *) (bp + 4))*/if (((uint32)bp[0])|((uint32)bp[2])|((uint32)bp[4])|((uint32)bp[6])) \
295                 FLIPPED (Offset, bp); \
296         } \
297     } \
298     else \
299     if (Tile & H_FLIP) \
300     { \
301         bp = pCache + 56 - StartLine; \
302         for (l = LineCount; l != 0; l--, bp -= 8, Offset += GFX.PPL) \
303         { \
304             /*if (*(uint32 *) (bp + 4))*/if (((uint32)bp[0])|((uint32)bp[2])|((uint32)bp[4])|((uint32)bp[6]))  \
305                 FLIPPED (Offset, bp); \
306         } \
307     } \
308     else \
309     { \
310         bp = pCache + 56 - StartLine; \
311         for (l = LineCount; l != 0; l--, bp -= 8, Offset += GFX.PPL) \
312         { \
313             /*if (*(uint32 *) bp)*/if (((uint32)bp[0])|((uint32)bp[2])|((uint32)bp[4])|((uint32)bp[6])) \
314                 NORMAL (Offset, bp); \
315         } \
316     }
317     
318     
319     
320 #define RENDER_CLIPPED_TILEHI(NORMAL, FLIPPED, N) \
321         d1=(d1&0xFF)|((d1&0xFF0000)>>8)|((d2&0xFF)<<16)|((d2&0xFF0000)<<8);\
322     if (!(Tile & (V_FLIP | H_FLIP))) \
323     { \
324         bp = pCache + StartLine; \
325         for (l = LineCount; l != 0; l--, bp += 8, Offset += GFX.PPL) \
326         { \
327             /*if ((dd = (*(uint32 *) bp) & d1))*/if ((dd = (((((uint32)bp[6])<<24)|(((uint32)bp[4])<<16)|(((uint32)bp[2])<<8)|((uint32)bp[0]))&d1))) \
328                 NORMAL (Offset, (uint8 *) &dd); \
329         } \
330     } \
331     else \
332     if (!(Tile & V_FLIP)) \
333     { \
334         bp = pCache + StartLine; \
335         SWAP_DWORD (d1); \
336         /*SWAP_DWORD (d2);*/ \
337         for (l = LineCount; l != 0; l--, bp += 8, Offset += GFX.PPL) \
338         { \
339             /*if ((dd = *(uint32 *) (bp + 4) & d1))*/if ((dd = (((((uint32)bp[6])<<24)|(((uint32)bp[4])<<16)|(((uint32)bp[2])<<8)|((uint32)bp[0]))&d1))) \
340                 FLIPPED (Offset, (uint8 *) &dd); \
341         } \
342     } \
343     else \
344     if (Tile & H_FLIP) \
345     { \
346         bp = pCache + 56 - StartLine; \
347         SWAP_DWORD (d1); \
348         /*SWAP_DWORD (d2);*/ \
349         for (l = LineCount; l != 0; l--, bp -= 8, Offset += GFX.PPL) \
350         { \
351             /*if ((dd = *(uint32 *) (bp + 4) & d1))*/if ((dd = (((((uint32)bp[6])<<24)|(((uint32)bp[4])<<16)|(((uint32)bp[2])<<8)|((uint32)bp[0]))&d1))) \
352                 FLIPPED (Offset, (uint8 *) &dd); \
353         } \
354     } \
355     else \
356     { \
357         bp = pCache + 56 - StartLine; \
358         for (l = LineCount; l != 0; l--, bp -= 8, Offset += GFX.PPL) \
359         { \
360             /*if ((dd = (*(uint32 *) bp) & d1))*/ if ((dd = (((((uint32)bp[6])<<24)|(((uint32)bp[4])<<16)|(((uint32)bp[2])<<8)|((uint32)bp[0]))&d1))) \
361                 NORMAL (Offset, (uint8 *) &dd); \
362         } \
363     }
364
365 extern uint32 HeadMask [4];
366 extern uint32 TailMask [5];
367
368 uint8 ConvertTile (uint8 *pCache, uint32 TileAddr)
369 {
370     register uint8 *tp = &Memory.VRAM[TileAddr];
371     uint32 *p = (uint32 *) pCache;
372     uint32 non_zero = 0;
373     uint8 line;
374         uint32 p1;
375         uint32 p2;
376         register uint8 pix;
377
378     switch (BG.BitShift)
379     {
380     case 8:
381         for (line = 8; line != 0; line--, tp += 2)
382         {
383             p1 = p2 = 0;
384             if ((pix = *(tp + 0)))
385             {
386                 p1 |= odd_high[0][pix >> 4];
387                 p2 |= odd_low[0][pix & 0xf];
388             }
389             if ((pix = *(tp + 1)))
390             {
391                 p1 |= even_high[0][pix >> 4];
392                 p2 |= even_low[0][pix & 0xf];
393             }
394             if ((pix = *(tp + 16)))
395             {
396                 p1 |= odd_high[1][pix >> 4];
397                 p2 |= odd_low[1][pix & 0xf];
398             }
399             if ((pix = *(tp + 17)))
400             {
401                 p1 |= even_high[1][pix >> 4];
402                 p2 |= even_low[1][pix & 0xf];
403             }
404             if ((pix = *(tp + 32)))
405             {
406                 p1 |= odd_high[2][pix >> 4];
407                 p2 |= odd_low[2][pix & 0xf];
408             }
409             if ((pix = *(tp + 33)))
410             {
411                 p1 |= even_high[2][pix >> 4];
412                 p2 |= even_low[2][pix & 0xf];
413             }
414             if ((pix = *(tp + 48)))
415             {
416                 p1 |= odd_high[3][pix >> 4];
417                 p2 |= odd_low[3][pix & 0xf];
418             }
419             if ((pix = *(tp + 49)))
420             {
421                 p1 |= even_high[3][pix >> 4];
422                 p2 |= even_low[3][pix & 0xf];
423             }
424             *p++ = p1;
425             *p++ = p2;
426             non_zero |= p1 | p2;
427         }
428         break;
429
430     case 4:
431         for (line = 8; line != 0; line--, tp += 2)
432         {
433             p1 = p2 = 0;
434             if ((pix = *(tp + 0)))
435             {
436                 p1 |= odd_high[0][pix >> 4];
437                 p2 |= odd_low[0][pix & 0xf];
438             }
439             if ((pix = *(tp + 1)))
440             {
441                 p1 |= even_high[0][pix >> 4];
442                 p2 |= even_low[0][pix & 0xf];
443             }
444             if ((pix = *(tp + 16)))
445             {
446                 p1 |= odd_high[1][pix >> 4];
447                 p2 |= odd_low[1][pix & 0xf];
448             }
449             if ((pix = *(tp + 17)))
450             {
451                 p1 |= even_high[1][pix >> 4];
452                 p2 |= even_low[1][pix & 0xf];
453             }
454             *p++ = p1;
455             *p++ = p2;
456             non_zero |= p1 | p2;
457         }
458         break;
459
460     case 2:
461         for (line = 8; line != 0; line--, tp += 2)
462         {
463             p1 = p2 = 0;
464             if ((pix = *(tp + 0)))
465             {
466                 p1 |= odd_high[0][pix >> 4];
467                 p2 |= odd_low[0][pix & 0xf];
468             }
469             if ((pix = *(tp + 1)))
470             {
471                 p1 |= even_high[0][pix >> 4];
472                 p2 |= even_low[0][pix & 0xf];
473             }
474             *p++ = p1;
475             *p++ = p2;
476             non_zero |= p1 | p2;
477         }
478         break;
479     }
480     return (non_zero ? TRUE : BLANK_TILE);
481 }
482
483 INLINE void WRITE_4PIXELS (uint32 Offset, uint8 *Pixels)
484 {
485     register uint8 Pixel;
486     uint8 *Screen = GFX.S + Offset;
487     uint8 *Depth = GFX.DB + Offset;
488
489 #define FN(N) \
490     if (GFX.Z1 > Depth [N] && (Pixel = Pixels[N])) \
491     { \
492         Screen [N] = (uint8) GFX.ScreenColors [Pixel]; \
493         Depth [N] = GFX.Z2; \
494     }
495
496     FN(0)
497     FN(1)
498     FN(2)
499     FN(3)
500 #undef FN
501 }
502
503 INLINE void WRITE_4PIXELS_FLIPPED (uint32 Offset, uint8 *Pixels)
504 {
505     register uint8 Pixel;
506     uint8 *Screen = GFX.S + Offset;
507     uint8 *Depth = GFX.DB + Offset;
508
509 #define FN(N) \
510     if (GFX.Z1 > Depth [N] && (Pixel = Pixels[3 - N])) \
511     { \
512         Screen [N] = (uint8) GFX.ScreenColors [Pixel]; \
513         Depth [N] = GFX.Z2; \
514     }
515
516     FN(0)
517     FN(1)
518     FN(2)
519     FN(3)
520 #undef FN
521 }
522
523 inline void WRITE_4PIXELSHI16 (uint32 Offset, uint8 *Pixels)
524 {
525     uint32 Pixel;
526     uint16 *Screen = (uint16 *) GFX.S + Offset;
527     uint8  *Depth = GFX.DB + Offset;
528
529 #define FN(N) \
530     if (GFX.Z1 > Depth [N] && (Pixel = Pixels[2*N])) \
531     { \
532         Screen [N] = GFX.ScreenColors [Pixel]; \
533         Depth [N] = GFX.Z2; \
534     }
535
536     FN(0)
537     FN(1)
538     FN(2)
539     FN(3)
540 #undef FN
541 }
542
543 inline void WRITE_4PIXELSHI16_FLIPPED (uint32 Offset, uint8 *Pixels)
544 {
545     uint32 Pixel;
546     uint16 *Screen = (uint16 *) GFX.S + Offset;
547     uint8  *Depth = GFX.DB + Offset;
548
549 #define FN(N) \
550     if (GFX.Z1 > Depth [N] && (Pixel = Pixels[6 - 2*N])) \
551     { \
552         Screen [N] = GFX.ScreenColors [Pixel]; \
553         Depth [N] = GFX.Z2; \
554     }
555
556     FN(0)
557     FN(1)
558     FN(2)
559     FN(3)
560 #undef FN
561 }
562
563 INLINE void WRITE_4PIXELSx2 (uint32 Offset, uint8 *Pixels)
564 {
565     register uint8 Pixel;
566     uint8 *Screen = GFX.S + Offset;
567     uint8 *Depth = GFX.DB + Offset;
568
569 #define FN(N) \
570     if (GFX.Z1 > Depth [0] && (Pixel = Pixels[N])) \
571     { \
572         Screen [N * 2] = Screen [N * 2 + 1] = (uint8) GFX.ScreenColors [Pixel]; \
573         Depth [N * 2] = Depth [N * 2 + 1] = GFX.Z2; \
574     }
575
576     FN(0)
577     FN(1)
578     FN(2)
579     FN(3)
580 #undef FN
581 }
582
583 INLINE void WRITE_4PIXELS_FLIPPEDx2 (uint32 Offset, uint8 *Pixels)
584 {
585     register uint8 Pixel;
586     uint8 *Screen = GFX.S + Offset;
587     uint8 *Depth = GFX.DB + Offset;
588
589 #define FN(N) \
590     if (GFX.Z1 > Depth [N * 2] && (Pixel = Pixels[3 - N])) \
591     { \
592         Screen [N * 2] = Screen [N * 2 + 1] = (uint8) GFX.ScreenColors [Pixel]; \
593         Depth [N * 2] = Depth [N * 2 + 1] = GFX.Z2; \
594     }
595
596     FN(0)
597     FN(1)
598     FN(2)
599     FN(3)
600 #undef FN
601 }
602
603 INLINE void WRITE_4PIXELSx2x2 (uint32 Offset, uint8 *Pixels)
604 {
605     register uint8 Pixel;
606     uint8 *Screen = GFX.S + Offset;
607     uint8 *Depth = GFX.DB + Offset;
608
609 #define FN(N) \
610     if (GFX.Z1 > Depth [N * 2] && (Pixel = Pixels[N])) \
611     { \
612         Screen [N * 2] = Screen [N * 2 + 1] = Screen [GFX.RealPitch + N * 2] =  \
613             Screen [GFX.RealPitch + N * 2 + 1] = (uint8) GFX.ScreenColors [Pixel]; \
614         Depth [N * 2] = Depth [N * 2 + 1] = Depth [GFX.RealPitch + N * 2] = \
615             Depth [GFX.RealPitch + N * 2 + 1] = GFX.Z2; \
616     }
617
618     FN(0)
619     FN(1)
620     FN(2)
621     FN(3)
622 #undef FN
623 }
624
625 INLINE void WRITE_4PIXELS_FLIPPEDx2x2 (uint32 Offset, uint8 *Pixels)
626 {
627     register uint8 Pixel;
628     uint8 *Screen = GFX.S + Offset;
629     uint8 *Depth = GFX.DB + Offset;
630
631 #define FN(N) \
632     if (GFX.Z1 > Depth [N * 2] && (Pixel = Pixels[3 - N])) \
633     { \
634         Screen [N * 2] = Screen [N * 2 + 1] = Screen [GFX.RealPitch + N * 2] =  \
635             Screen [GFX.RealPitch + N * 2 + 1] = (uint8) GFX.ScreenColors [Pixel]; \
636         Depth [N * 2] = Depth [N * 2 + 1] = Depth [GFX.RealPitch + N * 2] = \
637             Depth [GFX.RealPitch + N * 2 + 1] = GFX.Z2; \
638     }
639
640     FN(0)
641     FN(1)
642     FN(2)
643     FN(3)
644 #undef FN
645 }
646
647 void DrawTile(uint32 Tile, uint32 Offset, uint32 StartLine, uint32 LineCount)
648 {
649     TILE_PREAMBLE
650
651     register uint8 *bp;
652
653     RENDER_TILE(WRITE_4PIXELS, WRITE_4PIXELS_FLIPPED, 4)
654 }
655
656 void DrawClippedTile(uint32 Tile, uint32 Offset,
657                       uint32 StartPixel, uint32 Width,
658                       uint32 StartLine, uint32 LineCount)
659 {
660     TILE_PREAMBLE
661     register uint8 *bp;
662
663     TILE_CLIP_PREAMBLE
664     RENDER_CLIPPED_TILE(WRITE_4PIXELS, WRITE_4PIXELS_FLIPPED, 4)
665 }
666
667 void DrawTilex2 (uint32 Tile, uint32 Offset, uint32 StartLine, uint32 LineCount)
668 {
669     TILE_PREAMBLE
670
671     register uint8 *bp;
672
673     RENDER_TILE(WRITE_4PIXELSx2, WRITE_4PIXELS_FLIPPEDx2, 8)
674 }
675
676 void DrawClippedTilex2 (uint32 Tile, uint32 Offset,
677                         uint32 StartPixel, uint32 Width,
678                         uint32 StartLine, uint32 LineCount)
679 {
680     TILE_PREAMBLE
681     register uint8 *bp;
682
683     TILE_CLIP_PREAMBLE
684     RENDER_CLIPPED_TILE(WRITE_4PIXELSx2, WRITE_4PIXELS_FLIPPEDx2, 8)
685 }
686
687 void DrawTilex2x2 (uint32 Tile, uint32 Offset, uint32 StartLine,
688                    uint32 LineCount)
689 {
690     TILE_PREAMBLE
691
692     register uint8 *bp;
693
694     RENDER_TILE(WRITE_4PIXELSx2x2, WRITE_4PIXELS_FLIPPEDx2x2, 8)
695 }
696
697 void DrawClippedTilex2x2 (uint32 Tile, uint32 Offset,
698                           uint32 StartPixel, uint32 Width,
699                           uint32 StartLine, uint32 LineCount)
700 {
701     TILE_PREAMBLE
702     register uint8 *bp;
703
704     TILE_CLIP_PREAMBLE
705     RENDER_CLIPPED_TILE(WRITE_4PIXELSx2x2, WRITE_4PIXELS_FLIPPEDx2x2, 8)
706 }
707
708 void DrawLargePixel (uint32 Tile, uint32 Offset,
709                      uint32 StartPixel, uint32 Pixels,
710                      uint32 StartLine, uint32 LineCount)
711 {
712     TILE_PREAMBLE
713
714     register uint8 *sp = GFX.S + Offset;
715     uint8  *Depth = GFX.DB + Offset;
716     uint8 pixel;
717 #define PLOT_PIXEL(screen, pixel) (pixel)
718
719     RENDER_TILE_LARGE (((uint8) GFX.ScreenColors [pixel]), PLOT_PIXEL)
720 }
721
722 INLINE void WRITE_4PIXELS16 (uint32 Offset, uint8 *Pixels)
723 {
724     register uint32 Pixel;
725     uint16 *Screen = (uint16 *) GFX.S + Offset;
726     uint8  *Depth = GFX.DB + Offset;
727
728 #define FN(N) \
729     if (GFX.Z1 > Depth [N] && (Pixel = Pixels[N])) \
730     { \
731         Screen [N] = GFX.ScreenColors [Pixel]; \
732         Depth [N] = GFX.Z2; \
733     }
734
735     FN(0)
736     FN(1)
737     FN(2)
738     FN(3)
739 #undef FN
740 }
741
742 INLINE void WRITE_4PIXELS16_FLIPPED (uint32 Offset, uint8 *Pixels)
743 {
744     register uint32 Pixel;
745     uint16 *Screen = (uint16 *) GFX.S + Offset;
746     uint8  *Depth = GFX.DB + Offset;
747
748 #define FN(N) \
749     if (GFX.Z1 > Depth [N] && (Pixel = Pixels[3 - N])) \
750     { \
751         Screen [N] = GFX.ScreenColors [Pixel]; \
752         Depth [N] = GFX.Z2; \
753     }
754
755     FN(0)
756     FN(1)
757     FN(2)
758     FN(3)
759 #undef FN
760 }
761
762 INLINE void WRITE_4PIXELS16x2 (uint32 Offset, uint8 *Pixels)
763 {
764     register uint32 Pixel;
765     uint16 *Screen = (uint16 *) GFX.S + Offset;
766     uint8  *Depth = GFX.DB + Offset;
767
768 #define FN(N) \
769     if (GFX.Z1 > Depth [N * 2] && (Pixel = Pixels[N])) \
770     { \
771         Screen [N * 2] = Screen [N * 2 + 1] = GFX.ScreenColors [Pixel]; \
772         Depth [N * 2] = Depth [N * 2 + 1] = GFX.Z2; \
773     }
774
775     FN(0)
776     FN(1)
777     FN(2)
778     FN(3)
779 #undef FN
780 }
781
782 INLINE void WRITE_4PIXELS16_FLIPPEDx2 (uint32 Offset, uint8 *Pixels)
783 {
784     register uint32 Pixel;
785     uint16 *Screen = (uint16 *) GFX.S + Offset;
786     uint8  *Depth = GFX.DB + Offset;
787
788 #define FN(N) \
789     if (GFX.Z1 > Depth [N * 2] && (Pixel = Pixels[3 - N])) \
790     { \
791         Screen [N * 2] = Screen [N * 2 + 1] = GFX.ScreenColors [Pixel]; \
792         Depth [N * 2] = Depth [N * 2 + 1] = GFX.Z2; \
793     }
794
795     FN(0)
796     FN(1)
797     FN(2)
798     FN(3)
799 #undef FN
800 }
801
802 INLINE void WRITE_4PIXELS16x2x2 (uint32 Offset, uint8 *Pixels)
803 {
804     register uint32 Pixel;
805     uint16 *Screen = (uint16 *) GFX.S + Offset;
806     uint8  *Depth = GFX.DB + Offset;
807
808 #define FN(N) \
809     if (GFX.Z1 > Depth [N * 2] && (Pixel = Pixels[N])) \
810     { \
811         Screen [N * 2] = Screen [N * 2 + 1] = Screen [(GFX.RealPitch >> 1) + N * 2] = \
812             Screen [(GFX.RealPitch >> 1) + N * 2 + 1] = GFX.ScreenColors [Pixel]; \
813         Depth [N * 2] = Depth [N * 2 + 1] = Depth [(GFX.RealPitch >> 1) + N * 2] = \
814             Depth [(GFX.RealPitch >> 1) + N * 2 + 1] = GFX.Z2; \
815     }
816
817     FN(0)
818     FN(1)
819     FN(2)
820     FN(3)
821 #undef FN
822 }
823
824 INLINE void WRITE_4PIXELS16_FLIPPEDx2x2 (uint32 Offset, uint8 *Pixels)
825 {
826     register uint32 Pixel;
827     uint16 *Screen = (uint16 *) GFX.S + Offset;
828     uint8  *Depth = GFX.DB + Offset;
829
830 #define FN(N) \
831     if (GFX.Z1 > Depth [N * 2] && (Pixel = Pixels[3 - N])) \
832     { \
833         Screen [N * 2] = Screen [N * 2 + 1] = Screen [(GFX.RealPitch >> 1) + N * 2] = \
834             Screen [(GFX.RealPitch >> 1) + N * 2 + 1] = GFX.ScreenColors [Pixel]; \
835         Depth [N * 2] = Depth [N * 2 + 1] = Depth [(GFX.RealPitch >> 1) + N * 2] = \
836             Depth [(GFX.RealPitch >> 1) + N * 2 + 1] = GFX.Z2; \
837     }
838
839     FN(0)
840     FN(1)
841     FN(2)
842     FN(3)
843 #undef FN
844 }
845
846 void DrawTile16 (uint32 Tile, uint32 Offset, uint32 StartLine,
847                  uint32 LineCount)
848 {
849     TILE_PREAMBLE
850     register uint8 *bp;
851
852     RENDER_TILE(WRITE_4PIXELS16, WRITE_4PIXELS16_FLIPPED, 4)
853 }
854
855 void DrawClippedTile16 (uint32 Tile, uint32 Offset,
856                         uint32 StartPixel, uint32 Width,
857                         uint32 StartLine, uint32 LineCount)
858 {
859     TILE_PREAMBLE
860     register uint8 *bp;
861
862     TILE_CLIP_PREAMBLE
863     RENDER_CLIPPED_TILE(WRITE_4PIXELS16, WRITE_4PIXELS16_FLIPPED, 4)
864 }
865
866 void DrawTile16x2 (uint32 Tile, uint32 Offset, uint32 StartLine,
867                    uint32 LineCount)
868 {
869     TILE_PREAMBLE
870     register uint8 *bp;
871
872     RENDER_TILE(WRITE_4PIXELS16x2, WRITE_4PIXELS16_FLIPPEDx2, 8)
873 }
874
875 void DrawClippedTile16x2 (uint32 Tile, uint32 Offset,
876                           uint32 StartPixel, uint32 Width,
877                           uint32 StartLine, uint32 LineCount)
878 {
879     TILE_PREAMBLE
880     register uint8 *bp;
881
882     TILE_CLIP_PREAMBLE
883     RENDER_CLIPPED_TILE(WRITE_4PIXELS16x2, WRITE_4PIXELS16_FLIPPEDx2, 8)
884 }
885
886 void DrawTile16x2x2 (uint32 Tile, uint32 Offset, uint32 StartLine,
887                      uint32 LineCount)
888 {
889     TILE_PREAMBLE
890     register uint8 *bp;
891
892     RENDER_TILE(WRITE_4PIXELS16x2x2, WRITE_4PIXELS16_FLIPPEDx2x2, 8)
893 }
894
895 void DrawClippedTile16x2x2 (uint32 Tile, uint32 Offset,
896                             uint32 StartPixel, uint32 Width,
897                             uint32 StartLine, uint32 LineCount)
898 {
899     TILE_PREAMBLE
900     register uint8 *bp;
901
902     TILE_CLIP_PREAMBLE
903     RENDER_CLIPPED_TILE(WRITE_4PIXELS16x2x2, WRITE_4PIXELS16_FLIPPEDx2x2, 8)
904 }
905
906 void DrawLargePixel16 (uint32 Tile, uint32 Offset,
907                        uint32 StartPixel, uint32 Pixels,
908                        uint32 StartLine, uint32 LineCount)
909 {
910     TILE_PREAMBLE
911
912     register uint16 *sp = (uint16 *) GFX.S + Offset;
913     uint8  *Depth = GFX.DB + Offset;
914     uint16 pixel;
915
916     RENDER_TILE_LARGE (GFX.ScreenColors [pixel], PLOT_PIXEL)
917 }
918
919 INLINE void WRITE_4PIXELS16_ADD (uint32 Offset, uint8 *Pixels)
920 {
921     register uint32 Pixel;
922     uint16 *Screen = (uint16 *) GFX.S + Offset;
923     uint8  *Depth = GFX.ZBuffer + Offset;
924     uint8  *SubDepth = GFX.SubZBuffer + Offset;
925
926 #define FN(N) \
927     if (GFX.Z1 > Depth [N] && (Pixel = Pixels[N])) \
928     { \
929         if (SubDepth [N]) \
930         { \
931             if (SubDepth [N] != 1) \
932                 Screen [N] = COLOR_ADD (GFX.ScreenColors [Pixel], \
933                                         Screen [GFX.Delta + N]); \
934             else \
935                 Screen [N] = COLOR_ADD (GFX.ScreenColors [Pixel], \
936                                         GFX.FixedColour); \
937         } \
938         else \
939             Screen [N] = GFX.ScreenColors [Pixel]; \
940         Depth [N] = GFX.Z2; \
941     }
942
943     FN(0)
944     FN(1)
945     FN(2)
946     FN(3)
947
948 #undef FN
949 }
950
951 INLINE void WRITE_4PIXELS16_FLIPPED_ADD (uint32 Offset, uint8 *Pixels)
952 {
953     register uint32 Pixel;
954     uint16 *Screen = (uint16 *) GFX.S + Offset;
955     uint8  *Depth = GFX.ZBuffer + Offset;
956     uint8  *SubDepth = GFX.SubZBuffer + Offset;
957
958 #define FN(N) \
959     if (GFX.Z1 > Depth [N] && (Pixel = Pixels[3 - N])) \
960     { \
961         if (SubDepth [N]) \
962         { \
963             if (SubDepth [N] != 1) \
964                 Screen [N] = COLOR_ADD (GFX.ScreenColors [Pixel], \
965                                         Screen [GFX.Delta + N]); \
966             else \
967                 Screen [N] = COLOR_ADD (GFX.ScreenColors [Pixel], \
968                                         GFX.FixedColour); \
969         } \
970         else \
971             Screen [N] = GFX.ScreenColors [Pixel]; \
972         Depth [N] = GFX.Z2; \
973     }
974
975     FN(0)
976     FN(1)
977     FN(2)
978     FN(3)
979
980 #undef FN
981 }
982
983 INLINE void WRITE_4PIXELS16_ADD1_2 (uint32 Offset, uint8 *Pixels)
984 {
985     register uint32 Pixel;
986     uint16 *Screen = (uint16 *) GFX.S + Offset;
987     uint8  *Depth = GFX.ZBuffer + Offset;
988     uint8  *SubDepth = GFX.SubZBuffer + Offset;
989
990 #define FN(N) \
991     if (GFX.Z1 > Depth [N] && (Pixel = Pixels[N])) \
992     { \
993         if (SubDepth [N]) \
994         { \
995             if (SubDepth [N] != 1) \
996                 Screen [N] = (uint16) (COLOR_ADD1_2 (GFX.ScreenColors [Pixel], \
997                                                      Screen [GFX.Delta + N])); \
998             else \
999                 Screen [N] = COLOR_ADD (GFX.ScreenColors [Pixel], \
1000                                         GFX.FixedColour); \
1001         } \
1002         else \
1003             Screen [N] = GFX.ScreenColors [Pixel]; \
1004         Depth [N] = GFX.Z2; \
1005     }
1006
1007     FN(0)
1008     FN(1)
1009     FN(2)
1010     FN(3)
1011
1012 #undef FN
1013 }
1014
1015 INLINE void WRITE_4PIXELS16_FLIPPED_ADD1_2 (uint32 Offset, uint8 *Pixels)
1016 {
1017     register uint32 Pixel;
1018     uint16 *Screen = (uint16 *) GFX.S + Offset;
1019     uint8  *Depth = GFX.ZBuffer + Offset;
1020     uint8  *SubDepth = GFX.SubZBuffer + Offset;
1021
1022 #define FN(N) \
1023     if (GFX.Z1 > Depth [N] && (Pixel = Pixels[3 - N])) \
1024     { \
1025         if (SubDepth [N]) \
1026         { \
1027             if (SubDepth [N] != 1) \
1028                 Screen [N] = (uint16) (COLOR_ADD1_2 (GFX.ScreenColors [Pixel], \
1029                                                      Screen [GFX.Delta + N])); \
1030             else \
1031                 Screen [N] = COLOR_ADD (GFX.ScreenColors [Pixel], \
1032                                         GFX.FixedColour); \
1033         } \
1034         else \
1035             Screen [N] = GFX.ScreenColors [Pixel]; \
1036         Depth [N] = GFX.Z2; \
1037     }
1038
1039     FN(0)
1040     FN(1)
1041     FN(2)
1042     FN(3)
1043
1044 #undef FN
1045 }
1046
1047 INLINE void WRITE_4PIXELS16_SUB (uint32 Offset, uint8 *Pixels)
1048 {
1049     register uint32 Pixel;
1050     uint16 *Screen = (uint16 *) GFX.S + Offset;
1051     uint8  *Depth = GFX.ZBuffer + Offset;
1052     uint8  *SubDepth = GFX.SubZBuffer + Offset;
1053
1054 #define FN(N) \
1055     if (GFX.Z1 > Depth [N] && (Pixel = Pixels[N])) \
1056     { \
1057         if (SubDepth [N]) \
1058         { \
1059             if (SubDepth [N] != 1) \
1060                 Screen [N] = (uint16) COLOR_SUB (GFX.ScreenColors [Pixel], \
1061                                         Screen [GFX.Delta + N]); \
1062             else \
1063                 Screen [N] = (uint16) COLOR_SUB (GFX.ScreenColors [Pixel], \
1064                                         GFX.FixedColour); \
1065         } \
1066         else \
1067             Screen [N] = GFX.ScreenColors [Pixel]; \
1068         Depth [N] = GFX.Z2; \
1069     }
1070
1071     FN(0)
1072     FN(1)
1073     FN(2)
1074     FN(3)
1075
1076 #undef FN
1077 }
1078
1079 INLINE void WRITE_4PIXELS16_FLIPPED_SUB (uint32 Offset, uint8 *Pixels)
1080 {
1081     register uint32 Pixel;
1082     uint16 *Screen = (uint16 *) GFX.S + Offset;
1083     uint8  *Depth = GFX.ZBuffer + Offset;
1084     uint8  *SubDepth = GFX.SubZBuffer + Offset;
1085
1086 #define FN(N) \
1087     if (GFX.Z1 > Depth [N] && (Pixel = Pixels[3 - N])) \
1088     { \
1089         if (SubDepth [N]) \
1090         { \
1091             if (SubDepth [N] != 1) \
1092                 Screen [N] = (uint16) COLOR_SUB (GFX.ScreenColors [Pixel], \
1093                                         Screen [GFX.Delta + N]); \
1094             else \
1095                 Screen [N] = (uint16) COLOR_SUB (GFX.ScreenColors [Pixel], \
1096                                         GFX.FixedColour); \
1097         } \
1098         else \
1099             Screen [N] = GFX.ScreenColors [Pixel]; \
1100         Depth [N] = GFX.Z2; \
1101     }
1102
1103     FN(0)
1104     FN(1)
1105     FN(2)
1106     FN(3)
1107
1108 #undef FN
1109 }
1110
1111 INLINE void WRITE_4PIXELS16_SUB1_2 (uint32 Offset, uint8 *Pixels)
1112 {
1113     register uint32 Pixel;
1114     uint16 *Screen = (uint16 *) GFX.S + Offset;
1115     uint8  *Depth = GFX.ZBuffer + Offset;
1116     uint8  *SubDepth = GFX.SubZBuffer + Offset;
1117
1118 #define FN(N) \
1119     if (GFX.Z1 > Depth [N] && (Pixel = Pixels[N])) \
1120     { \
1121         if (SubDepth [N]) \
1122         { \
1123             if (SubDepth [N] != 1) \
1124                 Screen [N] = (uint16) COLOR_SUB1_2 (GFX.ScreenColors [Pixel], \
1125                                            Screen [GFX.Delta + N]); \
1126             else \
1127                 Screen [N] = (uint16) COLOR_SUB (GFX.ScreenColors [Pixel], \
1128                                         GFX.FixedColour); \
1129         } \
1130         else \
1131             Screen [N] = GFX.ScreenColors [Pixel]; \
1132         Depth [N] = GFX.Z2; \
1133     }
1134
1135     FN(0)
1136     FN(1)
1137     FN(2)
1138     FN(3)
1139
1140 #undef FN
1141 }
1142
1143 INLINE void WRITE_4PIXELS16_FLIPPED_SUB1_2 (uint32 Offset, uint8 *Pixels)
1144 {
1145     register uint32 Pixel;
1146     uint16 *Screen = (uint16 *) GFX.S + Offset;
1147     uint8  *Depth = GFX.ZBuffer + Offset;
1148     uint8  *SubDepth = GFX.SubZBuffer + Offset;
1149
1150 #define FN(N) \
1151     if (GFX.Z1 > Depth [N] && (Pixel = Pixels[3 - N])) \
1152     { \
1153         if (SubDepth [N]) \
1154         { \
1155             if (SubDepth [N] != 1) \
1156                 Screen [N] = (uint16) COLOR_SUB1_2 (GFX.ScreenColors [Pixel], \
1157                                            Screen [GFX.Delta + N]); \
1158             else \
1159                 Screen [N] = (uint16) COLOR_SUB (GFX.ScreenColors [Pixel], \
1160                                         GFX.FixedColour); \
1161         } \
1162         else \
1163             Screen [N] = GFX.ScreenColors [Pixel]; \
1164         Depth [N] = GFX.Z2; \
1165     }
1166
1167     FN(0)
1168     FN(1)
1169     FN(2)
1170     FN(3)
1171
1172 #undef FN
1173 }
1174
1175
1176 void DrawTile16Add (uint32 Tile, uint32 Offset, uint32 StartLine,
1177                     uint32 LineCount)
1178 {
1179     TILE_PREAMBLE
1180     register uint8 *bp;
1181
1182     RENDER_TILE(WRITE_4PIXELS16_ADD, WRITE_4PIXELS16_FLIPPED_ADD, 4)
1183 }
1184
1185 void DrawClippedTile16Add (uint32 Tile, uint32 Offset,
1186                            uint32 StartPixel, uint32 Width,
1187                            uint32 StartLine, uint32 LineCount)
1188 {
1189     TILE_PREAMBLE
1190     register uint8 *bp;
1191
1192     TILE_CLIP_PREAMBLE
1193     RENDER_CLIPPED_TILE(WRITE_4PIXELS16_ADD, WRITE_4PIXELS16_FLIPPED_ADD, 4)
1194 }
1195
1196 void DrawTile16Add1_2 (uint32 Tile, uint32 Offset, uint32 StartLine,
1197                        uint32 LineCount)
1198 {
1199     TILE_PREAMBLE
1200     register uint8 *bp;
1201
1202     RENDER_TILE(WRITE_4PIXELS16_ADD1_2, WRITE_4PIXELS16_FLIPPED_ADD1_2, 4)
1203 }
1204
1205 void DrawClippedTile16Add1_2 (uint32 Tile, uint32 Offset,
1206                               uint32 StartPixel, uint32 Width,
1207                               uint32 StartLine, uint32 LineCount)
1208 {
1209     TILE_PREAMBLE
1210     register uint8 *bp;
1211
1212     TILE_CLIP_PREAMBLE
1213     RENDER_CLIPPED_TILE(WRITE_4PIXELS16_ADD1_2, WRITE_4PIXELS16_FLIPPED_ADD1_2, 4)
1214 }
1215
1216 void DrawTile16Sub (uint32 Tile, uint32 Offset, uint32 StartLine,
1217                     uint32 LineCount)
1218 {
1219     TILE_PREAMBLE
1220     register uint8 *bp;
1221
1222     RENDER_TILE(WRITE_4PIXELS16_SUB, WRITE_4PIXELS16_FLIPPED_SUB, 4)
1223 }
1224
1225 void DrawClippedTile16Sub (uint32 Tile, uint32 Offset,
1226                            uint32 StartPixel, uint32 Width,
1227                            uint32 StartLine, uint32 LineCount)
1228 {
1229     TILE_PREAMBLE
1230     register uint8 *bp;
1231
1232     TILE_CLIP_PREAMBLE
1233     RENDER_CLIPPED_TILE(WRITE_4PIXELS16_SUB, WRITE_4PIXELS16_FLIPPED_SUB, 4)
1234 }
1235
1236 void DrawTile16Sub1_2 (uint32 Tile, uint32 Offset, uint32 StartLine,
1237                        uint32 LineCount)
1238 {
1239     TILE_PREAMBLE
1240     register uint8 *bp;
1241
1242     RENDER_TILE(WRITE_4PIXELS16_SUB1_2, WRITE_4PIXELS16_FLIPPED_SUB1_2, 4)
1243 }
1244
1245 void DrawClippedTile16Sub1_2 (uint32 Tile, uint32 Offset,
1246                               uint32 StartPixel, uint32 Width,
1247                               uint32 StartLine, uint32 LineCount)
1248 {
1249     TILE_PREAMBLE
1250     register uint8 *bp;
1251
1252     TILE_CLIP_PREAMBLE
1253     RENDER_CLIPPED_TILE(WRITE_4PIXELS16_SUB1_2, WRITE_4PIXELS16_FLIPPED_SUB1_2, 4)
1254 }
1255
1256 INLINE void WRITE_4PIXELS16_ADDF1_2 (uint32 Offset, uint8 *Pixels)
1257 {
1258     register uint32 Pixel;
1259     uint16 *Screen = (uint16 *) GFX.S + Offset;
1260     uint8  *Depth = GFX.ZBuffer + Offset;
1261     uint8  *SubDepth = GFX.SubZBuffer + Offset;
1262
1263 #define FN(N) \
1264     if (GFX.Z1 > Depth [N] && (Pixel = Pixels[N])) \
1265     { \
1266         if (SubDepth [N] == 1) \
1267             Screen [N] = (uint16) (COLOR_ADD1_2 (GFX.ScreenColors [Pixel], \
1268                                                  GFX.FixedColour)); \
1269         else \
1270             Screen [N] = GFX.ScreenColors [Pixel];\
1271         Depth [N] = GFX.Z2; \
1272     }
1273
1274     FN(0)
1275     FN(1)
1276     FN(2)
1277     FN(3)
1278
1279 #undef FN
1280 }
1281
1282 INLINE void WRITE_4PIXELS16_FLIPPED_ADDF1_2 (uint32 Offset, uint8 *Pixels)
1283 {
1284     register uint32 Pixel;
1285     uint16 *Screen = (uint16 *) GFX.S + Offset;
1286     uint8  *Depth = GFX.ZBuffer + Offset;
1287     uint8  *SubDepth = GFX.SubZBuffer + Offset;
1288
1289 #define FN(N) \
1290     if (GFX.Z1 > Depth [N] && (Pixel = Pixels[3 - N])) \
1291     { \
1292         if (SubDepth [N] == 1) \
1293             Screen [N] = (uint16) (COLOR_ADD1_2 (GFX.ScreenColors [Pixel], \
1294                                                  GFX.FixedColour)); \
1295         else \
1296             Screen [N] = GFX.ScreenColors [Pixel];\
1297         Depth [N] = GFX.Z2; \
1298     }
1299
1300     FN(0)
1301     FN(1)
1302     FN(2)
1303     FN(3)
1304
1305 #undef FN
1306 }
1307
1308 INLINE void WRITE_4PIXELS16_SUBF1_2 (uint32 Offset, uint8 *Pixels)
1309 {
1310     register uint32 Pixel;
1311     uint16 *Screen = (uint16 *) GFX.S + Offset;
1312     uint8  *Depth = GFX.ZBuffer + Offset;
1313     uint8  *SubDepth = GFX.SubZBuffer + Offset;
1314
1315 #define FN(N) \
1316     if (GFX.Z1 > Depth [N] && (Pixel = Pixels[N])) \
1317     { \
1318         if (SubDepth [N] == 1) \
1319             Screen [N] = (uint16) COLOR_SUB1_2 (GFX.ScreenColors [Pixel], \
1320                                                 GFX.FixedColour); \
1321         else \
1322             Screen [N] = GFX.ScreenColors [Pixel]; \
1323         Depth [N] = GFX.Z2; \
1324     }
1325
1326     FN(0)
1327     FN(1)
1328     FN(2)
1329     FN(3)
1330
1331 #undef FN
1332 }
1333
1334 INLINE void WRITE_4PIXELS16_FLIPPED_SUBF1_2 (uint32 Offset, uint8 *Pixels)
1335 {
1336     register uint32 Pixel;
1337     uint16 *Screen = (uint16 *) GFX.S + Offset;
1338     uint8  *Depth = GFX.ZBuffer + Offset;
1339     uint8  *SubDepth = GFX.SubZBuffer + Offset;
1340
1341 #define FN(N) \
1342     if (GFX.Z1 > Depth [N] && (Pixel = Pixels[3 - N])) \
1343     { \
1344         if (SubDepth [N] == 1) \
1345             Screen [N] = (uint16) COLOR_SUB1_2 (GFX.ScreenColors [Pixel], \
1346                                                 GFX.FixedColour); \
1347         else \
1348             Screen [N] = GFX.ScreenColors [Pixel]; \
1349         Depth [N] = GFX.Z2; \
1350     }
1351
1352     FN(0)
1353     FN(1)
1354     FN(2)
1355     FN(3)
1356
1357 #undef FN
1358 }
1359
1360 void DrawTile16FixedAdd1_2 (uint32 Tile, uint32 Offset, uint32 StartLine,
1361                             uint32 LineCount)
1362 {
1363     TILE_PREAMBLE
1364     register uint8 *bp;
1365
1366     RENDER_TILE(WRITE_4PIXELS16_ADDF1_2, WRITE_4PIXELS16_FLIPPED_ADDF1_2, 4)
1367 }
1368
1369 void DrawClippedTile16FixedAdd1_2 (uint32 Tile, uint32 Offset,
1370                                    uint32 StartPixel, uint32 Width,
1371                                    uint32 StartLine, uint32 LineCount)
1372 {
1373     TILE_PREAMBLE
1374     register uint8 *bp;
1375
1376     TILE_CLIP_PREAMBLE
1377     RENDER_CLIPPED_TILE(WRITE_4PIXELS16_ADDF1_2, 
1378                         WRITE_4PIXELS16_FLIPPED_ADDF1_2, 4)
1379 }
1380
1381 void DrawTile16FixedSub1_2 (uint32 Tile, uint32 Offset, uint32 StartLine,
1382                             uint32 LineCount)
1383 {
1384     TILE_PREAMBLE
1385     register uint8 *bp;
1386
1387     RENDER_TILE(WRITE_4PIXELS16_SUBF1_2, WRITE_4PIXELS16_FLIPPED_SUBF1_2, 4)
1388 }
1389
1390 void DrawClippedTile16FixedSub1_2 (uint32 Tile, uint32 Offset,
1391                                    uint32 StartPixel, uint32 Width,
1392                                    uint32 StartLine, uint32 LineCount)
1393 {
1394     TILE_PREAMBLE
1395     register uint8 *bp;
1396
1397     TILE_CLIP_PREAMBLE
1398     RENDER_CLIPPED_TILE(WRITE_4PIXELS16_SUBF1_2, 
1399                         WRITE_4PIXELS16_FLIPPED_SUBF1_2, 4)
1400 }
1401
1402 void DrawLargePixel16Add (uint32 Tile, uint32 Offset,
1403                           uint32 StartPixel, uint32 Pixels,
1404                           uint32 StartLine, uint32 LineCount)
1405 {
1406     TILE_PREAMBLE
1407
1408     register uint16 *sp = (uint16 *) GFX.S + Offset;
1409     uint8  *Depth = GFX.ZBuffer + Offset;
1410     register uint16 pixel;
1411
1412 #define LARGE_ADD_PIXEL(s, p) \
1413 (Depth [z + GFX.DepthDelta] ? (Depth [z + GFX.DepthDelta] != 1 ? \
1414                                COLOR_ADD (p, *(s + GFX.Delta))    : \
1415                                COLOR_ADD (p, GFX.FixedColour)) \
1416                             : p)
1417                               
1418     RENDER_TILE_LARGE (GFX.ScreenColors [pixel], LARGE_ADD_PIXEL)
1419 }
1420
1421 void DrawLargePixel16Add1_2 (uint32 Tile, uint32 Offset,
1422                              uint32 StartPixel, uint32 Pixels,
1423                              uint32 StartLine, uint32 LineCount)
1424 {
1425     TILE_PREAMBLE
1426
1427     register uint16 *sp = (uint16 *) GFX.S + Offset;
1428     uint8  *Depth = GFX.ZBuffer + Offset;
1429     register uint16 pixel;
1430
1431 #define LARGE_ADD_PIXEL1_2(s, p) \
1432 ((uint16) (Depth [z + GFX.DepthDelta] ? (Depth [z + GFX.DepthDelta] != 1 ? \
1433                                COLOR_ADD1_2 (p, *(s + GFX.Delta))    : \
1434                                COLOR_ADD (p, GFX.FixedColour)) \
1435                             : p))
1436                               
1437     RENDER_TILE_LARGE (GFX.ScreenColors [pixel], LARGE_ADD_PIXEL1_2)
1438 }
1439
1440 void DrawLargePixel16Sub (uint32 Tile, uint32 Offset,
1441                           uint32 StartPixel, uint32 Pixels,
1442                           uint32 StartLine, uint32 LineCount)
1443 {
1444     TILE_PREAMBLE
1445
1446     register uint16 *sp = (uint16 *) GFX.S + Offset;
1447     uint8  *Depth = GFX.ZBuffer + Offset;
1448     register uint16 pixel;
1449
1450 #define LARGE_SUB_PIXEL(s, p) \
1451 (Depth [z + GFX.DepthDelta] ? (Depth [z + GFX.DepthDelta] != 1 ? \
1452                                COLOR_SUB (p, *(s + GFX.Delta))    : \
1453                                COLOR_SUB (p, GFX.FixedColour)) \
1454                             : p)
1455                               
1456     RENDER_TILE_LARGE (GFX.ScreenColors [pixel], LARGE_SUB_PIXEL)
1457 }
1458
1459 void DrawLargePixel16Sub1_2 (uint32 Tile, uint32 Offset,
1460                              uint32 StartPixel, uint32 Pixels,
1461                              uint32 StartLine, uint32 LineCount)
1462 {
1463     TILE_PREAMBLE
1464
1465     register uint16 *sp = (uint16 *) GFX.S + Offset;
1466     uint8  *Depth = GFX.ZBuffer + Offset;
1467     uint16 pixel;
1468
1469 #define LARGE_SUB_PIXEL1_2(s, p) \
1470 (Depth [z + GFX.DepthDelta] ? (Depth [z + GFX.DepthDelta] != 1 ? \
1471                                COLOR_SUB1_2 (p, *(s + GFX.Delta))    : \
1472                                COLOR_SUB (p, GFX.FixedColour)) \
1473                             : p)
1474                               
1475     RENDER_TILE_LARGE (GFX.ScreenColors [pixel], LARGE_SUB_PIXEL1_2)
1476 }
1477
1478 void DrawHiResTile16 (uint32 Tile, uint32 Offset, uint32 StartLine,
1479                  uint32 LineCount)
1480 {
1481     TILE_PREAMBLE
1482     register uint8 *bp;
1483
1484     RENDER_TILEHI(WRITE_4PIXELSHI16, WRITE_4PIXELSHI16_FLIPPED, 4)
1485 }
1486
1487 void DrawHiResClippedTile16 (uint32 Tile, uint32 Offset,
1488                           uint32 StartPixel, uint32 Width,
1489                         uint32 StartLine, uint32 LineCount)
1490 {
1491     TILE_PREAMBLE
1492     register uint8 *bp;
1493
1494     TILE_CLIP_PREAMBLE
1495     RENDER_CLIPPED_TILEHI(WRITE_4PIXELSHI16, WRITE_4PIXELSHI16_FLIPPED, 4)
1496 }