5597a14f54fae93ff0c02746460dbf2fbb26b20f
[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 void DrawTile(uint32 Tile, uint32 Offset, uint32 StartLine, uint32 LineCount)
560 {
561     TILE_PREAMBLE
562
563     register uint8 *bp;
564
565     RENDER_TILE(WRITE_4PIXELS, WRITE_4PIXELS_FLIPPED, 4)
566 }
567
568 void DrawClippedTile(uint32 Tile, uint32 Offset,
569                       uint32 StartPixel, uint32 Width,
570                       uint32 StartLine, uint32 LineCount)
571 {
572     TILE_PREAMBLE
573     register uint8 *bp;
574
575     TILE_CLIP_PREAMBLE
576     RENDER_CLIPPED_TILE(WRITE_4PIXELS, WRITE_4PIXELS_FLIPPED, 4)
577 }
578
579 void DrawLargePixel (uint32 Tile, uint32 Offset,
580                      uint32 StartPixel, uint32 Pixels,
581                      uint32 StartLine, uint32 LineCount)
582 {
583     TILE_PREAMBLE
584
585     register uint8 *sp = GFX.S + Offset;
586     uint8  *Depth = GFX.DB + Offset;
587     uint8 pixel;
588 #define PLOT_PIXEL(screen, pixel) (pixel)
589
590     RENDER_TILE_LARGE (((uint8) GFX.ScreenColors [pixel]), PLOT_PIXEL)
591 }
592
593 STATIC INLINE void WRITE_4PIXELS16 (uint32 Offset, uint8 *Pixels)
594 {
595     register uint32 Pixel;
596     uint16 *Screen = (uint16 *) GFX.S + Offset;
597     uint8  *Depth = GFX.DB + Offset;
598
599 #define FN(N) \
600     if (GFX.Z1 > Depth [N] && (Pixel = Pixels[N])) \
601     { \
602         Screen [N] = GFX.ScreenColors [Pixel]; \
603         Depth [N] = GFX.Z2; \
604     }
605
606     FN(0)
607     FN(1)
608     FN(2)
609     FN(3)
610 #undef FN
611 }
612
613 STATIC INLINE void WRITE_4PIXELS16_FLIPPED (uint32 Offset, uint8 *Pixels)
614 {
615     register uint32 Pixel;
616     uint16 *Screen = (uint16 *) GFX.S + Offset;
617     uint8  *Depth = GFX.DB + Offset;
618
619 #define FN(N) \
620     if (GFX.Z1 > Depth [N] && (Pixel = Pixels[3 - N])) \
621     { \
622         Screen [N] = GFX.ScreenColors [Pixel]; \
623         Depth [N] = GFX.Z2; \
624     }
625
626     FN(0)
627     FN(1)
628     FN(2)
629     FN(3)
630 #undef FN
631 }
632
633 void DrawTile16 (uint32 Tile, uint32 Offset, uint32 StartLine,
634                  uint32 LineCount)
635 {
636     TILE_PREAMBLE
637     register uint8 *bp;
638
639     RENDER_TILE(WRITE_4PIXELS16, WRITE_4PIXELS16_FLIPPED, 4)
640 }
641
642 void DrawClippedTile16 (uint32 Tile, uint32 Offset,
643                         uint32 StartPixel, uint32 Width,
644                         uint32 StartLine, uint32 LineCount)
645 {
646     TILE_PREAMBLE
647     register uint8 *bp;
648
649     TILE_CLIP_PREAMBLE
650     RENDER_CLIPPED_TILE(WRITE_4PIXELS16, WRITE_4PIXELS16_FLIPPED, 4)
651 }
652
653 void DrawLargePixel16 (uint32 Tile, uint32 Offset,
654                        uint32 StartPixel, uint32 Pixels,
655                        uint32 StartLine, uint32 LineCount)
656 {
657     TILE_PREAMBLE
658
659     register uint16 *sp = (uint16 *) GFX.S + Offset;
660     uint8  *Depth = GFX.DB + Offset;
661     uint16 pixel;
662
663     RENDER_TILE_LARGE (GFX.ScreenColors [pixel], PLOT_PIXEL)
664 }
665
666 STATIC INLINE void WRITE_4PIXELS16_ADD (uint32 Offset, uint8 *Pixels)
667 {
668     register uint32 Pixel;
669     uint16 *Screen = (uint16 *) GFX.S + Offset;
670     uint8  *Depth = GFX.ZBuffer + Offset;
671     uint8  *SubDepth = GFX.SubZBuffer + Offset;
672
673 #define FN(N) \
674     if (GFX.Z1 > Depth [N] && (Pixel = Pixels[N])) \
675     { \
676         if (SubDepth [N]) \
677         { \
678             if (SubDepth [N] != 1) \
679                 Screen [N] = COLOR_ADD (GFX.ScreenColors [Pixel], \
680                                         Screen [GFX.Delta + N]); \
681             else \
682                 Screen [N] = COLOR_ADD (GFX.ScreenColors [Pixel], \
683                                         GFX.FixedColour); \
684         } \
685         else \
686             Screen [N] = GFX.ScreenColors [Pixel]; \
687         Depth [N] = GFX.Z2; \
688     }
689
690     FN(0)
691     FN(1)
692     FN(2)
693     FN(3)
694
695 #undef FN
696 }
697
698 STATIC INLINE void WRITE_4PIXELS16_FLIPPED_ADD (uint32 Offset, uint8 *Pixels)
699 {
700     register uint32 Pixel;
701     uint16 *Screen = (uint16 *) GFX.S + Offset;
702     uint8  *Depth = GFX.ZBuffer + Offset;
703     uint8  *SubDepth = GFX.SubZBuffer + Offset;
704
705 #define FN(N) \
706     if (GFX.Z1 > Depth [N] && (Pixel = Pixels[3 - N])) \
707     { \
708         if (SubDepth [N]) \
709         { \
710             if (SubDepth [N] != 1) \
711                 Screen [N] = COLOR_ADD (GFX.ScreenColors [Pixel], \
712                                         Screen [GFX.Delta + N]); \
713             else \
714                 Screen [N] = COLOR_ADD (GFX.ScreenColors [Pixel], \
715                                         GFX.FixedColour); \
716         } \
717         else \
718             Screen [N] = GFX.ScreenColors [Pixel]; \
719         Depth [N] = GFX.Z2; \
720     }
721
722     FN(0)
723     FN(1)
724     FN(2)
725     FN(3)
726
727 #undef FN
728 }
729
730 STATIC INLINE void WRITE_4PIXELS16_ADD1_2 (uint32 Offset, uint8 *Pixels)
731 {
732     register uint32 Pixel;
733     uint16 *Screen = (uint16 *) GFX.S + Offset;
734     uint8  *Depth = GFX.ZBuffer + Offset;
735     uint8  *SubDepth = GFX.SubZBuffer + Offset;
736
737 #define FN(N) \
738     if (GFX.Z1 > Depth [N] && (Pixel = Pixels[N])) \
739     { \
740         if (SubDepth [N]) \
741         { \
742             if (SubDepth [N] != 1) \
743                 Screen [N] = (uint16) (COLOR_ADD1_2 (GFX.ScreenColors [Pixel], \
744                                                      Screen [GFX.Delta + N])); \
745             else \
746                 Screen [N] = COLOR_ADD (GFX.ScreenColors [Pixel], \
747                                         GFX.FixedColour); \
748         } \
749         else \
750             Screen [N] = GFX.ScreenColors [Pixel]; \
751         Depth [N] = GFX.Z2; \
752     }
753
754     FN(0)
755     FN(1)
756     FN(2)
757     FN(3)
758
759 #undef FN
760 }
761
762 STATIC INLINE void WRITE_4PIXELS16_FLIPPED_ADD1_2 (uint32 Offset, uint8 *Pixels)
763 {
764     register uint32 Pixel;
765     uint16 *Screen = (uint16 *) GFX.S + Offset;
766     uint8  *Depth = GFX.ZBuffer + Offset;
767     uint8  *SubDepth = GFX.SubZBuffer + Offset;
768
769 #define FN(N) \
770     if (GFX.Z1 > Depth [N] && (Pixel = Pixels[3 - N])) \
771     { \
772         if (SubDepth [N]) \
773         { \
774             if (SubDepth [N] != 1) \
775                 Screen [N] = (uint16) (COLOR_ADD1_2 (GFX.ScreenColors [Pixel], \
776                                                      Screen [GFX.Delta + N])); \
777             else \
778                 Screen [N] = COLOR_ADD (GFX.ScreenColors [Pixel], \
779                                         GFX.FixedColour); \
780         } \
781         else \
782             Screen [N] = GFX.ScreenColors [Pixel]; \
783         Depth [N] = GFX.Z2; \
784     }
785
786     FN(0)
787     FN(1)
788     FN(2)
789     FN(3)
790
791 #undef FN
792 }
793
794 STATIC INLINE void WRITE_4PIXELS16_SUB (uint32 Offset, uint8 *Pixels)
795 {
796     register uint32 Pixel;
797     uint16 *Screen = (uint16 *) GFX.S + Offset;
798     uint8  *Depth = GFX.ZBuffer + Offset;
799     uint8  *SubDepth = GFX.SubZBuffer + Offset;
800
801 #define FN(N) \
802     if (GFX.Z1 > Depth [N] && (Pixel = Pixels[N])) \
803     { \
804         if (SubDepth [N]) \
805         { \
806             if (SubDepth [N] != 1) \
807                 Screen [N] = (uint16) COLOR_SUB (GFX.ScreenColors [Pixel], \
808                                         Screen [GFX.Delta + N]); \
809             else \
810                 Screen [N] = (uint16) COLOR_SUB (GFX.ScreenColors [Pixel], \
811                                         GFX.FixedColour); \
812         } \
813         else \
814             Screen [N] = GFX.ScreenColors [Pixel]; \
815         Depth [N] = GFX.Z2; \
816     }
817
818     FN(0)
819     FN(1)
820     FN(2)
821     FN(3)
822
823 #undef FN
824 }
825
826 STATIC INLINE void WRITE_4PIXELS16_FLIPPED_SUB (uint32 Offset, uint8 *Pixels)
827 {
828     register uint32 Pixel;
829     uint16 *Screen = (uint16 *) GFX.S + Offset;
830     uint8  *Depth = GFX.ZBuffer + Offset;
831     uint8  *SubDepth = GFX.SubZBuffer + Offset;
832
833 #define FN(N) \
834     if (GFX.Z1 > Depth [N] && (Pixel = Pixels[3 - N])) \
835     { \
836         if (SubDepth [N]) \
837         { \
838             if (SubDepth [N] != 1) \
839                 Screen [N] = (uint16) COLOR_SUB (GFX.ScreenColors [Pixel], \
840                                         Screen [GFX.Delta + N]); \
841             else \
842                 Screen [N] = (uint16) COLOR_SUB (GFX.ScreenColors [Pixel], \
843                                         GFX.FixedColour); \
844         } \
845         else \
846             Screen [N] = GFX.ScreenColors [Pixel]; \
847         Depth [N] = GFX.Z2; \
848     }
849
850     FN(0)
851     FN(1)
852     FN(2)
853     FN(3)
854
855 #undef FN
856 }
857
858 STATIC INLINE void WRITE_4PIXELS16_SUB1_2 (uint32 Offset, uint8 *Pixels)
859 {
860     register uint32 Pixel;
861     uint16 *Screen = (uint16 *) GFX.S + Offset;
862     uint8  *Depth = GFX.ZBuffer + Offset;
863     uint8  *SubDepth = GFX.SubZBuffer + Offset;
864
865 #define FN(N) \
866     if (GFX.Z1 > Depth [N] && (Pixel = Pixels[N])) \
867     { \
868         if (SubDepth [N]) \
869         { \
870             if (SubDepth [N] != 1) \
871                 Screen [N] = (uint16) COLOR_SUB1_2 (GFX.ScreenColors [Pixel], \
872                                            Screen [GFX.Delta + N]); \
873             else \
874                 Screen [N] = (uint16) COLOR_SUB (GFX.ScreenColors [Pixel], \
875                                         GFX.FixedColour); \
876         } \
877         else \
878             Screen [N] = GFX.ScreenColors [Pixel]; \
879         Depth [N] = GFX.Z2; \
880     }
881
882     FN(0)
883     FN(1)
884     FN(2)
885     FN(3)
886
887 #undef FN
888 }
889
890 STATIC INLINE void WRITE_4PIXELS16_FLIPPED_SUB1_2 (uint32 Offset, uint8 *Pixels)
891 {
892     register uint32 Pixel;
893     uint16 *Screen = (uint16 *) GFX.S + Offset;
894     uint8  *Depth = GFX.ZBuffer + Offset;
895     uint8  *SubDepth = GFX.SubZBuffer + Offset;
896
897 #define FN(N) \
898     if (GFX.Z1 > Depth [N] && (Pixel = Pixels[3 - N])) \
899     { \
900         if (SubDepth [N]) \
901         { \
902             if (SubDepth [N] != 1) \
903                 Screen [N] = (uint16) COLOR_SUB1_2 (GFX.ScreenColors [Pixel], \
904                                            Screen [GFX.Delta + N]); \
905             else \
906                 Screen [N] = (uint16) COLOR_SUB (GFX.ScreenColors [Pixel], \
907                                         GFX.FixedColour); \
908         } \
909         else \
910             Screen [N] = GFX.ScreenColors [Pixel]; \
911         Depth [N] = GFX.Z2; \
912     }
913
914     FN(0)
915     FN(1)
916     FN(2)
917     FN(3)
918
919 #undef FN
920 }
921
922
923 void DrawTile16Add (uint32 Tile, uint32 Offset, uint32 StartLine,
924                     uint32 LineCount)
925 {
926     TILE_PREAMBLE
927     register uint8 *bp;
928
929     RENDER_TILE(WRITE_4PIXELS16_ADD, WRITE_4PIXELS16_FLIPPED_ADD, 4)
930 }
931
932 void DrawClippedTile16Add (uint32 Tile, uint32 Offset,
933                            uint32 StartPixel, uint32 Width,
934                            uint32 StartLine, uint32 LineCount)
935 {
936     TILE_PREAMBLE
937     register uint8 *bp;
938
939     TILE_CLIP_PREAMBLE
940     RENDER_CLIPPED_TILE(WRITE_4PIXELS16_ADD, WRITE_4PIXELS16_FLIPPED_ADD, 4)
941 }
942
943 void DrawTile16Add1_2 (uint32 Tile, uint32 Offset, uint32 StartLine,
944                        uint32 LineCount)
945 {
946     TILE_PREAMBLE
947     register uint8 *bp;
948
949     RENDER_TILE(WRITE_4PIXELS16_ADD1_2, WRITE_4PIXELS16_FLIPPED_ADD1_2, 4)
950 }
951
952 void DrawClippedTile16Add1_2 (uint32 Tile, uint32 Offset,
953                               uint32 StartPixel, uint32 Width,
954                               uint32 StartLine, uint32 LineCount)
955 {
956     TILE_PREAMBLE
957     register uint8 *bp;
958
959     TILE_CLIP_PREAMBLE
960     RENDER_CLIPPED_TILE(WRITE_4PIXELS16_ADD1_2, WRITE_4PIXELS16_FLIPPED_ADD1_2, 4)
961 }
962
963 void DrawTile16Sub (uint32 Tile, uint32 Offset, uint32 StartLine,
964                     uint32 LineCount)
965 {
966     TILE_PREAMBLE
967     register uint8 *bp;
968
969     RENDER_TILE(WRITE_4PIXELS16_SUB, WRITE_4PIXELS16_FLIPPED_SUB, 4)
970 }
971
972 void DrawClippedTile16Sub (uint32 Tile, uint32 Offset,
973                            uint32 StartPixel, uint32 Width,
974                            uint32 StartLine, uint32 LineCount)
975 {
976     TILE_PREAMBLE
977     register uint8 *bp;
978
979     TILE_CLIP_PREAMBLE
980     RENDER_CLIPPED_TILE(WRITE_4PIXELS16_SUB, WRITE_4PIXELS16_FLIPPED_SUB, 4)
981 }
982
983 void DrawTile16Sub1_2 (uint32 Tile, uint32 Offset, uint32 StartLine,
984                        uint32 LineCount)
985 {
986     TILE_PREAMBLE
987     register uint8 *bp;
988
989     RENDER_TILE(WRITE_4PIXELS16_SUB1_2, WRITE_4PIXELS16_FLIPPED_SUB1_2, 4)
990 }
991
992 void DrawClippedTile16Sub1_2 (uint32 Tile, uint32 Offset,
993                               uint32 StartPixel, uint32 Width,
994                               uint32 StartLine, uint32 LineCount)
995 {
996     TILE_PREAMBLE
997     register uint8 *bp;
998
999     TILE_CLIP_PREAMBLE
1000     RENDER_CLIPPED_TILE(WRITE_4PIXELS16_SUB1_2, WRITE_4PIXELS16_FLIPPED_SUB1_2, 4)
1001 }
1002
1003 STATIC INLINE void WRITE_4PIXELS16_ADDF1_2 (uint32 Offset, uint8 *Pixels)
1004 {
1005     register uint32 Pixel;
1006     uint16 *Screen = (uint16 *) GFX.S + Offset;
1007     uint8  *Depth = GFX.ZBuffer + Offset;
1008     uint8  *SubDepth = GFX.SubZBuffer + Offset;
1009
1010 #define FN(N) \
1011     if (GFX.Z1 > Depth [N] && (Pixel = Pixels[N])) \
1012     { \
1013         if (SubDepth [N] == 1) \
1014             Screen [N] = (uint16) (COLOR_ADD1_2 (GFX.ScreenColors [Pixel], \
1015                                                  GFX.FixedColour)); \
1016         else \
1017             Screen [N] = GFX.ScreenColors [Pixel];\
1018         Depth [N] = GFX.Z2; \
1019     }
1020
1021     FN(0)
1022     FN(1)
1023     FN(2)
1024     FN(3)
1025
1026 #undef FN
1027 }
1028
1029 STATIC INLINE void WRITE_4PIXELS16_FLIPPED_ADDF1_2 (uint32 Offset, uint8 *Pixels)
1030 {
1031     register uint32 Pixel;
1032     uint16 *Screen = (uint16 *) GFX.S + Offset;
1033     uint8  *Depth = GFX.ZBuffer + Offset;
1034     uint8  *SubDepth = GFX.SubZBuffer + Offset;
1035
1036 #define FN(N) \
1037     if (GFX.Z1 > Depth [N] && (Pixel = Pixels[3 - N])) \
1038     { \
1039         if (SubDepth [N] == 1) \
1040             Screen [N] = (uint16) (COLOR_ADD1_2 (GFX.ScreenColors [Pixel], \
1041                                                  GFX.FixedColour)); \
1042         else \
1043             Screen [N] = GFX.ScreenColors [Pixel];\
1044         Depth [N] = GFX.Z2; \
1045     }
1046
1047     FN(0)
1048     FN(1)
1049     FN(2)
1050     FN(3)
1051
1052 #undef FN
1053 }
1054
1055 STATIC INLINE void WRITE_4PIXELS16_SUBF1_2 (uint32 Offset, uint8 *Pixels)
1056 {
1057     register uint32 Pixel;
1058     uint16 *Screen = (uint16 *) GFX.S + Offset;
1059     uint8  *Depth = GFX.ZBuffer + Offset;
1060     uint8  *SubDepth = GFX.SubZBuffer + Offset;
1061
1062 #define FN(N) \
1063     if (GFX.Z1 > Depth [N] && (Pixel = Pixels[N])) \
1064     { \
1065         if (SubDepth [N] == 1) \
1066             Screen [N] = (uint16) COLOR_SUB1_2 (GFX.ScreenColors [Pixel], \
1067                                                 GFX.FixedColour); \
1068         else \
1069             Screen [N] = GFX.ScreenColors [Pixel]; \
1070         Depth [N] = GFX.Z2; \
1071     }
1072
1073     FN(0)
1074     FN(1)
1075     FN(2)
1076     FN(3)
1077
1078 #undef FN
1079 }
1080
1081 STATIC INLINE void WRITE_4PIXELS16_FLIPPED_SUBF1_2 (uint32 Offset, uint8 *Pixels)
1082 {
1083     register uint32 Pixel;
1084     uint16 *Screen = (uint16 *) GFX.S + Offset;
1085     uint8  *Depth = GFX.ZBuffer + Offset;
1086     uint8  *SubDepth = GFX.SubZBuffer + Offset;
1087
1088 #define FN(N) \
1089     if (GFX.Z1 > Depth [N] && (Pixel = Pixels[3 - N])) \
1090     { \
1091         if (SubDepth [N] == 1) \
1092             Screen [N] = (uint16) COLOR_SUB1_2 (GFX.ScreenColors [Pixel], \
1093                                                 GFX.FixedColour); \
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 void DrawTile16FixedAdd1_2 (uint32 Tile, uint32 Offset, uint32 StartLine,
1108                             uint32 LineCount)
1109 {
1110     TILE_PREAMBLE
1111     register uint8 *bp;
1112
1113     RENDER_TILE(WRITE_4PIXELS16_ADDF1_2, WRITE_4PIXELS16_FLIPPED_ADDF1_2, 4)
1114 }
1115
1116 void DrawClippedTile16FixedAdd1_2 (uint32 Tile, uint32 Offset,
1117                                    uint32 StartPixel, uint32 Width,
1118                                    uint32 StartLine, uint32 LineCount)
1119 {
1120     TILE_PREAMBLE
1121     register uint8 *bp;
1122
1123     TILE_CLIP_PREAMBLE
1124     RENDER_CLIPPED_TILE(WRITE_4PIXELS16_ADDF1_2, 
1125                         WRITE_4PIXELS16_FLIPPED_ADDF1_2, 4)
1126 }
1127
1128 void DrawTile16FixedSub1_2 (uint32 Tile, uint32 Offset, uint32 StartLine,
1129                             uint32 LineCount)
1130 {
1131     TILE_PREAMBLE
1132     register uint8 *bp;
1133
1134     RENDER_TILE(WRITE_4PIXELS16_SUBF1_2, WRITE_4PIXELS16_FLIPPED_SUBF1_2, 4)
1135 }
1136
1137 void DrawClippedTile16FixedSub1_2 (uint32 Tile, uint32 Offset,
1138                                    uint32 StartPixel, uint32 Width,
1139                                    uint32 StartLine, uint32 LineCount)
1140 {
1141     TILE_PREAMBLE
1142     register uint8 *bp;
1143
1144     TILE_CLIP_PREAMBLE
1145     RENDER_CLIPPED_TILE(WRITE_4PIXELS16_SUBF1_2, 
1146                         WRITE_4PIXELS16_FLIPPED_SUBF1_2, 4)
1147 }
1148
1149 void DrawLargePixel16Add (uint32 Tile, uint32 Offset,
1150                           uint32 StartPixel, uint32 Pixels,
1151                           uint32 StartLine, uint32 LineCount)
1152 {
1153     TILE_PREAMBLE
1154
1155     register uint16 *sp = (uint16 *) GFX.S + Offset;
1156     uint8  *Depth = GFX.ZBuffer + Offset;
1157     register uint16 pixel;
1158
1159 #define LARGE_ADD_PIXEL(s, p) \
1160 (Depth [z + GFX.DepthDelta] ? (Depth [z + GFX.DepthDelta] != 1 ? \
1161                                COLOR_ADD (p, *(s + GFX.Delta))    : \
1162                                COLOR_ADD (p, GFX.FixedColour)) \
1163                             : p)
1164                               
1165     RENDER_TILE_LARGE (GFX.ScreenColors [pixel], LARGE_ADD_PIXEL)
1166 }
1167
1168 void DrawLargePixel16Add1_2 (uint32 Tile, uint32 Offset,
1169                              uint32 StartPixel, uint32 Pixels,
1170                              uint32 StartLine, uint32 LineCount)
1171 {
1172     TILE_PREAMBLE
1173
1174     register uint16 *sp = (uint16 *) GFX.S + Offset;
1175     uint8  *Depth = GFX.ZBuffer + Offset;
1176     register uint16 pixel;
1177
1178 #define LARGE_ADD_PIXEL1_2(s, p) \
1179 ((uint16) (Depth [z + GFX.DepthDelta] ? (Depth [z + GFX.DepthDelta] != 1 ? \
1180                                COLOR_ADD1_2 (p, *(s + GFX.Delta))    : \
1181                                COLOR_ADD (p, GFX.FixedColour)) \
1182                             : p))
1183                               
1184     RENDER_TILE_LARGE (GFX.ScreenColors [pixel], LARGE_ADD_PIXEL1_2)
1185 }
1186
1187 void DrawLargePixel16Sub (uint32 Tile, uint32 Offset,
1188                           uint32 StartPixel, uint32 Pixels,
1189                           uint32 StartLine, uint32 LineCount)
1190 {
1191     TILE_PREAMBLE
1192
1193     register uint16 *sp = (uint16 *) GFX.S + Offset;
1194     uint8  *Depth = GFX.ZBuffer + Offset;
1195     register uint16 pixel;
1196
1197 #define LARGE_SUB_PIXEL(s, p) \
1198 (Depth [z + GFX.DepthDelta] ? (Depth [z + GFX.DepthDelta] != 1 ? \
1199                                COLOR_SUB (p, *(s + GFX.Delta))    : \
1200                                COLOR_SUB (p, GFX.FixedColour)) \
1201                             : p)
1202                               
1203     RENDER_TILE_LARGE (GFX.ScreenColors [pixel], LARGE_SUB_PIXEL)
1204 }
1205
1206 void DrawLargePixel16Sub1_2 (uint32 Tile, uint32 Offset,
1207                              uint32 StartPixel, uint32 Pixels,
1208                              uint32 StartLine, uint32 LineCount)
1209 {
1210     TILE_PREAMBLE
1211
1212     register uint16 *sp = (uint16 *) GFX.S + Offset;
1213     uint8  *Depth = GFX.ZBuffer + Offset;
1214     uint16 pixel;
1215
1216 #define LARGE_SUB_PIXEL1_2(s, p) \
1217 (Depth [z + GFX.DepthDelta] ? (Depth [z + GFX.DepthDelta] != 1 ? \
1218                                COLOR_SUB1_2 (p, *(s + GFX.Delta))    : \
1219                                COLOR_SUB (p, GFX.FixedColour)) \
1220                             : p)
1221                               
1222     RENDER_TILE_LARGE (GFX.ScreenColors [pixel], LARGE_SUB_PIXEL1_2)
1223 }
1224
1225 void DrawHiResTile16 (uint32 Tile, uint32 Offset, uint32 StartLine,
1226                  uint32 LineCount)
1227 {
1228     TILE_PREAMBLE
1229     register uint8 *bp;
1230
1231     RENDER_TILEHI(WRITE_4PIXELSHI16, WRITE_4PIXELSHI16_FLIPPED, 4)
1232 }
1233
1234 void DrawHiResClippedTile16 (uint32 Tile, uint32 Offset,
1235                           uint32 StartPixel, uint32 Width,
1236                         uint32 StartLine, uint32 LineCount)
1237 {
1238     TILE_PREAMBLE
1239     register uint8 *bp;
1240
1241     TILE_CLIP_PREAMBLE
1242     RENDER_CLIPPED_TILEHI(WRITE_4PIXELSHI16, WRITE_4PIXELSHI16_FLIPPED, 4)
1243 }
1244