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