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