1 #include "../copyright"
2 
3 #ifndef _TILE_H_
4 #define _TILE_H_
5 
6 #define TILE_PREAMBLE_VARS() \
7     uint32_t l; \
8     uint16_t *ScreenColors; \
9     uint8_t *pCache; \
10     uint32_t TileNumber; \
11     uint32_t TileAddr
12 
13 #define TILE_PREAMBLE_CODE() \
14     TileAddr = BG.TileAddress + ((Tile & 0x3ff) << BG.TileShift); \
15     if ((Tile & 0x1ff) >= 256) \
16        TileAddr += BG.NameSelect; \
17     TileAddr &= 0xffff; \
18     pCache = &BG.Buffer[(TileNumber = (TileAddr >> BG.TileShift)) << 6]; \
19     if (!BG.Buffered [TileNumber]) \
20        BG.Buffered[TileNumber] = ConvertTile (pCache, TileAddr); \
21     if (BG.Buffered [TileNumber] == BLANK_TILE) \
22        return; \
23     if (BG.DirectColourMode) \
24     { \
25        if (IPPU.DirectColourMapsNeedRebuild) \
26           S9xBuildDirectColourMaps (); \
27        ScreenColors = DirectColourMaps [(Tile >> 10) & BG.PaletteMask]; \
28     } \
29     else \
30        ScreenColors = &IPPU.ScreenColors [(((Tile >> 10) & BG.PaletteMask) << BG.PaletteShift) + BG.StartPalette]
31 
32 #define RENDER_TILE(NORMAL, FLIPPED, N) \
33     switch (Tile & (V_FLIP | H_FLIP)) \
34     { \
35     case 0: \
36        bp = pCache + StartLine; \
37        for (l = LineCount; l != 0; l--, bp += 8, Offset += GFX.PPL) \
38        { \
39           NORMAL (Offset, bp, ScreenColors); \
40           NORMAL (Offset + N, bp + 4, ScreenColors); \
41        } \
42        break; \
43     case H_FLIP: \
44        bp = pCache + StartLine; \
45        for (l = LineCount; l != 0; l--, bp += 8, Offset += GFX.PPL) \
46        { \
47           FLIPPED (Offset, bp + 4, ScreenColors); \
48           FLIPPED (Offset + N, bp, ScreenColors); \
49        } \
50        break; \
51     case H_FLIP | V_FLIP: \
52        bp = pCache + 56 - StartLine; \
53        for (l = LineCount; l != 0; l--, bp -= 8, Offset += GFX.PPL) \
54        { \
55           FLIPPED (Offset, bp + 4, ScreenColors); \
56           FLIPPED (Offset + N, bp, ScreenColors); \
57        } \
58        break; \
59     case V_FLIP: \
60        bp = pCache + 56 - StartLine; \
61        for (l = LineCount; l != 0; l--, bp -= 8, Offset += GFX.PPL) \
62        { \
63           NORMAL (Offset, bp, ScreenColors); \
64           NORMAL (Offset + N, bp + 4, ScreenColors); \
65        } \
66        break; \
67     default: \
68        break; \
69     }
70 
71 #define TILE_CLIP_PREAMBLE_VARS() \
72     uint32_t d1; \
73     uint32_t d2
74 
75 #define TILE_CLIP_PREAMBLE_CODE() \
76     if (StartPixel < 4) \
77     { \
78        d1 = HeadMask [StartPixel]; \
79        if (StartPixel + Width < 4) \
80           d1 &= TailMask [StartPixel + Width]; \
81     } \
82     else \
83        d1 = 0; \
84     if (StartPixel + Width > 4) \
85     { \
86        if (StartPixel > 4) \
87           d2 = HeadMask [StartPixel - 4]; \
88        else \
89           d2 = 0xffffffff; \
90        d2 &= TailMask [(StartPixel + Width - 4)]; \
91     } \
92     else \
93        d2 = 0
94 
95 #define RENDER_CLIPPED_TILE_VARS() \
96     uint32_t dd
97 
98 #define RENDER_CLIPPED_TILE_CODE(NORMAL, FLIPPED, N) \
99     switch (Tile & (V_FLIP | H_FLIP)) \
100     { \
101     case 0: \
102        bp = pCache + StartLine; \
103        for (l = LineCount; l != 0; l--, bp += 8, Offset += GFX.PPL) \
104        { \
105           /* This is perfectly OK, regardless of endianness. The tiles are \
106            * cached in leftmost-endian order (when not horiz flipped) by \
107            * the ConvertTile function. */ \
108           if ((dd = (*(uint32_t *) bp) & d1)) \
109              NORMAL (Offset, (uint8_t *) &dd, ScreenColors); \
110           if ((dd = (*(uint32_t *) (bp + 4)) & d2)) \
111              NORMAL (Offset + N, (uint8_t *) &dd, ScreenColors); \
112        } \
113        break; \
114     case H_FLIP: \
115        bp = pCache + StartLine; \
116        SWAP_DWORD (d1); \
117        SWAP_DWORD (d2); \
118        for (l = LineCount; l != 0; l--, bp += 8, Offset += GFX.PPL) \
119        { \
120           if ((dd = *(uint32_t *) (bp + 4) & d1)) \
121              FLIPPED (Offset, (uint8_t *) &dd, ScreenColors); \
122           if ((dd = *(uint32_t *) bp & d2)) \
123              FLIPPED (Offset + N, (uint8_t *) &dd, ScreenColors); \
124        } \
125        break; \
126     case H_FLIP | V_FLIP: \
127        bp = pCache + 56 - StartLine; \
128        SWAP_DWORD (d1); \
129        SWAP_DWORD (d2); \
130        for (l = LineCount; l != 0; l--, bp -= 8, Offset += GFX.PPL) \
131        { \
132           if ((dd = *(uint32_t *) (bp + 4) & d1)) \
133              FLIPPED (Offset, (uint8_t *) &dd, ScreenColors); \
134           if ((dd = *(uint32_t *) bp & d2)) \
135              FLIPPED (Offset + N, (uint8_t *) &dd, ScreenColors); \
136        } \
137        break; \
138     case V_FLIP: \
139        bp = pCache + 56 - StartLine; \
140        for (l = LineCount; l != 0; l--, bp -= 8, Offset += GFX.PPL) \
141        { \
142           if ((dd = (*(uint32_t *) bp) & d1)) \
143              NORMAL (Offset, (uint8_t *) &dd, ScreenColors); \
144           if ((dd = (*(uint32_t *) (bp + 4)) & d2)) \
145              NORMAL (Offset + N, (uint8_t *) &dd, ScreenColors); \
146        } \
147        break; \
148     default: \
149        break; \
150     }
151 
152 #define RENDER_TILE_LARGE(PIXEL, FUNCTION) \
153     switch (Tile & (V_FLIP | H_FLIP)) \
154     { \
155     case H_FLIP: \
156        StartPixel = 7 - StartPixel; \
157        /* fallthrough for no-flip case - above was a horizontal flip */ \
158     case 0: \
159        if((pixel = pCache[StartLine + StartPixel])) \
160        { \
161           pixel = PIXEL; \
162           for (l = LineCount; l != 0; l--, sp += GFX.PPL, Depth += GFX.PPL) \
163           { \
164              int32_t z; \
165              for (z = Pixels - 1; z >= 0; z--) \
166              { \
167                 if (GFX.Z1 > Depth [z]) \
168                 { \
169                    sp [z] = FUNCTION(sp + z, pixel); \
170                    Depth [z] = GFX.Z2; \
171                 }\
172              } \
173           } \
174        } \
175        break; \
176     case H_FLIP | V_FLIP: \
177        StartPixel = 7 - StartPixel; \
178        /* fallthrough for V_FLIP-only case - above was a horizontal flip */ \
179     case V_FLIP: \
180        if((pixel = pCache[56 - StartLine + StartPixel])) \
181        { \
182           pixel = PIXEL; \
183           for (l = LineCount; l != 0; l--, sp += GFX.PPL, Depth += GFX.PPL) \
184           { \
185              int32_t z; \
186              for (z = Pixels - 1; z >= 0; z--) \
187              { \
188                 if (GFX.Z1 > Depth [z]) \
189                 { \
190                    sp [z] = FUNCTION(sp + z, pixel); \
191                    Depth [z] = GFX.Z2; \
192                 }\
193              } \
194           } \
195        } \
196        break; \
197     default: \
198        break; \
199     }
200 
201 #define RENDER_TILE_LARGE_HALFWIDTH(PIXEL, FUNCTION) \
202     switch (Tile & (V_FLIP | H_FLIP)) \
203     { \
204     case H_FLIP: \
205        StartPixel = 7 - StartPixel; \
206        /* fallthrough for no-flip case - above was a horizontal flip */ \
207     case 0: \
208        if((pixel = pCache[StartLine + StartPixel])) \
209        { \
210           pixel = PIXEL; \
211           for (l = LineCount; l != 0; l--, sp += GFX.PPL, Depth += GFX.PPL) \
212           { \
213              int32_t z; \
214              for (z = Pixels - 2; z >= 0; z -= 2) \
215              { \
216                 if (GFX.Z1 > Depth [z]) \
217                 { \
218                    sp [z >> 1] = FUNCTION(sp + z, pixel); \
219                    Depth [z >> 1] = GFX.Z2; \
220                 } \
221              } \
222           } \
223        } \
224        break; \
225     case H_FLIP | V_FLIP: \
226        StartPixel = 7 - StartPixel; \
227        /* fallthrough for V_FLIP-only case - above was a horizontal flip */ \
228     case V_FLIP: \
229        if((pixel = pCache[56 - StartLine + StartPixel])) \
230        { \
231           pixel = PIXEL; \
232           for (l = LineCount; l != 0; l--, sp += GFX.PPL, Depth += GFX.PPL) \
233           { \
234              int32_t z; \
235              for (z = Pixels - 2; z >= 0; z -= 2) \
236              { \
237                 if (GFX.Z1 > Depth [z]) \
238                 { \
239                    sp [z >> 1] = FUNCTION(sp + z, pixel); \
240                    Depth [z >> 1] = GFX.Z2; \
241                 } \
242              } \
243           } \
244        } \
245        break; \
246     default: \
247        break; \
248     }
249 #endif
250