PageRenderTime 61ms CodeModel.GetById 18ms 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

Large files files are truncated, but you can click here to view the full 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) >>

Large files files are truncated, but you can click here to view the full file