PageRenderTime 39ms CodeModel.GetById 10ms RepoModel.GetById 0ms app.codeStats 1ms

/src/snes/gfx.cpp

https://bitbucket.org/elemental/emumaster
C++ | 3912 lines | 3403 code | 313 blank | 196 comment | 741 complexity | fd748676192bc2c1a7bbf9dae10fe7c6 MD5 | raw file
  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. //#define _TRANSP_SUPPORT_
  42. //#include <e32cmn.h>
  43. #include "snes9x.h"
  44. #include "mem.h"
  45. #include "ppu.h"
  46. #include "cpu.h"
  47. #include "display.h"
  48. #include "gfx.h"
  49. #include "spu.h"
  50. #include "cheats.h"
  51. //#include "tile.h"
  52. #include "port.h"
  53. #include "snes.h"
  54. typedef unsigned int u32_t;
  55. #define M7 19
  56. #define M8 19
  57. void ComputeClipWindows ();
  58. extern u8 BitShifts[8][4];
  59. extern u8 TileShifts[8][4];
  60. extern u8 PaletteShifts[8][4];
  61. extern u8 PaletteMasks[8][4];
  62. extern u8 Depths[8][4];
  63. extern u8 BGSizes [2];
  64. extern NormalTileRenderer DrawTilePtr;
  65. extern ClippedTileRenderer DrawClippedTilePtr;
  66. extern NormalTileRenderer DrawHiResTilePtr;
  67. extern ClippedTileRenderer DrawHiResClippedTilePtr;
  68. extern LargePixelRenderer DrawLargePixelPtr;
  69. extern struct SBG BG;
  70. extern struct SLineData LineData[240];
  71. extern struct SLineMatrixData LineMatrixData [240];
  72. extern u8 Mode7Depths [2];
  73. #define ON_MAIN(N) \
  74. (GFX.r212c & (1 << (N)) && \
  75. !(PPU.BG_Forced & (1 << (N))))
  76. #define SUB_OR_ADD(N) \
  77. (GFX.r2131 & (1 << (N)))
  78. #define ON_SUB(N) \
  79. ((GFX.r2130 & 0x30) != 0x30 && \
  80. (GFX.r2130 & 2) && \
  81. (GFX.r212d & (1 << N)) && \
  82. !(PPU.BG_Forced & (1 << (N))))
  83. #define ANYTHING_ON_SUB \
  84. ((GFX.r2130 & 0x30) != 0x30 && \
  85. (GFX.r2130 & 2) && \
  86. (GFX.r212d & 0x1f))
  87. #define ADD_OR_SUB_ON_ANYTHING \
  88. (GFX.r2131 & 0x3f)
  89. #define BLACK BUILD_PIXEL(0,0,0)
  90. void DrawTile (u32 Tile, u32 Offset, u32 StartLine,
  91. u32 LineCount, struct SGFX * gfx);
  92. void DrawClippedTile (u32 Tile, u32 Offset,
  93. u32 StartPixel, u32 Width,
  94. u32 StartLine, u32 LineCount, struct SGFX * gfx);
  95. void DrawTilex2 (u32 Tile, u32 Offset, u32 StartLine,
  96. u32 LineCount, struct SGFX * gfx);
  97. void DrawClippedTilex2 (u32 Tile, u32 Offset,
  98. u32 StartPixel, u32 Width,
  99. u32 StartLine, u32 LineCount, struct SGFX * gfx);
  100. void DrawTilex2x2 (u32 Tile, u32 Offset, u32 StartLine,
  101. u32 LineCount, struct SGFX * gfx);
  102. void DrawClippedTilex2x2 (u32 Tile, u32 Offset,
  103. u32 StartPixel, u32 Width,
  104. u32 StartLine, u32 LineCount, struct SGFX * gfx);
  105. void DrawLargePixel (u32 Tile, u32 Offset,
  106. u32 StartPixel, u32 Pixels,
  107. u32 StartLine, u32 LineCount, struct SGFX * gfx);
  108. void DrawTile16 (u32 Tile, u32 Offset, u32 StartLine,
  109. u32 LineCount, struct SGFX * gfx);
  110. void DrawClippedTile16 (u32 Tile, u32 Offset,
  111. u32 StartPixel, u32 Width,
  112. u32 StartLine, u32 LineCount, struct SGFX * gfx);
  113. void DrawTile16x2 (u32 Tile, u32 Offset, u32 StartLine,
  114. u32 LineCount, struct SGFX * gfx);
  115. void DrawClippedTile16x2 (u32 Tile, u32 Offset,
  116. u32 StartPixel, u32 Width,
  117. u32 StartLine, u32 LineCount, struct SGFX * gfx);
  118. void DrawTile16x2x2 (u32 Tile, u32 Offset, u32 StartLine,
  119. u32 LineCount, struct SGFX * gfx);
  120. void DrawClippedTile16x2x2 (u32 Tile, u32 Offset,
  121. u32 StartPixel, u32 Width,
  122. u32 StartLine, u32 LineCount, struct SGFX * gfx);
  123. void DrawLargePixel16 (u32 Tile, u32 Offset,
  124. u32 StartPixel, u32 Pixels,
  125. u32 StartLine, u32 LineCount, struct SGFX * gfx);
  126. void DrawTile16Add (u32 Tile, u32 Offset, u32 StartLine,
  127. u32 LineCount, struct SGFX * gfx);
  128. void DrawClippedTile16Add (u32 Tile, u32 Offset,
  129. u32 StartPixel, u32 Width,
  130. u32 StartLine, u32 LineCount, struct SGFX * gfx);
  131. void DrawTile16Add1_2 (u32 Tile, u32 Offset, u32 StartLine,
  132. u32 LineCount, struct SGFX * gfx);
  133. void DrawClippedTile16Add1_2 (u32 Tile, u32 Offset,
  134. u32 StartPixel, u32 Width,
  135. u32 StartLine, u32 LineCount, struct SGFX * gfx);
  136. void DrawTile16FixedAdd1_2 (u32 Tile, u32 Offset, u32 StartLine,
  137. u32 LineCount, struct SGFX * gfx);
  138. void DrawClippedTile16FixedAdd1_2 (u32 Tile, u32 Offset,
  139. u32 StartPixel, u32 Width,
  140. u32 StartLine, u32 LineCount, struct SGFX * gfx);
  141. void DrawTile16Sub (u32 Tile, u32 Offset, u32 StartLine,
  142. u32 LineCount, struct SGFX * gfx);
  143. void DrawClippedTile16Sub (u32 Tile, u32 Offset,
  144. u32 StartPixel, u32 Width,
  145. u32 StartLine, u32 LineCount, struct SGFX * gfx);
  146. void DrawTile16Sub1_2 (u32 Tile, u32 Offset, u32 StartLine,
  147. u32 LineCount, struct SGFX * gfx);
  148. void DrawClippedTile16Sub1_2 (u32 Tile, u32 Offset,
  149. u32 StartPixel, u32 Width,
  150. u32 StartLine, u32 LineCount, struct SGFX * gfx);
  151. void DrawTile16FixedSub1_2 (u32 Tile, u32 Offset, u32 StartLine,
  152. u32 LineCount, struct SGFX * gfx);
  153. void DrawClippedTile16FixedSub1_2 (u32 Tile, u32 Offset,
  154. u32 StartPixel, u32 Width,
  155. u32 StartLine, u32 LineCount, struct SGFX * gfx);
  156. void DrawLargePixel16Add (u32 Tile, u32 Offset,
  157. u32 StartPixel, u32 Pixels,
  158. u32 StartLine, u32 LineCount, struct SGFX * gfx);
  159. void DrawLargePixel16Add1_2 (u32 Tile, u32 Offset,
  160. u32 StartPixel, u32 Pixels,
  161. u32 StartLine, u32 LineCount, struct SGFX * gfx);
  162. void DrawLargePixel16Sub (u32 Tile, u32 Offset,
  163. u32 StartPixel, u32 Pixels,
  164. u32 StartLine, u32 LineCount, struct SGFX * gfx);
  165. void DrawLargePixel16Sub1_2 (u32 Tile, u32 Offset,
  166. u32 StartPixel, u32 Pixels,
  167. u32 StartLine, u32 LineCount, struct SGFX * gfx);
  168. void DrawHiResClippedTile16 (u32 Tile, u32 Offset,
  169. u32 StartPixel, u32 Width,
  170. u32 StartLine, u32 LineCount, struct SGFX * gfx);
  171. void DrawHiResTile16 (u32 Tile, u32 Offset,
  172. u32 StartLine, u32 LineCount, struct SGFX * gfx);
  173. bool8_32 S9xGraphicsInit ()
  174. {
  175. register u32 PixelOdd = 1;
  176. register u32 PixelEven = 2;
  177. #ifdef GFX_MULTI_FORMAT
  178. if (GFX.BuildPixel == NULL)
  179. S9xSetRenderPixelFormat (RGB565);
  180. #endif
  181. for (u8 bitshift = 0; bitshift < 4; bitshift++)
  182. {
  183. for (register char i = 0; i < 16; i++)
  184. {
  185. register u32 h = 0;
  186. register u32 l = 0;
  187. #if defined(LSB_FIRST)
  188. if (i & 8)
  189. h |= PixelOdd;
  190. if (i & 4)
  191. h |= PixelOdd << 8;
  192. if (i & 2)
  193. h |= PixelOdd << 16;
  194. if (i & 1)
  195. h |= PixelOdd << 24;
  196. if (i & 8)
  197. l |= PixelOdd;
  198. if (i & 4)
  199. l |= PixelOdd << 8;
  200. if (i & 2)
  201. l |= PixelOdd << 16;
  202. if (i & 1)
  203. l |= PixelOdd << 24;
  204. #else
  205. if (i & 8)
  206. h |= (PixelOdd << 24);
  207. if (i & 4)
  208. h |= (PixelOdd << 16);
  209. if (i & 2)
  210. h |= (PixelOdd << 8);
  211. if (i & 1)
  212. h |= PixelOdd;
  213. if (i & 8)
  214. l |= (PixelOdd << 24);
  215. if (i & 4)
  216. l |= (PixelOdd << 16);
  217. if (i & 2)
  218. l |= (PixelOdd << 8);
  219. if (i & 1)
  220. l |= PixelOdd;
  221. #endif
  222. odd_high[bitshift][(u8)i] = h;
  223. odd_low[bitshift][(u8)i] = l;
  224. h = l = 0;
  225. #if defined(LSB_FIRST)
  226. if (i & 8)
  227. h |= PixelEven;
  228. if (i & 4)
  229. h |= PixelEven << 8;
  230. if (i & 2)
  231. h |= PixelEven << 16;
  232. if (i & 1)
  233. h |= PixelEven << 24;
  234. if (i & 8)
  235. l |= PixelEven;
  236. if (i & 4)
  237. l |= PixelEven << 8;
  238. if (i & 2)
  239. l |= PixelEven << 16;
  240. if (i & 1)
  241. l |= PixelEven << 24;
  242. #else
  243. if (i & 8)
  244. h |= (PixelEven << 24);
  245. if (i & 4)
  246. h |= (PixelEven << 16);
  247. if (i & 2)
  248. h |= (PixelEven << 8);
  249. if (i & 1)
  250. h |= PixelEven;
  251. if (i & 8)
  252. l |= (PixelEven << 24);
  253. if (i & 4)
  254. l |= (PixelEven << 16);
  255. if (i & 2)
  256. l |= (PixelEven << 8);
  257. if (i & 1)
  258. l |= PixelEven;
  259. #endif
  260. even_high[bitshift][(u8)i] = h;
  261. even_low[bitshift][(u8)i] = l;
  262. }
  263. PixelEven <<= 2;
  264. PixelOdd <<= 2;
  265. }
  266. GFX.RealPitch = GFX.Pitch2 = GFX.Pitch;
  267. GFX.ZPitch = GFX.Pitch;
  268. if (Settings.SixteenBit)
  269. GFX.ZPitch >>= 1;
  270. GFX.Delta = (GFX.SubScreen - GFX.Screen) >> 1;
  271. GFX.DepthDelta = GFX.SubZBuffer - GFX.ZBuffer;
  272. PPU.BG_Forced = 0;
  273. IPPU.OBJChanged = TRUE;
  274. if (Settings.Transparency)
  275. Settings.SixteenBit = TRUE;
  276. IPPU.DirectColourMapsNeedRebuild = TRUE;
  277. GFX.PixSize = 1;
  278. if (Settings.SixteenBit)
  279. {
  280. DrawTilePtr = DrawTile16;
  281. DrawClippedTilePtr = DrawClippedTile16;
  282. DrawLargePixelPtr = DrawLargePixel16;
  283. DrawHiResTilePtr= DrawHiResTile16;
  284. DrawHiResClippedTilePtr = DrawHiResClippedTile16;
  285. GFX.PPL = GFX.Pitch >> 1;
  286. GFX.PPLx2 = GFX.Pitch;
  287. }
  288. else
  289. {
  290. DrawTilePtr = DrawTile;
  291. DrawClippedTilePtr = DrawClippedTile;
  292. DrawLargePixelPtr = DrawLargePixel;
  293. DrawHiResTilePtr = DrawTile;
  294. DrawHiResClippedTilePtr = DrawClippedTile;
  295. GFX.PPL = GFX.Pitch;
  296. GFX.PPLx2 = GFX.Pitch * 2;
  297. }
  298. S9xFixColourBrightness ();
  299. if (Settings.SixteenBit)
  300. {
  301. if (!(GFX.X2 = (u16 *) malloc (sizeof (u16) * 0x10000)))
  302. return (FALSE);
  303. if (!(GFX.ZERO_OR_X2 = (u16 *) malloc (sizeof (u16) * 0x10000)) ||
  304. !(GFX.ZERO = (u16 *) malloc (sizeof (u16) * 0x10000)))
  305. {
  306. if (GFX.ZERO_OR_X2)
  307. {
  308. free ((char *) GFX.ZERO_OR_X2);
  309. GFX.ZERO_OR_X2 = NULL;
  310. }
  311. if (GFX.X2)
  312. {
  313. free ((char *) GFX.X2);
  314. GFX.X2 = NULL;
  315. }
  316. return (FALSE);
  317. }
  318. u32 r, g, b;
  319. // Build a lookup table that multiplies a packed RGB value by 2 with
  320. // saturation.
  321. for (r = 0; r <= MAX_RED; r++)
  322. {
  323. u32 r2 = r << 1;
  324. if (r2 > MAX_RED)
  325. r2 = MAX_RED;
  326. for (g = 0; g <= MAX_GREEN; g++)
  327. {
  328. u32 g2 = g << 1;
  329. if (g2 > MAX_GREEN)
  330. g2 = MAX_GREEN;
  331. for (b = 0; b <= MAX_BLUE; b++)
  332. {
  333. u32 b2 = b << 1;
  334. if (b2 > MAX_BLUE)
  335. b2 = MAX_BLUE;
  336. GFX.X2 [BUILD_PIXEL2 (r, g, b)] = BUILD_PIXEL2 (r2, g2, b2);
  337. GFX.X2 [BUILD_PIXEL2 (r, g, b) & ~ALPHA_BITS_MASK] = BUILD_PIXEL2 (r2, g2, b2);
  338. }
  339. }
  340. }
  341. ZeroMemory (GFX.ZERO, 0x10000 * sizeof (u16));
  342. ZeroMemory (GFX.ZERO_OR_X2, 0x10000 * sizeof (u16));
  343. // Build a lookup table that if the top bit of the color value is zero
  344. // then the value is zero, otherwise multiply the value by 2. Used by
  345. // the color subtraction code.
  346. #if defined(OLD_COLOUR_BLENDING)
  347. for (r = 0; r <= MAX_RED; r++)
  348. {
  349. u32 r2 = r;
  350. if ((r2 & 0x10) == 0)
  351. r2 = 0;
  352. else
  353. r2 = (r2 << 1) & MAX_RED;
  354. for (g = 0; g <= MAX_GREEN; g++)
  355. {
  356. u32 g2 = g;
  357. if ((g2 & GREEN_HI_BIT) == 0)
  358. g2 = 0;
  359. else
  360. g2 = (g2 << 1) & MAX_GREEN;
  361. for (b = 0; b <= MAX_BLUE; b++)
  362. {
  363. u32 b2 = b;
  364. if ((b2 & 0x10) == 0)
  365. b2 = 0;
  366. else
  367. b2 = (b2 << 1) & MAX_BLUE;
  368. GFX.ZERO_OR_X2 [BUILD_PIXEL2 (r, g, b)] = BUILD_PIXEL2 (r2, g2, b2);
  369. GFX.ZERO_OR_X2 [BUILD_PIXEL2 (r, g, b) & ~ALPHA_BITS_MASK] = BUILD_PIXEL2 (r2, g2, b2);
  370. }
  371. }
  372. }
  373. #else
  374. for (r = 0; r <= MAX_RED; r++)
  375. {
  376. u32 r2 = r;
  377. if ((r2 & 0x10) == 0)
  378. r2 = 0;
  379. else
  380. r2 = (r2 << 1) & MAX_RED;
  381. if (r2 == 0)
  382. r2 = 1;
  383. for (g = 0; g <= MAX_GREEN; g++)
  384. {
  385. u32 g2 = g;
  386. if ((g2 & GREEN_HI_BIT) == 0)
  387. g2 = 0;
  388. else
  389. g2 = (g2 << 1) & MAX_GREEN;
  390. if (g2 == 0)
  391. g2 = 1;
  392. for (b = 0; b <= MAX_BLUE; b++)
  393. {
  394. u32 b2 = b;
  395. if ((b2 & 0x10) == 0)
  396. b2 = 0;
  397. else
  398. b2 = (b2 << 1) & MAX_BLUE;
  399. if (b2 == 0)
  400. b2 = 1;
  401. GFX.ZERO_OR_X2 [BUILD_PIXEL2 (r, g, b)] = BUILD_PIXEL2 (r2, g2, b2);
  402. GFX.ZERO_OR_X2 [BUILD_PIXEL2 (r, g, b) & ~ALPHA_BITS_MASK] = BUILD_PIXEL2 (r2, g2, b2);
  403. }
  404. }
  405. }
  406. #endif
  407. // Build a lookup table that if the top bit of the color value is zero
  408. // then the value is zero, otherwise its just the value.
  409. for (r = 0; r <= MAX_RED; r++)
  410. {
  411. u32 r2 = r;
  412. if ((r2 & 0x10) == 0)
  413. r2 = 0;
  414. else
  415. r2 &= ~0x10;
  416. for (g = 0; g <= MAX_GREEN; g++)
  417. {
  418. u32 g2 = g;
  419. if ((g2 & GREEN_HI_BIT) == 0)
  420. g2 = 0;
  421. else
  422. g2 &= ~GREEN_HI_BIT;
  423. for (b = 0; b <= MAX_BLUE; b++)
  424. {
  425. u32 b2 = b;
  426. if ((b2 & 0x10) == 0)
  427. b2 = 0;
  428. else
  429. b2 &= ~0x10;
  430. GFX.ZERO [BUILD_PIXEL2 (r, g, b)] = BUILD_PIXEL2 (r2, g2, b2);
  431. GFX.ZERO [BUILD_PIXEL2 (r, g, b) & ~ALPHA_BITS_MASK] = BUILD_PIXEL2 (r2, g2, b2);
  432. }
  433. }
  434. }
  435. }
  436. else
  437. {
  438. GFX.X2 = NULL;
  439. GFX.ZERO_OR_X2 = NULL;
  440. GFX.ZERO = NULL;
  441. }
  442. return (TRUE);
  443. }
  444. void S9xGraphicsDeinit (void)
  445. {
  446. // Free any memory allocated in S9xGraphicsInit
  447. if (GFX.X2)
  448. {
  449. free ((char *) GFX.X2);
  450. GFX.X2 = NULL;
  451. }
  452. if (GFX.ZERO_OR_X2)
  453. {
  454. free ((char *) GFX.ZERO_OR_X2);
  455. GFX.ZERO_OR_X2 = NULL;
  456. }
  457. if (GFX.ZERO)
  458. {
  459. free ((char *) GFX.ZERO);
  460. GFX.ZERO = NULL;
  461. }
  462. }
  463. void S9xBuildDirectColourMaps ()
  464. {
  465. for (u32 p = 0; p < 8; p++)
  466. {
  467. for (u32 c = 0; c < 256; c++)
  468. {
  469. // XXX: Brightness
  470. DirectColourMaps [p][c] = BUILD_PIXEL (((c & 7) << 2) | ((p & 1) << 1),
  471. ((c & 0x38) >> 1) | (p & 2),
  472. ((c & 0xc0) >> 3) | (p & 4));
  473. }
  474. }
  475. IPPU.DirectColourMapsNeedRebuild = FALSE;
  476. }
  477. void S9xStartScreenRefresh ()
  478. {
  479. if (GFX.InfoStringTimeout > 0 && --GFX.InfoStringTimeout == 0)
  480. GFX.InfoString = NULL;
  481. if (IPPU.RenderThisFrame)
  482. {
  483. IPPU.RenderedFramesCount++;
  484. IPPU.PreviousLine = IPPU.CurrentLine = 0;
  485. IPPU.MaxBrightness = PPU.Brightness;
  486. IPPU.LatchedBlanking = PPU.ForcedBlanking;
  487. IPPU.LatchedInterlace = (Memory.FillRAM[0x2133] & 1);
  488. IPPU.RenderedScreenWidth = 256;
  489. IPPU.RenderedScreenHeight = PPU.ScreenHeight;
  490. IPPU.DoubleWidthPixels = FALSE;
  491. GFX.Pitch2 = GFX.Pitch = GFX.RealPitch;
  492. GFX.PPL = GFX.PPLx2 >> 1;
  493. GFX.ZPitch = GFX.RealPitch;
  494. if (Settings.SixteenBit)
  495. GFX.ZPitch >>= 1;
  496. PPU.RecomputeClipWindows = TRUE;
  497. GFX.DepthDelta = GFX.SubZBuffer - GFX.ZBuffer;
  498. GFX.Delta = (GFX.SubScreen - GFX.Screen) >> 1;
  499. }
  500. if (++IPPU.FrameCount % Memory.ROMFramesPerSecond == 0)
  501. {
  502. IPPU.DisplayedRenderedFrameCount = IPPU.RenderedFramesCount;
  503. IPPU.RenderedFramesCount = 0;
  504. IPPU.FrameCount = 0;
  505. }
  506. }
  507. void RenderLine (u8 C)
  508. {
  509. if (IPPU.RenderThisFrame)
  510. {
  511. LineData[C].BG[0].VOffset = PPU.BG[0].VOffset + 1;
  512. LineData[C].BG[0].HOffset = PPU.BG[0].HOffset;
  513. LineData[C].BG[1].VOffset = PPU.BG[1].VOffset + 1;
  514. LineData[C].BG[1].HOffset = PPU.BG[1].HOffset;
  515. if (PPU.BGMode == 7)
  516. {
  517. struct SLineMatrixData *p = &LineMatrixData [C];
  518. p->MatrixA = PPU.MatrixA;
  519. p->MatrixB = PPU.MatrixB;
  520. p->MatrixC = PPU.MatrixC;
  521. p->MatrixD = PPU.MatrixD;
  522. p->CentreX = PPU.CentreX;
  523. p->CentreY = PPU.CentreY;
  524. }
  525. else
  526. {
  527. if (Settings.StarfoxHack && PPU.BG[2].VOffset == 0 &&
  528. PPU.BG[2].HOffset == 0xe000)
  529. {
  530. LineData[C].BG[2].VOffset = 0xe1;
  531. LineData[C].BG[2].HOffset = 0;
  532. }
  533. else
  534. {
  535. LineData[C].BG[2].VOffset = PPU.BG[2].VOffset + 1;
  536. LineData[C].BG[2].HOffset = PPU.BG[2].HOffset;
  537. LineData[C].BG[3].VOffset = PPU.BG[3].VOffset + 1;
  538. LineData[C].BG[3].HOffset = PPU.BG[3].HOffset;
  539. }
  540. }
  541. IPPU.CurrentLine = C + 1;
  542. }
  543. }
  544. void S9xEndScreenRefresh ()
  545. {
  546. IPPU.HDMAStarted = FALSE;
  547. if (IPPU.RenderThisFrame)
  548. {
  549. FLUSH_REDRAW ();
  550. if (IPPU.ColorsChanged)
  551. {
  552. u32 saved = PPU.CGDATA[0];
  553. if (!Settings.SixteenBit)
  554. {
  555. // Hack for Super Mario World - to get its sky blue
  556. // (It uses Fixed colour addition on the backdrop colour)
  557. if (!(Memory.FillRAM [0x2131] & 0x80) &&
  558. (Memory.FillRAM[0x2131] & 0x20) &&
  559. (PPU.FixedColourRed || PPU.FixedColourGreen ||
  560. PPU.FixedColourBlue))
  561. {
  562. PPU.CGDATA[0] = PPU.FixedColourRed |
  563. (PPU.FixedColourGreen << 5) |
  564. (PPU.FixedColourBlue << 10);
  565. }
  566. }
  567. IPPU.ColorsChanged = FALSE;
  568. // S9xSetPalette ();
  569. PPU.CGDATA[0] = saved;
  570. }
  571. GFX.Pitch = GFX.Pitch2 = GFX.RealPitch;
  572. GFX.PPL = GFX.PPLx2 >> 1;
  573. }
  574. snesEmu.sync(IPPU.RenderedScreenWidth, IPPU.RenderedScreenHeight);
  575. #ifndef RC_OPTIMIZED
  576. S9xApplyCheats ();
  577. #endif
  578. #ifdef DEBUGGER
  579. if (CPU.Flags & FRAME_ADVANCE_FLAG)
  580. {
  581. if (ICPU.FrameAdvanceCount)
  582. {
  583. ICPU.FrameAdvanceCount--;
  584. IPPU.RenderThisFrame = TRUE;
  585. }
  586. else
  587. {
  588. CPU.Flags &= ~FRAME_ADVANCE_FLAG;
  589. CPU.Flags |= DEBUG_MODE_FLAG;
  590. }
  591. }
  592. #endif
  593. }
  594. void S9xSetInfoString (const char *string)
  595. {
  596. GFX.InfoString = string;
  597. GFX.InfoStringTimeout = 120;
  598. }
  599. INLINE void SelectTileRenderer (bool8_32 normal)
  600. {
  601. if (normal)
  602. {
  603. DrawTilePtr = DrawTile16;
  604. DrawClippedTilePtr = DrawClippedTile16;
  605. DrawLargePixelPtr = DrawLargePixel16;
  606. }
  607. else
  608. {
  609. if (GFX.r2131 & 0x80)
  610. {
  611. if (GFX.r2131 & 0x40)
  612. {
  613. if (GFX.r2130 & 2)
  614. {
  615. DrawTilePtr = DrawTile16Sub1_2;
  616. DrawClippedTilePtr = DrawClippedTile16Sub1_2;
  617. }
  618. else
  619. {
  620. // Fixed colour substraction
  621. DrawTilePtr = DrawTile16FixedSub1_2;
  622. DrawClippedTilePtr = DrawClippedTile16FixedSub1_2;
  623. }
  624. DrawLargePixelPtr = DrawLargePixel16Sub1_2;
  625. }
  626. else
  627. {
  628. DrawTilePtr = DrawTile16Sub;
  629. DrawClippedTilePtr = DrawClippedTile16Sub;
  630. DrawLargePixelPtr = DrawLargePixel16Sub;
  631. }
  632. }
  633. else
  634. {
  635. if (GFX.r2131 & 0x40)
  636. {
  637. if (GFX.r2130 & 2)
  638. {
  639. DrawTilePtr = DrawTile16Add1_2;
  640. DrawClippedTilePtr = DrawClippedTile16Add1_2;
  641. }
  642. else
  643. {
  644. // Fixed colour addition
  645. DrawTilePtr = DrawTile16FixedAdd1_2;
  646. DrawClippedTilePtr = DrawClippedTile16FixedAdd1_2;
  647. }
  648. DrawLargePixelPtr = DrawLargePixel16Add1_2;
  649. }
  650. else
  651. {
  652. DrawTilePtr = DrawTile16Add;
  653. DrawClippedTilePtr = DrawClippedTile16Add;
  654. DrawLargePixelPtr = DrawLargePixel16Add;
  655. }
  656. }
  657. }
  658. }
  659. void S9xSetupOBJ ()
  660. {
  661. int SmallSize;
  662. int LargeSize;
  663. switch (PPU.OBJSizeSelect)
  664. {
  665. case 0:
  666. SmallSize = 8;
  667. LargeSize = 16;
  668. break;
  669. case 1:
  670. SmallSize = 8;
  671. LargeSize = 32;
  672. break;
  673. case 2:
  674. SmallSize = 8;
  675. LargeSize = 64;
  676. break;
  677. case 3:
  678. SmallSize = 16;
  679. LargeSize = 32;
  680. break;
  681. case 4:
  682. SmallSize = 16;
  683. LargeSize = 64;
  684. break;
  685. case 5:
  686. default:
  687. SmallSize = 32;
  688. LargeSize = 64;
  689. break;
  690. }
  691. int C = 0;
  692. int FirstSprite = PPU.FirstSprite & 0x7f;
  693. int S = FirstSprite;
  694. do
  695. {
  696. int Size;
  697. if (PPU.OBJ [S].Size)
  698. Size = LargeSize;
  699. else
  700. Size = SmallSize;
  701. long VPos = PPU.OBJ [S].VPos;
  702. if (VPos >= PPU.ScreenHeight)
  703. VPos -= 256;
  704. if (PPU.OBJ [S].HPos < 256 && PPU.OBJ [S].HPos > -Size &&
  705. VPos < PPU.ScreenHeight && VPos > -Size)
  706. {
  707. GFX.OBJList [C++] = S;
  708. GFX.Sizes[S] = Size;
  709. GFX.VPositions[S] = VPos;
  710. }
  711. S = (S + 1) & 0x7f;
  712. } while (S != FirstSprite);
  713. // Terminate the list
  714. GFX.OBJList [C] = -1;
  715. IPPU.OBJChanged = FALSE;
  716. }
  717. void DrawOBJS (bool8_32 OnMain = FALSE, u8 D = 0)
  718. {
  719. u32 O;
  720. u32 BaseTile, Tile;
  721. CHECK_SOUND();
  722. BG.BitShift = 4;
  723. BG.TileShift = 5;
  724. BG.TileAddress = PPU.OBJNameBase;
  725. BG.StartPalette = 128;
  726. BG.PaletteShift = 4;
  727. BG.PaletteMask = 7;
  728. BG.Buffer = IPPU.TileCache [TILE_4BIT];
  729. BG.Buffered = IPPU.TileCached [TILE_4BIT];
  730. BG.NameSelect = PPU.OBJNameSelect;
  731. BG.DirectColourMode = FALSE;
  732. GFX.PixSize = 1;
  733. GFX.Z1 = D + 2;
  734. int I = 0;
  735. for (int S = GFX.OBJList [I++]; S >= 0; S = GFX.OBJList [I++])
  736. {
  737. int VPos = GFX.VPositions [S];
  738. int Size = GFX.Sizes[S];
  739. int TileInc = 1;
  740. int Offset;
  741. if (VPos + Size <= (int) GFX.StartY || VPos > (int) GFX.EndY)
  742. continue;
  743. if (OnMain && SUB_OR_ADD(4))
  744. {
  745. SelectTileRenderer (!GFX.Pseudo && PPU.OBJ [S].Palette < 4);
  746. }
  747. BaseTile = PPU.OBJ[S].Name | (PPU.OBJ[S].Palette << 10);
  748. if (PPU.OBJ[S].HFlip)
  749. {
  750. BaseTile += ((Size >> 3) - 1) | H_FLIP;
  751. TileInc = -1;
  752. }
  753. if (PPU.OBJ[S].VFlip)
  754. BaseTile |= V_FLIP;
  755. int clipcount = GFX.pCurrentClip->Count [4];
  756. if (!clipcount)
  757. clipcount = 1;
  758. GFX.Z2 = (PPU.OBJ[S].Priority + 1) * 4 + D;
  759. for (int clip = 0; clip < clipcount; clip++)
  760. {
  761. int Left;
  762. int Right;
  763. if (!GFX.pCurrentClip->Count [4])
  764. {
  765. Left = 0;
  766. Right = 256;
  767. }
  768. else
  769. {
  770. Left = GFX.pCurrentClip->Left [clip][4];
  771. Right = GFX.pCurrentClip->Right [clip][4];
  772. }
  773. if (Right <= Left || PPU.OBJ[S].HPos + Size <= Left ||
  774. PPU.OBJ[S].HPos >= Right)
  775. continue;
  776. for (int Y = 0; Y < Size; Y += 8)
  777. {
  778. if (VPos + Y + 7 >= (int) GFX.StartY && VPos + Y <= (int) GFX.EndY)
  779. {
  780. int StartLine;
  781. int TileLine;
  782. int LineCount;
  783. int Last;
  784. if ((StartLine = VPos + Y) < (int) GFX.StartY)
  785. {
  786. StartLine = GFX.StartY - StartLine;
  787. LineCount = 8 - StartLine;
  788. }
  789. else
  790. {
  791. StartLine = 0;
  792. LineCount = 8;
  793. }
  794. if ((Last = VPos + Y + 7 - GFX.EndY) > 0)
  795. if ((LineCount -= Last) <= 0)
  796. break;
  797. TileLine = StartLine << 3;
  798. O = (VPos + Y + StartLine) * GFX.PPL;
  799. if (!PPU.OBJ[S].VFlip)
  800. Tile = BaseTile + (Y << 1);
  801. else
  802. Tile = BaseTile + ((Size - Y - 8) << 1);
  803. int Middle = Size >> 3;
  804. if (PPU.OBJ[S].HPos < Left)
  805. {
  806. Tile += ((Left - PPU.OBJ[S].HPos) >> 3) * TileInc;
  807. Middle -= (Left - PPU.OBJ[S].HPos) >> 3;
  808. O += Left * GFX.PixSize;
  809. if ((Offset = (Left - PPU.OBJ[S].HPos) & 7))
  810. {
  811. O -= Offset * GFX.PixSize;
  812. int W = 8 - Offset;
  813. int Width = Right - Left;
  814. if (W > Width)
  815. W = Width;
  816. (*DrawClippedTilePtr) (Tile, O, Offset, W,
  817. TileLine, LineCount, &GFX);
  818. if (W >= Width)
  819. continue;
  820. Tile += TileInc;
  821. Middle--;
  822. O += 8 * GFX.PixSize;
  823. }
  824. }
  825. else
  826. O += PPU.OBJ[S].HPos * GFX.PixSize;
  827. if (PPU.OBJ[S].HPos + Size >= Right)
  828. {
  829. Middle -= ((PPU.OBJ[S].HPos + Size + 7) -
  830. Right) >> 3;
  831. Offset = (Right - (PPU.OBJ[S].HPos + Size)) & 7;
  832. }
  833. else
  834. Offset = 0;
  835. for (int X = 0; X < Middle; X++, O += 8 * GFX.PixSize,
  836. Tile += TileInc)
  837. {
  838. (*DrawTilePtr) (Tile, O, TileLine, LineCount, &GFX);
  839. }
  840. if (Offset)
  841. {
  842. (*DrawClippedTilePtr) (Tile, O, 0, Offset,
  843. TileLine, LineCount, &GFX);
  844. }
  845. }
  846. }
  847. }
  848. }
  849. }
  850. void DrawBackgroundMosaic (u32 BGMode, u32 bg, u8 Z1, u8 Z2)
  851. {
  852. CHECK_SOUND();
  853. u32 Tile;
  854. u16 *SC0;
  855. u16 *SC1;
  856. u16 *SC2;
  857. u16 *SC3;
  858. u8 depths [2] = {Z1, Z2};
  859. if (BGMode == 0)
  860. BG.StartPalette = bg << 5;
  861. else
  862. BG.StartPalette = 0;
  863. SC0 = (u16 *) &Memory.VRAM[PPU.BG[bg].SCBase << 1];
  864. if (PPU.BG[bg].SCSize & 1)
  865. SC1 = SC0 + 1024;
  866. else
  867. SC1 = SC0;
  868. if (PPU.BG[bg].SCSize & 2)
  869. SC2 = SC1 + 1024;
  870. else
  871. SC2 = SC0;
  872. if (PPU.BG[bg].SCSize & 1)
  873. SC3 = SC2 + 1024;
  874. else
  875. SC3 = SC2;
  876. u32 Lines;
  877. u32 OffsetMask;
  878. u32 OffsetShift;
  879. if (BG.TileSize == 16)
  880. {
  881. OffsetMask = 0x3ff;
  882. OffsetShift = 4;
  883. }
  884. else
  885. {
  886. OffsetMask = 0x1ff;
  887. OffsetShift = 3;
  888. }
  889. for (u32 Y = GFX.StartY; Y <= GFX.EndY; Y += Lines)
  890. {
  891. u32 VOffset = LineData [Y].BG[bg].VOffset;
  892. u32 HOffset = LineData [Y].BG[bg].HOffset;
  893. u32 MosaicOffset = Y % PPU.Mosaic;
  894. for (Lines = 1; Lines < PPU.Mosaic - MosaicOffset; Lines++)
  895. if ((VOffset != LineData [Y + Lines].BG[bg].VOffset) ||
  896. (HOffset != LineData [Y + Lines].BG[bg].HOffset))
  897. break;
  898. u32 MosaicLine = VOffset + Y - MosaicOffset;
  899. if (Y + Lines > GFX.EndY)
  900. Lines = GFX.EndY + 1 - Y;
  901. u32 VirtAlign = (MosaicLine & 7) << 3;
  902. u16 *b1;
  903. u16 *b2;
  904. u32 ScreenLine = MosaicLine >> OffsetShift;
  905. u32 Rem16 = MosaicLine & 15;
  906. if (ScreenLine & 0x20)
  907. b1 = SC2, b2 = SC3;
  908. else
  909. b1 = SC0, b2 = SC1;
  910. b1 += (ScreenLine & 0x1f) << 5;
  911. b2 += (ScreenLine & 0x1f) << 5;
  912. u16 *t;
  913. u32 Left = 0;
  914. u32 Right = 256;
  915. u32 ClipCount = GFX.pCurrentClip->Count [bg];
  916. u32 HPos = HOffset;
  917. u32 PixWidth = PPU.Mosaic;
  918. if (!ClipCount)
  919. ClipCount = 1;
  920. for (u32 clip = 0; clip < ClipCount; clip++)
  921. {
  922. if (GFX.pCurrentClip->Count [bg])
  923. {
  924. Left = GFX.pCurrentClip->Left [clip][bg];
  925. Right = GFX.pCurrentClip->Right [clip][bg];
  926. u32 r = Left % PPU.Mosaic;
  927. HPos = HOffset + Left;
  928. PixWidth = PPU.Mosaic - r;
  929. }
  930. u32 s = Y * GFX.PPL + Left * GFX.PixSize;
  931. for (u32 x = Left; x < Right; x += PixWidth,
  932. s += PixWidth * GFX.PixSize,
  933. HPos += PixWidth, PixWidth = PPU.Mosaic)
  934. {
  935. u32 Quot = (HPos & OffsetMask) >> 3;
  936. if (x + PixWidth >= Right)
  937. PixWidth = Right - x;
  938. if (BG.TileSize == 8)
  939. {
  940. if (Quot > 31)
  941. t = b2 + (Quot & 0x1f);
  942. else
  943. t = b1 + Quot;
  944. }
  945. else
  946. {
  947. if (Quot > 63)
  948. t = b2 + ((Quot >> 1) & 0x1f);
  949. else
  950. t = b1 + (Quot >> 1);
  951. }
  952. Tile = READ_2BYTES (t);
  953. GFX.Z1 = GFX.Z2 = depths [(Tile & 0x2000) >> 13];
  954. // Draw tile...
  955. if (BG.TileSize != 8)
  956. {
  957. if (Tile & H_FLIP)
  958. {
  959. // Horizontal flip, but what about vertical flip ?
  960. if (Tile & V_FLIP)
  961. {
  962. // Both horzontal & vertical flip
  963. if (Rem16 < 8)
  964. {
  965. (*DrawLargePixelPtr) (Tile + 17 - (Quot & 1), s,
  966. HPos & 7, PixWidth,
  967. VirtAlign, Lines, &GFX);
  968. }
  969. else
  970. {
  971. (*DrawLargePixelPtr) (Tile + 1 - (Quot & 1), s,
  972. HPos & 7, PixWidth,
  973. VirtAlign, Lines, &GFX);
  974. }
  975. }
  976. else
  977. {
  978. // Horizontal flip only
  979. if (Rem16 > 7)
  980. {
  981. (*DrawLargePixelPtr) (Tile + 17 - (Quot & 1), s,
  982. HPos & 7, PixWidth,
  983. VirtAlign, Lines, &GFX);
  984. }
  985. else
  986. {
  987. (*DrawLargePixelPtr) (Tile + 1 - (Quot & 1), s,
  988. HPos & 7, PixWidth,
  989. VirtAlign, Lines, &GFX);
  990. }
  991. }
  992. }
  993. else
  994. {
  995. // No horizontal flip, but is there a vertical flip ?
  996. if (Tile & V_FLIP)
  997. {
  998. // Vertical flip only
  999. if (Rem16 < 8)
  1000. {
  1001. (*DrawLargePixelPtr) (Tile + 16 + (Quot & 1), s,
  1002. HPos & 7, PixWidth,
  1003. VirtAlign, Lines, &GFX);
  1004. }
  1005. else
  1006. {
  1007. (*DrawLargePixelPtr) (Tile + (Quot & 1), s,
  1008. HPos & 7, PixWidth,
  1009. VirtAlign, Lines, &GFX);
  1010. }
  1011. }
  1012. else
  1013. {
  1014. // Normal unflipped
  1015. if (Rem16 > 7)
  1016. {
  1017. (*DrawLargePixelPtr) (Tile + 16 + (Quot & 1), s,
  1018. HPos & 7, PixWidth,
  1019. VirtAlign, Lines, &GFX);
  1020. }
  1021. else
  1022. {
  1023. (*DrawLargePixelPtr) (Tile + (Quot & 1), s,
  1024. HPos & 7, PixWidth,
  1025. VirtAlign, Lines, &GFX);
  1026. }
  1027. }
  1028. }
  1029. }
  1030. else
  1031. (*DrawLargePixelPtr) (Tile, s, HPos & 7, PixWidth,
  1032. VirtAlign, Lines, &GFX);
  1033. }
  1034. }
  1035. }
  1036. }
  1037. void DrawBackgroundOffset (u32 BGMode, u32 bg, u8 Z1, u8 Z2)
  1038. {
  1039. CHECK_SOUND();
  1040. u32 Tile;
  1041. u16 *SC0;
  1042. u16 *SC1;
  1043. u16 *SC2;
  1044. u16 *SC3;
  1045. u16 *BPS0;
  1046. u16 *BPS1;
  1047. u16 *BPS2;
  1048. u16 *BPS3;
  1049. u32 Width;
  1050. int VOffsetOffset = BGMode == 4 ? 0 : 32;
  1051. u8 depths [2] = {Z1, Z2};
  1052. BG.StartPalette = 0;
  1053. BPS0 = (u16 *) &Memory.VRAM[PPU.BG[2].SCBase << 1];
  1054. if (PPU.BG[2].SCSize & 1)
  1055. BPS1 = BPS0 + 1024;
  1056. else
  1057. BPS1 = BPS0;
  1058. if (PPU.BG[2].SCSize & 2)
  1059. BPS2 = BPS1 + 1024;
  1060. else
  1061. BPS2 = BPS0;
  1062. if (PPU.BG[2].SCSize & 1)
  1063. BPS3 = BPS2 + 1024;
  1064. else
  1065. BPS3 = BPS2;
  1066. SC0 = (u16 *) &Memory.VRAM[PPU.BG[bg].SCBase << 1];
  1067. if (PPU.BG[bg].SCSize & 1)
  1068. SC1 = SC0 + 1024;
  1069. else
  1070. SC1 = SC0;
  1071. if (PPU.BG[bg].SCSize & 2)
  1072. SC2 = SC1 + 1024;
  1073. else
  1074. SC2 = SC0;
  1075. if (PPU.BG[bg].SCSize & 1)
  1076. SC3 = SC2 + 1024;
  1077. else
  1078. SC3 = SC2;
  1079. static const int Lines = 1;
  1080. int OffsetMask;
  1081. int OffsetShift;
  1082. int OffsetEnableMask = 1 << (bg + 13);
  1083. if (BG.TileSize == 16)
  1084. {
  1085. OffsetMask = 0x3ff;
  1086. OffsetShift = 4;
  1087. }
  1088. else
  1089. {
  1090. OffsetMask = 0x1ff;
  1091. OffsetShift = 3;
  1092. }
  1093. for (u32 Y = GFX.StartY; Y <= GFX.EndY; Y++)
  1094. {
  1095. u32 VOff = LineData [Y].BG[2].VOffset;
  1096. u32 HOff = LineData [Y].BG[2].HOffset;
  1097. int VirtAlign;
  1098. int ScreenLine = VOff >> 3;
  1099. int t1;
  1100. int t2;
  1101. u16 *s0;
  1102. u16 *s1;
  1103. u16 *s2;
  1104. if (ScreenLine & 0x20)
  1105. s1 = BPS2, s2 = BPS3;
  1106. else
  1107. s1 = BPS0, s2 = BPS1;
  1108. s1 += (ScreenLine & 0x1f) << 5;
  1109. s2 += (ScreenLine & 0x1f) << 5;
  1110. int clipcount = GFX.pCurrentClip->Count [bg];
  1111. if (!clipcount)
  1112. clipcount = 1;
  1113. for (int clip = 0; clip < clipcount; clip++)
  1114. {
  1115. u32 Left;
  1116. u32 Right;
  1117. if (!GFX.pCurrentClip->Count [bg])
  1118. {
  1119. Left = 0;
  1120. Right = 256;
  1121. }
  1122. else
  1123. {
  1124. Left = GFX.pCurrentClip->Left [clip][bg];
  1125. Right = GFX.pCurrentClip->Right [clip][bg];
  1126. if (Right <= Left)
  1127. continue;
  1128. }
  1129. u32 VOffset;
  1130. u32 HOffset;
  1131. u32 LineHOffset=LineData [Y].BG[bg].HOffset;
  1132. u32 Offset;
  1133. u32 HPos;
  1134. u32 Quot;
  1135. u32 Count;
  1136. u16 *t;
  1137. u32 Quot2;
  1138. u32 VCellOffset;
  1139. u32 HCellOffset;
  1140. u16 *b1;
  1141. u16 *b2;
  1142. u32 TotalCount = 0;
  1143. u32 MaxCount = 8;
  1144. u32 s = Left * GFX.PixSize + Y * GFX.PPL;
  1145. bool8_32 left_hand_edge = (Left == 0);
  1146. Width = Right - Left;
  1147. if (Left & 7)
  1148. MaxCount = 8 - (Left & 7);
  1149. while (Left < Right)
  1150. {
  1151. if (left_hand_edge)
  1152. {
  1153. // The SNES offset-per-tile background mode has a
  1154. // hardware limitation that the offsets cannot be set
  1155. // for the tile at the left-hand edge of the screen.
  1156. VOffset = LineData [Y].BG[bg].VOffset;
  1157. HOffset = LineHOffset;
  1158. left_hand_edge = FALSE;
  1159. }
  1160. else
  1161. {
  1162. // All subsequent offset tile data is shifted left by one,
  1163. // hence the - 1 below.
  1164. Quot2 = ((HOff + Left - 1) & OffsetMask) >> 3;
  1165. if (Quot2 > 31)
  1166. s0 = s2 + (Quot2 & 0x1f);
  1167. else
  1168. s0 = s1 + Quot2;
  1169. HCellOffset = READ_2BYTES (s0);
  1170. if (BGMode == 4)
  1171. {
  1172. VOffset = LineData [Y].BG[bg].VOffset;
  1173. HOffset=LineHOffset;
  1174. if ((HCellOffset & OffsetEnableMask))
  1175. {
  1176. if (HCellOffset & 0x8000)
  1177. VOffset = HCellOffset + 1;
  1178. else
  1179. HOffset = HCellOffset;
  1180. }
  1181. }
  1182. else
  1183. {
  1184. VCellOffset = READ_2BYTES (s0 + VOffsetOffset);
  1185. if ((VCellOffset & OffsetEnableMask))
  1186. VOffset = VCellOffset + 1;
  1187. else
  1188. VOffset = LineData [Y].BG[bg].VOffset;
  1189. if ((HCellOffset & OffsetEnableMask))
  1190. HOffset = (HCellOffset & ~7)|(LineHOffset&7);
  1191. else
  1192. HOffset=LineHOffset;
  1193. }
  1194. }
  1195. VirtAlign = ((Y + VOffset) & 7) << 3;
  1196. ScreenLine = (VOffset + Y) >> OffsetShift;
  1197. if (((VOffset + Y) & 15) > 7)
  1198. {
  1199. t1 = 16;
  1200. t2 = 0;
  1201. }
  1202. else
  1203. {
  1204. t1 = 0;
  1205. t2 = 16;
  1206. }
  1207. if (ScreenLine & 0x20)
  1208. b1 = SC2, b2 = SC3;
  1209. else
  1210. b1 = SC0, b2 = SC1;
  1211. b1 += (ScreenLine & 0x1f) << 5;
  1212. b2 += (ScreenLine & 0x1f) << 5;
  1213. HPos = (HOffset + Left) & OffsetMask;
  1214. Quot = HPos >> 3;
  1215. if (BG.TileSize == 8)
  1216. {
  1217. if (Quot > 31)
  1218. t = b2 + (Quot & 0x1f);
  1219. else
  1220. t = b1 + Quot;
  1221. }
  1222. else
  1223. {
  1224. if (Quot > 63)
  1225. t = b2 + ((Quot >> 1) & 0x1f);
  1226. else
  1227. t = b1 + (Quot >> 1);
  1228. }
  1229. if (MaxCount + TotalCount > Width)
  1230. MaxCount = Width - TotalCount;
  1231. Offset = HPos & 7;
  1232. Count = 8 - Offset;
  1233. if (Count > MaxCount)
  1234. Count = MaxCount;
  1235. s -= Offset * GFX.PixSize;
  1236. Tile = READ_2BYTES(t);
  1237. GFX.Z1 = GFX.Z2 = depths [(Tile & 0x2000) >> 13];
  1238. if (BG.TileSize == 8)
  1239. (*DrawClippedTilePtr) (Tile, s, Offset, Count, VirtAlign, Lines, &GFX);
  1240. else
  1241. {
  1242. if (!(Tile & (V_FLIP | H_FLIP)))
  1243. {
  1244. // Normal, unflipped
  1245. (*DrawClippedTilePtr) (Tile + t1 + (Quot & 1),
  1246. s, Offset, Count, VirtAlign, Lines, &GFX);
  1247. }
  1248. else
  1249. if (Tile & H_FLIP)
  1250. {
  1251. if (Tile & V_FLIP)
  1252. {
  1253. // H & V flip
  1254. (*DrawClippedTilePtr) (Tile + t2 + 1 - (Quot & 1),
  1255. s, Offset, Count, VirtAlign, Lines, &GFX);
  1256. }
  1257. else
  1258. {
  1259. // H flip only
  1260. (*DrawClippedTilePtr) (Tile + t1 + 1 - (Quot & 1),
  1261. s, Offset, Count, VirtAlign, Lines, &GFX);
  1262. }
  1263. }
  1264. else
  1265. {
  1266. // V flip only
  1267. (*DrawClippedTilePtr) (Tile + t2 + (Quot & 1),
  1268. s, Offset, Count, VirtAlign, Lines, &GFX);
  1269. }
  1270. }
  1271. Left += Count;
  1272. TotalCount += Count;
  1273. s += (Offset + Count) * GFX.PixSize;
  1274. MaxCount = 8;
  1275. }
  1276. }
  1277. }
  1278. }
  1279. void DrawBackgroundMode5 (u32 /* BGMODE */, u32 bg, u8 Z1, u8 Z2)
  1280. {
  1281. CHECK_SOUND();
  1282. GFX.Pitch = GFX.RealPitch;
  1283. GFX.PPL = GFX.PPLx2 >> 1;
  1284. GFX.PixSize = 1;
  1285. u8 depths [2] = {Z1, Z2};
  1286. u32 Tile;
  1287. u16 *SC0;
  1288. u16 *SC1;
  1289. u16 *SC2;
  1290. u16 *SC3;
  1291. u32 Width;
  1292. BG.StartPalette = 0;
  1293. SC0 = (u16 *) &Memory.VRAM[PPU.BG[bg].SCBase << 1];
  1294. if ((PPU.BG[bg].SCSize & 1))
  1295. SC1 = SC0 + 1024;
  1296. else
  1297. SC1 = SC0;
  1298. if ((PPU.BG[bg].SCSize & 2))
  1299. SC2 = SC1 + 1024;
  1300. else
  1301. SC2 = SC0;
  1302. if ((PPU.BG[bg].SCSize & 1))
  1303. SC3 = SC2 + 1024;
  1304. else
  1305. SC3 = SC2;
  1306. int Lines;
  1307. int VOffsetMask;
  1308. int VOffsetShift;
  1309. if (BG.TileSize == 16)
  1310. {
  1311. VOffsetMask = 0x3ff;
  1312. VOffsetShift = 4;
  1313. }
  1314. else
  1315. {
  1316. VOffsetMask = 0x1ff;
  1317. VOffsetShift = 3;
  1318. }
  1319. // int endy = IPPU.LatchedInterlace ? GFX.EndY << 1 : GFX.EndY;
  1320. int endy = GFX.EndY;
  1321. // for (int Y = IPPU.LatchedInterlace ? GFX.StartY << 1 : GFX.StartY; Y <= endy; Y += Lines)
  1322. for (int Y = GFX.StartY; Y <= endy; Y += Lines)
  1323. {
  1324. // int y = IPPU.LatchedInterlace ? (Y >> 1) : Y;
  1325. int y = Y;
  1326. u32 VOffset = LineData [y].BG[bg].VOffset;
  1327. u32 HOffset = LineData [y].BG[bg].HOffset;
  1328. int VirtAlign = (Y + VOffset) & 7;
  1329. for (Lines = 1; Lines < 8 - VirtAlign; Lines++)
  1330. if ((VOffset != LineData [y + Lines].BG[bg].VOffset) ||
  1331. (HOffset != LineData [y + Lines].BG[bg].HOffset))
  1332. break;
  1333. HOffset <<= 1;
  1334. if (Y + Lines > endy)
  1335. Lines = endy + 1 - Y;
  1336. // VirtAlign <<= 3;
  1337. int ScreenLine = (VOffset + Y) >> VOffsetShift;
  1338. int t1;
  1339. int t2;
  1340. if (((VOffset + Y) & 15) > 7)
  1341. {
  1342. t1 = 16;
  1343. t2 = 0;
  1344. }
  1345. else
  1346. {
  1347. t1 = 0;
  1348. t2 = 16;
  1349. }
  1350. u16 *b1;
  1351. u16 *b2;
  1352. if (ScreenLine & 0x20)
  1353. b1 = SC2, b2 = SC3;
  1354. else
  1355. b1 = SC0, b2 = SC1;
  1356. b1 += (ScreenLine & 0x1f) << 5;
  1357. b2 += (ScreenLine & 0x1f) << 5;
  1358. int clipcount = GFX.pCurrentClip->Count [bg];
  1359. if (!clipcount)
  1360. clipcount = 1;
  1361. for (int clip = 0; clip < clipcount; clip++)
  1362. {
  1363. int Left;
  1364. int Right;
  1365. if (!GFX.pCurrentClip->Count [bg])
  1366. {
  1367. Left = 0;
  1368. Right = 512;
  1369. }
  1370. else
  1371. {
  1372. Left = GFX.pCurrentClip->Left [clip][bg] * 2;
  1373. Right = GFX.pCurrentClip->Right [clip][bg] * 2;
  1374. if (Right <= Left)
  1375. continue;
  1376. }
  1377. u32 s = (Left>>1) * GFX.PixSize + Y * GFX.PPL;
  1378. u32 HPos = (HOffset + Left * GFX.PixSize) & 0x3ff;
  1379. u32 Quot = HPos >> 3;
  1380. u32 Count = 0;
  1381. u16 *t;
  1382. if (Quot > 63)
  1383. t = b2 + ((Quot >> 1) & 0x1f);
  1384. else
  1385. t = b1 + (Quot >> 1);
  1386. Width = Right - Left;
  1387. // Left hand edge clipped tile
  1388. if (HPos & 7)
  1389. {
  1390. int Offset = (HPos & 7);
  1391. Count = 8 - Offset;
  1392. if (Count > Width)
  1393. Count = Width;
  1394. s -= (Offset>>1);
  1395. Tile = READ_2BYTES (t);
  1396. GFX.Z1 = GFX.Z2 = depths [(Tile & 0x2000) >> 13];
  1397. if (BG.TileSize == 8)
  1398. {
  1399. if (!(Tile & H_FLIP))
  1400. {
  1401. // Normal, unflipped
  1402. (*DrawHiResClippedTilePtr) (Tile + (Quot & 1),
  1403. s, Offset, Count, VirtAlign, Lines, &GFX);
  1404. }
  1405. else
  1406. {
  1407. // H flip
  1408. (*DrawHiResClippedTilePtr) (Tile + 1 - (Quot & 1),
  1409. s, Offset, Count, VirtAlign, Lines, &GFX);
  1410. }
  1411. }
  1412. else
  1413. {
  1414. if (!(Tile & (V_FLIP | H_FLIP)))
  1415. {
  1416. // Normal, unflipped
  1417. (*DrawHiResClippedTilePtr) (Tile + t1 + (Quot & 1),
  1418. s, Offset, Count, VirtAlign, Lines, &GFX);
  1419. }
  1420. else
  1421. if (Tile & H_FLIP)
  1422. {
  1423. if (Tile & V_FLIP)
  1424. {
  1425. // H & V flip
  1426. (*DrawHiResClippedTilePtr) (Tile + t2 + 1 - (Quot & 1),
  1427. s, Offset, Count, VirtAlign, Lines, &GFX);
  1428. }
  1429. else
  1430. {
  1431. // H flip only
  1432. (*DrawHiResClippedTilePtr) (Tile + t1 + 1 - (Quot & 1),
  1433. s, Offset, Count, VirtAlign, Lines, &GFX);
  1434. }
  1435. }
  1436. else
  1437. {
  1438. // V flip only
  1439. (*DrawHiResClippedTilePtr) (Tile + t2 + (Quot & 1),
  1440. s, Offset, Count, VirtAlign, Lines, &GFX);
  1441. }
  1442. }
  1443. t += Quot & 1;
  1444. if (Quot == 63)
  1445. t = b2;
  1446. else if (Quot == 127)
  1447. t = b1;
  1448. Quot++;
  1449. s += 4;
  1450. }
  1451. // Middle, unclipped tiles
  1452. Count = Width - Count;
  1453. int Middle = Count >> 3;
  1454. Count &= 7;
  1455. for (int C = Middle; C > 0; s += 4, Quot++, C--)
  1456. {
  1457. Tile = READ_2BYTES(t);
  1458. GFX.Z1 = GFX.Z2 = depths [(Tile & 0x2000) >> 13];
  1459. if (BG.TileSize == 8)
  1460. {
  1461. if (!(Tile & H_FLIP))
  1462. {
  1463. // Normal, unflipped
  1464. (*DrawHiResTilePtr) (Tile + (Quot & 1),
  1465. s, VirtAlign, Lines, &GFX);
  1466. }
  1467. else
  1468. {
  1469. // H flip
  1470. (*DrawHiResTilePtr) (Tile + 1 - (Quot & 1),
  1471. s, VirtAlign, Lines, &GFX);
  1472. }
  1473. }
  1474. else
  1475. {
  1476. if (!(Tile & (V_FLIP | H_FLIP)))
  1477. {
  1478. // Normal, unflipped
  1479. (*DrawHiResTilePtr) (Tile + t1 + (Quot & 1),
  1480. s, VirtAlign, Lines, &GFX);
  1481. }
  1482. else
  1483. if (Tile & H_FLIP)
  1484. {
  1485. if (Tile & V_FLIP)
  1486. {
  1487. // H & V flip
  1488. (*DrawHiResTilePtr) (Tile + t2 + 1 - (Quot & 1),
  1489. s, VirtAlign, Lines, &GFX);
  1490. }
  1491. else
  1492. {
  1493. // H flip only
  1494. (*DrawHiResTilePtr) (Tile + t1 + 1 - (Quot & 1),
  1495. s, VirtAlign, Lines, &GFX);
  1496. }
  1497. }
  1498. else
  1499. {
  1500. // V flip only
  1501. (*DrawHiResTilePtr) (Tile + t2 + (Quot & 1),
  1502. s, VirtAlign, Lines, &GFX);
  1503. }
  1504. }
  1505. t += Quot & 1;
  1506. if (Quot == 63)
  1507. t = b2;
  1508. else
  1509. if (Quot == 127)
  1510. t = b1;
  1511. }
  1512. // Right-hand edge clipped tiles
  1513. if (Count)
  1514. {
  1515. Tile = READ_2BYTES(t);
  1516. GFX.Z1 = GFX.Z2 = depths [(Tile & 0x2000) >> 13];
  1517. if (BG.TileSize == 8)
  1518. {
  1519. if (!(Tile & H_FLIP))
  1520. {
  1521. // Normal, unflipped
  1522. (*DrawHiResClippedTilePtr) (Tile + (Quot & 1),
  1523. s, 0, Count, VirtAlign, Lines, &GFX);
  1524. }
  1525. else
  1526. {
  1527. // H flip
  1528. (*DrawHiResClippedTilePtr) (Tile + 1 - (Quot & 1),
  1529. s, 0, Count, VirtAlign, Lines, &GFX);
  1530. }
  1531. }
  1532. else
  1533. {
  1534. if (!(Tile & (V_FLIP | H_FLIP)))
  1535. {
  1536. // Normal, unflipped
  1537. (*DrawHiResClippedTilePtr) (Tile + t1 + (Quot & 1),
  1538. s, 0, Count, VirtAlign, Lines, &GFX);
  1539. }
  1540. else
  1541. if (Tile & H_FLIP)
  1542. {
  1543. if (Tile & V_FLIP)
  1544. {
  1545. // H & V flip
  1546. (*DrawHiResClippedTilePtr) (Tile + t2 + 1 - (Quot & 1),
  1547. s, 0, Count, VirtAlign, Lines, &GFX);
  1548. }
  1549. else
  1550. {
  1551. // H flip only
  1552. (*DrawHiResClippedTilePtr) (Tile + t1 + 1 - (Quot & 1),
  1553. s, 0, Count, VirtAlign, Lines, &GFX);
  1554. }
  1555. }
  1556. else
  1557. {
  1558. // V flip only
  1559. (*DrawHiResClippedTilePtr) (Tile + t2 + (Quot & 1),
  1560. s, 0, Count, VirtAlign, Lines, &GFX);
  1561. }
  1562. }
  1563. }
  1564. }
  1565. }
  1566. }
  1567. void DrawBackground (u32 BGMode, u32 bg, u8 Z1, u8 Z2)
  1568. {
  1569. GFX.PixSize = 1;
  1570. BG.TileSize = BGSizes [PPU.BG[bg].BGSize];
  1571. BG.BitShift = BitShifts[BGMode][bg];
  1572. BG.TileShift = TileShifts[BGMode][bg];
  1573. BG.TileAddress = PPU.BG[bg].NameBase << 1;
  1574. BG.NameSelect = 0;
  1575. BG.Buffer = IPPU.TileCache [Depths [BGMode][bg]];
  1576. BG.Buffered = IPPU.TileCached [Depths [BGMode][bg]];
  1577. BG.PaletteShift = PaletteShifts[BGMode][bg];
  1578. BG.PaletteMask = PaletteMasks[BGMode][bg];
  1579. BG.DirectColourMode = (BGMode == 3 || BGMode == 4) && bg == 0 &&
  1580. (GFX.r2130 & 1);
  1581. if (PPU.BGMosaic [bg] && PPU.Mosaic > 1)
  1582. {
  1583. DrawBackgroundMosaic (BGMode, bg, Z1, Z2);
  1584. return;
  1585. }
  1586. switch (BGMode)
  1587. {
  1588. case 2:
  1589. if (Settings.WrestlemaniaArcade)
  1590. break;
  1591. case 4: // Used by Puzzle Bobble
  1592. DrawBackgroundOffset (BGMode, bg, Z1, Z2);
  1593. return;
  1594. case 5:
  1595. case 6: // XXX: is also offset per tile.
  1596. DrawBackgroundMode5 (BGMode, bg, Z1, Z2);
  1597. return;
  1598. }
  1599. CHECK_SOUND();
  1600. u32 Tile;
  1601. u16 *SC0;
  1602. u16 *SC1;
  1603. u16 *SC2;
  1604. u16 *SC3;
  1605. u32 Width;
  1606. u8 depths [2] = {Z1, Z2};
  1607. if (BGMode == 0)
  1608. BG.StartPalette = bg << 5;
  1609. else
  1610. BG.StartPalette = 0;
  1611. SC0 = (u16 *) &Memory.VRAM[PPU.BG[bg].SCBase << 1];
  1612. if (PPU.BG[bg].SCSize & 1)
  1613. SC1 = SC0 + 1024;
  1614. else
  1615. SC1 = SC0;
  1616. if (PPU.BG[bg].SCSize & 2)
  1617. SC2 = SC1 + 1024;
  1618. else
  1619. SC2 = SC0;
  1620. if (PPU.BG[bg].SCSize & 1)
  1621. SC3 = SC2 + 1024;
  1622. else
  1623. SC3 = SC2;
  1624. int Lines;
  1625. int OffsetMask;
  1626. int OffsetShift;
  1627. if (BG.TileSize == 16)
  1628. {
  1629. OffsetMask = 0x3ff;
  1630. OffsetShift = 4;
  1631. }
  1632. else
  1633. {
  1634. OffsetMask = 0x1ff;
  1635. OffsetShift = 3;
  1636. }
  1637. // outermost loop
  1638. for (u32 Y = GFX.StartY; Y <= GFX.EndY; Y += Lines)
  1639. {
  1640. u32 VOffset = LineData [Y].BG[bg].VOffset;
  1641. u32 HOffset = LineData [Y].BG[bg].HOffset;
  1642. int VirtAlign = (Y + VOffset) & 7;
  1643. for (Lines = 1; Lines < 8 - VirtAlign; Lines++)
  1644. if ((VOffset != LineData [Y + Lines].BG[bg].VOffset) ||
  1645. (HOffset != LineData [Y + Lines].BG[bg].HOffset))
  1646. break;
  1647. if (Y + Lines > GFX.EndY)
  1648. Lines = GFX.EndY + 1 - Y;
  1649. VirtAlign <<= 3;
  1650. u32 ScreenLine = (VOffset + Y) >> OffsetShift;
  1651. u32 t1;
  1652. u32 t2;
  1653. if (((VOffset + Y) & 15) > 7)
  1654. {
  1655. t1 = 16;
  1656. t2 = 0;
  1657. }
  1658. else
  1659. {
  1660. t1 = 0;
  1661. t2 = 16;
  1662. }
  1663. u16 *b1;
  1664. u16 *b2;
  1665. if (ScreenLine & 0x20)
  1666. b1 = SC2, b2 = SC3;
  1667. else
  1668. b1 = SC0, b2 = SC1;
  1669. b1 += (ScreenLine & 0x1f) << 5;
  1670. b2 += (ScreenLine & 0x1f) << 5;
  1671. int clipcount = GFX.pCurrentClip->Count [bg];
  1672. if (!clipcount)
  1673. clipcount = 1;
  1674. for (int clip = 0; clip < clipcount; clip++)
  1675. {
  1676. u32 Left;
  1677. u32 Right;
  1678. if (!GFX.pCurrentClip->Count [bg])
  1679. {
  1680. Left = 0;
  1681. Right = 256;
  1682. }
  1683. else
  1684. {
  1685. Left = GFX.pCurrentClip->Left [clip][bg];
  1686. Right = GFX.pCurrentClip->Right [clip][bg];
  1687. if (Right <= Left)
  1688. continue;
  1689. }
  1690. u32 s = Left * GFX.PixSize + Y * GFX.PPL;
  1691. u32 HPos = (HOffset + Left) & OffsetMask;
  1692. u32 Quot = HPos >> 3;
  1693. u32 Count = 0;
  1694. u16 *t;
  1695. if (BG.TileSize == 8)
  1696. {
  1697. if (Quot > 31)
  1698. t = b2 + (Quot & 0x1f);
  1699. else
  1700. t = b1 + Quot;
  1701. }
  1702. else
  1703. {
  1704. if (Quot > 63)
  1705. t = b2 + ((Quot >> 1) & 0x1f);
  1706. else
  1707. t = b1 + (Quot >> 1);
  1708. }
  1709. Width = Right - Left;
  1710. // Left hand edge clipped tile
  1711. if (HPos & 7)
  1712. {
  1713. u32 Offset = (HPos & 7);
  1714. Count = 8 - Offset;
  1715. if (Count > Width)
  1716. Count = Width;
  1717. s -= Offset * GFX.PixSize;
  1718. Tile = READ_2BYTES(t);
  1719. GFX.Z1 = GFX.Z2 = depths [(Tile & 0x2000) >> 13];
  1720. if (BG.TileSize == 8)
  1721. {
  1722. (*DrawClippedTilePtr) (Tile, s, Offset, Count, VirtAlign,
  1723. Lines, &GFX);
  1724. }
  1725. else
  1726. {
  1727. if (!(Tile & (V_FLIP | H_FLIP)))
  1728. {
  1729. // Normal, unflipped
  1730. (*DrawClippedTilePtr) (Tile + t1 + (Quot & 1),
  1731. s, Offset, Count, VirtAlign, Lines, &GFX);
  1732. }
  1733. else
  1734. if (Tile & H_FLIP)
  1735. {
  1736. if (Tile & V_FLIP)
  1737. {
  1738. // H & V flip
  1739. (*DrawClippedTilePtr) (Tile + t2 + 1 - (Quot & 1),
  1740. s, Offset, Count, VirtAlign, Lines, &GFX);
  1741. }
  1742. else
  1743. {
  1744. // H flip only
  1745. (*DrawClippedTilePtr) (Tile + t1 + 1 - (Quot & 1),
  1746. s, Offset, Count, VirtAlign, Lines, &GFX);
  1747. }
  1748. }
  1749. else
  1750. {
  1751. // V flip only
  1752. (*DrawClippedTilePtr) (Tile + t2 + (Quot & 1), s,
  1753. Offset, Count, VirtAlign, Lines, &GFX);
  1754. }
  1755. }
  1756. if (BG.TileSize == 8)
  1757. {
  1758. t++;
  1759. if (Quot == 31)
  1760. t = b2;
  1761. else if (Quot == 63)
  1762. t = b1;
  1763. }
  1764. else
  1765. {
  1766. t += Quot & 1;
  1767. if (Quot == 63)
  1768. t = b2;
  1769. else if (Quot == 127)
  1770. t = b1;
  1771. }
  1772. Quot++;
  1773. s += 8 * GFX.PixSize;
  1774. }
  1775. // Middle, unclipped tiles
  1776. Count = Width - Count;
  1777. int Middle = Count >> 3;
  1778. Count &= 7;
  1779. for (int C = Middle; C > 0; s += 8 * GFX.PixSize, Quot++, C--)
  1780. {
  1781. Tile = READ_2BYTES(t);
  1782. GFX.Z1 = GFX.Z2 = depths [(Tile & 0x2000) >> 13];
  1783. if (BG.TileSize != 8)
  1784. {
  1785. if (Tile & H_FLIP)
  1786. {
  1787. // Horizontal flip, but what about vertical flip ?
  1788. if (Tile & V_FLIP)
  1789. {
  1790. // Both horzontal & vertical flip
  1791. (*DrawTilePtr) (Tile + t2 + 1 - (Quot & 1), s,
  1792. VirtAlign, Lines, &GFX);
  1793. }
  1794. else
  1795. {
  1796. // Horizontal flip only
  1797. (*DrawTilePtr) (Tile + t1 + 1 - (Quot & 1), s,
  1798. VirtAlign, Lines, &GFX);
  1799. }
  1800. }
  1801. else
  1802. {
  1803. // No horizontal flip, but is there a vertical flip ?
  1804. if (Tile & V_FLIP)
  1805. {
  1806. // Vertical flip only
  1807. (*DrawTilePtr) (Tile + t2 + (Quot & 1), s,
  1808. VirtAlign, Lines, &GFX);
  1809. }
  1810. else
  1811. {
  1812. // Normal unflipped
  1813. (*DrawTilePtr) (Tile + t1 + (Quot & 1), s,
  1814. VirtAlign, Lines, &GFX);
  1815. }
  1816. }
  1817. }
  1818. else
  1819. {
  1820. (*DrawTilePtr) (Tile, s, VirtAlign, Lines, &GFX);
  1821. }
  1822. if (BG.TileSize == 8)
  1823. {
  1824. t++;
  1825. if (Quot == 31)
  1826. t = b2;
  1827. else
  1828. if (Quot == 63)
  1829. t = b1;
  1830. }
  1831. else
  1832. {
  1833. t += Quot & 1;
  1834. if (Quot == 63)
  1835. t = b2;
  1836. else
  1837. if (Quot == 127)
  1838. t = b1;
  1839. }
  1840. }
  1841. // Right-hand edge clipped tiles
  1842. if (Count)
  1843. {
  1844. Tile = READ_2BYTES(t);
  1845. GFX.Z1 = GFX.Z2 = depths [(Tile & 0x2000) >> 13];
  1846. if (BG.TileSize == 8)
  1847. (*DrawClippedTilePtr) (Tile, s, 0, Count, VirtAlign,
  1848. Lines, &GFX);
  1849. else
  1850. {
  1851. if (!(Tile & (V_FLIP | H_FLIP)))
  1852. {
  1853. // Normal, unflipped
  1854. (*DrawClippedTilePtr) (Tile + t1 + (Quot & 1), s, 0,
  1855. Count, VirtAlign, Lines, &GFX);
  1856. }
  1857. else
  1858. if (Tile & H_FLIP)
  1859. {
  1860. if (Tile & V_FLIP)
  1861. {
  1862. // H & V flip
  1863. (*DrawClippedTilePtr) (Tile + t2 + 1 - (Quot & 1),
  1864. s, 0, Count, VirtAlign,
  1865. Lines, &GFX);
  1866. }
  1867. else
  1868. {
  1869. // H flip only
  1870. (*DrawClippedTilePtr) (Tile + t1 + 1 - (Quot & 1),
  1871. s, 0, Count, VirtAlign,
  1872. Lines, &GFX);
  1873. }
  1874. }
  1875. else
  1876. {
  1877. // V flip only
  1878. (*DrawClippedTilePtr) (Tile + t2 + (Quot & 1),
  1879. s, 0, Count, VirtAlign,
  1880. Lines, &GFX);
  1881. }
  1882. }
  1883. }
  1884. }
  1885. }
  1886. }
  1887. #define RENDER_BACKGROUND_MODE7(TYPE,FUNC) \
  1888. CHECK_SOUND(); \
  1889. \
  1890. u8 *VRAM1 = Memory.VRAM + 1; \
  1891. if (GFX.r2130 & 1) \
  1892. { \
  1893. if (IPPU.DirectColourMapsNeedRebuild) \
  1894. S9xBuildDirectColourMaps (); \
  1895. GFX.ScreenColors = DirectColourMaps [0]; \
  1896. } \
  1897. else \
  1898. GFX.ScreenColors = IPPU.ScreenColors; \
  1899. \
  1900. int aa, cc; \
  1901. int dir; \
  1902. int startx, endx; \
  1903. u32 Left = 0; \
  1904. u32 Right = 256; \
  1905. u32 ClipCount = GFX.pCurrentClip->Count [bg]; \
  1906. \
  1907. if (!ClipCount) \
  1908. ClipCount = 1; \
  1909. \
  1910. Screen += GFX.StartY * GFX.Pitch; \
  1911. u8 *Depth = GFX.DB + GFX.StartY * GFX.PPL; \
  1912. struct SLineMatrixData *l = &LineMatrixData [GFX.StartY]; \
  1913. \
  1914. for (u32 Line = GFX.StartY; Line <= GFX.EndY; Line++, Screen += GFX.Pitch, Depth += GFX.PPL, l++) \
  1915. { \
  1916. int yy; \
  1917. \
  1918. s32 HOffset = ((s32) LineData [Line].BG[0].HOffset << M7) >> M7; \
  1919. s32 VOffset = ((s32) LineData [Line].BG[0].VOffset << M7) >> M7; \
  1920. \
  1921. s32 CentreX = ((s32) l->CentreX << M7) >> M7; \
  1922. s32 CentreY = ((s32) l->CentreY << M7) >> M7; \
  1923. \
  1924. if (PPU.Mode7VFlip) \
  1925. yy = 261 - (int) Line; \
  1926. else \
  1927. yy = Line; \
  1928. \
  1929. if (PPU.Mode7Repeat == 0) \
  1930. yy += (VOffset - CentreY) % 1023; \
  1931. else \
  1932. yy += VOffset - CentreY; \
  1933. int BB = l->MatrixB * yy + (CentreX << 8); \
  1934. int DD = l->MatrixD * yy + (CentreY << 8); \
  1935. \
  1936. for (u32 clip = 0; clip < ClipCount; clip++) \
  1937. { \
  1938. if (GFX.pCurrentClip->Count [bg]) \
  1939. { \
  1940. Left = GFX.pCurrentClip->Left [clip][bg]; \
  1941. Right = GFX.pCurrentClip->Right [clip][bg]; \
  1942. if (Right <= Left) \
  1943. continue; \
  1944. } \
  1945. TYPE *p = (TYPE *) Screen + Left; \
  1946. u8 *d = Depth + Left; \
  1947. \
  1948. if (PPU.Mode7HFlip) \
  1949. { \
  1950. startx = Right - 1; \
  1951. endx = Left - 1; \
  1952. dir = -1; \
  1953. aa = -l->MatrixA; \
  1954. cc = -l->MatrixC; \
  1955. } \
  1956. else \
  1957. { \
  1958. startx = Left; \
  1959. endx = Right; \
  1960. dir = 1; \
  1961. aa = l->MatrixA; \
  1962. cc = l->MatrixC; \
  1963. } \
  1964. int xx; \
  1965. if (PPU.Mode7Repeat == 0) \
  1966. xx = startx + (HOffset - CentreX) % 1023; \
  1967. else \
  1968. xx = startx + HOffset - CentreX; \
  1969. int AA = l->MatrixA * xx; \
  1970. int CC = l->MatrixC * xx; \
  1971. \
  1972. if (!PPU.Mode7Repeat) \
  1973. { \
  1974. for (int x = startx; x != endx; x += dir, AA += aa, CC += cc, p++, d++) \
  1975. { \
  1976. int X = ((AA + BB) >> 8) & 0x3ff; \
  1977. int Y = ((CC + DD) >> 8) & 0x3ff; \
  1978. u8 *TileData = VRAM1 + (Memory.VRAM[((Y & ~7) << 5) + ((X >> 2) & ~1)] << 7); \
  1979. u32 b = *(TileData + ((Y & 7) << 4) + ((X & 7) << 1)); \
  1980. GFX.Z1 = Mode7Depths [(b & GFX.Mode7PriorityMask) >> 7]; \
  1981. if (GFX.Z1 > *d && b) \
  1982. { \
  1983. *p = (FUNC); \
  1984. *d = GFX.Z1; \
  1985. } \
  1986. } \
  1987. } \
  1988. else \
  1989. { \
  1990. for (int x = startx; x != endx; x += dir, AA += aa, CC += cc, p++, d++) \
  1991. { \
  1992. int X = ((AA + BB) >> 8); \
  1993. int Y = ((CC + DD) >> 8); \
  1994. \
  1995. if (Settings.Dezaemon && PPU.Mode7Repeat == 2) \
  1996. { \
  1997. X &= 0x7ff; \
  1998. Y &= 0x7ff; \
  1999. } \
  2000. \
  2001. if (((X | Y) & ~0x3ff) == 0) \
  2002. { \
  2003. u8 *TileData = VRAM1 + (Memory.VRAM[((Y & ~7) << 5) + ((X >> 2) & ~1)] << 7); \
  2004. u32 b = *(TileData + ((Y & 7) << 4) + ((X & 7) << 1)); \
  2005. GFX.Z1 = Mode7Depths [(b & GFX.Mode7PriorityMask) >> 7]; \
  2006. if (GFX.Z1 > *d && b) \
  2007. { \
  2008. *p = (FUNC); \
  2009. *d = GFX.Z1; \
  2010. } \
  2011. } \
  2012. else \
  2013. { \
  2014. if (PPU.Mode7Repeat == 3) \
  2015. { \
  2016. X = (x + HOffset) & 7; \
  2017. Y = (yy + CentreY) & 7; \
  2018. u32 b = *(VRAM1 + ((Y & 7) << 4) + ((X & 7) << 1)); \
  2019. GFX.Z1 = Mode7Depths [(b & GFX.Mode7PriorityMask) >> 7]; \
  2020. if (GFX.Z1 > *d && b) \
  2021. { \
  2022. *p = (FUNC); \
  2023. *d = GFX.Z1; \
  2024. } \
  2025. } \
  2026. } \
  2027. } \
  2028. } \
  2029. } \
  2030. }
  2031. void DrawBGMode7Background (u8 *Screen, int bg)
  2032. {
  2033. RENDER_BACKGROUND_MODE7 (u8, (u8) (b & GFX.Mode7Mask))
  2034. }
  2035. void DrawBGMode7Background16 (u8 *Screen, int bg)
  2036. {
  2037. RENDER_BACKGROUND_MODE7 (u16, GFX.ScreenColors [b & GFX.Mode7Mask]);
  2038. }
  2039. void DrawBGMode7Background16Add (u8 *Screen, int bg)
  2040. {
  2041. RENDER_BACKGROUND_MODE7 (u16, *(d + GFX.DepthDelta) ?
  2042. (*(d + GFX.DepthDelta) != 1 ?
  2043. COLOR_ADD (GFX.ScreenColors [b & GFX.Mode7Mask],
  2044. p [GFX.Delta]) :
  2045. COLOR_ADD (GFX.ScreenColors [b & GFX.Mode7Mask],
  2046. GFX.FixedColour)) :
  2047. GFX.ScreenColors [b & GFX.Mode7Mask]);
  2048. }
  2049. void DrawBGMode7Background16Add1_2 (u8 *Screen, int bg)
  2050. {
  2051. RENDER_BACKGROUND_MODE7(u16, *(d + GFX.DepthDelta) ?
  2052. (*(d + GFX.DepthDelta) != 1 ?
  2053. COLOR_ADD1_2 (GFX.ScreenColors [b & GFX.Mode7Mask],
  2054. p [GFX.Delta]) :
  2055. COLOR_ADD (GFX.ScreenColors [b & GFX.Mode7Mask],
  2056. GFX.FixedColour)) :
  2057. GFX.ScreenColors [b & GFX.Mode7Mask]);
  2058. }
  2059. void DrawBGMode7Background16Sub (u8 *Screen, int bg)
  2060. {
  2061. RENDER_BACKGROUND_MODE7 (u16, *(d + GFX.DepthDelta) ?
  2062. (*(d + GFX.DepthDelta) != 1 ?
  2063. COLOR_SUB (GFX.ScreenColors [b & GFX.Mode7Mask],
  2064. p [GFX.Delta]) :
  2065. COLOR_SUB (GFX.ScreenColors [b & GFX.Mode7Mask],
  2066. GFX.FixedColour)) :
  2067. GFX.ScreenColors [b & GFX.Mode7Mask]);
  2068. }
  2069. void DrawBGMode7Background16Sub1_2 (u8 *Screen, int bg)
  2070. {
  2071. RENDER_BACKGROUND_MODE7 (u16, *(d + GFX.DepthDelta) ?
  2072. (*(d + GFX.DepthDelta) != 1 ?
  2073. COLOR_SUB1_2 (GFX.ScreenColors [b & GFX.Mode7Mask],
  2074. p [GFX.Delta]) :
  2075. COLOR_SUB (GFX.ScreenColors [b & GFX.Mode7Mask],
  2076. GFX.FixedColour)) :
  2077. GFX.ScreenColors [b & GFX.Mode7Mask]);
  2078. }
  2079. #define RENDER_BACKGROUND_MODE7_i(TYPE,FUNC,COLORFUNC) \
  2080. CHECK_SOUND(); \
  2081. \
  2082. u8 *VRAM1 = Memory.VRAM + 1; \
  2083. if (GFX.r2130 & 1) \
  2084. { \
  2085. if (IPPU.DirectColourMapsNeedRebuild) \
  2086. S9xBuildDirectColourMaps (); \
  2087. GFX.ScreenColors = DirectColourMaps [0]; \
  2088. } \
  2089. else \
  2090. GFX.ScreenColors = IPPU.ScreenColors; \
  2091. \
  2092. int aa, cc; \
  2093. int dir; \
  2094. int startx, endx; \
  2095. u32 Left = 0; \
  2096. u32 Right = 256; \
  2097. u32 ClipCount = GFX.pCurrentClip->Count [bg]; \
  2098. \
  2099. if (!ClipCount) \
  2100. ClipCount = 1; \
  2101. \
  2102. Screen += GFX.StartY * GFX.Pitch; \
  2103. u8 *Depth = GFX.DB + GFX.StartY * GFX.PPL; \
  2104. struct SLineMatrixData *l = &LineMatrixData [GFX.StartY]; \
  2105. bool8_32 allowSimpleCase = FALSE; \
  2106. if (!l->MatrixB && !l->MatrixC && (l->MatrixA == 0x0100) && (l->MatrixD == 0x0100) \
  2107. && !LineMatrixData[GFX.EndY].MatrixB && !LineMatrixData[GFX.EndY].MatrixC \
  2108. && (LineMatrixData[GFX.EndY].MatrixA == 0x0100) && (LineMatrixData[GFX.EndY].MatrixD == 0x0100) \
  2109. ) \
  2110. allowSimpleCase = TRUE; \
  2111. \
  2112. for (u32 Line = GFX.StartY; Line <= GFX.EndY; Line++, Screen += GFX.Pitch, Depth += GFX.PPL, l++) \
  2113. { \
  2114. int yy; \
  2115. \
  2116. int HOffset = ((int) LineData [Line].BG[0].HOffset << M7) >> M7; \
  2117. int VOffset = ((int) LineData [Line].BG[0].VOffset << M7) >> M7; \
  2118. \
  2119. int CentreX = ((int) l->CentreX << M7) >> M7; \
  2120. int CentreY = ((int) l->CentreY << M7) >> M7; \
  2121. \
  2122. if (PPU.Mode7VFlip) \
  2123. yy = 261 - (int) Line; \
  2124. else \
  2125. yy = Line; \
  2126. \
  2127. if (PPU.Mode7Repeat == 0) \
  2128. yy += (VOffset - CentreY) % 1023; \
  2129. else \
  2130. yy += VOffset - CentreY; \
  2131. bool8_32 simpleCase = FALSE; \
  2132. int BB; \
  2133. int DD; \
  2134. /* Make a special case for the identity matrix, since it's a common case and */ \
  2135. /* can be done much more quickly without special effects */ \
  2136. if (allowSimpleCase && !l->MatrixB && !l->MatrixC && (l->MatrixA == 0x0100) && (l->MatrixD == 0x0100)) \
  2137. { \
  2138. BB = CentreX << 8; \
  2139. DD = (yy + CentreY) << 8; \
  2140. simpleCase = TRUE; \
  2141. } \
  2142. else \
  2143. { \
  2144. BB = l->MatrixB * yy + (CentreX << 8); \
  2145. DD = l->MatrixD * yy + (CentreY << 8); \
  2146. } \
  2147. \
  2148. for (u32 clip = 0; clip < ClipCount; clip++) \
  2149. { \
  2150. if (GFX.pCurrentClip->Count [bg]) \
  2151. { \
  2152. Left = GFX.pCurrentClip->Left [clip][bg]; \
  2153. Right = GFX.pCurrentClip->Right [clip][bg]; \
  2154. if (Right <= Left) \
  2155. continue; \
  2156. } \
  2157. TYPE *p = (TYPE *) Screen + Left; \
  2158. u8 *d = Depth + Left; \
  2159. \
  2160. if (PPU.Mode7HFlip) \
  2161. { \
  2162. startx = Right - 1; \
  2163. endx = Left - 1; \
  2164. dir = -1; \
  2165. aa = -l->MatrixA; \
  2166. cc = -l->MatrixC; \
  2167. } \
  2168. else \
  2169. { \
  2170. startx = Left; \
  2171. endx = Right; \
  2172. dir = 1; \
  2173. aa = l->MatrixA; \
  2174. cc = l->MatrixC; \
  2175. } \
  2176. int xx; \
  2177. if (PPU.Mode7Repeat == 0) \
  2178. xx = startx + (HOffset - CentreX) % 1023; \
  2179. else \
  2180. xx = startx + HOffset - CentreX; \
  2181. int AA, CC = 0; \
  2182. if (simpleCase) \
  2183. { \
  2184. AA = xx << 8; \
  2185. } \
  2186. else \
  2187. { \
  2188. AA = l->MatrixA * xx; \
  2189. CC = l->MatrixC * xx; \
  2190. } \
  2191. if (simpleCase) \
  2192. { \
  2193. if (!PPU.Mode7Repeat) \
  2194. { \
  2195. int x = startx; \
  2196. do \
  2197. { \
  2198. int X = ((AA + BB) >> 8) & 0x3ff; \
  2199. int Y = (DD >> 8) & 0x3ff; \
  2200. u8 *TileData = VRAM1 + (Memory.VRAM[((Y & ~7) << 5) + ((X >> 2) & ~1)] << 7); \
  2201. u32 b = *(TileData + ((Y & 7) << 4) + ((X & 7) << 1)); \
  2202. GFX.Z1 = Mode7Depths [(b & GFX.Mode7PriorityMask) >> 7]; \
  2203. if (GFX.Z1 > *d && b) \
  2204. { \
  2205. TYPE theColor = COLORFUNC; \
  2206. *p = (FUNC) | ALPHA_BITS_MASK; \
  2207. *d = GFX.Z1; \
  2208. } \
  2209. AA += aa, p++, d++; \
  2210. x += dir; \
  2211. } while (x != endx); \
  2212. } \
  2213. else \
  2214. { \
  2215. int x = startx; \
  2216. do { \
  2217. int X = (AA + BB) >> 8; \
  2218. int Y = DD >> 8; \
  2219. \
  2220. if(Settings.Dezaemon && PPU.Mode7Repeat == 2) \
  2221. { \
  2222. X &= 0x7ff; \
  2223. Y &= 0x7ff; \
  2224. } \
  2225. \
  2226. if (((X | Y) & ~0x3ff) == 0) \
  2227. { \
  2228. u8 *TileData = VRAM1 + (Memory.VRAM[((Y & ~7) << 5) + ((X >> 2) & ~1)] << 7); \
  2229. u32 b = *(TileData + ((Y & 7) << 4) + ((X & 7) << 1)); \
  2230. GFX.Z1 = Mode7Depths [(b & GFX.Mode7PriorityMask) >> 7]; \
  2231. if (GFX.Z1 > *d && b) \
  2232. { \
  2233. TYPE theColor = COLORFUNC; \
  2234. *p = (FUNC) | ALPHA_BITS_MASK; \
  2235. *d = GFX.Z1; \
  2236. } \
  2237. } \
  2238. else if (PPU.Mode7Repeat == 3) \
  2239. { \
  2240. X = (x + HOffset) & 7; \
  2241. Y = (yy + CentreY) & 7; \
  2242. u8 *TileData = VRAM1 + (Memory.VRAM[((Y & ~7) << 5) + ((X >> 2) & ~1)] << 7); \
  2243. u32 b = *(TileData + ((Y & 7) << 4) + ((X & 7) << 1)); \
  2244. GFX.Z1 = Mode7Depths [(b & GFX.Mode7PriorityMask) >> 7]; \
  2245. if (GFX.Z1 > *d && b) \
  2246. { \
  2247. TYPE theColor = COLORFUNC; \
  2248. *p = (FUNC) | ALPHA_BITS_MASK; \
  2249. *d = GFX.Z1; \
  2250. } \
  2251. } \
  2252. AA += aa; p++; d++; \
  2253. x += dir; \
  2254. } while (x != endx); \
  2255. } \
  2256. } \
  2257. else if (!PPU.Mode7Repeat) \
  2258. { \
  2259. /* The bilinear interpolator: get the colors at the four points surrounding */ \
  2260. /* the location of one point in the _sampled_ image, and weight them according */ \
  2261. /* to their (city block) distance. It's very smooth, but blurry with "close up" */ \
  2262. /* points. */ \
  2263. \
  2264. /* 460 (slightly less than 2 source pixels per displayed pixel) is an educated */ \
  2265. /* guess for where bilinear filtering will become a poor method for averaging. */ \
  2266. /* (When reducing the image, the weighting used by a bilinear filter becomes */ \
  2267. /* arbitrary, and a simple mean is a better way to represent the source image.) */ \
  2268. /* You can think of this as a kind of mipmapping. */ \
  2269. if ((aa < 460 && aa > -460) && (cc < 460 && cc > -460)) \
  2270. {\
  2271. for (int x = startx; x != endx; x += dir, AA += aa, CC += cc, p++, d++) \
  2272. { \
  2273. u32 xPos = AA + BB; \
  2274. u32 xPix = xPos >> 8; \
  2275. u32 yPos = CC + DD; \
  2276. u32 yPix = yPos >> 8; \
  2277. u32 X = xPix & 0x3ff; \
  2278. u32 Y = yPix & 0x3ff; \
  2279. u8 *TileData = VRAM1 + (Memory.VRAM[((Y & ~7) << 5) + ((X >> 2) & ~1)] << 7); \
  2280. u32 b = *(TileData + ((Y & 7) << 4) + ((X & 7) << 1)); \
  2281. GFX.Z1 = Mode7Depths [(b & GFX.Mode7PriorityMask) >> 7]; \
  2282. if (GFX.Z1 > *d && b) \
  2283. { \
  2284. /* X10 and Y01 are the X and Y coordinates of the next source point over. */ \
  2285. u32 X10 = (xPix + dir) & 0x3ff; \
  2286. u32 Y01 = (yPix + dir) & 0x3ff; \
  2287. u8 *TileData10 = VRAM1 + (Memory.VRAM[((Y & ~7) << 5) + ((X10 >> 2) & ~1)] << 7); \
  2288. u8 *TileData11 = VRAM1 + (Memory.VRAM[((Y01 & ~7) << 5) + ((X10 >> 2) & ~1)] << 7); \
  2289. u8 *TileData01 = VRAM1 + (Memory.VRAM[((Y01 & ~7) << 5) + ((X >> 2) & ~1)] << 7); \
  2290. u32 p1 = COLORFUNC; \
  2291. p1 = (p1 & FIRST_THIRD_COLOR_MASK) | ((p1 & SECOND_COLOR_MASK) << 16); \
  2292. b = *(TileData10 + ((Y & 7) << 4) + ((X10 & 7) << 1)); \
  2293. u32 p2 = COLORFUNC; \
  2294. p2 = (p2 & FIRST_THIRD_COLOR_MASK) | ((p2 & SECOND_COLOR_MASK) << 16); \
  2295. b = *(TileData11 + ((Y01 & 7) << 4) + ((X10 & 7) << 1)); \
  2296. u32 p4 = COLORFUNC; \
  2297. p4 = (p4 & FIRST_THIRD_COLOR_MASK) | ((p4 & SECOND_COLOR_MASK) << 16); \
  2298. b = *(TileData01 + ((Y01 & 7) << 4) + ((X & 7) << 1)); \
  2299. u32 p3 = COLORFUNC; \
  2300. p3 = (p3 & FIRST_THIRD_COLOR_MASK) | ((p3 & SECOND_COLOR_MASK) << 16); \
  2301. /* Xdel, Ydel: position (in 1/32nds) between the points */ \
  2302. u32 Xdel = (xPos >> 3) & 0x1F; \
  2303. u32 Ydel = (yPos >> 3) & 0x1F; \
  2304. u32 XY = (Xdel*Ydel) >> 5; \
  2305. u32 area1 = 0x20 + XY - Xdel - Ydel; \
  2306. u32 area2 = Xdel - XY; \
  2307. u32 area3 = Ydel - XY; \
  2308. u32 area4 = XY; \
  2309. u32 tempColor = ((area1 * p1) + \
  2310. (area2 * p2) + \
  2311. (area3 * p3) + \
  2312. (area4 * p4)) >> 5; \
  2313. TYPE theColor = (tempColor & FIRST_THIRD_COLOR_MASK) | ((tempColor >> 16) & SECOND_COLOR_MASK); \
  2314. *p = (FUNC) | ALPHA_BITS_MASK; \
  2315. *d = GFX.Z1; \
  2316. } \
  2317. } \
  2318. } \
  2319. else \
  2320. /* The oversampling method: get the colors at four corners of a square */ \
  2321. /* in the _displayed_ image, and average them. It's sharp and clean, but */ \
  2322. /* gives the usual huge pixels when the source image gets "close." */ \
  2323. { \
  2324. /* Find the dimensions of the square in the source image whose corners will be examined. */ \
  2325. u32 aaDelX = aa >> 1; \
  2326. u32 ccDelX = cc >> 1; \
  2327. u32 bbDelY = l->MatrixB >> 1; \
  2328. u32 ddDelY = l->MatrixD >> 1; \
  2329. /* Offset the location within the source image so that the four sampled points */ \
  2330. /* center around where the single point would otherwise have been drawn. */ \
  2331. BB -= (bbDelY >> 1); \
  2332. DD -= (ddDelY >> 1); \
  2333. AA -= (aaDelX >> 1); \
  2334. CC -= (ccDelX >> 1); \
  2335. u32 BB10 = BB + aaDelX; \
  2336. u32 BB01 = BB + bbDelY; \
  2337. u32 BB11 = BB + aaDelX + bbDelY; \
  2338. u32 DD10 = DD + ccDelX; \
  2339. u32 DD01 = DD + ddDelY; \
  2340. u32 DD11 = DD + ccDelX + ddDelY; \
  2341. for (int x = startx; x != endx; x += dir, AA += aa, CC += cc, p++, d++) \
  2342. { \
  2343. u32 X = ((AA + BB) >> 8) & 0x3ff; \
  2344. u32 Y = ((CC + DD) >> 8) & 0x3ff; \
  2345. u8 *TileData = VRAM1 + (Memory.VRAM[((Y & ~7) << 5) + ((X >> 2) & ~1)] << 7); \
  2346. u32 b = *(TileData + ((Y & 7) << 4) + ((X & 7) << 1)); \
  2347. GFX.Z1 = Mode7Depths [(b & GFX.Mode7PriorityMask) >> 7]; \
  2348. if (GFX.Z1 > *d && b) \
  2349. { \
  2350. /* X, Y, X10, Y10, etc. are the coordinates of the four pixels within the */ \
  2351. /* source image that we're going to examine. */ \
  2352. u32 X10 = ((AA + BB10) >> 8) & 0x3ff; \
  2353. u32 Y10 = ((CC + DD10) >> 8) & 0x3ff; \
  2354. u32 X01 = ((AA + BB01) >> 8) & 0x3ff; \
  2355. u32 Y01 = ((CC + DD01) >> 8) & 0x3ff; \
  2356. u32 X11 = ((AA + BB11) >> 8) & 0x3ff; \
  2357. u32 Y11 = ((CC + DD11) >> 8) & 0x3ff; \
  2358. u8 *TileData10 = VRAM1 + (Memory.VRAM[((Y10 & ~7) << 5) + ((X10 >> 2) & ~1)] << 7); \
  2359. u8 *TileData01 = VRAM1 + (Memory.VRAM[((Y01 & ~7) << 5) + ((X01 >> 2) & ~1)] << 7); \
  2360. u8 *TileData11 = VRAM1 + (Memory.VRAM[((Y11 & ~7) << 5) + ((X11 >> 2) & ~1)] << 7); \
  2361. TYPE p1 = COLORFUNC; \
  2362. b = *(TileData10 + ((Y10 & 7) << 4) + ((X10 & 7) << 1)); \
  2363. TYPE p2 = COLORFUNC; \
  2364. b = *(TileData01 + ((Y01 & 7) << 4) + ((X01 & 7) << 1)); \
  2365. TYPE p3 = COLORFUNC; \
  2366. b = *(TileData11 + ((Y11 & 7) << 4) + ((X11 & 7) << 1)); \
  2367. TYPE p4 = COLORFUNC; \
  2368. TYPE theColor = Q_INTERPOLATE(p1, p2, p3, p4); \
  2369. *p = (FUNC) | ALPHA_BITS_MASK; \
  2370. *d = GFX.Z1; \
  2371. } \
  2372. } \
  2373. } \
  2374. } \
  2375. else \
  2376. { \
  2377. for (int x = startx; x != endx; x += dir, AA += aa, CC += cc, p++, d++) \
  2378. { \
  2379. u32 xPos = AA + BB; \
  2380. u32 xPix = xPos >> 8; \
  2381. u32 yPos = CC + DD; \
  2382. u32 yPix = yPos >> 8; \
  2383. u32 X = xPix; \
  2384. u32 Y = yPix; \
  2385. \
  2386. \
  2387. if(Settings.Dezaemon && PPU.Mode7Repeat == 2) \
  2388. { \
  2389. X &= 0x7ff; \
  2390. Y &= 0x7ff; \
  2391. } \
  2392. \
  2393. if (((X | Y) & ~0x3ff) == 0) \
  2394. { \
  2395. u8 *TileData = VRAM1 + (Memory.VRAM[((Y & ~7) << 5) + ((X >> 2) & ~1)] << 7); \
  2396. u32 b = *(TileData + ((Y & 7) << 4) + ((X & 7) << 1)); \
  2397. GFX.Z1 = Mode7Depths [(b & GFX.Mode7PriorityMask) >> 7]; \
  2398. if (GFX.Z1 > *d && b) \
  2399. { \
  2400. /* X10 and Y01 are the X and Y coordinates of the next source point over. */ \
  2401. u32 X10 = (xPix + dir) & 0x3ff; \
  2402. u32 Y01 = (yPix + dir) & 0x3ff; \
  2403. u8 *TileData10 = VRAM1 + (Memory.VRAM[((Y & ~7) << 5) + ((X10 >> 2) & ~1)] << 7); \
  2404. u8 *TileData11 = VRAM1 + (Memory.VRAM[((Y01 & ~7) << 5) + ((X10 >> 2) & ~1)] << 7); \
  2405. u8 *TileData01 = VRAM1 + (Memory.VRAM[((Y01 & ~7) << 5) + ((X >> 2) & ~1)] << 7); \
  2406. u32 p1 = COLORFUNC; \
  2407. p1 = (p1 & FIRST_THIRD_COLOR_MASK) | ((p1 & SECOND_COLOR_MASK) << 16); \
  2408. b = *(TileData10 + ((Y & 7) << 4) + ((X10 & 7) << 1)); \
  2409. u32 p2 = COLORFUNC; \
  2410. p2 = (p2 & FIRST_THIRD_COLOR_MASK) | ((p2 & SECOND_COLOR_MASK) << 16); \
  2411. b = *(TileData11 + ((Y01 & 7) << 4) + ((X10 & 7) << 1)); \
  2412. u32 p4 = COLORFUNC; \
  2413. p4 = (p4 & FIRST_THIRD_COLOR_MASK) | ((p4 & SECOND_COLOR_MASK) << 16); \
  2414. b = *(TileData01 + ((Y01 & 7) << 4) + ((X & 7) << 1)); \
  2415. u32 p3 = COLORFUNC; \
  2416. p3 = (p3 & FIRST_THIRD_COLOR_MASK) | ((p3 & SECOND_COLOR_MASK) << 16); \
  2417. /* Xdel, Ydel: position (in 1/32nds) between the points */ \
  2418. u32 Xdel = (xPos >> 3) & 0x1F; \
  2419. u32 Ydel = (yPos >> 3) & 0x1F; \
  2420. u32 XY = (Xdel*Ydel) >> 5; \
  2421. u32 area1 = 0x20 + XY - Xdel - Ydel; \
  2422. u32 area2 = Xdel - XY; \
  2423. u32 area3 = Ydel - XY; \
  2424. u32 area4 = XY; \
  2425. u32 tempColor = ((area1 * p1) + \
  2426. (area2 * p2) + \
  2427. (area3 * p3) + \
  2428. (area4 * p4)) >> 5; \
  2429. TYPE theColor = (tempColor & FIRST_THIRD_COLOR_MASK) | ((tempColor >> 16) & SECOND_COLOR_MASK); \
  2430. *p = (FUNC) | ALPHA_BITS_MASK; \
  2431. *d = GFX.Z1; \
  2432. } \
  2433. } \
  2434. else \
  2435. { \
  2436. if (PPU.Mode7Repeat == 3) \
  2437. { \
  2438. X = (x + HOffset) & 7; \
  2439. Y = (yy + CentreY) & 7; \
  2440. u32 b = *(VRAM1 + ((Y & 7) << 4) + ((X & 7) << 1)); \
  2441. GFX.Z1 = Mode7Depths [(b & GFX.Mode7PriorityMask) >> 7]; \
  2442. if (GFX.Z1 > *d && b) \
  2443. { \
  2444. TYPE theColor = COLORFUNC; \
  2445. *p = (FUNC) | ALPHA_BITS_MASK; \
  2446. *d = GFX.Z1; \
  2447. } \
  2448. } \
  2449. } \
  2450. } \
  2451. } \
  2452. } \
  2453. }
  2454. STATIC u32 Q_INTERPOLATE(u32 A, u32 B, u32 C, u32 D)
  2455. {
  2456. register u32 x = ((A >> 2) & HIGH_BITS_SHIFTED_TWO_MASK) +
  2457. ((B >> 2) & HIGH_BITS_SHIFTED_TWO_MASK) +
  2458. ((C >> 2) & HIGH_BITS_SHIFTED_TWO_MASK) +
  2459. ((D >> 2) & HIGH_BITS_SHIFTED_TWO_MASK);
  2460. register u32 y = (A & TWO_LOW_BITS_MASK) +
  2461. (B & TWO_LOW_BITS_MASK) +
  2462. (C & TWO_LOW_BITS_MASK) +
  2463. (D & TWO_LOW_BITS_MASK);
  2464. y = (y>>2) & TWO_LOW_BITS_MASK;
  2465. return x+y;
  2466. }
  2467. void DrawBGMode7Background16_i (u8 *Screen, int bg)
  2468. {
  2469. RENDER_BACKGROUND_MODE7_i (u16, theColor, (GFX.ScreenColors[b & GFX.Mode7Mask]));
  2470. }
  2471. void DrawBGMode7Background16Add_i (u8 *Screen, int bg)
  2472. {
  2473. RENDER_BACKGROUND_MODE7_i (u16, *(d + GFX.DepthDelta) ?
  2474. (*(d + GFX.DepthDelta) != 1 ?
  2475. (COLOR_ADD (theColor,
  2476. p [GFX.Delta])) :
  2477. (COLOR_ADD (theColor,
  2478. GFX.FixedColour))) :
  2479. theColor, (GFX.ScreenColors[b & GFX.Mode7Mask]));
  2480. }
  2481. void DrawBGMode7Background16Add1_2_i (u8 *Screen, int bg)
  2482. {
  2483. RENDER_BACKGROUND_MODE7_i (u16, *(d + GFX.DepthDelta) ?
  2484. (*(d + GFX.DepthDelta) != 1 ?
  2485. COLOR_ADD1_2 (theColor,
  2486. p [GFX.Delta]) :
  2487. COLOR_ADD (theColor,
  2488. GFX.FixedColour)) :
  2489. theColor, (GFX.ScreenColors[b & GFX.Mode7Mask]));
  2490. }
  2491. void DrawBGMode7Background16Sub_i (u8 *Screen, int bg)
  2492. {
  2493. RENDER_BACKGROUND_MODE7_i (u16, *(d + GFX.DepthDelta) ?
  2494. (*(d + GFX.DepthDelta) != 1 ?
  2495. COLOR_SUB (theColor,
  2496. p [GFX.Delta]) :
  2497. COLOR_SUB (theColor,
  2498. GFX.FixedColour)) :
  2499. theColor, (GFX.ScreenColors[b & GFX.Mode7Mask]));
  2500. }
  2501. void DrawBGMode7Background16Sub1_2_i (u8 *Screen, int bg)
  2502. {
  2503. RENDER_BACKGROUND_MODE7_i (u16, *(d + GFX.DepthDelta) ?
  2504. (*(d + GFX.DepthDelta) != 1 ?
  2505. COLOR_SUB1_2 (theColor,
  2506. p [GFX.Delta]) :
  2507. COLOR_SUB (theColor,
  2508. GFX.FixedColour)) :
  2509. theColor, (GFX.ScreenColors[b & GFX.Mode7Mask]));
  2510. }
  2511. #define _BUILD_SETUP(F) \
  2512. GFX.BuildPixel = BuildPixel##F; \
  2513. GFX.BuildPixel2 = BuildPixel2##F; \
  2514. GFX.DecomposePixel = DecomposePixel##F; \
  2515. RED_LOW_BIT_MASK = RED_LOW_BIT_MASK_##F; \
  2516. GREEN_LOW_BIT_MASK = GREEN_LOW_BIT_MASK_##F; \
  2517. BLUE_LOW_BIT_MASK = BLUE_LOW_BIT_MASK_##F; \
  2518. RED_HI_BIT_MASK = RED_HI_BIT_MASK_##F; \
  2519. GREEN_HI_BIT_MASK = GREEN_HI_BIT_MASK_##F; \
  2520. BLUE_HI_BIT_MASK = BLUE_HI_BIT_MASK_##F; \
  2521. MAX_RED = MAX_RED_##F; \
  2522. MAX_GREEN = MAX_GREEN_##F; \
  2523. MAX_BLUE = MAX_BLUE_##F; \
  2524. GREEN_HI_BIT = ((MAX_GREEN_##F + 1) >> 1); \
  2525. SPARE_RGB_BIT_MASK = SPARE_RGB_BIT_MASK_##F; \
  2526. RGB_LOW_BITS_MASK = (RED_LOW_BIT_MASK_##F | \
  2527. GREEN_LOW_BIT_MASK_##F | \
  2528. BLUE_LOW_BIT_MASK_##F); \
  2529. RGB_HI_BITS_MASK = (RED_HI_BIT_MASK_##F | \
  2530. GREEN_HI_BIT_MASK_##F | \
  2531. BLUE_HI_BIT_MASK_##F); \
  2532. RGB_HI_BITS_MASKx2 = ((RED_HI_BIT_MASK_##F | \
  2533. GREEN_HI_BIT_MASK_##F | \
  2534. BLUE_HI_BIT_MASK_##F) << 1); \
  2535. RGB_REMOVE_LOW_BITS_MASK = ~RGB_LOW_BITS_MASK; \
  2536. FIRST_COLOR_MASK = FIRST_COLOR_MASK_##F; \
  2537. SECOND_COLOR_MASK = SECOND_COLOR_MASK_##F; \
  2538. THIRD_COLOR_MASK = THIRD_COLOR_MASK_##F; \
  2539. ALPHA_BITS_MASK = ALPHA_BITS_MASK_##F; \
  2540. FIRST_THIRD_COLOR_MASK = FIRST_COLOR_MASK | THIRD_COLOR_MASK; \
  2541. TWO_LOW_BITS_MASK = RGB_LOW_BITS_MASK | (RGB_LOW_BITS_MASK << 1); \
  2542. HIGH_BITS_SHIFTED_TWO_MASK = (( (FIRST_COLOR_MASK | SECOND_COLOR_MASK | THIRD_COLOR_MASK) & \
  2543. ~TWO_LOW_BITS_MASK ) >> 2);
  2544. void RenderScreen (u8 *Screen, bool8_32 sub, bool8_32 force_no_add, u8 D)
  2545. {
  2546. bool8_32 BG0;
  2547. bool8_32 BG1;
  2548. bool8_32 BG2;
  2549. bool8_32 BG3;
  2550. bool8_32 OB;
  2551. GFX.S = Screen;
  2552. if (!sub)
  2553. {
  2554. GFX.pCurrentClip = &IPPU.Clip [0];
  2555. BG0 = ON_MAIN (0) && !(Settings.os9x_hack & GFX_IGNORE_BG0);
  2556. BG1 = ON_MAIN (1) && !(Settings.os9x_hack & GFX_IGNORE_BG1);
  2557. BG2 = ON_MAIN (2) && !(Settings.os9x_hack & GFX_IGNORE_BG2);
  2558. BG3 = ON_MAIN (3) && !(Settings.os9x_hack & GFX_IGNORE_BG3);
  2559. OB = ON_MAIN (4) && !(Settings.os9x_hack & GFX_IGNORE_OBJ);
  2560. }
  2561. else
  2562. {
  2563. GFX.pCurrentClip = &IPPU.Clip [1];
  2564. BG0 = ON_SUB (0) && !(Settings.os9x_hack & GFX_IGNORE_BG0);
  2565. BG1 = ON_SUB (1) && !(Settings.os9x_hack & GFX_IGNORE_BG1);
  2566. BG2 = ON_SUB (2) && !(Settings.os9x_hack & GFX_IGNORE_BG2);
  2567. BG3 = ON_SUB (3) && !(Settings.os9x_hack & GFX_IGNORE_BG3);
  2568. OB = ON_SUB (4) && !(Settings.os9x_hack & GFX_IGNORE_OBJ);
  2569. }
  2570. sub |= force_no_add;
  2571. if (PPU.BGMode <= 1)
  2572. {
  2573. if (OB)
  2574. {
  2575. SelectTileRenderer (sub || !SUB_OR_ADD(4));
  2576. DrawOBJS (!sub, D);
  2577. }
  2578. if (BG0)
  2579. {
  2580. SelectTileRenderer (sub || !SUB_OR_ADD(0));
  2581. DrawBackground (PPU.BGMode, 0, D + 10, D + 14);
  2582. }
  2583. if (BG1)
  2584. {
  2585. SelectTileRenderer (sub || !SUB_OR_ADD(1));
  2586. DrawBackground (PPU.BGMode, 1, D + 9, D + 13);
  2587. }
  2588. if (BG2)
  2589. {
  2590. SelectTileRenderer (sub || !SUB_OR_ADD(2));
  2591. DrawBackground (PPU.BGMode, 2, D + 3,
  2592. (Memory.FillRAM [0x2105] & 8) == 0 ? D + 6 : D + 17);
  2593. }
  2594. if (BG3 && PPU.BGMode == 0)
  2595. {
  2596. SelectTileRenderer (sub || !SUB_OR_ADD(3));
  2597. DrawBackground (PPU.BGMode, 3, D + 2, D + 5);
  2598. }
  2599. }
  2600. else if (PPU.BGMode != 7)
  2601. {
  2602. if (OB)
  2603. {
  2604. SelectTileRenderer (sub || !SUB_OR_ADD(4));
  2605. DrawOBJS (!sub, D);
  2606. }
  2607. if (BG0)
  2608. {
  2609. SelectTileRenderer (sub || !SUB_OR_ADD(0));
  2610. DrawBackground (PPU.BGMode, 0, D + 5, D + 13);
  2611. }
  2612. if (PPU.BGMode != 6 && BG1)
  2613. {
  2614. SelectTileRenderer (sub || !SUB_OR_ADD(1));
  2615. DrawBackground (PPU.BGMode, 1, D + 2, D + 9);
  2616. }
  2617. }
  2618. else
  2619. {
  2620. if (OB)
  2621. {
  2622. SelectTileRenderer (sub || !SUB_OR_ADD(4));
  2623. DrawOBJS (!sub, D);
  2624. }
  2625. if (BG0 || ((Memory.FillRAM [0x2133] & 0x40) && BG1))
  2626. {
  2627. int bg;
  2628. if (Memory.FillRAM [0x2133] & 0x40)
  2629. {
  2630. GFX.Mode7Mask = 0x7f;
  2631. GFX.Mode7PriorityMask = 0x80;
  2632. Mode7Depths [0] = 5 + D;
  2633. Mode7Depths [1] = 9 + D;
  2634. bg = 1;
  2635. }
  2636. else
  2637. {
  2638. GFX.Mode7Mask = 0xff;
  2639. GFX.Mode7PriorityMask = 0;
  2640. Mode7Depths [0] = 5 + D;
  2641. Mode7Depths [1] = 5 + D;
  2642. bg = 0;
  2643. }
  2644. if (sub || !SUB_OR_ADD(0))
  2645. {
  2646. if (!Settings.Mode7Interpolate)
  2647. DrawBGMode7Background16 (Screen, bg);
  2648. else
  2649. DrawBGMode7Background16_i (Screen, bg);
  2650. }
  2651. else
  2652. {
  2653. if (GFX.r2131 & 0x80)
  2654. {
  2655. if (GFX.r2131 & 0x40)
  2656. {
  2657. if (!Settings.Mode7Interpolate)
  2658. DrawBGMode7Background16Sub1_2 (Screen, bg);
  2659. else
  2660. DrawBGMode7Background16Sub1_2_i (Screen, bg);
  2661. }
  2662. else
  2663. {
  2664. if (!Settings.Mode7Interpolate)
  2665. DrawBGMode7Background16Sub (Screen, bg);
  2666. else
  2667. DrawBGMode7Background16Sub_i (Screen, bg);
  2668. }
  2669. }
  2670. else
  2671. {
  2672. if (GFX.r2131 & 0x40)
  2673. {
  2674. if (!Settings.Mode7Interpolate)
  2675. DrawBGMode7Background16Add1_2 (Screen, bg);
  2676. else
  2677. DrawBGMode7Background16Add1_2_i (Screen, bg);
  2678. }
  2679. else
  2680. {
  2681. if (!Settings.Mode7Interpolate)
  2682. DrawBGMode7Background16Add (Screen, bg);
  2683. else
  2684. DrawBGMode7Background16Add_i (Screen, bg);
  2685. }
  2686. }
  2687. }
  2688. }
  2689. }
  2690. }
  2691. void S9xUpdateScreen ()
  2692. {
  2693. s32 x2 = 1;
  2694. GFX.S = GFX.Screen;
  2695. unsigned char *memoryfillram = Memory.FillRAM;
  2696. // get local copies of vid registers to be used later
  2697. GFX.r2131 = memoryfillram [0x2131]; // ADDITION/SUBTRACTION & SUBTRACTION DESIGNATION FOR EACH SCREEN
  2698. GFX.r212c = memoryfillram [0x212c]; // MAIN SCREEN, DESIGNATION - used to enable BGS
  2699. GFX.r212d = memoryfillram [0x212d]; // SUB SCREEN DESIGNATION - used to enable sub BGS
  2700. GFX.r2130 = memoryfillram [0x2130]; // INITIAL SETTINGS FOR FIXED COLOR ADDITION OR SCREEN ADDITION
  2701. GFX.Pseudo = (memoryfillram [0x2133] & 8) != 0 && // Use EXTERNAL SYNCHRONIZATION?
  2702. (GFX.r212c & 15) != (GFX.r212d & 15) && // Are the main screens different from the sub screens?
  2703. (GFX.r2131 & 0x3f) == 0; // Is colour data addition/subtraction disabled on all BGS?
  2704. // refresh the sprites.
  2705. if (IPPU.OBJChanged)
  2706. {
  2707. S9xSetupOBJ ();
  2708. }
  2709. if (PPU.RecomputeClipWindows)
  2710. {
  2711. ComputeClipWindows ();
  2712. PPU.RecomputeClipWindows = FALSE;
  2713. }
  2714. GFX.StartY = IPPU.PreviousLine;
  2715. if ((GFX.EndY = IPPU.CurrentLine - 1) >= PPU.ScreenHeight)
  2716. GFX.EndY = PPU.ScreenHeight - 1;
  2717. u32 starty = GFX.StartY;
  2718. u32 endy = GFX.EndY;
  2719. #ifndef RC_OPTIMIZED
  2720. if (Settings.SupportHiRes &&
  2721. (PPU.BGMode == 5 || PPU.BGMode == 6 || IPPU.LatchedInterlace))
  2722. {
  2723. if (PPU.BGMode == 5 || PPU.BGMode == 6)
  2724. {
  2725. IPPU.RenderedScreenWidth = 512;
  2726. x2 = 2;
  2727. }
  2728. if (IPPU.LatchedInterlace)
  2729. {
  2730. starty = GFX.StartY * 2;
  2731. endy = GFX.EndY * 2 + 1;
  2732. }
  2733. if (!IPPU.DoubleWidthPixels)
  2734. {
  2735. // The game has switched from lo-res to hi-res mode part way down
  2736. // the screen. Scale any existing lo-res pixels on screen
  2737. #ifndef _SNESPPC
  2738. if (Settings.SixteenBit)
  2739. #endif
  2740. {
  2741. #if defined (USE_GLIDE) || defined (USE_OPENGL)
  2742. if (
  2743. #ifdef USE_GLIDE
  2744. (Settings.GlideEnable && GFX.Pitch == 512) ||
  2745. #endif
  2746. #ifdef USE_OPENGL
  2747. (Settings.OpenGLEnable && GFX.Pitch == 512) ||
  2748. #endif
  2749. 0)
  2750. {
  2751. // Have to back out of the speed up hack where the low res.
  2752. // SNES image was rendered into a 256x239 sized buffer,
  2753. // ignoring the true, larger size of the buffer.
  2754. for (register s32 y = (s32) GFX.StartY - 1; y >= 0; y--)
  2755. {
  2756. register u16 *p = (u16 *) (GFX.Screen + y * GFX.Pitch) + 255;
  2757. register u16 *q = (u16 *) (GFX.Screen + y * GFX.RealPitch) + 510;
  2758. for (register int x = 255; x >= 0; x--, p--, q -= 2)
  2759. *q = *(q + 1) = *p;
  2760. }
  2761. GFX.Pitch = GFX.Pitch2 = GFX.RealPitch;
  2762. GFX.PPL = GFX.Pitch >> 1;
  2763. GFX.PPLx2 = GFX.Pitch;
  2764. GFX.ZPitch = GFX.PPL;
  2765. }
  2766. else
  2767. #endif
  2768. for (register u32 y = 0; y < GFX.StartY; y++)
  2769. {
  2770. register u16 *p = (u16 *) (GFX.Screen + y * GFX.Pitch) + 255;
  2771. register u16 *q = (u16 *) (GFX.Screen + y * GFX.Pitch) + 510;
  2772. for (register int x = 255; x >= 0; x--, p--, q -= 2)
  2773. *q = *(q + 1) = *p;
  2774. }
  2775. }
  2776. #ifndef _SNESPPC
  2777. else
  2778. {
  2779. for (register u32 y = 0; y < GFX.StartY; y++)
  2780. {
  2781. register u8 *p = GFX.Screen + y * GFX.Pitch + 255;
  2782. register u8 *q = GFX.Screen + y * GFX.Pitch + 510;
  2783. for (register int x = 255; x >= 0; x--, p--, q -= 2)
  2784. *q = *(q + 1) = *p;
  2785. }
  2786. }
  2787. #endif
  2788. IPPU.DoubleWidthPixels = TRUE;
  2789. }
  2790. }
  2791. #endif //RC_OPTIMIZED (DONT DO ABOVE)
  2792. u32 black = BLACK | (BLACK << 16);
  2793. // Are we worrying about transparencies?
  2794. if (Settings.Transparency && Settings.SixteenBit)
  2795. {
  2796. if (GFX.Pseudo)
  2797. {
  2798. GFX.r2131 = 0x5f; //0101 1111 - enable addition/subtraction on all BGS and sprites and "1/2 OF COLOR DATA" DESIGNATION
  2799. GFX.r212d = (Memory.FillRAM [0x212c] ^ // any BGS which are set as main and as sub then switch off the sub
  2800. Memory.FillRAM [0x212d]) & 15;
  2801. GFX.r212c &= ~GFX.r212d; // make sure the main BG reg is the reverse of the sub BG reg
  2802. GFX.r2130 |= 2; // enable ADDITION/SUBTRACTION FOR SUB SCREEN
  2803. }
  2804. // Check to see if any transparency effects are currently in use
  2805. if (!PPU.ForcedBlanking && ADD_OR_SUB_ON_ANYTHING &&
  2806. (GFX.r2130 & 0x30) != 0x30 &&
  2807. !((GFX.r2130 & 0x30) == 0x10 && IPPU.Clip[1].Count[5] == 0))
  2808. {
  2809. // transparency effects in use, so lets get busy!
  2810. struct ClipData *pClip;
  2811. u32 fixedColour;
  2812. GFX.FixedColour = BUILD_PIXEL (IPPU.XB [PPU.FixedColourRed],
  2813. IPPU.XB [PPU.FixedColourGreen],
  2814. IPPU.XB [PPU.FixedColourBlue]);
  2815. fixedColour = (GFX.FixedColour<<16|GFX.FixedColour);
  2816. // Clear the z-buffer, marking areas 'covered' by the fixed
  2817. // colour as depth 1.
  2818. pClip = &IPPU.Clip [1];
  2819. // Clear the z-buffer
  2820. if (pClip->Count [5])
  2821. {
  2822. // Colour window enabled.
  2823. #ifdef RC_OPTIMIZED
  2824. for (u32 y = starty; y <= endy; y++)
  2825. {
  2826. ZeroMemory (GFX.SubZBuffer + y * GFX.ZPitch,
  2827. IPPU.RenderedScreenWidth);
  2828. ZeroMemory (GFX.ZBuffer + y * GFX.ZPitch,
  2829. IPPU.RenderedScreenWidth);
  2830. if (IPPU.Clip [0].Count [5])
  2831. {
  2832. memset ((GFX.SubScreen + y * GFX.Pitch2), black, IPPU.RenderedScreenWidth);
  2833. }
  2834. for (u32 c = 0; c < pClip->Count [5]; c++)
  2835. {
  2836. if (pClip->Right [c][5] > pClip->Left [c][5])
  2837. {
  2838. memset (GFX.SubZBuffer + y * GFX.ZPitch + pClip->Left [c][5] * x2,
  2839. 1, (pClip->Right [c][5] - pClip->Left [c][5]) * x2);
  2840. if (IPPU.Clip [0].Count [5])
  2841. {
  2842. // Blast, have to clear the sub-screen to the fixed-colour
  2843. // because there is a colour window in effect clipping
  2844. // the main screen that will allow the sub-screen
  2845. // 'underneath' to show through.
  2846. memset ((GFX.SubScreen + y * GFX.Pitch2) + pClip->Left [c][5] * x2,
  2847. GFX.FixedColour,
  2848. pClip->Right[c][5]*x2 - pClip->Left [c][5] * x2);
  2849. }
  2850. }
  2851. }
  2852. }
  2853. #else // NOT RC_OPTIMIZED
  2854. // loop around all of the lines being updated
  2855. for (u32 y = starty; y <= endy; y++)
  2856. {
  2857. // Clear the subZbuffer
  2858. memset32 ((u32_t*)(GFX.SubZBuffer + y * GFX.ZPitch),0,
  2859. IPPU.RenderedScreenWidth>>2);
  2860. // Clear the Zbuffer
  2861. memset32 ((u32_t*)(GFX.ZBuffer + y * GFX.ZPitch),0,
  2862. IPPU.RenderedScreenWidth>>2);
  2863. // if there is clipping then clear subscreen to a black color
  2864. if (IPPU.Clip [0].Count [5])
  2865. {
  2866. memset32 ((u32_t*)(GFX.SubScreen + y * GFX.Pitch2), black, IPPU.RenderedScreenWidth>>1);
  2867. }
  2868. // loop through all window clippings
  2869. for (u32 c = 0; c < pClip->Count [5]; c++)
  2870. {
  2871. if (pClip->Right [c][5] > pClip->Left [c][5])
  2872. {
  2873. memset (GFX.SubZBuffer + y * GFX.ZPitch + pClip->Left [c][5] * x2,
  2874. 1, (pClip->Right [c][5] - pClip->Left [c][5]) * x2);
  2875. if (IPPU.Clip [0].Count [5])
  2876. {
  2877. // Blast, have to clear the sub-screen to the fixed-colour
  2878. // because there is a colour window in effect clipping
  2879. // the main screen that will allow the sub-screen
  2880. // 'underneath' to show through.
  2881. register u16 *p = (u16 *) (GFX.SubScreen + y * GFX.Pitch2);
  2882. register u16 *q = p + pClip->Right [c][5] * x2;
  2883. p += pClip->Left [c][5] * x2;
  2884. while (p < q)
  2885. *p++ = (u16) GFX.FixedColour;
  2886. }
  2887. }
  2888. }
  2889. }
  2890. #endif
  2891. //#undef RC_OPTIMIZED
  2892. }
  2893. else
  2894. {
  2895. // No windows are clipping the main screen
  2896. // this simplifies the screen clearing process
  2897. #ifdef RC_OPTIMIZED
  2898. if (GFX.ZPitch == (u32)IPPU.RenderedScreenWidth)
  2899. {
  2900. memset (GFX.ZBuffer + starty * GFX.ZPitch, 0, GFX.ZPitch * (endy - starty - 1));
  2901. memset (GFX.SubZBuffer + starty * GFX.ZPitch, 1, GFX.ZPitch * (endy - starty - 1));
  2902. }
  2903. else
  2904. {
  2905. for (u32 y = starty; y <= endy; y++)
  2906. {
  2907. ZeroMemory (GFX.ZBuffer + y * GFX.ZPitch,
  2908. IPPU.RenderedScreenWidth);
  2909. memset (GFX.SubZBuffer + y * GFX.ZPitch, 1,
  2910. IPPU.RenderedScreenWidth);
  2911. }
  2912. }
  2913. if (IPPU.Clip [0].Count [5])
  2914. {
  2915. // Blast, have to clear the sub-screen to the fixed-colour
  2916. // because there is a colour window in effect clipping
  2917. // the main screen that will allow the sub-screen
  2918. // 'underneath' to show through.
  2919. if (GFX.Pitch2 == (u32)IPPU.RenderedScreenWidth)
  2920. {
  2921. memset ((GFX.SubScreen + starty * GFX.Pitch2),
  2922. GFX.FixedColour | (GFX.FixedColour << 16),
  2923. GFX.Pitch2 * (endy - starty - 1));
  2924. }
  2925. else
  2926. {
  2927. for (u32 y = starty; y <= endy; y++)
  2928. {
  2929. memset ((GFX.SubScreen + y * GFX.Pitch2),
  2930. GFX.FixedColour | (GFX.FixedColour << 16),
  2931. IPPU.RenderedScreenWidth);
  2932. }
  2933. }
  2934. }
  2935. #else // NOT RC_OPTIMIZED
  2936. // loop through all of the lines to be updated
  2937. for (u32 y = starty; y <= endy; y++)
  2938. {
  2939. // Clear the Zbuffer
  2940. memset32 ((u32_t*)(GFX.ZBuffer + y * GFX.ZPitch),0,
  2941. IPPU.RenderedScreenWidth>>2);
  2942. // clear the sub Zbuffer to 1
  2943. memset32 ((u32_t*)(GFX.SubZBuffer + y * GFX.ZPitch), 0x01010101,
  2944. IPPU.RenderedScreenWidth>>2);
  2945. if (IPPU.Clip [0].Count [5])
  2946. {
  2947. // Blast, have to clear the sub-screen to the fixed-colour
  2948. // because there is a colour window in effect clipping
  2949. // the main screen that will allow the sub-screen
  2950. // 'underneath' to show through.
  2951. memset32 ((u32_t*)(GFX.SubScreen + y * GFX.Pitch2), fixedColour,
  2952. IPPU.RenderedScreenWidth>>1);
  2953. }
  2954. }
  2955. #endif
  2956. }
  2957. if (ANYTHING_ON_SUB)
  2958. {
  2959. GFX.DB = GFX.SubZBuffer;
  2960. RenderScreen (GFX.SubScreen, TRUE, TRUE, SUB_SCREEN_DEPTH);
  2961. }
  2962. if (IPPU.Clip [0].Count [5])
  2963. {
  2964. for (u32 y = starty; y <= endy; y++)
  2965. {
  2966. register u16 *p = (u16 *) (GFX.Screen + y * GFX.Pitch2);
  2967. register u8 *d = GFX.SubZBuffer + y * GFX.ZPitch ;
  2968. register u8 *e = d + SNES_WIDTH;
  2969. while (d < e)
  2970. {
  2971. if (*d > 1)
  2972. *p = *(p + GFX.Delta);
  2973. else
  2974. *p = BLACK;
  2975. d++;
  2976. p++;
  2977. }
  2978. }
  2979. }
  2980. GFX.DB = GFX.ZBuffer;
  2981. RenderScreen (GFX.Screen, FALSE, FALSE, MAIN_SCREEN_DEPTH);
  2982. if (SUB_OR_ADD(5))
  2983. {
  2984. u32 back = IPPU.ScreenColors [0];
  2985. u32 Left = 0;
  2986. u32 Right = 256;
  2987. u32 Count;
  2988. pClip = &IPPU.Clip [0];
  2989. for (u32 y = starty; y <= endy; y++)
  2990. {
  2991. if (!(Count = pClip->Count [5]))
  2992. {
  2993. Left = 0;
  2994. Right = 256 * x2;
  2995. Count = 1;
  2996. }
  2997. for (u32 b = 0; b < Count; b++)
  2998. {
  2999. if (pClip->Count [5])
  3000. {
  3001. Left = pClip->Left [b][5] * x2;
  3002. Right = pClip->Right [b][5] * x2;
  3003. if (Right <= Left)
  3004. continue;
  3005. }
  3006. if (GFX.r2131 & 0x80)
  3007. {
  3008. if (GFX.r2131 & 0x40)
  3009. {
  3010. // Subtract, halving the result.
  3011. register u16 *p = (u16 *) (GFX.Screen + y * GFX.Pitch2) + Left;
  3012. register u8 *d = GFX.ZBuffer + y * GFX.ZPitch;
  3013. register u8 *s = GFX.SubZBuffer + y * GFX.ZPitch + Left;
  3014. register u8 *e = d + Right;
  3015. u16 back_fixed = COLOR_SUB (back, GFX.FixedColour);
  3016. d += Left;
  3017. while (d < e)
  3018. {
  3019. if (*d == 0)
  3020. {
  3021. if (*s)
  3022. {
  3023. if (*s != 1)
  3024. *p = COLOR_SUB1_2 (back, *(p + GFX.Delta));
  3025. else
  3026. *p = back_fixed;
  3027. }
  3028. else
  3029. *p = (u16) back;
  3030. }
  3031. d++;
  3032. p++;
  3033. s++;
  3034. }
  3035. }
  3036. else
  3037. {
  3038. // Subtract
  3039. register u16 *p = (u16 *) (GFX.Screen + y * GFX.Pitch2) + Left;
  3040. register u8 *s = GFX.SubZBuffer + y * GFX.ZPitch + Left;
  3041. register u8 *d = GFX.ZBuffer + y * GFX.ZPitch;
  3042. register u8 *e = d + Right;
  3043. u16 back_fixed = COLOR_SUB (back, GFX.FixedColour);
  3044. d += Left;
  3045. while (d < e)
  3046. {
  3047. if (*d == 0)
  3048. {
  3049. if (*s)
  3050. {
  3051. if (*s != 1)
  3052. *p = COLOR_SUB (back, *(p + GFX.Delta));
  3053. else
  3054. *p = back_fixed;
  3055. }
  3056. else
  3057. *p = (u16) back;
  3058. }
  3059. d++;
  3060. p++;
  3061. s++;
  3062. }
  3063. }
  3064. }
  3065. else
  3066. if (GFX.r2131 & 0x40)
  3067. {
  3068. register u16 *p = (u16 *) (GFX.Screen + y * GFX.Pitch2) + Left;
  3069. register u8 *d = GFX.ZBuffer + y * GFX.ZPitch;
  3070. register u8 *s = GFX.SubZBuffer + y * GFX.ZPitch + Left;
  3071. register u8 *e = d + Right;
  3072. u16 back_fixed = COLOR_ADD (back, GFX.FixedColour);
  3073. d += Left;
  3074. while (d < e)
  3075. {
  3076. if (*d == 0)
  3077. {
  3078. if (*s)
  3079. {
  3080. if (*s != 1)
  3081. *p = COLOR_ADD1_2 (back, *(p + GFX.Delta));
  3082. else
  3083. *p = back_fixed;
  3084. }
  3085. else
  3086. *p = (u16) back;
  3087. }
  3088. d++;
  3089. p++;
  3090. s++;
  3091. }
  3092. }
  3093. else
  3094. if (back != 0)
  3095. {
  3096. register u16 *p = (u16 *) (GFX.Screen + y * GFX.Pitch2) + Left;
  3097. register u8 *d = GFX.ZBuffer + y * GFX.ZPitch;
  3098. register u8 *s = GFX.SubZBuffer + y * GFX.ZPitch + Left;
  3099. register u8 *e = d + Right;
  3100. u16 back_fixed = COLOR_ADD (back, GFX.FixedColour);
  3101. d += Left;
  3102. while (d < e)
  3103. {
  3104. if (*d == 0)
  3105. {
  3106. if (*s)
  3107. {
  3108. if (*s != 1)
  3109. *p = COLOR_ADD (back, *(p + GFX.Delta));
  3110. else
  3111. *p = back_fixed;
  3112. }
  3113. else
  3114. *p = (u16) back;
  3115. }
  3116. d++;
  3117. p++;
  3118. s++;
  3119. }
  3120. }
  3121. else
  3122. {
  3123. if (!pClip->Count [5])
  3124. {
  3125. // The backdrop has not been cleared yet - so
  3126. // copy the sub-screen to the main screen
  3127. // or fill it with the back-drop colour if the
  3128. // sub-screen is clear.
  3129. register u16 *p = (u16 *) (GFX.Screen + y * GFX.Pitch2) + Left;
  3130. register u8 *d = GFX.ZBuffer + y * GFX.ZPitch;
  3131. register u8 *s = GFX.SubZBuffer + y * GFX.ZPitch + Left;
  3132. register u8 *e = d + Right;
  3133. d += Left;
  3134. while (d < e)
  3135. {
  3136. if (*d == 0)
  3137. {
  3138. if (*s)
  3139. {
  3140. if (*s != 1)
  3141. *p = *(p + GFX.Delta);
  3142. else
  3143. *p = GFX.FixedColour;
  3144. }
  3145. else
  3146. *p = (u16) back;
  3147. }
  3148. d++;
  3149. p++;
  3150. s++;
  3151. }
  3152. }
  3153. }
  3154. }
  3155. }
  3156. }
  3157. else
  3158. {
  3159. // Subscreen not being added to back
  3160. u32 back = IPPU.ScreenColors [0] | (IPPU.ScreenColors [0] << 16);
  3161. pClip = &IPPU.Clip [0];
  3162. if (pClip->Count [5])
  3163. {
  3164. for (u32 y = starty; y <= endy; y++)
  3165. {
  3166. for (u32 b = 0; b < pClip->Count [5]; b++)
  3167. {
  3168. u32 Left = pClip->Left [b][5] * x2;
  3169. u32 Right = pClip->Right [b][5] * x2;
  3170. register u16 *p = (u16 *) (GFX.Screen + y * GFX.Pitch2) + Left;
  3171. register u8 *d = GFX.ZBuffer + y * GFX.ZPitch;
  3172. register u8 *e = d + Right;
  3173. d += Left;
  3174. while (d < e)
  3175. {
  3176. if (*d++ == 0)
  3177. *p = (s16) back;
  3178. p++;
  3179. }
  3180. }
  3181. }
  3182. }
  3183. else
  3184. {
  3185. for (u32 y = starty; y <= endy; y++)
  3186. {
  3187. register u16 *p = (u16 *) (GFX.Screen + y * GFX.Pitch2);
  3188. register u8 *d = GFX.ZBuffer + y * GFX.ZPitch;
  3189. register u8 *e = d + 256 * x2;
  3190. while (d < e)
  3191. {
  3192. if (*d == 0)
  3193. #ifdef RC_OPTIMIZED
  3194. *p++ = back;
  3195. d++;
  3196. #else
  3197. *p = (s16) back;
  3198. d++;
  3199. p++;
  3200. #endif
  3201. }
  3202. }
  3203. }
  3204. }
  3205. }
  3206. else
  3207. {
  3208. // 16bit and transparency but currently no transparency effects in
  3209. // operation.
  3210. // get the back colour of the current screen
  3211. u32 back = IPPU.ScreenColors [0] |
  3212. (IPPU.ScreenColors [0] << 16);
  3213. // if forceblanking in use then use black instead of the back color
  3214. if (PPU.ForcedBlanking)
  3215. back = black;
  3216. // not sure what Clip is used for yet
  3217. // could be a check to see if there is any clipping present?
  3218. if (IPPU.Clip [0].Count[5])
  3219. {
  3220. #ifdef RC_OPTIMIZED
  3221. if (GFX.Pitch2 == (u32)IPPU.RenderedScreenWidth)
  3222. {
  3223. memset (GFX.Screen + starty * GFX.Pitch2, black,
  3224. GFX.Pitch2 * (endy - starty - 1));
  3225. }
  3226. else
  3227. {
  3228. for (u32 y = starty; y <= endy; y++)
  3229. {
  3230. memset (GFX.Screen + y * GFX.Pitch2, black,
  3231. GFX.Pitch2);
  3232. }
  3233. }
  3234. for (u32 y = starty; y <= endy; y++)
  3235. {
  3236. for (u32 c = 0; c < IPPU.Clip [0].Count [5]; c++)
  3237. {
  3238. if (IPPU.Clip [0].Right [c][5] > IPPU.Clip [0].Left [c][5])
  3239. {
  3240. memset ((GFX.Screen + y * GFX.Pitch2) + IPPU.Clip [0].Left [c][5] * x2,
  3241. back,
  3242. IPPU.Clip [0].Right [c][5] * x2 - IPPU.Clip [0].Left [c][5] * x2);
  3243. }
  3244. }
  3245. }
  3246. #else
  3247. // loop through all of the lines that are going to be updated as part of this screen update
  3248. for (u32 y = starty; y <= endy; y++)
  3249. {
  3250. memset32 ((u32_t*)(GFX.Screen + y * GFX.Pitch2), black,
  3251. IPPU.RenderedScreenWidth>>1);
  3252. if (black!=back)
  3253. {
  3254. for (u32 c = 0; c < IPPU.Clip [0].Count [5]; c++)
  3255. {
  3256. if (IPPU.Clip [0].Right [c][5] > IPPU.Clip [0].Left [c][5])
  3257. {
  3258. register u16 *p = (u16 *) (GFX.Screen + y * GFX.Pitch2); // get pointer to current line in screen buffer
  3259. register u16 *q = p + IPPU.Clip [0].Right [c][5] * x2; // get pointer to end of line
  3260. p += IPPU.Clip [0].Left [c][5] * x2;
  3261. while (p < q)
  3262. *p++ = (u16) back; // fill all pixels in clipped section with the back colour
  3263. }
  3264. }
  3265. }
  3266. }
  3267. #endif
  3268. }
  3269. else
  3270. {
  3271. #ifdef RC_OPTIMIZED
  3272. if (GFX.Pitch2 == (u32)IPPU.RenderedScreenWidth)
  3273. {
  3274. memset (GFX.Screen + starty * GFX.Pitch2, back,
  3275. GFX.Pitch2 * (endy - starty - 1));
  3276. }
  3277. else
  3278. {
  3279. for (u32 y = starty; y <= endy; y++)
  3280. {
  3281. memset (GFX.Screen + y * GFX.Pitch2, back,
  3282. GFX.Pitch2);
  3283. }
  3284. }
  3285. #else
  3286. // there is no clipping to worry about so just fill with the back colour
  3287. for (u32 y = starty; y <= endy; y++)
  3288. {
  3289. memset32 ((u32_t*)(GFX.Screen + y * GFX.Pitch2), back,
  3290. IPPU.RenderedScreenWidth>>1);
  3291. }
  3292. #endif
  3293. }
  3294. // If Forced blanking is not in effect
  3295. if (!PPU.ForcedBlanking)
  3296. {
  3297. #ifdef RC_OPTIMIZED
  3298. if (GFX.ZPitch == (u32)IPPU.RenderedScreenWidth)
  3299. {
  3300. memset (GFX.ZBuffer + starty * GFX.ZPitch, 0,
  3301. GFX.ZPitch * (endy - starty - 1));
  3302. }
  3303. else
  3304. {
  3305. for (u32 y = starty; y <= endy; y++)
  3306. {
  3307. memset (GFX.ZBuffer + y * GFX.ZPitch, 0,
  3308. GFX.ZPitch);
  3309. }
  3310. }
  3311. #else
  3312. // Clear the Zbuffer for each of the lines which are going to be updated
  3313. for (u32 y = starty; y <= endy; y++)
  3314. {
  3315. memset32 ((u32_t*)(GFX.ZBuffer + y * GFX.ZPitch), 0,
  3316. GFX.ZPitch>>2);
  3317. }
  3318. #endif
  3319. GFX.DB = GFX.ZBuffer; // save pointer to Zbuffer in GFX object
  3320. RenderScreen (GFX.Screen, FALSE, TRUE, SUB_SCREEN_DEPTH);
  3321. }
  3322. }
  3323. }
  3324. else // Transparencys are disabled, ahh lovely ... nice and easy.
  3325. {
  3326. #ifndef _SNESPPC
  3327. if (Settings.SixteenBit)
  3328. #endif
  3329. {
  3330. // get back colour to be used in clearing the screen
  3331. register u32 back;
  3332. if (!(Memory.FillRAM [0x2131] & 0x80) &&(Memory.FillRAM[0x2131] & 0x20) &&
  3333. (PPU.FixedColourRed || PPU.FixedColourGreen || PPU.FixedColourBlue))
  3334. {
  3335. back = (IPPU.XB[PPU.FixedColourRed]<<11) |
  3336. (IPPU.XB[PPU.FixedColourGreen] << 6) |
  3337. (IPPU.XB[PPU.FixedColourBlue] << 1) | 1;
  3338. back = (back << 16) | back;
  3339. }
  3340. else
  3341. {
  3342. back = IPPU.ScreenColors [0] | (IPPU.ScreenColors [0] << 16);
  3343. }
  3344. // if Forcedblanking in use then back colour becomes black
  3345. if (PPU.ForcedBlanking)
  3346. back = black;
  3347. else
  3348. {
  3349. SelectTileRenderer (TRUE); //selects the tile renderers to be used
  3350. // TRUE means to use the default
  3351. // FALSE means use best renderer based on current
  3352. // graphics register settings
  3353. }
  3354. // now clear all graphics lines which are being updated using the back colour
  3355. for (register u32 y = starty; y <= endy; y++)
  3356. {
  3357. memset32 ((u32_t*)(GFX.Screen + y * GFX.Pitch2), back,
  3358. IPPU.RenderedScreenWidth>>1);
  3359. }
  3360. }
  3361. #ifndef _SNESPPC
  3362. else // Settings.SixteenBit == false
  3363. {
  3364. // because we are in 8 bit we can just use 0 to clear the screen
  3365. // this means we can use the Zero Memory function
  3366. // Loop through all lines being updated and clear the pixels to 0
  3367. for (u32 y = starty; y <= endy; y++)
  3368. {
  3369. ZeroMemory (GFX.Screen + y * GFX.Pitch2,
  3370. IPPU.RenderedScreenWidth);
  3371. }
  3372. }
  3373. #endif
  3374. if (!PPU.ForcedBlanking)
  3375. {
  3376. // Loop through all lines being updated and clear the
  3377. // zbuffer for each of the lines
  3378. for (u32 y = starty; y <= endy; y++)
  3379. {
  3380. memset32 ((u32_t*)(GFX.ZBuffer + y * GFX.ZPitch), 0,
  3381. IPPU.RenderedScreenWidth>>2);
  3382. }
  3383. GFX.DB = GFX.ZBuffer; // save pointer to Zbuffer in GFX object
  3384. GFX.pCurrentClip = &IPPU.Clip [0];
  3385. // Define an inline function to handle clipping
  3386. #define FIXCLIP(n) \
  3387. if (GFX.r212c & (1 << (n))) \
  3388. GFX.pCurrentClip = &IPPU.Clip [0]; \
  3389. else \
  3390. GFX.pCurrentClip = &IPPU.Clip [1]
  3391. // Define an inline function to handle which BGs are being displayed
  3392. #define DISPLAY(n) \
  3393. ((!(PPU.BG_Forced & n) && \
  3394. (GFX.r212c & n)) || \
  3395. ((GFX.r212d & n) && subadd))
  3396. u8 subadd = GFX.r2131 & 0x3f;
  3397. // go through all BGS are check if they need to be displayed
  3398. bool8_32 BG0 = DISPLAY(1) && !(Settings.os9x_hack & GFX_IGNORE_BG0);
  3399. bool8_32 BG1 = DISPLAY(2) && !(Settings.os9x_hack & GFX_IGNORE_BG1);
  3400. bool8_32 BG2 = DISPLAY(4) && !(Settings.os9x_hack & GFX_IGNORE_BG2);
  3401. bool8_32 BG3 = DISPLAY(8) && !(Settings.os9x_hack & GFX_IGNORE_BG3);
  3402. bool8_32 OB = DISPLAY(16) && !(Settings.os9x_hack & GFX_IGNORE_OBJ);
  3403. if (PPU.BGMode <= 1)
  3404. {
  3405. // screen modes 0 and 1
  3406. if (OB)
  3407. {
  3408. FIXCLIP(4);
  3409. DrawOBJS ();
  3410. }
  3411. if (BG0)
  3412. {
  3413. FIXCLIP(0);
  3414. DrawBackground (PPU.BGMode, 0, 10, 14);
  3415. }
  3416. if (BG1)
  3417. {
  3418. FIXCLIP(1);
  3419. DrawBackground (PPU.BGMode, 1, 9, 13);
  3420. }
  3421. if (BG2)
  3422. {
  3423. FIXCLIP(2);
  3424. DrawBackground (PPU.BGMode, 2, 3,
  3425. (Memory.FillRAM [0x2105] & 8) == 0 ? 6 : 17);
  3426. }
  3427. if (BG3 && PPU.BGMode == 0)
  3428. {
  3429. FIXCLIP(3);
  3430. DrawBackground (PPU.BGMode, 3, 2, 5);
  3431. }
  3432. }
  3433. else if (PPU.BGMode != 7)
  3434. {
  3435. // screen modes 2 and up but not mode 7
  3436. if (OB)
  3437. {
  3438. FIXCLIP(4);
  3439. DrawOBJS ();
  3440. }
  3441. if (BG0)
  3442. {
  3443. FIXCLIP(0);
  3444. DrawBackground (PPU.BGMode, 0, 5, 13);
  3445. }
  3446. if (BG1 && PPU.BGMode != 6)
  3447. {
  3448. FIXCLIP(1);
  3449. DrawBackground (PPU.BGMode, 1, 2, 9);
  3450. }
  3451. }
  3452. else
  3453. {
  3454. // screen mode 7
  3455. if (OB)
  3456. {
  3457. FIXCLIP(4);
  3458. DrawOBJS ();
  3459. }
  3460. if (BG0 || ((Memory.FillRAM [0x2133] & 0x40) && BG1))
  3461. {
  3462. int bg;
  3463. FIXCLIP(0);
  3464. if (Memory.FillRAM [0x2133] & 0x40)
  3465. {
  3466. GFX.Mode7Mask = 0x7f;
  3467. GFX.Mode7PriorityMask = 0x80;
  3468. Mode7Depths [0] = 5;
  3469. Mode7Depths [1] = 9;
  3470. bg = 1;
  3471. }
  3472. else
  3473. {
  3474. GFX.Mode7Mask = 0xff;
  3475. GFX.Mode7PriorityMask = 0;
  3476. Mode7Depths [0] = 5;
  3477. Mode7Depths [1] = 5;
  3478. bg = 0;
  3479. }
  3480. #ifndef _SNESPPC
  3481. if (!Settings.SixteenBit)
  3482. DrawBGMode7Background (GFX.Screen, bg);
  3483. else
  3484. #endif
  3485. {
  3486. if (!Settings.Mode7Interpolate)
  3487. {
  3488. DrawBGMode7Background16 (GFX.Screen, bg);
  3489. }
  3490. else
  3491. {
  3492. DrawBGMode7Background16_i (GFX.Screen, bg);
  3493. }
  3494. }
  3495. }
  3496. }
  3497. }
  3498. }
  3499. #ifndef RC_OPTIMIZE // no hi res
  3500. if (Settings.SupportHiRes && PPU.BGMode != 5 && PPU.BGMode != 6)
  3501. {
  3502. if (IPPU.DoubleWidthPixels)
  3503. {
  3504. // Mixure of background modes used on screen - scale width
  3505. // of all non-mode 5 and 6 pixels.
  3506. #ifndef _SNESPPC
  3507. if (Settings.SixteenBit)
  3508. #endif
  3509. {
  3510. for (register u32 y = GFX.StartY; y <= GFX.EndY; y++)
  3511. {
  3512. register u16 *p = (u16 *) (GFX.Screen + y * GFX.Pitch) + 255;
  3513. register u16 *q = (u16 *) (GFX.Screen + y * GFX.Pitch) + 510;
  3514. for (register int x = 255; x >= 0; x--, p--, q -= 2)
  3515. *q = *(q + 1) = *p;
  3516. }
  3517. }
  3518. #ifndef _SNESPPC
  3519. else
  3520. {
  3521. for (register u32 y = GFX.StartY; y <= GFX.EndY; y++)
  3522. {
  3523. register u8 *p = GFX.Screen + y * GFX.Pitch + 255;
  3524. register u8 *q = GFX.Screen + y * GFX.Pitch + 510;
  3525. for (register int x = 255; x >= 0; x--, p--, q -= 2)
  3526. *q = *(q + 1) = *p;
  3527. }
  3528. }
  3529. #endif
  3530. }
  3531. if (IPPU.LatchedInterlace)
  3532. {
  3533. // Interlace is enabled - double the height of all non-mode 5 and 6
  3534. // pixels.
  3535. for (u32 y = GFX.StartY; y <= GFX.EndY; y++)
  3536. {
  3537. memcpy32 ((u32_t*)(GFX.Screen + (y * 2 + 1) * GFX.Pitch2),
  3538. (u32_t*)(GFX.Screen + y * 2 * GFX.Pitch2),
  3539. GFX.Pitch2>>2);
  3540. }
  3541. }
  3542. }
  3543. #endif
  3544. IPPU.PreviousLine = IPPU.CurrentLine;
  3545. }
  3546. #ifdef GFX_MULTI_FORMAT
  3547. #define _BUILD_PIXEL(F) \
  3548. u32 BuildPixel##F(u32 R, u32 G, u32 B) \
  3549. { \
  3550. return (BUILD_PIXEL_##F(R,G,B)); \
  3551. }\
  3552. u32 BuildPixel2##F(u32 R, u32 G, u32 B) \
  3553. { \
  3554. return (BUILD_PIXEL2_##F(R,G,B)); \
  3555. } \
  3556. void DecomposePixel##F(u32 pixel, u32 &R, u32 &G, u32 &B) \
  3557. { \
  3558. DECOMPOSE_PIXEL_##F(pixel,R,G,B); \
  3559. }
  3560. _BUILD_PIXEL(RGB565)
  3561. _BUILD_PIXEL(RGB555)
  3562. _BUILD_PIXEL(BGR565)
  3563. _BUILD_PIXEL(BGR555)
  3564. _BUILD_PIXEL(GBR565)
  3565. _BUILD_PIXEL(GBR555)
  3566. _BUILD_PIXEL(RGB5551)
  3567. bool8_32 S9xSetRenderPixelFormat (int format)
  3568. {
  3569. extern u32 current_graphic_format;
  3570. current_graphic_format = format;
  3571. switch (format)
  3572. {
  3573. case RGB565:
  3574. _BUILD_SETUP(RGB565)
  3575. return (TRUE);
  3576. case RGB555:
  3577. _BUILD_SETUP(RGB555)
  3578. return (TRUE);
  3579. case BGR565:
  3580. _BUILD_SETUP(BGR565)
  3581. return (TRUE);
  3582. case BGR555:
  3583. _BUILD_SETUP(BGR555)
  3584. return (TRUE);
  3585. case GBR565:
  3586. _BUILD_SETUP(GBR565)
  3587. return (TRUE);
  3588. case GBR555:
  3589. _BUILD_SETUP(GBR555)
  3590. return (TRUE);
  3591. case RGB5551:
  3592. _BUILD_SETUP(RGB5551)
  3593. return (TRUE);
  3594. default:
  3595. break;
  3596. }
  3597. return (FALSE);
  3598. }
  3599. #endif