completely remove paletted color support
[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 #define PLOT_PIXEL(screen, pixel) (pixel)
362
363 extern uint32 HeadMask [4];
364 extern uint32 TailMask [5];
365
366 uint8 ConvertTile (uint8 *pCache, uint32 TileAddr)
367 {
368     register uint8 *tp = &Memory.VRAM[TileAddr];
369     uint32 *p = (uint32 *) pCache;
370     uint32 non_zero = 0;
371     uint8 line;
372         uint32 p1;
373         uint32 p2;
374         register uint8 pix;
375
376     switch (BG.BitShift)
377     {
378     case 8:
379         for (line = 8; line != 0; line--, tp += 2)
380         {
381             p1 = p2 = 0;
382             if ((pix = *(tp + 0)))
383             {
384                 p1 |= odd_high[0][pix >> 4];
385                 p2 |= odd_low[0][pix & 0xf];
386             }
387             if ((pix = *(tp + 1)))
388             {
389                 p1 |= even_high[0][pix >> 4];
390                 p2 |= even_low[0][pix & 0xf];
391             }
392             if ((pix = *(tp + 16)))
393             {
394                 p1 |= odd_high[1][pix >> 4];
395                 p2 |= odd_low[1][pix & 0xf];
396             }
397             if ((pix = *(tp + 17)))
398             {
399                 p1 |= even_high[1][pix >> 4];
400                 p2 |= even_low[1][pix & 0xf];
401             }
402             if ((pix = *(tp + 32)))
403             {
404                 p1 |= odd_high[2][pix >> 4];
405                 p2 |= odd_low[2][pix & 0xf];
406             }
407             if ((pix = *(tp + 33)))
408             {
409                 p1 |= even_high[2][pix >> 4];
410                 p2 |= even_low[2][pix & 0xf];
411             }
412             if ((pix = *(tp + 48)))
413             {
414                 p1 |= odd_high[3][pix >> 4];
415                 p2 |= odd_low[3][pix & 0xf];
416             }
417             if ((pix = *(tp + 49)))
418             {
419                 p1 |= even_high[3][pix >> 4];
420                 p2 |= even_low[3][pix & 0xf];
421             }
422             *p++ = p1;
423             *p++ = p2;
424             non_zero |= p1 | p2;
425         }
426         break;
427
428     case 4:
429         for (line = 8; line != 0; line--, tp += 2)
430         {
431             p1 = p2 = 0;
432             if ((pix = *(tp + 0)))
433             {
434                 p1 |= odd_high[0][pix >> 4];
435                 p2 |= odd_low[0][pix & 0xf];
436             }
437             if ((pix = *(tp + 1)))
438             {
439                 p1 |= even_high[0][pix >> 4];
440                 p2 |= even_low[0][pix & 0xf];
441             }
442             if ((pix = *(tp + 16)))
443             {
444                 p1 |= odd_high[1][pix >> 4];
445                 p2 |= odd_low[1][pix & 0xf];
446             }
447             if ((pix = *(tp + 17)))
448             {
449                 p1 |= even_high[1][pix >> 4];
450                 p2 |= even_low[1][pix & 0xf];
451             }
452             *p++ = p1;
453             *p++ = p2;
454             non_zero |= p1 | p2;
455         }
456         break;
457
458     case 2:
459         for (line = 8; line != 0; line--, tp += 2)
460         {
461             p1 = p2 = 0;
462             if ((pix = *(tp + 0)))
463             {
464                 p1 |= odd_high[0][pix >> 4];
465                 p2 |= odd_low[0][pix & 0xf];
466             }
467             if ((pix = *(tp + 1)))
468             {
469                 p1 |= even_high[0][pix >> 4];
470                 p2 |= even_low[0][pix & 0xf];
471             }
472             *p++ = p1;
473             *p++ = p2;
474             non_zero |= p1 | p2;
475         }
476         break;
477     }
478     return (non_zero ? TRUE : BLANK_TILE);
479 }
480
481 inline void WRITE_4PIXELSHI16 (tile_offset_t Offset, uint8 *Pixels)
482 {
483     uint32 Pixel;
484     uint16 *Screen = (uint16 *) GFX.S + Offset;
485     uint8  *Depth = GFX.DB + Offset;
486
487 #define FN(N) \
488     if (GFX.Z1 > Depth [N] && (Pixel = Pixels[2*N])) \
489     { \
490         Screen [N] = GFX.ScreenColors [Pixel]; \
491         Depth [N] = GFX.Z2; \
492     }
493
494     FN(0)
495     FN(1)
496     FN(2)
497     FN(3)
498 #undef FN
499 }
500
501 inline void WRITE_4PIXELSHI16_FLIPPED (tile_offset_t Offset, uint8 *Pixels)
502 {
503     uint32 Pixel;
504     uint16 *Screen = (uint16 *) GFX.S + Offset;
505     uint8  *Depth = GFX.DB + Offset;
506
507 #define FN(N) \
508     if (GFX.Z1 > Depth [N] && (Pixel = Pixels[6 - 2*N])) \
509     { \
510         Screen [N] = GFX.ScreenColors [Pixel]; \
511         Depth [N] = GFX.Z2; \
512     }
513
514     FN(0)
515     FN(1)
516     FN(2)
517     FN(3)
518 #undef FN
519 }
520
521 STATIC INLINE void WRITE_4PIXELS16 (tile_offset_t Offset, uint8 *Pixels)
522 {
523     register uint32 Pixel;
524     uint16 *Screen = (uint16 *) GFX.S + Offset;
525     uint8  *Depth = GFX.DB + Offset;
526
527 #define FN(N) \
528     if (GFX.Z1 > Depth [N] && (Pixel = Pixels[N])) \
529     { \
530         Screen [N] = GFX.ScreenColors [Pixel]; \
531         Depth [N] = GFX.Z2; \
532     }
533
534     FN(0)
535     FN(1)
536     FN(2)
537     FN(3)
538 #undef FN
539 }
540
541 STATIC INLINE void WRITE_4PIXELS16_FLIPPED (tile_offset_t Offset, uint8 *Pixels)
542 {
543     register uint32 Pixel;
544     uint16 *Screen = (uint16 *) GFX.S + Offset;
545     uint8  *Depth = GFX.DB + Offset;
546
547 #define FN(N) \
548     if (GFX.Z1 > Depth [N] && (Pixel = Pixels[3 - N])) \
549     { \
550         Screen [N] = GFX.ScreenColors [Pixel]; \
551         Depth [N] = GFX.Z2; \
552     }
553
554     FN(0)
555     FN(1)
556     FN(2)
557     FN(3)
558 #undef FN
559 }
560
561 void DrawTile16 (uint32 Tile, tile_offset_t Offset, uint32 StartLine,
562                  uint32 LineCount)
563 {
564     TILE_PREAMBLE
565     register uint8 *bp;
566
567     RENDER_TILE(WRITE_4PIXELS16, WRITE_4PIXELS16_FLIPPED, 4)
568 }
569
570 void DrawClippedTile16 (uint32 Tile, tile_offset_t Offset,
571                         uint32 StartPixel, uint32 Width,
572                         uint32 StartLine, uint32 LineCount)
573 {
574     TILE_PREAMBLE
575     register uint8 *bp;
576
577     TILE_CLIP_PREAMBLE
578     RENDER_CLIPPED_TILE(WRITE_4PIXELS16, WRITE_4PIXELS16_FLIPPED, 4)
579 }
580
581 void DrawLargePixel16 (uint32 Tile, tile_offset_t Offset,
582                        uint32 StartPixel, uint32 Pixels,
583                        uint32 StartLine, uint32 LineCount)
584 {
585     TILE_PREAMBLE
586
587     register uint16 *sp = (uint16 *) GFX.S + Offset;
588     uint8  *Depth = GFX.DB + Offset;
589     uint16 pixel;
590
591     RENDER_TILE_LARGE (GFX.ScreenColors [pixel], PLOT_PIXEL)
592 }
593
594 STATIC INLINE void WRITE_4PIXELS16_ADD (tile_offset_t Offset, uint8 *Pixels)
595 {
596     register uint32 Pixel;
597     uint16 *Screen = (uint16 *) GFX.S + Offset;
598     uint8  *Depth = GFX.ZBuffer + Offset;
599     uint8  *SubDepth = GFX.SubZBuffer + Offset;
600
601 #define FN(N) \
602     if (GFX.Z1 > Depth [N] && (Pixel = Pixels[N])) \
603     { \
604         if (SubDepth [N]) \
605         { \
606             if (SubDepth [N] != 1) \
607                 Screen [N] = COLOR_ADD (GFX.ScreenColors [Pixel], \
608                                         Screen [GFX.Delta + N]); \
609             else \
610                 Screen [N] = COLOR_ADD (GFX.ScreenColors [Pixel], \
611                                         GFX.FixedColour); \
612         } \
613         else \
614             Screen [N] = GFX.ScreenColors [Pixel]; \
615         Depth [N] = GFX.Z2; \
616     }
617
618     FN(0)
619     FN(1)
620     FN(2)
621     FN(3)
622
623 #undef FN
624 }
625
626 STATIC INLINE void WRITE_4PIXELS16_FLIPPED_ADD (tile_offset_t Offset, uint8 *Pixels)
627 {
628     register uint32 Pixel;
629     uint16 *Screen = (uint16 *) GFX.S + Offset;
630     uint8  *Depth = GFX.ZBuffer + Offset;
631     uint8  *SubDepth = GFX.SubZBuffer + Offset;
632
633 #define FN(N) \
634     if (GFX.Z1 > Depth [N] && (Pixel = Pixels[3 - N])) \
635     { \
636         if (SubDepth [N]) \
637         { \
638             if (SubDepth [N] != 1) \
639                 Screen [N] = COLOR_ADD (GFX.ScreenColors [Pixel], \
640                                         Screen [GFX.Delta + N]); \
641             else \
642                 Screen [N] = COLOR_ADD (GFX.ScreenColors [Pixel], \
643                                         GFX.FixedColour); \
644         } \
645         else \
646             Screen [N] = GFX.ScreenColors [Pixel]; \
647         Depth [N] = GFX.Z2; \
648     }
649
650     FN(0)
651     FN(1)
652     FN(2)
653     FN(3)
654
655 #undef FN
656 }
657
658 STATIC INLINE void WRITE_4PIXELS16_ADD1_2 (tile_offset_t Offset, uint8 *Pixels)
659 {
660     register uint32 Pixel;
661     uint16 *Screen = (uint16 *) GFX.S + Offset;
662     uint8  *Depth = GFX.ZBuffer + Offset;
663     uint8  *SubDepth = GFX.SubZBuffer + Offset;
664
665 #define FN(N) \
666     if (GFX.Z1 > Depth [N] && (Pixel = Pixels[N])) \
667     { \
668         if (SubDepth [N]) \
669         { \
670             if (SubDepth [N] != 1) \
671                 Screen [N] = (uint16) (COLOR_ADD1_2 (GFX.ScreenColors [Pixel], \
672                                                      Screen [GFX.Delta + N])); \
673             else \
674                 Screen [N] = COLOR_ADD (GFX.ScreenColors [Pixel], \
675                                         GFX.FixedColour); \
676         } \
677         else \
678             Screen [N] = GFX.ScreenColors [Pixel]; \
679         Depth [N] = GFX.Z2; \
680     }
681
682     FN(0)
683     FN(1)
684     FN(2)
685     FN(3)
686
687 #undef FN
688 }
689
690 STATIC INLINE void WRITE_4PIXELS16_FLIPPED_ADD1_2 (tile_offset_t Offset, uint8 *Pixels)
691 {
692     register uint32 Pixel;
693     uint16 *Screen = (uint16 *) GFX.S + Offset;
694     uint8  *Depth = GFX.ZBuffer + Offset;
695     uint8  *SubDepth = GFX.SubZBuffer + Offset;
696
697 #define FN(N) \
698     if (GFX.Z1 > Depth [N] && (Pixel = Pixels[3 - N])) \
699     { \
700         if (SubDepth [N]) \
701         { \
702             if (SubDepth [N] != 1) \
703                 Screen [N] = (uint16) (COLOR_ADD1_2 (GFX.ScreenColors [Pixel], \
704                                                      Screen [GFX.Delta + N])); \
705             else \
706                 Screen [N] = COLOR_ADD (GFX.ScreenColors [Pixel], \
707                                         GFX.FixedColour); \
708         } \
709         else \
710             Screen [N] = GFX.ScreenColors [Pixel]; \
711         Depth [N] = GFX.Z2; \
712     }
713
714     FN(0)
715     FN(1)
716     FN(2)
717     FN(3)
718
719 #undef FN
720 }
721
722 STATIC INLINE void WRITE_4PIXELS16_SUB (tile_offset_t Offset, uint8 *Pixels)
723 {
724     register uint32 Pixel;
725     uint16 *Screen = (uint16 *) GFX.S + Offset;
726     uint8  *Depth = GFX.ZBuffer + Offset;
727     uint8  *SubDepth = GFX.SubZBuffer + Offset;
728
729 #define FN(N) \
730     if (GFX.Z1 > Depth [N] && (Pixel = Pixels[N])) \
731     { \
732         if (SubDepth [N]) \
733         { \
734             if (SubDepth [N] != 1) \
735                 Screen [N] = (uint16) COLOR_SUB (GFX.ScreenColors [Pixel], \
736                                         Screen [GFX.Delta + N]); \
737             else \
738                 Screen [N] = (uint16) COLOR_SUB (GFX.ScreenColors [Pixel], \
739                                         GFX.FixedColour); \
740         } \
741         else \
742             Screen [N] = GFX.ScreenColors [Pixel]; \
743         Depth [N] = GFX.Z2; \
744     }
745
746     FN(0)
747     FN(1)
748     FN(2)
749     FN(3)
750
751 #undef FN
752 }
753
754 STATIC INLINE void WRITE_4PIXELS16_FLIPPED_SUB (tile_offset_t Offset, uint8 *Pixels)
755 {
756     register uint32 Pixel;
757     uint16 *Screen = (uint16 *) GFX.S + Offset;
758     uint8  *Depth = GFX.ZBuffer + Offset;
759     uint8  *SubDepth = GFX.SubZBuffer + Offset;
760
761 #define FN(N) \
762     if (GFX.Z1 > Depth [N] && (Pixel = Pixels[3 - N])) \
763     { \
764         if (SubDepth [N]) \
765         { \
766             if (SubDepth [N] != 1) \
767                 Screen [N] = (uint16) COLOR_SUB (GFX.ScreenColors [Pixel], \
768                                         Screen [GFX.Delta + N]); \
769             else \
770                 Screen [N] = (uint16) COLOR_SUB (GFX.ScreenColors [Pixel], \
771                                         GFX.FixedColour); \
772         } \
773         else \
774             Screen [N] = GFX.ScreenColors [Pixel]; \
775         Depth [N] = GFX.Z2; \
776     }
777
778     FN(0)
779     FN(1)
780     FN(2)
781     FN(3)
782
783 #undef FN
784 }
785
786 STATIC INLINE void WRITE_4PIXELS16_SUB1_2 (tile_offset_t Offset, uint8 *Pixels)
787 {
788     register uint32 Pixel;
789     uint16 *Screen = (uint16 *) GFX.S + Offset;
790     uint8  *Depth = GFX.ZBuffer + Offset;
791     uint8  *SubDepth = GFX.SubZBuffer + Offset;
792
793 #define FN(N) \
794     if (GFX.Z1 > Depth [N] && (Pixel = Pixels[N])) \
795     { \
796         if (SubDepth [N]) \
797         { \
798             if (SubDepth [N] != 1) \
799                 Screen [N] = (uint16) COLOR_SUB1_2 (GFX.ScreenColors [Pixel], \
800                                            Screen [GFX.Delta + N]); \
801             else \
802                 Screen [N] = (uint16) COLOR_SUB (GFX.ScreenColors [Pixel], \
803                                         GFX.FixedColour); \
804         } \
805         else \
806             Screen [N] = GFX.ScreenColors [Pixel]; \
807         Depth [N] = GFX.Z2; \
808     }
809
810     FN(0)
811     FN(1)
812     FN(2)
813     FN(3)
814
815 #undef FN
816 }
817
818 STATIC INLINE void WRITE_4PIXELS16_FLIPPED_SUB1_2 (tile_offset_t Offset, uint8 *Pixels)
819 {
820     register uint32 Pixel;
821     uint16 *Screen = (uint16 *) GFX.S + Offset;
822     uint8  *Depth = GFX.ZBuffer + Offset;
823     uint8  *SubDepth = GFX.SubZBuffer + Offset;
824
825 #define FN(N) \
826     if (GFX.Z1 > Depth [N] && (Pixel = Pixels[3 - N])) \
827     { \
828         if (SubDepth [N]) \
829         { \
830             if (SubDepth [N] != 1) \
831                 Screen [N] = (uint16) COLOR_SUB1_2 (GFX.ScreenColors [Pixel], \
832                                            Screen [GFX.Delta + N]); \
833             else \
834                 Screen [N] = (uint16) COLOR_SUB (GFX.ScreenColors [Pixel], \
835                                         GFX.FixedColour); \
836         } \
837         else \
838             Screen [N] = GFX.ScreenColors [Pixel]; \
839         Depth [N] = GFX.Z2; \
840     }
841
842     FN(0)
843     FN(1)
844     FN(2)
845     FN(3)
846
847 #undef FN
848 }
849
850
851 void DrawTile16Add (uint32 Tile, tile_offset_t Offset, uint32 StartLine,
852                     uint32 LineCount)
853 {
854     TILE_PREAMBLE
855     register uint8 *bp;
856
857     RENDER_TILE(WRITE_4PIXELS16_ADD, WRITE_4PIXELS16_FLIPPED_ADD, 4)
858 }
859
860 void DrawClippedTile16Add (uint32 Tile, tile_offset_t Offset,
861                            uint32 StartPixel, uint32 Width,
862                            uint32 StartLine, uint32 LineCount)
863 {
864     TILE_PREAMBLE
865     register uint8 *bp;
866
867     TILE_CLIP_PREAMBLE
868     RENDER_CLIPPED_TILE(WRITE_4PIXELS16_ADD, WRITE_4PIXELS16_FLIPPED_ADD, 4)
869 }
870
871 void DrawTile16Add1_2 (uint32 Tile, tile_offset_t Offset, uint32 StartLine,
872                        uint32 LineCount)
873 {
874     TILE_PREAMBLE
875     register uint8 *bp;
876
877     RENDER_TILE(WRITE_4PIXELS16_ADD1_2, WRITE_4PIXELS16_FLIPPED_ADD1_2, 4)
878 }
879
880 void DrawClippedTile16Add1_2 (uint32 Tile, tile_offset_t Offset,
881                               uint32 StartPixel, uint32 Width,
882                               uint32 StartLine, uint32 LineCount)
883 {
884     TILE_PREAMBLE
885     register uint8 *bp;
886
887     TILE_CLIP_PREAMBLE
888     RENDER_CLIPPED_TILE(WRITE_4PIXELS16_ADD1_2, WRITE_4PIXELS16_FLIPPED_ADD1_2, 4)
889 }
890
891 void DrawTile16Sub (uint32 Tile, tile_offset_t Offset, uint32 StartLine,
892                     uint32 LineCount)
893 {
894     TILE_PREAMBLE
895     register uint8 *bp;
896
897     RENDER_TILE(WRITE_4PIXELS16_SUB, WRITE_4PIXELS16_FLIPPED_SUB, 4)
898 }
899
900 void DrawClippedTile16Sub (uint32 Tile, tile_offset_t Offset,
901                            uint32 StartPixel, uint32 Width,
902                            uint32 StartLine, uint32 LineCount)
903 {
904     TILE_PREAMBLE
905     register uint8 *bp;
906
907     TILE_CLIP_PREAMBLE
908     RENDER_CLIPPED_TILE(WRITE_4PIXELS16_SUB, WRITE_4PIXELS16_FLIPPED_SUB, 4)
909 }
910
911 void DrawTile16Sub1_2 (uint32 Tile, tile_offset_t Offset, uint32 StartLine,
912                        uint32 LineCount)
913 {
914     TILE_PREAMBLE
915     register uint8 *bp;
916
917     RENDER_TILE(WRITE_4PIXELS16_SUB1_2, WRITE_4PIXELS16_FLIPPED_SUB1_2, 4)
918 }
919
920 void DrawClippedTile16Sub1_2 (uint32 Tile, tile_offset_t Offset,
921                               uint32 StartPixel, uint32 Width,
922                               uint32 StartLine, uint32 LineCount)
923 {
924     TILE_PREAMBLE
925     register uint8 *bp;
926
927     TILE_CLIP_PREAMBLE
928     RENDER_CLIPPED_TILE(WRITE_4PIXELS16_SUB1_2, WRITE_4PIXELS16_FLIPPED_SUB1_2, 4)
929 }
930
931 STATIC INLINE void WRITE_4PIXELS16_ADDF1_2 (tile_offset_t Offset, uint8 *Pixels)
932 {
933     register uint32 Pixel;
934     uint16 *Screen = (uint16 *) GFX.S + Offset;
935     uint8  *Depth = GFX.ZBuffer + Offset;
936     uint8  *SubDepth = GFX.SubZBuffer + Offset;
937
938 #define FN(N) \
939     if (GFX.Z1 > Depth [N] && (Pixel = Pixels[N])) \
940     { \
941         if (SubDepth [N] == 1) \
942             Screen [N] = (uint16) (COLOR_ADD1_2 (GFX.ScreenColors [Pixel], \
943                                                  GFX.FixedColour)); \
944         else \
945             Screen [N] = GFX.ScreenColors [Pixel];\
946         Depth [N] = GFX.Z2; \
947     }
948
949     FN(0)
950     FN(1)
951     FN(2)
952     FN(3)
953
954 #undef FN
955 }
956
957 STATIC INLINE void WRITE_4PIXELS16_FLIPPED_ADDF1_2 (tile_offset_t Offset, uint8 *Pixels)
958 {
959     register uint32 Pixel;
960     uint16 *Screen = (uint16 *) GFX.S + Offset;
961     uint8  *Depth = GFX.ZBuffer + Offset;
962     uint8  *SubDepth = GFX.SubZBuffer + Offset;
963
964 #define FN(N) \
965     if (GFX.Z1 > Depth [N] && (Pixel = Pixels[3 - N])) \
966     { \
967         if (SubDepth [N] == 1) \
968             Screen [N] = (uint16) (COLOR_ADD1_2 (GFX.ScreenColors [Pixel], \
969                                                  GFX.FixedColour)); \
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 STATIC INLINE void WRITE_4PIXELS16_SUBF1_2 (tile_offset_t 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] == 1) \
994             Screen [N] = (uint16) COLOR_SUB1_2 (GFX.ScreenColors [Pixel], \
995                                                 GFX.FixedColour); \
996         else \
997             Screen [N] = GFX.ScreenColors [Pixel]; \
998         Depth [N] = GFX.Z2; \
999     }
1000
1001     FN(0)
1002     FN(1)
1003     FN(2)
1004     FN(3)
1005
1006 #undef FN
1007 }
1008
1009 STATIC INLINE void WRITE_4PIXELS16_FLIPPED_SUBF1_2 (tile_offset_t Offset, uint8 *Pixels)
1010 {
1011     register uint32 Pixel;
1012     uint16 *Screen = (uint16 *) GFX.S + Offset;
1013     uint8  *Depth = GFX.ZBuffer + Offset;
1014     uint8  *SubDepth = GFX.SubZBuffer + Offset;
1015
1016 #define FN(N) \
1017     if (GFX.Z1 > Depth [N] && (Pixel = Pixels[3 - N])) \
1018     { \
1019         if (SubDepth [N] == 1) \
1020             Screen [N] = (uint16) COLOR_SUB1_2 (GFX.ScreenColors [Pixel], \
1021                                                 GFX.FixedColour); \
1022         else \
1023             Screen [N] = GFX.ScreenColors [Pixel]; \
1024         Depth [N] = GFX.Z2; \
1025     }
1026
1027     FN(0)
1028     FN(1)
1029     FN(2)
1030     FN(3)
1031
1032 #undef FN
1033 }
1034
1035 void DrawTile16FixedAdd1_2 (uint32 Tile, tile_offset_t Offset, uint32 StartLine,
1036                             uint32 LineCount)
1037 {
1038     TILE_PREAMBLE
1039     register uint8 *bp;
1040
1041     RENDER_TILE(WRITE_4PIXELS16_ADDF1_2, WRITE_4PIXELS16_FLIPPED_ADDF1_2, 4)
1042 }
1043
1044 void DrawClippedTile16FixedAdd1_2 (uint32 Tile, tile_offset_t Offset,
1045                                    uint32 StartPixel, uint32 Width,
1046                                    uint32 StartLine, uint32 LineCount)
1047 {
1048     TILE_PREAMBLE
1049     register uint8 *bp;
1050
1051     TILE_CLIP_PREAMBLE
1052     RENDER_CLIPPED_TILE(WRITE_4PIXELS16_ADDF1_2, 
1053                         WRITE_4PIXELS16_FLIPPED_ADDF1_2, 4)
1054 }
1055
1056 void DrawTile16FixedSub1_2 (uint32 Tile, tile_offset_t Offset, uint32 StartLine,
1057                             uint32 LineCount)
1058 {
1059     TILE_PREAMBLE
1060     register uint8 *bp;
1061
1062     RENDER_TILE(WRITE_4PIXELS16_SUBF1_2, WRITE_4PIXELS16_FLIPPED_SUBF1_2, 4)
1063 }
1064
1065 void DrawClippedTile16FixedSub1_2 (uint32 Tile, tile_offset_t Offset,
1066                                    uint32 StartPixel, uint32 Width,
1067                                    uint32 StartLine, uint32 LineCount)
1068 {
1069     TILE_PREAMBLE
1070     register uint8 *bp;
1071
1072     TILE_CLIP_PREAMBLE
1073     RENDER_CLIPPED_TILE(WRITE_4PIXELS16_SUBF1_2, 
1074                         WRITE_4PIXELS16_FLIPPED_SUBF1_2, 4)
1075 }
1076
1077 void DrawLargePixel16Add (uint32 Tile, tile_offset_t Offset,
1078                           uint32 StartPixel, uint32 Pixels,
1079                           uint32 StartLine, uint32 LineCount)
1080 {
1081     TILE_PREAMBLE
1082
1083     register uint16 *sp = (uint16 *) GFX.S + Offset;
1084     uint8  *Depth = GFX.ZBuffer + Offset;
1085     register uint16 pixel;
1086
1087 #define LARGE_ADD_PIXEL(s, p) \
1088 (Depth [z + GFX.DepthDelta] ? (Depth [z + GFX.DepthDelta] != 1 ? \
1089                                COLOR_ADD (p, *(s + GFX.Delta))    : \
1090                                COLOR_ADD (p, GFX.FixedColour)) \
1091                             : p)
1092                               
1093     RENDER_TILE_LARGE (GFX.ScreenColors [pixel], LARGE_ADD_PIXEL)
1094 }
1095
1096 void DrawLargePixel16Add1_2 (uint32 Tile, tile_offset_t Offset,
1097                              uint32 StartPixel, uint32 Pixels,
1098                              uint32 StartLine, uint32 LineCount)
1099 {
1100     TILE_PREAMBLE
1101
1102     register uint16 *sp = (uint16 *) GFX.S + Offset;
1103     uint8  *Depth = GFX.ZBuffer + Offset;
1104     register uint16 pixel;
1105
1106 #define LARGE_ADD_PIXEL1_2(s, p) \
1107 ((uint16) (Depth [z + GFX.DepthDelta] ? (Depth [z + GFX.DepthDelta] != 1 ? \
1108                                COLOR_ADD1_2 (p, *(s + GFX.Delta))    : \
1109                                COLOR_ADD (p, GFX.FixedColour)) \
1110                             : p))
1111                               
1112     RENDER_TILE_LARGE (GFX.ScreenColors [pixel], LARGE_ADD_PIXEL1_2)
1113 }
1114
1115 void DrawLargePixel16Sub (uint32 Tile, tile_offset_t Offset,
1116                           uint32 StartPixel, uint32 Pixels,
1117                           uint32 StartLine, uint32 LineCount)
1118 {
1119     TILE_PREAMBLE
1120
1121     register uint16 *sp = (uint16 *) GFX.S + Offset;
1122     uint8  *Depth = GFX.ZBuffer + Offset;
1123     register uint16 pixel;
1124
1125 #define LARGE_SUB_PIXEL(s, p) \
1126 (Depth [z + GFX.DepthDelta] ? (Depth [z + GFX.DepthDelta] != 1 ? \
1127                                COLOR_SUB (p, *(s + GFX.Delta))    : \
1128                                COLOR_SUB (p, GFX.FixedColour)) \
1129                             : p)
1130                               
1131     RENDER_TILE_LARGE (GFX.ScreenColors [pixel], LARGE_SUB_PIXEL)
1132 }
1133
1134 void DrawLargePixel16Sub1_2 (uint32 Tile, tile_offset_t Offset,
1135                              uint32 StartPixel, uint32 Pixels,
1136                              uint32 StartLine, uint32 LineCount)
1137 {
1138     TILE_PREAMBLE
1139
1140     register uint16 *sp = (uint16 *) GFX.S + Offset;
1141     uint8  *Depth = GFX.ZBuffer + Offset;
1142     uint16 pixel;
1143
1144 #define LARGE_SUB_PIXEL1_2(s, p) \
1145 (Depth [z + GFX.DepthDelta] ? (Depth [z + GFX.DepthDelta] != 1 ? \
1146                                COLOR_SUB1_2 (p, *(s + GFX.Delta))    : \
1147                                COLOR_SUB (p, GFX.FixedColour)) \
1148                             : p)
1149                               
1150     RENDER_TILE_LARGE (GFX.ScreenColors [pixel], LARGE_SUB_PIXEL1_2)
1151 }
1152
1153 void DrawHiResTile16 (uint32 Tile, tile_offset_t Offset, uint32 StartLine,
1154                  uint32 LineCount)
1155 {
1156     TILE_PREAMBLE
1157     register uint8 *bp;
1158
1159     RENDER_TILEHI(WRITE_4PIXELSHI16, WRITE_4PIXELSHI16_FLIPPED, 4)
1160 }
1161
1162 void DrawHiResClippedTile16 (uint32 Tile, tile_offset_t Offset,
1163                           uint32 StartPixel, uint32 Width,
1164                         uint32 StartLine, uint32 LineCount)
1165 {
1166     TILE_PREAMBLE
1167     register uint8 *bp;
1168
1169     TILE_CLIP_PREAMBLE
1170     RENDER_CLIPPED_TILEHI(WRITE_4PIXELSHI16, WRITE_4PIXELSHI16_FLIPPED, 4)
1171 }
1172