tile.cpp
1 #include <Arduino.h> 2 3 /*****************************************************************************\ 4 Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. 5 This file is licensed under the Snes9x License. 6 For further information, consult the LICENSE file in the root directory. 7 \*****************************************************************************/ 8 9 // This file includes itself multiple times. 10 // The other option would be to have 4 files, where A includes B, and B includes C 3 times, and C includes D 5 times. 11 // Look for the following marker to find where the divisions are. 12 13 // Top-level compilation. 14 15 #ifndef _NEWTILE_CPP 16 #define _NEWTILE_CPP 17 18 // #pragma GCC optimize("Os") 19 20 #include "snes9x.h" 21 #include "ppu.h" 22 #include "tile.h" 23 24 static uint32 pixbit[8][16]; 25 static uint8 hrbit_odd[256]; 26 static uint8 hrbit_even[256]; 27 static SNESPixel BlackColourMap[256]; 28 static SNESPixel DirectColourMaps[8][256]; 29 static uint8 brightness_cap[64]; 30 static struct SLineMatrixData LineMatrixData[240]; 31 PROGMEM static uint8 mul_brightness[16][32] = 32 { 33 { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 34 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, 35 { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 36 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02 }, 37 { 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 38 0x02, 0x02, 0x02, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x04, 0x04, 0x04, 0x04, 0x04 }, 39 { 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x03, 0x03, 0x03, 40 0x03, 0x03, 0x04, 0x04, 0x04, 0x04, 0x04, 0x05, 0x05, 0x05, 0x05, 0x05, 0x06, 0x06, 0x06, 0x06 }, 41 { 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x03, 0x03, 0x03, 0x03, 0x04, 0x04, 42 0x04, 0x05, 0x05, 0x05, 0x05, 0x06, 0x06, 0x06, 0x06, 0x07, 0x07, 0x07, 0x07, 0x08, 0x08, 0x08 }, 43 { 0x00, 0x00, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x03, 0x03, 0x03, 0x04, 0x04, 0x04, 0x05, 0x05, 44 0x05, 0x06, 0x06, 0x06, 0x07, 0x07, 0x07, 0x08, 0x08, 0x08, 0x09, 0x09, 0x09, 0x0a, 0x0a, 0x0a }, 45 { 0x00, 0x00, 0x01, 0x01, 0x02, 0x02, 0x02, 0x03, 0x03, 0x04, 0x04, 0x04, 0x05, 0x05, 0x06, 0x06, 46 0x06, 0x07, 0x07, 0x08, 0x08, 0x08, 0x09, 0x09, 0x0a, 0x0a, 0x0a, 0x0b, 0x0b, 0x0c, 0x0c, 0x0c }, 47 { 0x00, 0x00, 0x01, 0x01, 0x02, 0x02, 0x03, 0x03, 0x04, 0x04, 0x05, 0x05, 0x06, 0x06, 0x07, 0x07, 48 0x07, 0x08, 0x08, 0x09, 0x09, 0x0a, 0x0a, 0x0b, 0x0b, 0x0c, 0x0c, 0x0d, 0x0d, 0x0e, 0x0e, 0x0e }, 49 { 0x00, 0x01, 0x01, 0x02, 0x02, 0x03, 0x03, 0x04, 0x04, 0x05, 0x05, 0x06, 0x06, 0x07, 0x07, 0x08, 50 0x09, 0x09, 0x0a, 0x0a, 0x0b, 0x0b, 0x0c, 0x0c, 0x0d, 0x0d, 0x0e, 0x0e, 0x0f, 0x0f, 0x10, 0x11 }, 51 { 0x00, 0x01, 0x01, 0x02, 0x02, 0x03, 0x04, 0x04, 0x05, 0x05, 0x06, 0x07, 0x07, 0x08, 0x08, 0x09, 52 0x0a, 0x0a, 0x0b, 0x0b, 0x0c, 0x0d, 0x0d, 0x0e, 0x0e, 0x0f, 0x10, 0x10, 0x11, 0x11, 0x12, 0x13 }, 53 { 0x00, 0x01, 0x01, 0x02, 0x03, 0x03, 0x04, 0x05, 0x05, 0x06, 0x07, 0x07, 0x08, 0x09, 0x09, 0x0a, 54 0x0b, 0x0b, 0x0c, 0x0d, 0x0d, 0x0e, 0x0f, 0x0f, 0x10, 0x11, 0x11, 0x12, 0x13, 0x13, 0x14, 0x15 }, 55 { 0x00, 0x01, 0x01, 0x02, 0x03, 0x04, 0x04, 0x05, 0x06, 0x07, 0x07, 0x08, 0x09, 0x0a, 0x0a, 0x0b, 56 0x0c, 0x0c, 0x0d, 0x0e, 0x0f, 0x0f, 0x10, 0x11, 0x12, 0x12, 0x13, 0x14, 0x15, 0x15, 0x16, 0x17 }, 57 { 0x00, 0x01, 0x02, 0x02, 0x03, 0x04, 0x05, 0x06, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0a, 0x0b, 0x0c, 58 0x0d, 0x0e, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x12, 0x13, 0x14, 0x15, 0x16, 0x16, 0x17, 0x18, 0x19 }, 59 { 0x00, 0x01, 0x02, 0x03, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0a, 0x0b, 0x0c, 0x0d, 60 0x0e, 0x0f, 0x10, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x17, 0x18, 0x19, 0x1a, 0x1b }, 61 { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 62 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d }, 63 { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 64 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f } 65 }; 66 67 68 void S9xInitTileRenderer (void) 69 { 70 memset(BlackColourMap, 0, 256 * sizeof(SNESPixel)); 71 72 S9xBuildDirectColourMaps(); 73 S9xFixColourBrightness(); 74 75 for (int i = 0; i < 16; i++) 76 { 77 uint32 b = 0; 78 79 #ifdef LSB_FIRST 80 if (i & 8) b |= 1; 81 if (i & 4) b |= 1 << 8; 82 if (i & 2) b |= 1 << 16; 83 if (i & 1) b |= 1 << 24; 84 #else 85 if (i & 8) b |= 1 << 24; 86 if (i & 4) b |= 1 << 16; 87 if (i & 2) b |= 1 << 8; 88 if (i & 1) b |= 1; 89 #endif 90 91 for (int bitshift = 0; bitshift < 8; bitshift++) 92 pixbit[bitshift][i] = b << bitshift; 93 } 94 95 for (int i = 0; i < 256; i++) 96 { 97 uint32 m = 0; 98 uint32 s = 0; 99 100 if (i & 0x80) s |= 8; 101 if (i & 0x40) m |= 8; 102 if (i & 0x20) s |= 4; 103 if (i & 0x10) m |= 4; 104 if (i & 0x08) s |= 2; 105 if (i & 0x04) m |= 2; 106 if (i & 0x02) s |= 1; 107 if (i & 0x01) m |= 1; 108 109 hrbit_odd[i] = m; 110 hrbit_even[i] = s; 111 } 112 } 113 114 void S9xBuildDirectColourMaps (void) 115 { 116 IPPU.XB = (uint8 *)mul_brightness[PPU.Brightness]; 117 118 for (int p = 0; p < 8; p++) 119 { 120 for (int c = 0; c < 256; c++) 121 { 122 uint8 r = IPPU.XB[((c & 7) << 2) | ((p & 1) << 1)]; 123 uint8 g = IPPU.XB[((c & 0x38) >> 1) | (p & 2)]; 124 uint8 b = IPPU.XB[((c & 0xc0) >> 3) | (p & 4)]; 125 DirectColourMaps[p][c] = BUILD_PIXEL(r, g, b); 126 //if ( DirectColourMaps[p][c] ) emu_printi(DirectColourMaps[p][c]); 127 } 128 } 129 } 130 131 void S9xFixColourBrightness (void) 132 { 133 IPPU.XB = (uint8 *)mul_brightness[PPU.Brightness]; 134 135 for (int i = 0; i < 64; i++) 136 { 137 if (i > IPPU.XB[0x1f]) 138 brightness_cap[i] = IPPU.XB[0x1f]; 139 else 140 brightness_cap[i] = i; 141 } 142 143 for (int i = 0; i < 256; i++) 144 { 145 uint8 r = IPPU.XB[(PPU.CGDATA[i]) & 0x1f]; 146 uint8 g = IPPU.XB[(PPU.CGDATA[i] >> 5) & 0x1f]; 147 uint8 b = IPPU.XB[(PPU.CGDATA[i] >> 10) & 0x1f]; 148 IPPU.ScreenColors[i] = BUILD_PIXEL(r, g, b); 149 } 150 } 151 152 void S9UpdateLineMatrix(int line) 153 { 154 struct SLineMatrixData *p = &LineMatrixData[line]; 155 p->MatrixA = PPU.MatrixA; 156 p->MatrixB = PPU.MatrixB; 157 p->MatrixC = PPU.MatrixC; 158 p->MatrixD = PPU.MatrixD; 159 p->CentreX = PPU.CentreX; 160 p->CentreY = PPU.CentreY; 161 p->M7HOFS = PPU.M7HOFS; 162 p->M7VOFS = PPU.M7VOFS; 163 } 164 165 #define COLOR_ADD1_2(C1, C2) \ 166 ((((((C1) & RGB_REMOVE_LOW_BITS_MASK) + \ 167 ((C2) & RGB_REMOVE_LOW_BITS_MASK)) >> 1) + \ 168 ((C1) & (C2) & RGB_LOW_BITS_MASK)) ) 169 #define COLOR_ADD_BRIGHTNESS1_2 COLOR_ADD1_2 170 171 172 static inline uint16 COLOR_ADD_BRIGHTNESS(uint32 C1, uint32 C2) 173 { 174 return ((brightness_cap[ (C1 >> RED_SHIFT_BITS) + (C2 >> RED_SHIFT_BITS) ] << RED_SHIFT_BITS) | 175 (brightness_cap[((C1 >> GREEN_SHIFT_BITS) & 0x1f) + ((C2 >> GREEN_SHIFT_BITS) & 0x1f)] << GREEN_SHIFT_BITS) | 176 // Proper 15->16bit color conversion moves the high bit of green into the low bit. 177 #if GREEN_SHIFT_BITS == 6 178 ((brightness_cap[((C1 >> 6) & 0x1f) + ((C2 >> 6) & 0x1f)] & 0x10) << 1) | 179 #endif 180 (brightness_cap[ (C1 & 0x1f) + (C2 & 0x1f)] )); 181 } 182 183 static inline uint16 COLOR_ADD(uint32 C1, uint32 C2) 184 { 185 // return C1; 186 187 const uint32 RED_MASK = 0x1F << RED_SHIFT_BITS; 188 const uint32 GREEN_MASK = 0x1F << GREEN_SHIFT_BITS; 189 const uint32 BLUE_MASK = 0x1F; 190 191 int rb = C1 & (RED_MASK | BLUE_MASK); 192 rb += C2 & (RED_MASK | BLUE_MASK); 193 int rbcarry = rb & ((0x20 << RED_SHIFT_BITS) | (0x20 << 0)); 194 int g = (C1 & (GREEN_MASK)) + (C2 & (GREEN_MASK)); 195 int rgbsaturate = (((g & (0x20 << GREEN_SHIFT_BITS)) | rbcarry) >> 5) * 0x1f; 196 uint16 retval = (rb & (RED_MASK | BLUE_MASK)) | (g & GREEN_MASK) | rgbsaturate; 197 #if GREEN_SHIFT_BITS == 6 198 retval |= (retval & 0x0400) >> 5; 199 #endif 200 // int rr = (retval & 0xF800) >> (2+11); 201 // int gg = (retval & 0x07E0) >> (3+5); 202 // int bb = (retval & 0x001F) >> 3 ; 203 // retval = (rr << 5) + (gg << 2) + bb; 204 return retval; 205 206 } 207 208 #define COLOR_SUB1_2(C1, C2) \ 209 GFX.ZERO[(((C1) | RGB_HI_BITS_MASKx2) - \ 210 ((C2) & RGB_REMOVE_LOW_BITS_MASK)) >> 1] 211 212 static inline uint16 COLOR_SUB (uint32 C1, uint32 C2) 213 { 214 // return C1; 215 216 int rb1 = (C1 & (THIRD_COLOR_MASK | FIRST_COLOR_MASK)) | ((0x20 << 0) | (0x20 << RED_SHIFT_BITS)); 217 int rb2 = C2 & (THIRD_COLOR_MASK | FIRST_COLOR_MASK); 218 int rb = rb1 - rb2; 219 int rbcarry = rb & ((0x20 << RED_SHIFT_BITS) | (0x20 << 0)); 220 int g = ((C1 & (SECOND_COLOR_MASK)) | (0x20 << GREEN_SHIFT_BITS)) - (C2 & (SECOND_COLOR_MASK)); 221 int rgbsaturate = (((g & (0x20 << GREEN_SHIFT_BITS)) | rbcarry) >> 5) * 0x1f; 222 uint16 retval = ((rb & (THIRD_COLOR_MASK | FIRST_COLOR_MASK)) | (g & SECOND_COLOR_MASK)) & rgbsaturate; 223 #if GREEN_SHIFT_BITS == 6 224 retval |= (retval & 0x0400) >> 5; 225 #endif 226 // int rr = (retval & 0xF800) >> (2+11); 227 // int gg = (retval & 0x07E0) >> (3+5); 228 // int bb = (retval & 0x001F) >> 3 ; 229 // retval = (rr << 5) + (gg << 2) + bb; 230 return retval; 231 232 } 233 234 // Here are the tile converters, selected by S9xSelectTileConverter(). 235 // Really, except for the definition of DOBIT and the number of times it is called, they're all the same. 236 237 #define DOBIT(n, i) \ 238 if ((pix = *(tp + (n)))) \ 239 { \ 240 p1 |= pixbit[(i)][pix >> 4]; \ 241 p2 |= pixbit[(i)][pix & 0xf]; \ 242 } 243 244 static uint8 ConvertTile2 (uint8 *pCache, uint32 TileAddr, uint32 Unused) 245 { 246 uint8 *tp = &Memory.VRAM[TileAddr]; 247 uint32 *p = (uint32 *) pCache; 248 uint32 non_zero = 0; 249 250 for (int line = 8; line != 0; line--, tp += 2) 251 { 252 uint32 p1 = 0; 253 uint32 p2 = 0; 254 uint32 pix; 255 256 DOBIT( 0, 0); 257 DOBIT( 1, 1); 258 *p++ = p1; 259 *p++ = p2; 260 non_zero |= p1 | p2; 261 } 262 263 return (non_zero ? TRUE : BLANK_TILE); 264 } 265 266 static uint8 ConvertTile4 (uint8 *pCache, uint32 TileAddr, uint32 Unused) 267 { 268 uint8 *tp = &Memory.VRAM[TileAddr]; 269 uint32 *p = (uint32 *) pCache; 270 uint32 non_zero = 0; 271 272 for (int line = 8; line != 0; line--, tp += 2) 273 { 274 uint32 p1 = 0; 275 uint32 p2 = 0; 276 uint32 pix; 277 278 DOBIT( 0, 0); 279 DOBIT( 1, 1); 280 DOBIT(16, 2); 281 DOBIT(17, 3); 282 *p++ = p1; 283 *p++ = p2; 284 non_zero |= p1 | p2; 285 } 286 287 return (non_zero ? TRUE : BLANK_TILE); 288 } 289 290 static uint8 ConvertTile8 (uint8 *pCache, uint32 TileAddr, uint32 Unused) 291 { 292 uint8 *tp = &Memory.VRAM[TileAddr]; 293 uint32 *p = (uint32 *) pCache; 294 uint32 non_zero = 0; 295 296 for (int line = 8; line != 0; line--, tp += 2) 297 { 298 uint32 p1 = 0; 299 uint32 p2 = 0; 300 uint32 pix; 301 302 DOBIT( 0, 0); 303 DOBIT( 1, 1); 304 DOBIT(16, 2); 305 DOBIT(17, 3); 306 DOBIT(32, 4); 307 DOBIT(33, 5); 308 DOBIT(48, 6); 309 DOBIT(49, 7); 310 *p++ = p1; 311 *p++ = p2; 312 non_zero |= p1 | p2; 313 } 314 315 return (non_zero ? TRUE : BLANK_TILE); 316 } 317 318 #undef DOBIT 319 320 #define DOBIT(n, i) \ 321 if ((pix = hrbit_odd[*(tp1 + (n))])) \ 322 p1 |= pixbit[(i)][pix]; \ 323 if ((pix = hrbit_odd[*(tp2 + (n))])) \ 324 p2 |= pixbit[(i)][pix]; 325 326 static uint8 ConvertTile2h_odd (uint8 *pCache, uint32 TileAddr, uint32 Tile) 327 { 328 uint8 *tp1 = &Memory.VRAM[TileAddr], *tp2; 329 uint32 *p = (uint32 *) pCache; 330 uint32 non_zero = 0; 331 332 if (Tile == 0x3ff) 333 tp2 = tp1 - (0x3ff << 4); 334 else 335 tp2 = tp1 + (1 << 4); 336 337 for (int line = 8; line != 0; line--, tp1 += 2, tp2 += 2) 338 { 339 uint32 p1 = 0; 340 uint32 p2 = 0; 341 uint32 pix; 342 343 DOBIT( 0, 0); 344 DOBIT( 1, 1); 345 *p++ = p1; 346 *p++ = p2; 347 non_zero |= p1 | p2; 348 } 349 350 return (non_zero ? TRUE : BLANK_TILE); 351 } 352 353 static uint8 ConvertTile4h_odd (uint8 *pCache, uint32 TileAddr, uint32 Tile) 354 { 355 uint8 *tp1 = &Memory.VRAM[TileAddr], *tp2; 356 uint32 *p = (uint32 *) pCache; 357 uint32 non_zero = 0; 358 359 if (Tile == 0x3ff) 360 tp2 = tp1 - (0x3ff << 5); 361 else 362 tp2 = tp1 + (1 << 5); 363 364 for (int line = 8; line != 0; line--, tp1 += 2, tp2 += 2) 365 { 366 uint32 p1 = 0; 367 uint32 p2 = 0; 368 uint8 pix; 369 370 DOBIT( 0, 0); 371 DOBIT( 1, 1); 372 DOBIT(16, 2); 373 DOBIT(17, 3); 374 *p++ = p1; 375 *p++ = p2; 376 non_zero |= p1 | p2; 377 } 378 379 return (non_zero ? TRUE : BLANK_TILE); 380 } 381 382 #undef DOBIT 383 384 #define DOBIT(n, i) \ 385 if ((pix = hrbit_even[*(tp1 + (n))])) \ 386 p1 |= pixbit[(i)][pix]; \ 387 if ((pix = hrbit_even[*(tp2 + (n))])) \ 388 p2 |= pixbit[(i)][pix]; 389 390 static uint8 ConvertTile2h_even (uint8 *pCache, uint32 TileAddr, uint32 Tile) 391 { 392 uint8 *tp1 = &Memory.VRAM[TileAddr], *tp2; 393 uint32 *p = (uint32 *) pCache; 394 uint32 non_zero = 0; 395 396 if (Tile == 0x3ff) 397 tp2 = tp1 - (0x3ff << 4); 398 else 399 tp2 = tp1 + (1 << 4); 400 401 for (int line = 8; line != 0; line--, tp1 += 2, tp2 += 2) 402 { 403 uint32 p1 = 0; 404 uint32 p2 = 0; 405 uint32 pix; 406 407 DOBIT( 0, 0); 408 DOBIT( 1, 1); 409 *p++ = p1; 410 *p++ = p2; 411 non_zero |= p1 | p2; 412 } 413 414 return (non_zero ? TRUE : BLANK_TILE); 415 } 416 417 static uint8 ConvertTile4h_even (uint8 *pCache, uint32 TileAddr, uint32 Tile) 418 { 419 uint8 *tp1 = &Memory.VRAM[TileAddr], *tp2; 420 uint32 *p = (uint32 *) pCache; 421 uint32 non_zero = 0; 422 423 if (Tile == 0x3ff) 424 tp2 = tp1 - (0x3ff << 5); 425 else 426 tp2 = tp1 + (1 << 5); 427 428 for (int line = 8; line != 0; line--, tp1 += 2, tp2 += 2) 429 { 430 uint32 p1 = 0; 431 uint32 p2 = 0; 432 uint32 pix; 433 434 DOBIT( 0, 0); 435 DOBIT( 1, 1); 436 DOBIT(16, 2); 437 DOBIT(17, 3); 438 *p++ = p1; 439 *p++ = p2; 440 non_zero |= p1 | p2; 441 } 442 443 return (non_zero ? TRUE : BLANK_TILE); 444 } 445 446 #undef DOBIT 447 448 // First-level include: Get all the renderers. 449 #include "tile.cpp" 450 451 // Functions to select which converter and renderer to use. 452 453 void S9xSelectTileRenderers (int BGMode, bool8 sub, bool8 obj) 454 { 455 void (**DT) (uint32, uint32, uint32, uint32); 456 void (**DCT) (uint32, uint32, uint32, uint32, uint32, uint32); 457 void (**DMP) (uint32, uint32, uint32, uint32, uint32, uint32); 458 void (**DB) (uint32, uint32, uint32); 459 void (**DM7BG1) (uint32, uint32, int); 460 void (**DM7BG2) (uint32, uint32, int); 461 bool8 M7M1, M7M2; 462 463 M7M1 = PPU.BGMosaic[0] && PPU.Mosaic > 1; 464 M7M2 = PPU.BGMosaic[1] && PPU.Mosaic > 1; 465 466 DT = Renderers_DrawTile16Normal1x1; 467 DCT = Renderers_DrawClippedTile16Normal1x1; 468 DMP = Renderers_DrawMosaicPixel16Normal1x1; 469 DB = Renderers_DrawBackdrop16Normal1x1; 470 DM7BG1 = M7M1 ? Renderers_DrawMode7MosaicBG1Normal1x1 : Renderers_DrawMode7BG1Normal1x1; 471 DM7BG2 = M7M2 ? Renderers_DrawMode7MosaicBG2Normal1x1 : Renderers_DrawMode7BG2Normal1x1; 472 473 GFX.DrawTileNomath = DT[0]; 474 GFX.DrawClippedTileNomath = DCT[0]; 475 GFX.DrawMosaicPixelNomath = DMP[0]; 476 GFX.DrawBackdropNomath = DB[0]; 477 GFX.DrawMode7BG1Nomath = DM7BG1[0]; 478 GFX.DrawMode7BG2Nomath = DM7BG2[0]; 479 480 int i = 0; 481 482 if (Settings.Transparency) 483 { 484 i = (Memory.PPU_IO[0x131] & 0x80) ? 4 : 1; 485 if (Memory.PPU_IO[0x131] & 0x40) 486 { 487 i++; 488 if (Memory.PPU_IO[0x130] & 2) 489 i++; 490 } 491 if (IPPU.MaxBrightness != 0xf) 492 { 493 if (i == 1) 494 i = 7; 495 else if (i == 3) 496 i = 8; 497 } 498 } 499 500 GFX.DrawTileMath = DT[i]; 501 GFX.DrawClippedTileMath = DCT[i]; 502 GFX.DrawMosaicPixelMath = DMP[i]; 503 GFX.DrawBackdropMath = DB[i]; 504 GFX.DrawMode7BG1Math = DM7BG1[i]; 505 GFX.DrawMode7BG2Math = DM7BG2[i]; 506 } 507 508 void S9xSelectTileConverter (int depth, bool8 hires, bool8 sub, bool8 mosaic) 509 { 510 switch (depth) 511 { 512 case 8: 513 BG.ConvertTile = BG.ConvertTileFlip = ConvertTile8; 514 BG.Buffered = BG.BufferedFlip = TILE_8BIT; 515 BG.TileShift = 6; 516 BG.PaletteShift = 0; 517 BG.PaletteMask = 0; 518 BG.DirectColourMode = Memory.PPU_IO[0x130] & 1; 519 520 break; 521 522 case 4: 523 if (hires) 524 { 525 if (sub || mosaic) 526 { 527 BG.ConvertTile = ConvertTile4h_even; 528 BG.Buffered = TILE_4BIT_EVEN; 529 BG.ConvertTileFlip = ConvertTile4h_odd; 530 BG.BufferedFlip = TILE_4BIT_ODD; 531 } 532 else 533 { 534 BG.ConvertTile = ConvertTile4h_odd; 535 BG.Buffered = TILE_4BIT_ODD; 536 BG.ConvertTileFlip = ConvertTile4h_even; 537 BG.BufferedFlip = TILE_4BIT_EVEN; 538 } 539 } 540 else 541 { 542 BG.ConvertTile = BG.ConvertTileFlip = ConvertTile4; 543 BG.Buffered = BG.BufferedFlip = TILE_4BIT; 544 } 545 546 BG.TileShift = 5; 547 BG.PaletteShift = 10 - 4; 548 BG.PaletteMask = 7 << 4; 549 BG.DirectColourMode = FALSE; 550 551 break; 552 553 case 2: 554 if (hires) 555 { 556 if (sub || mosaic) 557 { 558 BG.ConvertTile = ConvertTile2h_even; 559 BG.Buffered = TILE_2BIT_EVEN; 560 BG.ConvertTileFlip = ConvertTile2h_odd; 561 BG.BufferedFlip = TILE_2BIT_ODD; 562 } 563 else 564 { 565 BG.ConvertTile = ConvertTile2h_odd; 566 BG.Buffered = TILE_2BIT_ODD; 567 BG.ConvertTileFlip = ConvertTile2h_even; 568 BG.BufferedFlip = TILE_2BIT_EVEN; 569 } 570 } 571 else 572 { 573 BG.ConvertTile = BG.ConvertTileFlip = ConvertTile2; 574 BG.Buffered = BG.BufferedFlip = TILE_2BIT; 575 } 576 577 BG.TileShift = 4; 578 BG.PaletteShift = 10 - 2; 579 BG.PaletteMask = 7 << 2; 580 BG.DirectColourMode = FALSE; 581 582 break; 583 } 584 } 585 586 /*****************************************************************************/ 587 #else 588 #ifndef NAME1 // First-level: Get all the renderers. 589 /*****************************************************************************/ 590 591 #define GET_CACHED_TILE() \ 592 uint32 TileNumber; \ 593 uint32 TileAddr = BG.TileAddress + ((Tile & 0x3ff) << BG.TileShift); \ 594 if (Tile & 0x100) \ 595 TileAddr += BG.NameSelect; \ 596 TileAddr &= 0xffff; \ 597 TileNumber = TileAddr >> BG.TileShift; \ 598 pCache = &IPPU.TileCacheData[TileNumber << 6]; \ 599 if (Tile & H_FLIP) \ 600 { \ 601 if (IPPU.TileCache[TileNumber] != (BG.BufferedFlip|TILE_CACHE_VALID|TILE_CACHE_FLIP)) { \ 602 if (BG.ConvertTileFlip(pCache, TileAddr, Tile & 0x3ff) == BLANK_TILE) \ 603 IPPU.TileCache[TileNumber] = BG.BufferedFlip|TILE_CACHE_VALID|TILE_CACHE_BLANK|TILE_CACHE_FLIP; \ 604 else \ 605 IPPU.TileCache[TileNumber] = BG.BufferedFlip|TILE_CACHE_VALID|TILE_CACHE_FLIP; \ 606 } \ 607 } \ 608 else \ 609 { \ 610 if (IPPU.TileCache[TileNumber] != (BG.Buffered|TILE_CACHE_VALID)) { \ 611 if (BG.ConvertTile(pCache, TileAddr, Tile & 0x3ff) == BLANK_TILE) \ 612 IPPU.TileCache[TileNumber] = BG.Buffered|TILE_CACHE_VALID|TILE_CACHE_BLANK; \ 613 else \ 614 IPPU.TileCache[TileNumber] = BG.Buffered|TILE_CACHE_VALID; \ 615 } \ 616 } 617 618 #define IS_BLANK_TILE() \ 619 (IPPU.TileCache[TileNumber] & TILE_CACHE_BLANK) 620 621 #define SELECT_PALETTE() \ 622 if (BG.DirectColourMode) \ 623 { \ 624 GFX.RealScreenColors = DirectColourMaps[(Tile >> 10) & 7]; \ 625 } \ 626 else \ 627 GFX.RealScreenColors = &IPPU.ScreenColors[((Tile >> BG.PaletteShift) & BG.PaletteMask) + BG.StartPalette]; \ 628 GFX.ScreenColors = GFX.ClipColors ? BlackColourMap : GFX.RealScreenColors 629 630 #define NOMATH(Op, Main, Sub, SD) \ 631 (Main) 632 633 #define REGMATH(Op, Main, Sub, SD) \ 634 (COLOR_##Op((Main), ((SD) & 0x20) ? (Sub) : GFX.FixedColour)) 635 636 #define MATHF1_2(Op, Main, Sub, SD) \ 637 (GFX.ClipColors ? (COLOR_##Op((Main), GFX.FixedColour)) : (COLOR_##Op##1_2((Main), GFX.FixedColour))) 638 639 #define MATHS1_2(Op, Main, Sub, SD) \ 640 (GFX.ClipColors ? REGMATH(Op, Main, Sub, SD) : (((SD) & 0x20) ? COLOR_##Op##1_2((Main), (Sub)) : COLOR_##Op((Main), GFX.FixedColour))) 641 642 // Basic routine to render an unclipped tile. 643 // Input parameters: 644 // DRAW_PIXEL(N, M) is a routine to actually draw the pixel. N is the pixel in the row to draw, 645 // and M is a test which if false means the pixel should be skipped. 646 // Z1 is the "draw if Z1 > cur_depth". 647 // Z2 is the "cur_depth = new_depth". OBJ need the two separate. 648 // Pix is the pixel to draw. 649 650 #define Z1 GFX.Z1 651 #define Z2 GFX.Z2 652 653 #define DRAW_TILE() \ 654 uint8 *pCache; \ 655 int32 l; \ 656 uint8 *bp, Pix; \ 657 \ 658 GET_CACHED_TILE(); \ 659 if (IS_BLANK_TILE()) \ 660 return; \ 661 SELECT_PALETTE(); \ 662 \ 663 if (!(Tile & (V_FLIP | H_FLIP))) \ 664 { \ 665 bp = pCache + StartLine; \ 666 OFFSET_IN_LINE; \ 667 for (l = LineCount; l > 0; l--, bp += 8, Offset += GFX.PPL) \ 668 { \ 669 for (int x = 0; x < 8; x++) { \ 670 DRAW_PIXEL(x, Pix = bp[x]); \ 671 } \ 672 } \ 673 } \ 674 else \ 675 if (!(Tile & V_FLIP)) \ 676 { \ 677 bp = pCache + StartLine; \ 678 OFFSET_IN_LINE; \ 679 for (l = LineCount; l > 0; l--, bp += 8, Offset += GFX.PPL) \ 680 { \ 681 for (int x = 0; x < 8; x++) { \ 682 DRAW_PIXEL(x, Pix = bp[7 - x]); \ 683 } \ 684 } \ 685 } \ 686 else \ 687 if (!(Tile & H_FLIP)) \ 688 { \ 689 bp = pCache + 56 - StartLine; \ 690 OFFSET_IN_LINE; \ 691 for (l = LineCount; l > 0; l--, bp -= 8, Offset += GFX.PPL) \ 692 { \ 693 for (int x = 0; x < 8; x++) { \ 694 DRAW_PIXEL(x, Pix = bp[x]); \ 695 } \ 696 } \ 697 } \ 698 else \ 699 { \ 700 bp = pCache + 56 - StartLine; \ 701 OFFSET_IN_LINE; \ 702 for (l = LineCount; l > 0; l--, bp -= 8, Offset += GFX.PPL) \ 703 { \ 704 for (int x = 0; x < 8; x++) { \ 705 DRAW_PIXEL(x, Pix = bp[7 - x]); \ 706 } \ 707 } \ 708 } 709 710 #define NAME1 DrawTile16 711 #define ARGS uint32 Tile, uint32 Offset, uint32 StartLine, uint32 LineCount 712 713 // Second-level include: Get the DrawTile16 renderers. 714 715 #include "tile.cpp" 716 717 #undef NAME1 718 #undef ARGS 719 #undef DRAW_TILE 720 #undef Z1 721 #undef Z2 722 723 // Basic routine to render a clipped tile. Inputs same as above. 724 725 #define Z1 GFX.Z1 726 #define Z2 GFX.Z2 727 728 #define DRAW_TILE() \ 729 uint8 *pCache; \ 730 int32 l; \ 731 uint8 *bp, Pix, w; \ 732 \ 733 GET_CACHED_TILE(); \ 734 if (IS_BLANK_TILE()) \ 735 return; \ 736 SELECT_PALETTE(); \ 737 \ 738 if (!(Tile & (V_FLIP | H_FLIP))) \ 739 { \ 740 bp = pCache + StartLine; \ 741 OFFSET_IN_LINE; \ 742 for (l = LineCount; l > 0; l--, bp += 8 , Offset += GFX.PPL) \ 743 { \ 744 w = Width; \ 745 switch (StartPixel) \ 746 { \ 747 case 0: DRAW_PIXEL(0, Pix = bp[0]); if (!--w) break; /* Fall through */ \ 748 case 1: DRAW_PIXEL(1, Pix = bp[1]); if (!--w) break; /* Fall through */ \ 749 case 2: DRAW_PIXEL(2, Pix = bp[2]); if (!--w) break; /* Fall through */ \ 750 case 3: DRAW_PIXEL(3, Pix = bp[3]); if (!--w) break; /* Fall through */ \ 751 case 4: DRAW_PIXEL(4, Pix = bp[4]); if (!--w) break; /* Fall through */ \ 752 case 5: DRAW_PIXEL(5, Pix = bp[5]); if (!--w) break; /* Fall through */ \ 753 case 6: DRAW_PIXEL(6, Pix = bp[6]); if (!--w) break; /* Fall through */ \ 754 case 7: DRAW_PIXEL(7, Pix = bp[7]); break; \ 755 } \ 756 } \ 757 } \ 758 else \ 759 if (!(Tile & V_FLIP)) \ 760 { \ 761 bp = pCache + StartLine; \ 762 OFFSET_IN_LINE; \ 763 for (l = LineCount; l > 0; l--, bp += 8, Offset += GFX.PPL) \ 764 { \ 765 w = Width; \ 766 switch (StartPixel) \ 767 { \ 768 case 0: DRAW_PIXEL(0, Pix = bp[7]); if (!--w) break; /* Fall through */ \ 769 case 1: DRAW_PIXEL(1, Pix = bp[6]); if (!--w) break; /* Fall through */ \ 770 case 2: DRAW_PIXEL(2, Pix = bp[5]); if (!--w) break; /* Fall through */ \ 771 case 3: DRAW_PIXEL(3, Pix = bp[4]); if (!--w) break; /* Fall through */ \ 772 case 4: DRAW_PIXEL(4, Pix = bp[3]); if (!--w) break; /* Fall through */ \ 773 case 5: DRAW_PIXEL(5, Pix = bp[2]); if (!--w) break; /* Fall through */ \ 774 case 6: DRAW_PIXEL(6, Pix = bp[1]); if (!--w) break; /* Fall through */ \ 775 case 7: DRAW_PIXEL(7, Pix = bp[0]); break; \ 776 } \ 777 } \ 778 } \ 779 else \ 780 if (!(Tile & H_FLIP)) \ 781 { \ 782 bp = pCache + 56 - StartLine; \ 783 OFFSET_IN_LINE; \ 784 for (l = LineCount; l > 0; l--, bp -= 8, Offset += GFX.PPL) \ 785 { \ 786 w = Width; \ 787 switch (StartPixel) \ 788 { \ 789 case 0: DRAW_PIXEL(0, Pix = bp[0]); if (!--w) break; /* Fall through */ \ 790 case 1: DRAW_PIXEL(1, Pix = bp[1]); if (!--w) break; /* Fall through */ \ 791 case 2: DRAW_PIXEL(2, Pix = bp[2]); if (!--w) break; /* Fall through */ \ 792 case 3: DRAW_PIXEL(3, Pix = bp[3]); if (!--w) break; /* Fall through */ \ 793 case 4: DRAW_PIXEL(4, Pix = bp[4]); if (!--w) break; /* Fall through */ \ 794 case 5: DRAW_PIXEL(5, Pix = bp[5]); if (!--w) break; /* Fall through */ \ 795 case 6: DRAW_PIXEL(6, Pix = bp[6]); if (!--w) break; /* Fall through */ \ 796 case 7: DRAW_PIXEL(7, Pix = bp[7]); break; \ 797 } \ 798 } \ 799 } \ 800 else \ 801 { \ 802 bp = pCache + 56 - StartLine; \ 803 OFFSET_IN_LINE; \ 804 for (l = LineCount; l > 0; l--, bp -= 8, Offset += GFX.PPL) \ 805 { \ 806 w = Width; \ 807 switch (StartPixel) \ 808 { \ 809 case 0: DRAW_PIXEL(0, Pix = bp[7]); if (!--w) break; /* Fall through */ \ 810 case 1: DRAW_PIXEL(1, Pix = bp[6]); if (!--w) break; /* Fall through */ \ 811 case 2: DRAW_PIXEL(2, Pix = bp[5]); if (!--w) break; /* Fall through */ \ 812 case 3: DRAW_PIXEL(3, Pix = bp[4]); if (!--w) break; /* Fall through */ \ 813 case 4: DRAW_PIXEL(4, Pix = bp[3]); if (!--w) break; /* Fall through */ \ 814 case 5: DRAW_PIXEL(5, Pix = bp[2]); if (!--w) break; /* Fall through */ \ 815 case 6: DRAW_PIXEL(6, Pix = bp[1]); if (!--w) break; /* Fall through */ \ 816 case 7: DRAW_PIXEL(7, Pix = bp[0]); break; \ 817 } \ 818 } \ 819 } 820 821 #define NAME1 DrawClippedTile16 822 #define ARGS uint32 Tile, uint32 Offset, uint32 StartPixel, uint32 Width, uint32 StartLine, uint32 LineCount 823 824 // Second-level include: Get the DrawClippedTile16 renderers. 825 826 #include "tile.cpp" 827 828 #undef NAME1 829 #undef ARGS 830 #undef DRAW_TILE 831 #undef Z1 832 #undef Z2 833 834 // Basic routine to render a single mosaic pixel. 835 // DRAW_PIXEL, Z1, Z2 and Pix are the same as above 836 837 #define Z1 GFX.Z1 838 #define Z2 GFX.Z2 839 840 #define DRAW_TILE() \ 841 uint8 *pCache; \ 842 int32 l, w; \ 843 uint8 Pix; \ 844 \ 845 GET_CACHED_TILE(); \ 846 if (IS_BLANK_TILE()) \ 847 return; \ 848 SELECT_PALETTE(); \ 849 \ 850 if (Tile & H_FLIP) \ 851 StartPixel = 7 - StartPixel; \ 852 \ 853 if (Tile & V_FLIP) \ 854 Pix = pCache[56 - StartLine + StartPixel]; \ 855 else \ 856 Pix = pCache[StartLine + StartPixel]; \ 857 \ 858 if (Pix) \ 859 { \ 860 OFFSET_IN_LINE; \ 861 for (l = LineCount; l > 0; l--, Offset += GFX.PPL) \ 862 { \ 863 for (w = Width - 1; w >= 0; w--) \ 864 DRAW_PIXEL(w, 1); \ 865 } \ 866 } 867 868 #define NAME1 DrawMosaicPixel16 869 #define ARGS uint32 Tile, uint32 Offset, uint32 StartLine, uint32 StartPixel, uint32 Width, uint32 LineCount 870 871 // Second-level include: Get the DrawMosaicPixel16 renderers. 872 873 #include "tile.cpp" 874 875 #undef NAME1 876 #undef ARGS 877 #undef DRAW_TILE 878 #undef Z1 879 #undef Z2 880 881 // Basic routine to render the backdrop. 882 // DRAW_PIXEL is the same as above 883 // (or interlace at all, really). 884 // The backdrop is always depth = 1, so Z1 = Z2 = 1. And backdrop is always color 0. 885 886 #define Z1 1 887 #define Z2 1 888 #define Pix 0 889 890 #define DRAW_TILE() \ 891 uint32 l, x; \ 892 \ 893 GFX.RealScreenColors = IPPU.ScreenColors; \ 894 GFX.ScreenColors = GFX.ClipColors ? BlackColourMap : GFX.RealScreenColors; \ 895 \ 896 OFFSET_IN_LINE; \ 897 for (l = GFX.StartY; l <= GFX.EndY; l++, Offset += GFX.PPL) \ 898 { \ 899 for (x = Left; x < Right; x++) \ 900 DRAW_PIXEL(x, 1); \ 901 } 902 903 #define NAME1 DrawBackdrop16 904 #define ARGS uint32 Offset, uint32 Left, uint32 Right 905 906 // Second-level include: Get the DrawBackdrop16 renderers. 907 908 #include "tile.cpp" 909 910 #undef NAME1 911 #undef ARGS 912 #undef DRAW_TILE 913 #undef Pix 914 #undef Z1 915 #undef Z2 916 917 // Basic routine to render a chunk of a Mode 7 BG. 918 // We get some new parameters, so we can use the same DRAW_TILE to do BG1 or BG2: 919 // DCMODE tests if Direct Color should apply. 920 // BG is the BG, so we use the right clip window. 921 // MASK is 0xff or 0x7f, the 'color' portion of the pixel. 922 // We define Z1/Z2 to either be constant 5 or to vary depending on the 'priority' portion of the pixel. 923 924 #define CLIP_10_BIT_SIGNED(a) (((a) & 0x2000) ? ((a) | ~0x3ff) : ((a) & 0x3ff)) 925 926 #define Z1 (D + 7) 927 #define Z2 (D + 7) 928 #define MASK 0xff 929 #define DCMODE (Memory.PPU_IO[0x130] & 1) 930 #define BG 0 931 932 #define DRAW_TILE_NORMAL() \ 933 uint8 *VRAM1 = Memory.VRAM + 1; \ 934 \ 935 if (DCMODE) \ 936 { \ 937 GFX.RealScreenColors = DirectColourMaps[0]; \ 938 } \ 939 else \ 940 GFX.RealScreenColors = IPPU.ScreenColors; \ 941 \ 942 GFX.ScreenColors = GFX.ClipColors ? BlackColourMap : GFX.RealScreenColors; \ 943 \ 944 int aa, cc; \ 945 int startx; \ 946 \ 947 uint32 Offset = GFX.StartY * GFX.PPL; \ 948 struct SLineMatrixData *l = &LineMatrixData[GFX.StartY]; \ 949 \ 950 OFFSET_IN_LINE; \ 951 for (uint32 Line = GFX.StartY; Line <= GFX.EndY; Line++, Offset += GFX.PPL, l++) \ 952 { \ 953 int yy, starty; \ 954 \ 955 int32 HOffset = ((int32) l->M7HOFS << 19) >> 19; \ 956 int32 VOffset = ((int32) l->M7VOFS << 19) >> 19; \ 957 \ 958 int32 CentreX = ((int32) l->CentreX << 19) >> 19; \ 959 int32 CentreY = ((int32) l->CentreY << 19) >> 19; \ 960 \ 961 if (PPU.Mode7VFlip) \ 962 starty = 255 - (int) (Line + 1); \ 963 else \ 964 starty = Line + 1; \ 965 \ 966 yy = CLIP_10_BIT_SIGNED(VOffset - CentreY); \ 967 \ 968 int BB = ((l->MatrixB * starty) & ~63) + ((l->MatrixB * yy) & ~63) + (CentreX << 8); \ 969 int DD = ((l->MatrixD * starty) & ~63) + ((l->MatrixD * yy) & ~63) + (CentreY << 8); \ 970 \ 971 if (PPU.Mode7HFlip) \ 972 { \ 973 startx = Right - 1; \ 974 aa = -l->MatrixA; \ 975 cc = -l->MatrixC; \ 976 } \ 977 else \ 978 { \ 979 startx = Left; \ 980 aa = l->MatrixA; \ 981 cc = l->MatrixC; \ 982 } \ 983 \ 984 int xx = CLIP_10_BIT_SIGNED(HOffset - CentreX); \ 985 int AA = l->MatrixA * startx + ((l->MatrixA * xx) & ~63); \ 986 int CC = l->MatrixC * startx + ((l->MatrixC * xx) & ~63); \ 987 \ 988 uint8 Pix; \ 989 \ 990 if (!PPU.Mode7Repeat) \ 991 { \ 992 for (uint32 x = Left; x < Right; x++, AA += aa, CC += cc) \ 993 { \ 994 int X = ((AA + BB) >> 8) & 0x3ff; \ 995 int Y = ((CC + DD) >> 8) & 0x3ff; \ 996 \ 997 uint8 *TileData = VRAM1 + (Memory.VRAM[((Y & ~7) << 5) + ((X >> 2) & ~1)] << 7); \ 998 uint8 b = *(TileData + ((Y & 7) << 4) + ((X & 7) << 1)); \ 999 \ 1000 DRAW_PIXEL(x, Pix = (b & MASK)); \ 1001 } \ 1002 } \ 1003 else \ 1004 { \ 1005 for (uint32 x = Left; x < Right; x++, AA += aa, CC += cc) \ 1006 { \ 1007 int X = ((AA + BB) >> 8); \ 1008 int Y = ((CC + DD) >> 8); \ 1009 \ 1010 uint8 b; \ 1011 \ 1012 if (((X | Y) & ~0x3ff) == 0) \ 1013 { \ 1014 uint8 *TileData = VRAM1 + (Memory.VRAM[((Y & ~7) << 5) + ((X >> 2) & ~1)] << 7); \ 1015 b = *(TileData + ((Y & 7) << 4) + ((X & 7) << 1)); \ 1016 } \ 1017 else \ 1018 if (PPU.Mode7Repeat == 3) \ 1019 b = *(VRAM1 + ((Y & 7) << 4) + ((X & 7) << 1)); \ 1020 else \ 1021 continue; \ 1022 \ 1023 DRAW_PIXEL(x, Pix = (b & MASK)); \ 1024 } \ 1025 } \ 1026 } 1027 1028 #define DRAW_TILE_MOSAIC() \ 1029 uint8 *VRAM1 = Memory.VRAM + 1; \ 1030 \ 1031 if (DCMODE) \ 1032 { \ 1033 GFX.RealScreenColors = DirectColourMaps[0]; \ 1034 } \ 1035 else \ 1036 GFX.RealScreenColors = IPPU.ScreenColors; \ 1037 \ 1038 GFX.ScreenColors = GFX.ClipColors ? BlackColourMap : GFX.RealScreenColors; \ 1039 \ 1040 int aa, cc; \ 1041 int startx, StartY = GFX.StartY; \ 1042 \ 1043 int HMosaic = 1, VMosaic = 1, MosaicStart = 0; \ 1044 int32 MLeft = Left, MRight = Right; \ 1045 \ 1046 if (PPU.BGMosaic[0]) \ 1047 { \ 1048 VMosaic = PPU.Mosaic; \ 1049 MosaicStart = ((uint32) GFX.StartY - PPU.MosaicStart) % VMosaic; \ 1050 StartY -= MosaicStart; \ 1051 } \ 1052 \ 1053 if (PPU.BGMosaic[BG]) \ 1054 { \ 1055 HMosaic = PPU.Mosaic; \ 1056 MLeft -= MLeft % HMosaic; \ 1057 MRight += HMosaic - 1; \ 1058 MRight -= MRight % HMosaic; \ 1059 } \ 1060 \ 1061 uint32 Offset = StartY * GFX.PPL; \ 1062 struct SLineMatrixData *l = &LineMatrixData[StartY]; \ 1063 \ 1064 OFFSET_IN_LINE; \ 1065 for (uint32 Line = StartY; Line <= GFX.EndY; Line += VMosaic, Offset += VMosaic * GFX.PPL, l += VMosaic) \ 1066 { \ 1067 if (Line + VMosaic > GFX.EndY) \ 1068 VMosaic = GFX.EndY - Line + 1; \ 1069 \ 1070 int yy, starty; \ 1071 \ 1072 int32 HOffset = ((int32) l->M7HOFS << 19) >> 19; \ 1073 int32 VOffset = ((int32) l->M7VOFS << 19) >> 19; \ 1074 \ 1075 int32 CentreX = ((int32) l->CentreX << 19) >> 19; \ 1076 int32 CentreY = ((int32) l->CentreY << 19) >> 19; \ 1077 \ 1078 if (PPU.Mode7VFlip) \ 1079 starty = 255 - (int) (Line + 1); \ 1080 else \ 1081 starty = Line + 1; \ 1082 \ 1083 yy = CLIP_10_BIT_SIGNED(VOffset - CentreY); \ 1084 \ 1085 int BB = ((l->MatrixB * starty) & ~63) + ((l->MatrixB * yy) & ~63) + (CentreX << 8); \ 1086 int DD = ((l->MatrixD * starty) & ~63) + ((l->MatrixD * yy) & ~63) + (CentreY << 8); \ 1087 \ 1088 if (PPU.Mode7HFlip) \ 1089 { \ 1090 startx = MRight - 1; \ 1091 aa = -l->MatrixA; \ 1092 cc = -l->MatrixC; \ 1093 } \ 1094 else \ 1095 { \ 1096 startx = MLeft; \ 1097 aa = l->MatrixA; \ 1098 cc = l->MatrixC; \ 1099 } \ 1100 \ 1101 int xx = CLIP_10_BIT_SIGNED(HOffset - CentreX); \ 1102 int AA = l->MatrixA * startx + ((l->MatrixA * xx) & ~63); \ 1103 int CC = l->MatrixC * startx + ((l->MatrixC * xx) & ~63); \ 1104 \ 1105 uint8 Pix; \ 1106 uint8 ctr = 1; \ 1107 \ 1108 if (!PPU.Mode7Repeat) \ 1109 { \ 1110 for (int x = MLeft; x < MRight; x++, AA += aa, CC += cc) \ 1111 { \ 1112 if (--ctr) \ 1113 continue; \ 1114 ctr = HMosaic; \ 1115 \ 1116 int X = ((AA + BB) >> 8) & 0x3ff; \ 1117 int Y = ((CC + DD) >> 8) & 0x3ff; \ 1118 \ 1119 uint8 *TileData = VRAM1 + (Memory.VRAM[((Y & ~7) << 5) + ((X >> 2) & ~1)] << 7); \ 1120 uint8 b = *(TileData + ((Y & 7) << 4) + ((X & 7) << 1)); \ 1121 \ 1122 if ((Pix = (b & MASK))) \ 1123 { \ 1124 for (int h = MosaicStart; h < VMosaic; h++) \ 1125 { \ 1126 for (int w = x + HMosaic - 1; w >= x; w--) \ 1127 DRAW_PIXEL(w + h * GFX.PPL, (w >= (int32) Left && w < (int32) Right)); \ 1128 } \ 1129 } \ 1130 } \ 1131 } \ 1132 else \ 1133 { \ 1134 for (int x = MLeft; x < MRight; x++, AA += aa, CC += cc) \ 1135 { \ 1136 if (--ctr) \ 1137 continue; \ 1138 ctr = HMosaic; \ 1139 \ 1140 int X = ((AA + BB) >> 8); \ 1141 int Y = ((CC + DD) >> 8); \ 1142 \ 1143 uint8 b; \ 1144 \ 1145 if (((X | Y) & ~0x3ff) == 0) \ 1146 { \ 1147 uint8 *TileData = VRAM1 + (Memory.VRAM[((Y & ~7) << 5) + ((X >> 2) & ~1)] << 7); \ 1148 b = *(TileData + ((Y & 7) << 4) + ((X & 7) << 1)); \ 1149 } \ 1150 else \ 1151 if (PPU.Mode7Repeat == 3) \ 1152 b = *(VRAM1 + ((Y & 7) << 4) + ((X & 7) << 1)); \ 1153 else \ 1154 continue; \ 1155 \ 1156 if ((Pix = (b & MASK))) \ 1157 { \ 1158 for (int h = MosaicStart; h < VMosaic; h++) \ 1159 { \ 1160 for (int w = x + HMosaic - 1; w >= x; w--) \ 1161 DRAW_PIXEL(w + h * GFX.PPL, (w >= (int32) Left && w < (int32) Right)); \ 1162 } \ 1163 } \ 1164 } \ 1165 } \ 1166 \ 1167 MosaicStart = 0; \ 1168 } 1169 1170 #define DRAW_TILE() DRAW_TILE_NORMAL() 1171 #define NAME1 DrawMode7BG1 1172 #define ARGS uint32 Left, uint32 Right, int D 1173 1174 // Second-level include: Get the DrawMode7BG1 renderers. 1175 1176 #include "tile.cpp" 1177 1178 #undef NAME1 1179 #undef DRAW_TILE 1180 1181 #define DRAW_TILE() DRAW_TILE_MOSAIC() 1182 #define NAME1 DrawMode7MosaicBG1 1183 1184 // Second-level include: Get the DrawMode7MosaicBG1 renderers. 1185 1186 #include "tile.cpp" 1187 1188 #undef DRAW_TILE 1189 #undef NAME1 1190 #undef Z1 1191 #undef Z2 1192 #undef MASK 1193 #undef DCMODE 1194 #undef BG 1195 1196 #define NAME1 DrawMode7BG2 1197 #define DRAW_TILE() DRAW_TILE_NORMAL() 1198 #define Z1 (D + ((b & 0x80) ? 11 : 3)) 1199 #define Z2 (D + ((b & 0x80) ? 11 : 3)) 1200 #define MASK 0x7f 1201 #define DCMODE 0 1202 #define BG 1 1203 1204 // Second-level include: Get the DrawMode7BG2 renderers. 1205 1206 #include "tile.cpp" 1207 1208 #undef NAME1 1209 #undef DRAW_TILE 1210 1211 #define DRAW_TILE() DRAW_TILE_MOSAIC() 1212 #define NAME1 DrawMode7MosaicBG2 1213 1214 // Second-level include: Get the DrawMode7MosaicBG2 renderers. 1215 1216 #include "tile.cpp" 1217 1218 #undef MASK 1219 #undef DCMODE 1220 #undef BG 1221 #undef NAME1 1222 #undef ARGS 1223 #undef DRAW_TILE 1224 #undef DRAW_TILE_NORMAL 1225 #undef DRAW_TILE_MOSAIC 1226 #undef Z1 1227 #undef Z2 1228 1229 /*****************************************************************************/ 1230 #else 1231 #ifndef NAME2 // Second-level: Get all the NAME1 renderers. 1232 /*****************************************************************************/ 1233 1234 // The 1x1 pixel plotter, for speedhacking modes. 1235 1236 #define OFFSET_IN_LINE 1237 #define DRAW_PIXEL(N, M) \ 1238 if (Z1 > GFX.DB[Offset + N] && (M)) \ 1239 { \ 1240 GFX.S[Offset + N] = MATH(GFX.ScreenColors[Pix], GFX.SubScreen[Offset + N], GFX.SubZBuffer[Offset + N]); \ 1241 GFX.DB[Offset + N] = Z2; \ 1242 } 1243 1244 #define NAME2 Normal1x1 1245 1246 // Third-level include: Get the Normal1x1 renderers. 1247 1248 #include "tile.cpp" 1249 1250 #undef NAME2 1251 #undef DRAW_PIXEL 1252 1253 /*****************************************************************************/ 1254 #else // Third-level: Renderers for each math mode for NAME1 + NAME2. 1255 /*****************************************************************************/ 1256 1257 #define CONCAT3(A, B, C) A##B##C 1258 #define MAKENAME(A, B, C) CONCAT3(A, B, C) 1259 1260 static void MAKENAME(NAME1, _, NAME2) (ARGS) 1261 { 1262 #define MATH(A, B, C) NOMATH(x, A, B, C) 1263 DRAW_TILE(); 1264 #undef MATH 1265 } 1266 1267 static void MAKENAME(NAME1, Add_, NAME2) (ARGS) 1268 { 1269 #define MATH(A, B, C) REGMATH(ADD, A, B, C) 1270 DRAW_TILE(); 1271 #undef MATH 1272 } 1273 1274 static void MAKENAME(NAME1, Add_Brightness_, NAME2) (ARGS) 1275 { 1276 #define MATH(A, B, C) REGMATH(ADD_BRIGHTNESS, A, B, C) 1277 DRAW_TILE(); 1278 #undef MATH 1279 } 1280 1281 static void MAKENAME(NAME1, AddF1_2_, NAME2) (ARGS) 1282 { 1283 #define MATH(A, B, C) MATHF1_2(ADD, A, B, C) 1284 DRAW_TILE(); 1285 #undef MATH 1286 } 1287 1288 static void MAKENAME(NAME1, AddS1_2_, NAME2) (ARGS) 1289 { 1290 #define MATH(A, B, C) MATHS1_2(ADD, A, B, C) 1291 DRAW_TILE(); 1292 #undef MATH 1293 } 1294 1295 static void MAKENAME(NAME1, AddS1_2_Brightness_, NAME2) (ARGS) 1296 { 1297 #define MATH(A, B, C) MATHS1_2(ADD_BRIGHTNESS, A, B, C) 1298 DRAW_TILE(); 1299 #undef MATH 1300 } 1301 1302 static void MAKENAME(NAME1, Sub_, NAME2) (ARGS) 1303 { 1304 #define MATH(A, B, C) REGMATH(SUB, A, B, C) 1305 DRAW_TILE(); 1306 #undef MATH 1307 } 1308 1309 static void MAKENAME(NAME1, SubF1_2_, NAME2) (ARGS) 1310 { 1311 #define MATH(A, B, C) MATHF1_2(SUB, A, B, C) 1312 DRAW_TILE(); 1313 #undef MATH 1314 } 1315 1316 static void MAKENAME(NAME1, SubS1_2_, NAME2) (ARGS) 1317 { 1318 #define MATH(A, B, C) MATHS1_2(SUB, A, B, C) 1319 DRAW_TILE(); 1320 #undef MATH 1321 } 1322 1323 static void (*MAKENAME(Renderers_, NAME1, NAME2)[9]) (ARGS) = 1324 { 1325 MAKENAME(NAME1, _, NAME2), 1326 MAKENAME(NAME1, Add_, NAME2), 1327 MAKENAME(NAME1, AddF1_2_, NAME2), 1328 MAKENAME(NAME1, AddS1_2_, NAME2), 1329 MAKENAME(NAME1, Sub_, NAME2), 1330 MAKENAME(NAME1, SubF1_2_, NAME2), 1331 MAKENAME(NAME1, SubS1_2_, NAME2), 1332 MAKENAME(NAME1, Add_Brightness_, NAME2), 1333 MAKENAME(NAME1, AddS1_2_Brightness_, NAME2) 1334 }; 1335 1336 #undef MAKENAME 1337 #undef CONCAT3 1338 1339 #endif 1340 #endif 1341 #endif