PageRenderTime 76ms CodeModel.GetById 23ms RepoModel.GetById 0ms app.codeStats 1ms

/src/snes4iphone_src/gfx.cpp

https://github.com/zodttd/snes4iphone
C++ | 4061 lines | 3527 code | 337 blank | 197 comment | 752 complexity | 55d65387bc7e8439071bf4c21ba6cdf5 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. #include "snes9x.h"
  42. #include "memmap.h"
  43. #include "ppu.h"
  44. #include "cpuexec.h"
  45. #include "display.h"
  46. #include "gfx.h"
  47. #include "apu.h"
  48. #include "cheats.h"
  49. #include <stdint.h>
  50. //#include "asmmemfuncs.h"
  51. #define M7 19
  52. #define M8 19
  53. void ComputeClipWindows ();
  54. static void S9xDisplayFrameRate ();
  55. static void S9xDisplayString (const char *string);
  56. extern uint8 BitShifts[8][4];
  57. extern uint8 TileShifts[8][4];
  58. extern uint8 PaletteShifts[8][4];
  59. extern uint8 PaletteMasks[8][4];
  60. extern uint8 Depths[8][4];
  61. extern uint8 BGSizes [2];
  62. extern NormalTileRenderer DrawTilePtr;
  63. extern ClippedTileRenderer DrawClippedTilePtr;
  64. extern NormalTileRenderer DrawHiResTilePtr;
  65. extern ClippedTileRenderer DrawHiResClippedTilePtr;
  66. extern LargePixelRenderer DrawLargePixelPtr;
  67. extern struct SBG BG;
  68. extern struct SLineData LineData[240];
  69. extern struct SLineMatrixData LineMatrixData [240];
  70. extern uint8 Mode7Depths [2];
  71. #define ON_MAIN(N) \
  72. (GFX.r212c & (1 << (N)) && \
  73. !(PPU.BG_Forced & (1 << (N))))
  74. #define SUB_OR_ADD(N) \
  75. (GFX.r2131 & (1 << (N)))
  76. #define ON_SUB(N) \
  77. ((GFX.r2130 & 0x30) != 0x30 && \
  78. (GFX.r2130 & 2) && \
  79. (GFX.r212d & (1 << N)) && \
  80. !(PPU.BG_Forced & (1 << (N))))
  81. #define ANYTHING_ON_SUB \
  82. ((GFX.r2130 & 0x30) != 0x30 && \
  83. (GFX.r2130 & 2) && \
  84. (GFX.r212d & 0x1f))
  85. #define ADD_OR_SUB_ON_ANYTHING \
  86. (GFX.r2131 & 0x3f)
  87. #define BLACK BUILD_PIXEL(0,0,0)
  88. void DrawTile (uint32 Tile, uint32 Offset, uint32 StartLine,
  89. uint32 LineCount, struct SGFX * gfx);
  90. void DrawClippedTile (uint32 Tile, uint32 Offset,
  91. uint32 StartPixel, uint32 Width,
  92. uint32 StartLine, uint32 LineCount, struct SGFX * gfx);
  93. void DrawTilex2 (uint32 Tile, uint32 Offset, uint32 StartLine,
  94. uint32 LineCount, struct SGFX * gfx);
  95. void DrawClippedTilex2 (uint32 Tile, uint32 Offset,
  96. uint32 StartPixel, uint32 Width,
  97. uint32 StartLine, uint32 LineCount, struct SGFX * gfx);
  98. void DrawTilex2x2 (uint32 Tile, uint32 Offset, uint32 StartLine,
  99. uint32 LineCount, struct SGFX * gfx);
  100. void DrawClippedTilex2x2 (uint32 Tile, uint32 Offset,
  101. uint32 StartPixel, uint32 Width,
  102. uint32 StartLine, uint32 LineCount, struct SGFX * gfx);
  103. void DrawLargePixel (uint32 Tile, uint32 Offset,
  104. uint32 StartPixel, uint32 Pixels,
  105. uint32 StartLine, uint32 LineCount, struct SGFX * gfx);
  106. void DrawTile16 (uint32 Tile, uint32 Offset, uint32 StartLine,
  107. uint32 LineCount, struct SGFX * gfx);
  108. void DrawClippedTile16 (uint32 Tile, uint32 Offset,
  109. uint32 StartPixel, uint32 Width,
  110. uint32 StartLine, uint32 LineCount, struct SGFX * gfx);
  111. void DrawTile16x2 (uint32 Tile, uint32 Offset, uint32 StartLine,
  112. uint32 LineCount, struct SGFX * gfx);
  113. void DrawClippedTile16x2 (uint32 Tile, uint32 Offset,
  114. uint32 StartPixel, uint32 Width,
  115. uint32 StartLine, uint32 LineCount, struct SGFX * gfx);
  116. void DrawTile16x2x2 (uint32 Tile, uint32 Offset, uint32 StartLine,
  117. uint32 LineCount, struct SGFX * gfx);
  118. void DrawClippedTile16x2x2 (uint32 Tile, uint32 Offset,
  119. uint32 StartPixel, uint32 Width,
  120. uint32 StartLine, uint32 LineCount, struct SGFX * gfx);
  121. void DrawLargePixel16 (uint32 Tile, uint32 Offset,
  122. uint32 StartPixel, uint32 Pixels,
  123. uint32 StartLine, uint32 LineCount, struct SGFX * gfx);
  124. void DrawTile16Add (uint32 Tile, uint32 Offset, uint32 StartLine,
  125. uint32 LineCount, struct SGFX * gfx);
  126. void DrawClippedTile16Add (uint32 Tile, uint32 Offset,
  127. uint32 StartPixel, uint32 Width,
  128. uint32 StartLine, uint32 LineCount, struct SGFX * gfx);
  129. void DrawTile16Add1_2 (uint32 Tile, uint32 Offset, uint32 StartLine,
  130. uint32 LineCount, struct SGFX * gfx);
  131. void DrawClippedTile16Add1_2 (uint32 Tile, uint32 Offset,
  132. uint32 StartPixel, uint32 Width,
  133. uint32 StartLine, uint32 LineCount, struct SGFX * gfx);
  134. void DrawTile16FixedAdd1_2 (uint32 Tile, uint32 Offset, uint32 StartLine,
  135. uint32 LineCount, struct SGFX * gfx);
  136. void DrawClippedTile16FixedAdd1_2 (uint32 Tile, uint32 Offset,
  137. uint32 StartPixel, uint32 Width,
  138. uint32 StartLine, uint32 LineCount, struct SGFX * gfx);
  139. void DrawTile16Sub (uint32 Tile, uint32 Offset, uint32 StartLine,
  140. uint32 LineCount, struct SGFX * gfx);
  141. void DrawClippedTile16Sub (uint32 Tile, uint32 Offset,
  142. uint32 StartPixel, uint32 Width,
  143. uint32 StartLine, uint32 LineCount, struct SGFX * gfx);
  144. void DrawTile16Sub1_2 (uint32 Tile, uint32 Offset, uint32 StartLine,
  145. uint32 LineCount, struct SGFX * gfx);
  146. void DrawClippedTile16Sub1_2 (uint32 Tile, uint32 Offset,
  147. uint32 StartPixel, uint32 Width,
  148. uint32 StartLine, uint32 LineCount, struct SGFX * gfx);
  149. void DrawTile16FixedSub1_2 (uint32 Tile, uint32 Offset, uint32 StartLine,
  150. uint32 LineCount, struct SGFX * gfx);
  151. void DrawClippedTile16FixedSub1_2 (uint32 Tile, uint32 Offset,
  152. uint32 StartPixel, uint32 Width,
  153. uint32 StartLine, uint32 LineCount, struct SGFX * gfx);
  154. void DrawLargePixel16Add (uint32 Tile, uint32 Offset,
  155. uint32 StartPixel, uint32 Pixels,
  156. uint32 StartLine, uint32 LineCount, struct SGFX * gfx);
  157. void DrawLargePixel16Add1_2 (uint32 Tile, uint32 Offset,
  158. uint32 StartPixel, uint32 Pixels,
  159. uint32 StartLine, uint32 LineCount, struct SGFX * gfx);
  160. void DrawLargePixel16Sub (uint32 Tile, uint32 Offset,
  161. uint32 StartPixel, uint32 Pixels,
  162. uint32 StartLine, uint32 LineCount, struct SGFX * gfx);
  163. void DrawLargePixel16Sub1_2 (uint32 Tile, uint32 Offset,
  164. uint32 StartPixel, uint32 Pixels,
  165. uint32 StartLine, uint32 LineCount, struct SGFX * gfx);
  166. void DrawHiResClippedTile16 (uint32 Tile, uint32 Offset,
  167. uint32 StartPixel, uint32 Width,
  168. uint32 StartLine, uint32 LineCount, struct SGFX * gfx);
  169. void DrawHiResTile16 (uint32 Tile, uint32 Offset,
  170. uint32 StartLine, uint32 LineCount, struct SGFX * gfx);
  171. bool8_32 S9xGraphicsInit ()
  172. {
  173. register uint32 PixelOdd = 1;
  174. register uint32 PixelEven = 2;
  175. #ifdef GFX_MULTI_FORMAT
  176. if (GFX.BuildPixel == NULL)
  177. S9xSetRenderPixelFormat (RGB565);
  178. #endif
  179. for (uint8 bitshift = 0; bitshift < 4; bitshift++)
  180. {
  181. for (register char i = 0; i < 16; i++)
  182. {
  183. register uint32 h = 0;
  184. register uint32 l = 0;
  185. #if defined(LSB_FIRST)
  186. if (i & 8)
  187. h |= PixelOdd;
  188. if (i & 4)
  189. h |= PixelOdd << 8;
  190. if (i & 2)
  191. h |= PixelOdd << 16;
  192. if (i & 1)
  193. h |= PixelOdd << 24;
  194. if (i & 8)
  195. l |= PixelOdd;
  196. if (i & 4)
  197. l |= PixelOdd << 8;
  198. if (i & 2)
  199. l |= PixelOdd << 16;
  200. if (i & 1)
  201. l |= PixelOdd << 24;
  202. #else
  203. if (i & 8)
  204. h |= (PixelOdd << 24);
  205. if (i & 4)
  206. h |= (PixelOdd << 16);
  207. if (i & 2)
  208. h |= (PixelOdd << 8);
  209. if (i & 1)
  210. h |= PixelOdd;
  211. if (i & 8)
  212. l |= (PixelOdd << 24);
  213. if (i & 4)
  214. l |= (PixelOdd << 16);
  215. if (i & 2)
  216. l |= (PixelOdd << 8);
  217. if (i & 1)
  218. l |= PixelOdd;
  219. #endif
  220. odd_high[bitshift][i] = h;
  221. odd_low[bitshift][i] = l;
  222. h = l = 0;
  223. #if defined(LSB_FIRST)
  224. if (i & 8)
  225. h |= PixelEven;
  226. if (i & 4)
  227. h |= PixelEven << 8;
  228. if (i & 2)
  229. h |= PixelEven << 16;
  230. if (i & 1)
  231. h |= PixelEven << 24;
  232. if (i & 8)
  233. l |= PixelEven;
  234. if (i & 4)
  235. l |= PixelEven << 8;
  236. if (i & 2)
  237. l |= PixelEven << 16;
  238. if (i & 1)
  239. l |= PixelEven << 24;
  240. #else
  241. if (i & 8)
  242. h |= (PixelEven << 24);
  243. if (i & 4)
  244. h |= (PixelEven << 16);
  245. if (i & 2)
  246. h |= (PixelEven << 8);
  247. if (i & 1)
  248. h |= PixelEven;
  249. if (i & 8)
  250. l |= (PixelEven << 24);
  251. if (i & 4)
  252. l |= (PixelEven << 16);
  253. if (i & 2)
  254. l |= (PixelEven << 8);
  255. if (i & 1)
  256. l |= PixelEven;
  257. #endif
  258. even_high[bitshift][i] = h;
  259. even_low[bitshift][i] = l;
  260. }
  261. PixelEven <<= 2;
  262. PixelOdd <<= 2;
  263. }
  264. GFX.RealPitch = GFX.Pitch2 = GFX.Pitch;
  265. GFX.ZPitch = GFX.Pitch;
  266. if (Settings.SixteenBit)
  267. GFX.ZPitch >>= 1;
  268. GFX.Delta = (GFX.SubScreen - GFX.Screen) >> 1;
  269. GFX.DepthDelta = GFX.SubZBuffer - GFX.ZBuffer;
  270. //GFX.InfoStringTimeout = 0;
  271. //GFX.InfoString = NULL;
  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 = (uint16 *) malloc (sizeof (uint16) * 0x10000)))
  302. return (FALSE);
  303. if (!(GFX.ZERO_OR_X2 = (uint16 *) malloc (sizeof (uint16) * 0x10000)) ||
  304. !(GFX.ZERO = (uint16 *) malloc (sizeof (uint16) * 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. uint32 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. uint32 r2 = r << 1;
  324. if (r2 > MAX_RED)
  325. r2 = MAX_RED;
  326. for (g = 0; g <= MAX_GREEN; g++)
  327. {
  328. uint32 g2 = g << 1;
  329. if (g2 > MAX_GREEN)
  330. g2 = MAX_GREEN;
  331. for (b = 0; b <= MAX_BLUE; b++)
  332. {
  333. uint32 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 (uint16));
  342. ZeroMemory (GFX.ZERO_OR_X2, 0x10000 * sizeof (uint16));
  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. uint32 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. uint32 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. uint32 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. uint32 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. uint32 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. uint32 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. uint32 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. uint32 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. uint32 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 (uint32 p = 0; p < 8; p++)
  466. {
  467. for (uint32 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. #ifndef _SNESPPC
  484. if (!S9xInitUpdate ())
  485. {
  486. IPPU.RenderThisFrame = FALSE;
  487. return;
  488. }
  489. #endif
  490. IPPU.RenderedFramesCount++;
  491. IPPU.PreviousLine = IPPU.CurrentLine = 0;
  492. IPPU.MaxBrightness = PPU.Brightness;
  493. IPPU.LatchedBlanking = PPU.ForcedBlanking;
  494. IPPU.LatchedInterlace = (Memory.FillRAM[0x2133] & 1);
  495. IPPU.RenderedScreenWidth = 256;
  496. IPPU.RenderedScreenHeight = PPU.ScreenHeight;
  497. IPPU.DoubleWidthPixels = FALSE;
  498. GFX.Pitch2 = GFX.Pitch = GFX.RealPitch;
  499. GFX.PPL = GFX.PPLx2 >> 1;
  500. GFX.ZPitch = GFX.RealPitch;
  501. if (Settings.SixteenBit)
  502. GFX.ZPitch >>= 1;
  503. PPU.RecomputeClipWindows = TRUE;
  504. GFX.DepthDelta = GFX.SubZBuffer - GFX.ZBuffer;
  505. GFX.Delta = (GFX.SubScreen - GFX.Screen) >> 1;
  506. }
  507. if (++IPPU.FrameCount % Memory.ROMFramesPerSecond == 0)
  508. {
  509. IPPU.DisplayedRenderedFrameCount = IPPU.RenderedFramesCount;
  510. IPPU.RenderedFramesCount = 0;
  511. IPPU.FrameCount = 0;
  512. }
  513. }
  514. void RenderLine (uint8 C)
  515. {
  516. if (IPPU.RenderThisFrame)
  517. {
  518. LineData[C].BG[0].VOffset = PPU.BG[0].VOffset + 1;
  519. LineData[C].BG[0].HOffset = PPU.BG[0].HOffset;
  520. LineData[C].BG[1].VOffset = PPU.BG[1].VOffset + 1;
  521. LineData[C].BG[1].HOffset = PPU.BG[1].HOffset;
  522. if (PPU.BGMode == 7)
  523. {
  524. struct SLineMatrixData *p = &LineMatrixData [C];
  525. p->MatrixA = PPU.MatrixA;
  526. p->MatrixB = PPU.MatrixB;
  527. p->MatrixC = PPU.MatrixC;
  528. p->MatrixD = PPU.MatrixD;
  529. p->CentreX = PPU.CentreX;
  530. p->CentreY = PPU.CentreY;
  531. }
  532. else
  533. {
  534. #ifndef RC_OPTIMIZED
  535. if (Settings.StarfoxHack && PPU.BG[2].VOffset == 0 &&
  536. PPU.BG[2].HOffset == 0xe000)
  537. {
  538. LineData[C].BG[2].VOffset = 0xe1;
  539. LineData[C].BG[2].HOffset = 0;
  540. }
  541. else
  542. #endif
  543. {
  544. LineData[C].BG[2].VOffset = PPU.BG[2].VOffset + 1;
  545. LineData[C].BG[2].HOffset = PPU.BG[2].HOffset;
  546. LineData[C].BG[3].VOffset = PPU.BG[3].VOffset + 1;
  547. LineData[C].BG[3].HOffset = PPU.BG[3].HOffset;
  548. }
  549. }
  550. IPPU.CurrentLine = C + 1;
  551. }
  552. }
  553. void S9xEndScreenRefresh()
  554. {
  555. IPPU.HDMAStarted = FALSE;
  556. //RC
  557. if (IPPU.RenderThisFrame)
  558. {
  559. FLUSH_REDRAW ();
  560. if (IPPU.ColorsChanged)
  561. {
  562. uint32 saved = PPU.CGDATA[0];
  563. if (!Settings.SixteenBit)
  564. {
  565. // Hack for Super Mario World - to get its sky blue
  566. // (It uses Fixed colour addition on the backdrop colour)
  567. if (!(Memory.FillRAM [0x2131] & 0x80) &&
  568. (Memory.FillRAM[0x2131] & 0x20) &&
  569. (PPU.FixedColourRed || PPU.FixedColourGreen ||
  570. PPU.FixedColourBlue))
  571. {
  572. PPU.CGDATA[0] = PPU.FixedColourRed |
  573. (PPU.FixedColourGreen << 5) |
  574. (PPU.FixedColourBlue << 10);
  575. }
  576. }
  577. IPPU.ColorsChanged = FALSE;
  578. S9xSetPalette ();
  579. PPU.CGDATA[0] = saved;
  580. }
  581. GFX.Pitch = GFX.Pitch2 = GFX.RealPitch;
  582. GFX.PPL = GFX.PPLx2 >> 1;
  583. if (Settings.DisplayFrameRate)
  584. S9xDisplayFrameRate ();
  585. if (GFX.InfoString)
  586. S9xDisplayString (GFX.InfoString);
  587. S9xDeinitUpdate (IPPU.RenderedScreenWidth, IPPU.RenderedScreenHeight,
  588. Settings.SixteenBit);
  589. }
  590. #ifndef RC_OPTIMIZED
  591. S9xApplyCheats ();
  592. #endif
  593. #ifdef DEBUGGER
  594. if (CPU.Flags & FRAME_ADVANCE_FLAG)
  595. {
  596. if (ICPU.FrameAdvanceCount)
  597. {
  598. ICPU.FrameAdvanceCount--;
  599. IPPU.RenderThisFrame = TRUE;
  600. IPPU.FrameSkip = 0;
  601. }
  602. else
  603. {
  604. CPU.Flags &= ~FRAME_ADVANCE_FLAG;
  605. CPU.Flags |= DEBUG_MODE_FLAG;
  606. }
  607. }
  608. #endif
  609. if (CPU.SRAMModified)
  610. {
  611. if (!CPU.AutoSaveTimer)
  612. {
  613. if (!(CPU.AutoSaveTimer = Settings.AutoSaveDelay * Memory.ROMFramesPerSecond))
  614. CPU.SRAMModified = FALSE;
  615. }
  616. else
  617. {
  618. if (!--CPU.AutoSaveTimer)
  619. {
  620. S9xAutoSaveSRAM ();
  621. CPU.SRAMModified = FALSE;
  622. }
  623. }
  624. }
  625. }
  626. void S9xSetInfoString (const char *string)
  627. {
  628. GFX.InfoString = string;
  629. GFX.InfoStringTimeout = 120;
  630. }
  631. INLINE void SelectTileRenderer (bool8_32 normal)
  632. {
  633. if (normal)
  634. {
  635. DrawTilePtr = DrawTile16;
  636. DrawClippedTilePtr = DrawClippedTile16;
  637. DrawLargePixelPtr = DrawLargePixel16;
  638. }
  639. else
  640. {
  641. if (GFX.r2131 & 0x80)
  642. {
  643. if (GFX.r2131 & 0x40)
  644. {
  645. if (GFX.r2130 & 2)
  646. {
  647. DrawTilePtr = DrawTile16Sub1_2;
  648. DrawClippedTilePtr = DrawClippedTile16Sub1_2;
  649. }
  650. else
  651. {
  652. // Fixed colour substraction
  653. DrawTilePtr = DrawTile16FixedSub1_2;
  654. DrawClippedTilePtr = DrawClippedTile16FixedSub1_2;
  655. }
  656. DrawLargePixelPtr = DrawLargePixel16Sub1_2;
  657. }
  658. else
  659. {
  660. DrawTilePtr = DrawTile16Sub;
  661. DrawClippedTilePtr = DrawClippedTile16Sub;
  662. DrawLargePixelPtr = DrawLargePixel16Sub;
  663. }
  664. }
  665. else
  666. {
  667. if (GFX.r2131 & 0x40)
  668. {
  669. if (GFX.r2130 & 2)
  670. {
  671. DrawTilePtr = DrawTile16Add1_2;
  672. DrawClippedTilePtr = DrawClippedTile16Add1_2;
  673. }
  674. else
  675. {
  676. // Fixed colour addition
  677. DrawTilePtr = DrawTile16FixedAdd1_2;
  678. DrawClippedTilePtr = DrawClippedTile16FixedAdd1_2;
  679. }
  680. DrawLargePixelPtr = DrawLargePixel16Add1_2;
  681. }
  682. else
  683. {
  684. DrawTilePtr = DrawTile16Add;
  685. DrawClippedTilePtr = DrawClippedTile16Add;
  686. DrawLargePixelPtr = DrawLargePixel16Add;
  687. }
  688. }
  689. }
  690. }
  691. void S9xSetupOBJ ()
  692. {
  693. int SmallSize;
  694. int LargeSize;
  695. switch (PPU.OBJSizeSelect)
  696. {
  697. case 0:
  698. SmallSize = 8;
  699. LargeSize = 16;
  700. break;
  701. case 1:
  702. SmallSize = 8;
  703. LargeSize = 32;
  704. break;
  705. case 2:
  706. SmallSize = 8;
  707. LargeSize = 64;
  708. break;
  709. case 3:
  710. SmallSize = 16;
  711. LargeSize = 32;
  712. break;
  713. case 4:
  714. SmallSize = 16;
  715. LargeSize = 64;
  716. break;
  717. case 5:
  718. default:
  719. SmallSize = 32;
  720. LargeSize = 64;
  721. break;
  722. }
  723. int C = 0;
  724. int FirstSprite = PPU.FirstSprite & 0x7f;
  725. int S = FirstSprite;
  726. do
  727. {
  728. int Size;
  729. if (PPU.OBJ [S].Size)
  730. Size = LargeSize;
  731. else
  732. Size = SmallSize;
  733. long VPos = PPU.OBJ [S].VPos;
  734. if (VPos >= PPU.ScreenHeight)
  735. VPos -= 256;
  736. if (PPU.OBJ [S].HPos < 256 && PPU.OBJ [S].HPos > -Size &&
  737. VPos < PPU.ScreenHeight && VPos > -Size)
  738. {
  739. GFX.OBJList [C++] = S;
  740. GFX.Sizes[S] = Size;
  741. GFX.VPositions[S] = VPos;
  742. }
  743. S = (S + 1) & 0x7f;
  744. } while (S != FirstSprite);
  745. // Terminate the list
  746. GFX.OBJList [C] = -1;
  747. IPPU.OBJChanged = FALSE;
  748. }
  749. void DrawOBJS (bool8_32 OnMain = FALSE, uint8 D = 0)
  750. {
  751. uint32 O;
  752. uint32 BaseTile, Tile;
  753. CHECK_SOUND();
  754. BG.BitShift = 4;
  755. BG.TileShift = 5;
  756. BG.TileAddress = PPU.OBJNameBase;
  757. BG.StartPalette = 128;
  758. BG.PaletteShift = 4;
  759. BG.PaletteMask = 7;
  760. BG.Buffer = IPPU.TileCache [TILE_4BIT];
  761. BG.Buffered = IPPU.TileCached [TILE_4BIT];
  762. BG.NameSelect = PPU.OBJNameSelect;
  763. BG.DirectColourMode = FALSE;
  764. GFX.PixSize = 1;
  765. GFX.Z1 = D + 2;
  766. int I = 0;
  767. for (int S = GFX.OBJList [I++]; S >= 0; S = GFX.OBJList [I++])
  768. {
  769. int VPos = GFX.VPositions [S];
  770. int Size = GFX.Sizes[S];
  771. int TileInc = 1;
  772. int Offset;
  773. if (VPos + Size <= (int) GFX.StartY || VPos > (int) GFX.EndY)
  774. continue;
  775. if (OnMain && SUB_OR_ADD(4))
  776. {
  777. SelectTileRenderer (!GFX.Pseudo && PPU.OBJ [S].Palette < 4);
  778. }
  779. BaseTile = PPU.OBJ[S].Name | (PPU.OBJ[S].Palette << 10);
  780. if (PPU.OBJ[S].HFlip)
  781. {
  782. BaseTile += ((Size >> 3) - 1) | H_FLIP;
  783. TileInc = -1;
  784. }
  785. if (PPU.OBJ[S].VFlip)
  786. BaseTile |= V_FLIP;
  787. int clipcount = GFX.pCurrentClip->Count [4];
  788. if (!clipcount)
  789. clipcount = 1;
  790. GFX.Z2 = (PPU.OBJ[S].Priority + 1) * 4 + D;
  791. for (int clip = 0; clip < clipcount; clip++)
  792. {
  793. int Left;
  794. int Right;
  795. if (!GFX.pCurrentClip->Count [4])
  796. {
  797. Left = 0;
  798. Right = 256;
  799. }
  800. else
  801. {
  802. Left = GFX.pCurrentClip->Left [clip][4];
  803. Right = GFX.pCurrentClip->Right [clip][4];
  804. }
  805. if (Right <= Left || PPU.OBJ[S].HPos + Size <= Left ||
  806. PPU.OBJ[S].HPos >= Right)
  807. continue;
  808. for (int Y = 0; Y < Size; Y += 8)
  809. {
  810. if (VPos + Y + 7 >= (int) GFX.StartY && VPos + Y <= (int) GFX.EndY)
  811. {
  812. int StartLine;
  813. int TileLine;
  814. int LineCount;
  815. int Last;
  816. if ((StartLine = VPos + Y) < (int) GFX.StartY)
  817. {
  818. StartLine = GFX.StartY - StartLine;
  819. LineCount = 8 - StartLine;
  820. }
  821. else
  822. {
  823. StartLine = 0;
  824. LineCount = 8;
  825. }
  826. if ((Last = VPos + Y + 7 - GFX.EndY) > 0)
  827. if ((LineCount -= Last) <= 0)
  828. break;
  829. TileLine = StartLine << 3;
  830. O = (VPos + Y + StartLine) * GFX.PPL;
  831. if (!PPU.OBJ[S].VFlip)
  832. Tile = BaseTile + (Y << 1);
  833. else
  834. Tile = BaseTile + ((Size - Y - 8) << 1);
  835. int Middle = Size >> 3;
  836. if (PPU.OBJ[S].HPos < Left)
  837. {
  838. Tile += ((Left - PPU.OBJ[S].HPos) >> 3) * TileInc;
  839. Middle -= (Left - PPU.OBJ[S].HPos) >> 3;
  840. O += Left * GFX.PixSize;
  841. if ((Offset = (Left - PPU.OBJ[S].HPos) & 7))
  842. {
  843. O -= Offset * GFX.PixSize;
  844. int W = 8 - Offset;
  845. int Width = Right - Left;
  846. if (W > Width)
  847. W = Width;
  848. (*DrawClippedTilePtr) (Tile, O, Offset, W,
  849. TileLine, LineCount, &GFX);
  850. if (W >= Width)
  851. continue;
  852. Tile += TileInc;
  853. Middle--;
  854. O += 8 * GFX.PixSize;
  855. }
  856. }
  857. else
  858. O += PPU.OBJ[S].HPos * GFX.PixSize;
  859. if (PPU.OBJ[S].HPos + Size >= Right)
  860. {
  861. Middle -= ((PPU.OBJ[S].HPos + Size + 7) -
  862. Right) >> 3;
  863. Offset = (Right - (PPU.OBJ[S].HPos + Size)) & 7;
  864. }
  865. else
  866. Offset = 0;
  867. for (int X = 0; X < Middle; X++, O += 8 * GFX.PixSize,
  868. Tile += TileInc)
  869. {
  870. (*DrawTilePtr) (Tile, O, TileLine, LineCount, &GFX);
  871. }
  872. if (Offset)
  873. {
  874. (*DrawClippedTilePtr) (Tile, O, 0, Offset,
  875. TileLine, LineCount, &GFX);
  876. }
  877. }
  878. }
  879. }
  880. }
  881. }
  882. void DrawBackgroundMosaic (uint32 BGMode, uint32 bg, uint8 Z1, uint8 Z2)
  883. {
  884. CHECK_SOUND();
  885. uint32 Tile;
  886. uint16 *SC0;
  887. uint16 *SC1;
  888. uint16 *SC2;
  889. uint16 *SC3;
  890. uint8 depths [2] = {Z1, Z2};
  891. if (BGMode == 0)
  892. BG.StartPalette = bg << 5;
  893. else
  894. BG.StartPalette = 0;
  895. SC0 = (uint16 *) &Memory.VRAM[PPU.BG[bg].SCBase << 1];
  896. if (PPU.BG[bg].SCSize & 1)
  897. SC1 = SC0 + 1024;
  898. else
  899. SC1 = SC0;
  900. if (PPU.BG[bg].SCSize & 2)
  901. SC2 = SC1 + 1024;
  902. else
  903. SC2 = SC0;
  904. if (PPU.BG[bg].SCSize & 1)
  905. SC3 = SC2 + 1024;
  906. else
  907. SC3 = SC2;
  908. uint32 Lines;
  909. uint32 OffsetMask;
  910. uint32 OffsetShift;
  911. if (BG.TileSize == 16)
  912. {
  913. OffsetMask = 0x3ff;
  914. OffsetShift = 4;
  915. }
  916. else
  917. {
  918. OffsetMask = 0x1ff;
  919. OffsetShift = 3;
  920. }
  921. for (uint32 Y = GFX.StartY; Y <= GFX.EndY; Y += Lines)
  922. {
  923. uint32 VOffset = LineData [Y].BG[bg].VOffset;
  924. uint32 HOffset = LineData [Y].BG[bg].HOffset;
  925. uint32 MosaicOffset = Y % PPU.Mosaic;
  926. for (Lines = 1; Lines < PPU.Mosaic - MosaicOffset; Lines++)
  927. if ((VOffset != LineData [Y + Lines].BG[bg].VOffset) ||
  928. (HOffset != LineData [Y + Lines].BG[bg].HOffset))
  929. break;
  930. uint32 MosaicLine = VOffset + Y - MosaicOffset;
  931. if (Y + Lines > GFX.EndY)
  932. Lines = GFX.EndY + 1 - Y;
  933. uint32 VirtAlign = (MosaicLine & 7) << 3;
  934. uint16 *b1;
  935. uint16 *b2;
  936. uint32 ScreenLine = MosaicLine >> OffsetShift;
  937. uint32 Rem16 = MosaicLine & 15;
  938. if (ScreenLine & 0x20)
  939. b1 = SC2, b2 = SC3;
  940. else
  941. b1 = SC0, b2 = SC1;
  942. b1 += (ScreenLine & 0x1f) << 5;
  943. b2 += (ScreenLine & 0x1f) << 5;
  944. uint16 *t;
  945. uint32 Left = 0;
  946. uint32 Right = 256;
  947. uint32 ClipCount = GFX.pCurrentClip->Count [bg];
  948. uint32 HPos = HOffset;
  949. uint32 PixWidth = PPU.Mosaic;
  950. if (!ClipCount)
  951. ClipCount = 1;
  952. for (uint32 clip = 0; clip < ClipCount; clip++)
  953. {
  954. if (GFX.pCurrentClip->Count [bg])
  955. {
  956. Left = GFX.pCurrentClip->Left [clip][bg];
  957. Right = GFX.pCurrentClip->Right [clip][bg];
  958. uint32 r = Left % PPU.Mosaic;
  959. HPos = HOffset + Left;
  960. PixWidth = PPU.Mosaic - r;
  961. }
  962. uint32 s = Y * GFX.PPL + Left * GFX.PixSize;
  963. for (uint32 x = Left; x < Right; x += PixWidth,
  964. s += PixWidth * GFX.PixSize,
  965. HPos += PixWidth, PixWidth = PPU.Mosaic)
  966. {
  967. uint32 Quot = (HPos & OffsetMask) >> 3;
  968. if (x + PixWidth >= Right)
  969. PixWidth = Right - x;
  970. if (BG.TileSize == 8)
  971. {
  972. if (Quot > 31)
  973. t = b2 + (Quot & 0x1f);
  974. else
  975. t = b1 + Quot;
  976. }
  977. else
  978. {
  979. if (Quot > 63)
  980. t = b2 + ((Quot >> 1) & 0x1f);
  981. else
  982. t = b1 + (Quot >> 1);
  983. }
  984. Tile = READ_2BYTES (t);
  985. GFX.Z1 = GFX.Z2 = depths [(Tile & 0x2000) >> 13];
  986. // Draw tile...
  987. if (BG.TileSize != 8)
  988. {
  989. if (Tile & H_FLIP)
  990. {
  991. // Horizontal flip, but what about vertical flip ?
  992. if (Tile & V_FLIP)
  993. {
  994. // Both horzontal & vertical flip
  995. if (Rem16 < 8)
  996. {
  997. (*DrawLargePixelPtr) (Tile + 17 - (Quot & 1), s,
  998. HPos & 7, PixWidth,
  999. VirtAlign, Lines, &GFX);
  1000. }
  1001. else
  1002. {
  1003. (*DrawLargePixelPtr) (Tile + 1 - (Quot & 1), s,
  1004. HPos & 7, PixWidth,
  1005. VirtAlign, Lines, &GFX);
  1006. }
  1007. }
  1008. else
  1009. {
  1010. // Horizontal flip only
  1011. if (Rem16 > 7)
  1012. {
  1013. (*DrawLargePixelPtr) (Tile + 17 - (Quot & 1), s,
  1014. HPos & 7, PixWidth,
  1015. VirtAlign, Lines, &GFX);
  1016. }
  1017. else
  1018. {
  1019. (*DrawLargePixelPtr) (Tile + 1 - (Quot & 1), s,
  1020. HPos & 7, PixWidth,
  1021. VirtAlign, Lines, &GFX);
  1022. }
  1023. }
  1024. }
  1025. else
  1026. {
  1027. // No horizontal flip, but is there a vertical flip ?
  1028. if (Tile & V_FLIP)
  1029. {
  1030. // Vertical flip only
  1031. if (Rem16 < 8)
  1032. {
  1033. (*DrawLargePixelPtr) (Tile + 16 + (Quot & 1), s,
  1034. HPos & 7, PixWidth,
  1035. VirtAlign, Lines, &GFX);
  1036. }
  1037. else
  1038. {
  1039. (*DrawLargePixelPtr) (Tile + (Quot & 1), s,
  1040. HPos & 7, PixWidth,
  1041. VirtAlign, Lines, &GFX);
  1042. }
  1043. }
  1044. else
  1045. {
  1046. // Normal unflipped
  1047. if (Rem16 > 7)
  1048. {
  1049. (*DrawLargePixelPtr) (Tile + 16 + (Quot & 1), s,
  1050. HPos & 7, PixWidth,
  1051. VirtAlign, Lines, &GFX);
  1052. }
  1053. else
  1054. {
  1055. (*DrawLargePixelPtr) (Tile + (Quot & 1), s,
  1056. HPos & 7, PixWidth,
  1057. VirtAlign, Lines, &GFX);
  1058. }
  1059. }
  1060. }
  1061. }
  1062. else
  1063. (*DrawLargePixelPtr) (Tile, s, HPos & 7, PixWidth,
  1064. VirtAlign, Lines, &GFX);
  1065. }
  1066. }
  1067. }
  1068. }
  1069. void DrawBackgroundOffset (uint32 BGMode, uint32 bg, uint8 Z1, uint8 Z2)
  1070. {
  1071. CHECK_SOUND();
  1072. uint32 Tile;
  1073. uint16 *SC0;
  1074. uint16 *SC1;
  1075. uint16 *SC2;
  1076. uint16 *SC3;
  1077. uint16 *BPS0;
  1078. uint16 *BPS1;
  1079. uint16 *BPS2;
  1080. uint16 *BPS3;
  1081. uint32 Width;
  1082. int VOffsetOffset = BGMode == 4 ? 0 : 32;
  1083. uint8 depths [2] = {Z1, Z2};
  1084. BG.StartPalette = 0;
  1085. BPS0 = (uint16 *) &Memory.VRAM[PPU.BG[2].SCBase << 1];
  1086. if (PPU.BG[2].SCSize & 1)
  1087. BPS1 = BPS0 + 1024;
  1088. else
  1089. BPS1 = BPS0;
  1090. if (PPU.BG[2].SCSize & 2)
  1091. BPS2 = BPS1 + 1024;
  1092. else
  1093. BPS2 = BPS0;
  1094. if (PPU.BG[2].SCSize & 1)
  1095. BPS3 = BPS2 + 1024;
  1096. else
  1097. BPS3 = BPS2;
  1098. SC0 = (uint16 *) &Memory.VRAM[PPU.BG[bg].SCBase << 1];
  1099. if (PPU.BG[bg].SCSize & 1)
  1100. SC1 = SC0 + 1024;
  1101. else
  1102. SC1 = SC0;
  1103. if (PPU.BG[bg].SCSize & 2)
  1104. SC2 = SC1 + 1024;
  1105. else
  1106. SC2 = SC0;
  1107. if (PPU.BG[bg].SCSize & 1)
  1108. SC3 = SC2 + 1024;
  1109. else
  1110. SC3 = SC2;
  1111. static const int Lines = 1;
  1112. int OffsetMask;
  1113. int OffsetShift;
  1114. int OffsetEnableMask = 1 << (bg + 13);
  1115. if (BG.TileSize == 16)
  1116. {
  1117. OffsetMask = 0x3ff;
  1118. OffsetShift = 4;
  1119. }
  1120. else
  1121. {
  1122. OffsetMask = 0x1ff;
  1123. OffsetShift = 3;
  1124. }
  1125. for (uint32 Y = GFX.StartY; Y <= GFX.EndY; Y++)
  1126. {
  1127. uint32 VOff = LineData [Y].BG[2].VOffset;
  1128. uint32 HOff = LineData [Y].BG[2].HOffset;
  1129. int VirtAlign;
  1130. int ScreenLine = VOff >> 3;
  1131. int t1;
  1132. int t2;
  1133. uint16 *s0;
  1134. uint16 *s1;
  1135. uint16 *s2;
  1136. if (ScreenLine & 0x20)
  1137. s1 = BPS2, s2 = BPS3;
  1138. else
  1139. s1 = BPS0, s2 = BPS1;
  1140. s1 += (ScreenLine & 0x1f) << 5;
  1141. s2 += (ScreenLine & 0x1f) << 5;
  1142. int clipcount = GFX.pCurrentClip->Count [bg];
  1143. if (!clipcount)
  1144. clipcount = 1;
  1145. for (int clip = 0; clip < clipcount; clip++)
  1146. {
  1147. uint32 Left;
  1148. uint32 Right;
  1149. if (!GFX.pCurrentClip->Count [bg])
  1150. {
  1151. Left = 0;
  1152. Right = 256;
  1153. }
  1154. else
  1155. {
  1156. Left = GFX.pCurrentClip->Left [clip][bg];
  1157. Right = GFX.pCurrentClip->Right [clip][bg];
  1158. if (Right <= Left)
  1159. continue;
  1160. }
  1161. uint32 VOffset;
  1162. uint32 HOffset;
  1163. uint32 LineHOffset=LineData [Y].BG[bg].HOffset;
  1164. uint32 Offset;
  1165. uint32 HPos;
  1166. uint32 Quot;
  1167. uint32 Count;
  1168. uint16 *t;
  1169. uint32 Quot2;
  1170. uint32 VCellOffset;
  1171. uint32 HCellOffset;
  1172. uint16 *b1;
  1173. uint16 *b2;
  1174. uint32 TotalCount = 0;
  1175. uint32 MaxCount = 8;
  1176. uint32 s = Left * GFX.PixSize + Y * GFX.PPL;
  1177. bool8_32 left_hand_edge = (Left == 0);
  1178. Width = Right - Left;
  1179. if (Left & 7)
  1180. MaxCount = 8 - (Left & 7);
  1181. while (Left < Right)
  1182. {
  1183. if (left_hand_edge)
  1184. {
  1185. // The SNES offset-per-tile background mode has a
  1186. // hardware limitation that the offsets cannot be set
  1187. // for the tile at the left-hand edge of the screen.
  1188. VOffset = LineData [Y].BG[bg].VOffset;
  1189. HOffset = LineHOffset;
  1190. left_hand_edge = FALSE;
  1191. }
  1192. else
  1193. {
  1194. // All subsequent offset tile data is shifted left by one,
  1195. // hence the - 1 below.
  1196. Quot2 = ((HOff + Left - 1) & OffsetMask) >> 3;
  1197. if (Quot2 > 31)
  1198. s0 = s2 + (Quot2 & 0x1f);
  1199. else
  1200. s0 = s1 + Quot2;
  1201. HCellOffset = READ_2BYTES (s0);
  1202. if (BGMode == 4)
  1203. {
  1204. VOffset = LineData [Y].BG[bg].VOffset;
  1205. HOffset=LineHOffset;
  1206. if ((HCellOffset & OffsetEnableMask))
  1207. {
  1208. if (HCellOffset & 0x8000)
  1209. VOffset = HCellOffset + 1;
  1210. else
  1211. HOffset = HCellOffset;
  1212. }
  1213. }
  1214. else
  1215. {
  1216. VCellOffset = READ_2BYTES (s0 + VOffsetOffset);
  1217. if ((VCellOffset & OffsetEnableMask))
  1218. VOffset = VCellOffset + 1;
  1219. else
  1220. VOffset = LineData [Y].BG[bg].VOffset;
  1221. if ((HCellOffset & OffsetEnableMask))
  1222. HOffset = (HCellOffset & ~7)|(LineHOffset&7);
  1223. else
  1224. HOffset=LineHOffset;
  1225. }
  1226. }
  1227. VirtAlign = ((Y + VOffset) & 7) << 3;
  1228. ScreenLine = (VOffset + Y) >> OffsetShift;
  1229. if (((VOffset + Y) & 15) > 7)
  1230. {
  1231. t1 = 16;
  1232. t2 = 0;
  1233. }
  1234. else
  1235. {
  1236. t1 = 0;
  1237. t2 = 16;
  1238. }
  1239. if (ScreenLine & 0x20)
  1240. b1 = SC2, b2 = SC3;
  1241. else
  1242. b1 = SC0, b2 = SC1;
  1243. b1 += (ScreenLine & 0x1f) << 5;
  1244. b2 += (ScreenLine & 0x1f) << 5;
  1245. HPos = (HOffset + Left) & OffsetMask;
  1246. Quot = HPos >> 3;
  1247. if (BG.TileSize == 8)
  1248. {
  1249. if (Quot > 31)
  1250. t = b2 + (Quot & 0x1f);
  1251. else
  1252. t = b1 + Quot;
  1253. }
  1254. else
  1255. {
  1256. if (Quot > 63)
  1257. t = b2 + ((Quot >> 1) & 0x1f);
  1258. else
  1259. t = b1 + (Quot >> 1);
  1260. }
  1261. if (MaxCount + TotalCount > Width)
  1262. MaxCount = Width - TotalCount;
  1263. Offset = HPos & 7;
  1264. Count = 8 - Offset;
  1265. if (Count > MaxCount)
  1266. Count = MaxCount;
  1267. s -= Offset * GFX.PixSize;
  1268. Tile = READ_2BYTES(t);
  1269. GFX.Z1 = GFX.Z2 = depths [(Tile & 0x2000) >> 13];
  1270. if (BG.TileSize == 8)
  1271. (*DrawClippedTilePtr) (Tile, s, Offset, Count, VirtAlign, Lines, &GFX);
  1272. else
  1273. {
  1274. if (!(Tile & (V_FLIP | H_FLIP)))
  1275. {
  1276. // Normal, unflipped
  1277. (*DrawClippedTilePtr) (Tile + t1 + (Quot & 1),
  1278. s, Offset, Count, VirtAlign, Lines, &GFX);
  1279. }
  1280. else
  1281. if (Tile & H_FLIP)
  1282. {
  1283. if (Tile & V_FLIP)
  1284. {
  1285. // H & V flip
  1286. (*DrawClippedTilePtr) (Tile + t2 + 1 - (Quot & 1),
  1287. s, Offset, Count, VirtAlign, Lines, &GFX);
  1288. }
  1289. else
  1290. {
  1291. // H flip only
  1292. (*DrawClippedTilePtr) (Tile + t1 + 1 - (Quot & 1),
  1293. s, Offset, Count, VirtAlign, Lines, &GFX);
  1294. }
  1295. }
  1296. else
  1297. {
  1298. // V flip only
  1299. (*DrawClippedTilePtr) (Tile + t2 + (Quot & 1),
  1300. s, Offset, Count, VirtAlign, Lines, &GFX);
  1301. }
  1302. }
  1303. Left += Count;
  1304. TotalCount += Count;
  1305. s += (Offset + Count) * GFX.PixSize;
  1306. MaxCount = 8;
  1307. }
  1308. }
  1309. }
  1310. }
  1311. void DrawBackgroundMode5 (uint32 /* BGMODE */, uint32 bg, uint8 Z1, uint8 Z2)
  1312. {
  1313. CHECK_SOUND();
  1314. GFX.Pitch = GFX.RealPitch;
  1315. GFX.PPL = GFX.PPLx2 >> 1;
  1316. GFX.PixSize = 1;
  1317. uint8 depths [2] = {Z1, Z2};
  1318. uint32 Tile;
  1319. uint16 *SC0;
  1320. uint16 *SC1;
  1321. uint16 *SC2;
  1322. uint16 *SC3;
  1323. uint32 Width;
  1324. BG.StartPalette = 0;
  1325. SC0 = (uint16 *) &Memory.VRAM[PPU.BG[bg].SCBase << 1];
  1326. if ((PPU.BG[bg].SCSize & 1))
  1327. SC1 = SC0 + 1024;
  1328. else
  1329. SC1 = SC0;
  1330. if ((PPU.BG[bg].SCSize & 2))
  1331. SC2 = SC1 + 1024;
  1332. else
  1333. SC2 = SC0;
  1334. if ((PPU.BG[bg].SCSize & 1))
  1335. SC3 = SC2 + 1024;
  1336. else
  1337. SC3 = SC2;
  1338. int Lines;
  1339. int VOffsetMask;
  1340. int VOffsetShift;
  1341. if (BG.TileSize == 16)
  1342. {
  1343. VOffsetMask = 0x3ff;
  1344. VOffsetShift = 4;
  1345. }
  1346. else
  1347. {
  1348. VOffsetMask = 0x1ff;
  1349. VOffsetShift = 3;
  1350. }
  1351. int endy = GFX.EndY;
  1352. for (int Y = GFX.StartY; Y <= endy; Y += Lines)
  1353. {
  1354. int y = Y;
  1355. uint32 VOffset = LineData [y].BG[bg].VOffset;
  1356. uint32 HOffset = LineData [y].BG[bg].HOffset;
  1357. int VirtAlign = (Y + VOffset) & 7;
  1358. for (Lines = 1; Lines < 8 - VirtAlign; Lines++)
  1359. if ((VOffset != LineData [y + Lines].BG[bg].VOffset) ||
  1360. (HOffset != LineData [y + Lines].BG[bg].HOffset))
  1361. break;
  1362. HOffset <<= 1;
  1363. if (Y + Lines > endy)
  1364. Lines = endy + 1 - Y;
  1365. int ScreenLine = (VOffset + Y) >> VOffsetShift;
  1366. int t1;
  1367. int t2;
  1368. if (((VOffset + Y) & 15) > 7)
  1369. {
  1370. t1 = 16;
  1371. t2 = 0;
  1372. }
  1373. else
  1374. {
  1375. t1 = 0;
  1376. t2 = 16;
  1377. }
  1378. uint16 *b1;
  1379. uint16 *b2;
  1380. if (ScreenLine & 0x20)
  1381. b1 = SC2, b2 = SC3;
  1382. else
  1383. b1 = SC0, b2 = SC1;
  1384. b1 += (ScreenLine & 0x1f) << 5;
  1385. b2 += (ScreenLine & 0x1f) << 5;
  1386. int clipcount = GFX.pCurrentClip->Count [bg];
  1387. if (!clipcount)
  1388. clipcount = 1;
  1389. for (int clip = 0; clip < clipcount; clip++)
  1390. {
  1391. int Left;
  1392. int Right;
  1393. if (!GFX.pCurrentClip->Count [bg])
  1394. {
  1395. Left = 0;
  1396. Right = 512;
  1397. }
  1398. else
  1399. {
  1400. Left = GFX.pCurrentClip->Left [clip][bg] * 2;
  1401. Right = GFX.pCurrentClip->Right [clip][bg] * 2;
  1402. if (Right <= Left)
  1403. continue;
  1404. }
  1405. uint32 s = (Left>>1) * GFX.PixSize + Y * GFX.PPL;
  1406. uint32 HPos = (HOffset + Left * GFX.PixSize) & 0x3ff;
  1407. uint32 Quot = HPos >> 3;
  1408. uint32 Count = 0;
  1409. uint16 *t;
  1410. if (Quot > 63)
  1411. t = b2 + ((Quot >> 1) & 0x1f);
  1412. else
  1413. t = b1 + (Quot >> 1);
  1414. Width = Right - Left;
  1415. // Left hand edge clipped tile
  1416. if (HPos & 7)
  1417. {
  1418. int Offset = (HPos & 7);
  1419. Count = 8 - Offset;
  1420. if (Count > Width)
  1421. Count = Width;
  1422. s -= (Offset>>1);
  1423. Tile = READ_2BYTES (t);
  1424. GFX.Z1 = GFX.Z2 = depths [(Tile & 0x2000) >> 13];
  1425. if (BG.TileSize == 8)
  1426. {
  1427. if (!(Tile & H_FLIP))
  1428. {
  1429. // Normal, unflipped
  1430. (*DrawHiResClippedTilePtr) (Tile + (Quot & 1),
  1431. s, Offset, Count, VirtAlign, Lines, &GFX);
  1432. }
  1433. else
  1434. {
  1435. // H flip
  1436. (*DrawHiResClippedTilePtr) (Tile + 1 - (Quot & 1),
  1437. s, Offset, Count, VirtAlign, Lines, &GFX);
  1438. }
  1439. }
  1440. else
  1441. {
  1442. if (!(Tile & (V_FLIP | H_FLIP)))
  1443. {
  1444. // Normal, unflipped
  1445. (*DrawHiResClippedTilePtr) (Tile + t1 + (Quot & 1),
  1446. s, Offset, Count, VirtAlign, Lines, &GFX);
  1447. }
  1448. else
  1449. if (Tile & H_FLIP)
  1450. {
  1451. if (Tile & V_FLIP)
  1452. {
  1453. // H & V flip
  1454. (*DrawHiResClippedTilePtr) (Tile + t2 + 1 - (Quot & 1),
  1455. s, Offset, Count, VirtAlign, Lines, &GFX);
  1456. }
  1457. else
  1458. {
  1459. // H flip only
  1460. (*DrawHiResClippedTilePtr) (Tile + t1 + 1 - (Quot & 1),
  1461. s, Offset, Count, VirtAlign, Lines, &GFX);
  1462. }
  1463. }
  1464. else
  1465. {
  1466. // V flip only
  1467. (*DrawHiResClippedTilePtr) (Tile + t2 + (Quot & 1),
  1468. s, Offset, Count, VirtAlign, Lines, &GFX);
  1469. }
  1470. }
  1471. t += Quot & 1;
  1472. if (Quot == 63)
  1473. t = b2;
  1474. else if (Quot == 127)
  1475. t = b1;
  1476. Quot++;
  1477. s += 4;
  1478. }
  1479. // Middle, unclipped tiles
  1480. Count = Width - Count;
  1481. int Middle = Count >> 3;
  1482. Count &= 7;
  1483. for (int C = Middle; C > 0; s += 4, Quot++, C--)
  1484. {
  1485. Tile = READ_2BYTES(t);
  1486. GFX.Z1 = GFX.Z2 = depths [(Tile & 0x2000) >> 13];
  1487. if (BG.TileSize == 8)
  1488. {
  1489. if (!(Tile & H_FLIP))
  1490. {
  1491. // Normal, unflipped
  1492. (*DrawHiResTilePtr) (Tile + (Quot & 1),
  1493. s, VirtAlign, Lines, &GFX);
  1494. }
  1495. else
  1496. {
  1497. // H flip
  1498. (*DrawHiResTilePtr) (Tile + 1 - (Quot & 1),
  1499. s, VirtAlign, Lines, &GFX);
  1500. }
  1501. }
  1502. else
  1503. {
  1504. if (!(Tile & (V_FLIP | H_FLIP)))
  1505. {
  1506. // Normal, unflipped
  1507. (*DrawHiResTilePtr) (Tile + t1 + (Quot & 1),
  1508. s, VirtAlign, Lines, &GFX);
  1509. }
  1510. else
  1511. if (Tile & H_FLIP)
  1512. {
  1513. if (Tile & V_FLIP)
  1514. {
  1515. // H & V flip
  1516. (*DrawHiResTilePtr) (Tile + t2 + 1 - (Quot & 1),
  1517. s, VirtAlign, Lines, &GFX);
  1518. }
  1519. else
  1520. {
  1521. // H flip only
  1522. (*DrawHiResTilePtr) (Tile + t1 + 1 - (Quot & 1),
  1523. s, VirtAlign, Lines, &GFX);
  1524. }
  1525. }
  1526. else
  1527. {
  1528. // V flip only
  1529. (*DrawHiResTilePtr) (Tile + t2 + (Quot & 1),
  1530. s, VirtAlign, Lines, &GFX);
  1531. }
  1532. }
  1533. t += Quot & 1;
  1534. if (Quot == 63)
  1535. t = b2;
  1536. else
  1537. if (Quot == 127)
  1538. t = b1;
  1539. }
  1540. // Right-hand edge clipped tiles
  1541. if (Count)
  1542. {
  1543. Tile = READ_2BYTES(t);
  1544. GFX.Z1 = GFX.Z2 = depths [(Tile & 0x2000) >> 13];
  1545. if (BG.TileSize == 8)
  1546. {
  1547. if (!(Tile & H_FLIP))
  1548. {
  1549. // Normal, unflipped
  1550. (*DrawHiResClippedTilePtr) (Tile + (Quot & 1),
  1551. s, 0, Count, VirtAlign, Lines, &GFX);
  1552. }
  1553. else
  1554. {
  1555. // H flip
  1556. (*DrawHiResClippedTilePtr) (Tile + 1 - (Quot & 1),
  1557. s, 0, Count, VirtAlign, Lines, &GFX);
  1558. }
  1559. }
  1560. else
  1561. {
  1562. if (!(Tile & (V_FLIP | H_FLIP)))
  1563. {
  1564. // Normal, unflipped
  1565. (*DrawHiResClippedTilePtr) (Tile + t1 + (Quot & 1),
  1566. s, 0, Count, VirtAlign, Lines, &GFX);
  1567. }
  1568. else
  1569. if (Tile & H_FLIP)
  1570. {
  1571. if (Tile & V_FLIP)
  1572. {
  1573. // H & V flip
  1574. (*DrawHiResClippedTilePtr) (Tile + t2 + 1 - (Quot & 1),
  1575. s, 0, Count, VirtAlign, Lines, &GFX);
  1576. }
  1577. else
  1578. {
  1579. // H flip only
  1580. (*DrawHiResClippedTilePtr) (Tile + t1 + 1 - (Quot & 1),
  1581. s, 0, Count, VirtAlign, Lines, &GFX);
  1582. }
  1583. }
  1584. else
  1585. {
  1586. // V flip only
  1587. (*DrawHiResClippedTilePtr) (Tile + t2 + (Quot & 1),
  1588. s, 0, Count, VirtAlign, Lines, &GFX);
  1589. }
  1590. }
  1591. }
  1592. }
  1593. }
  1594. }
  1595. void DrawBackground (uint32 BGMode, uint32 bg, uint8 Z1, uint8 Z2)
  1596. {
  1597. GFX.PixSize = 1;
  1598. BG.TileSize = BGSizes [PPU.BG[bg].BGSize];
  1599. BG.BitShift = BitShifts[BGMode][bg];
  1600. BG.TileShift = TileShifts[BGMode][bg];
  1601. BG.TileAddress = PPU.BG[bg].NameBase << 1;
  1602. BG.NameSelect = 0;
  1603. BG.Buffer = IPPU.TileCache [Depths [BGMode][bg]];
  1604. BG.Buffered = IPPU.TileCached [Depths [BGMode][bg]];
  1605. BG.PaletteShift = PaletteShifts[BGMode][bg];
  1606. BG.PaletteMask = PaletteMasks[BGMode][bg];
  1607. BG.DirectColourMode = (BGMode == 3 || BGMode == 4) && bg == 0 &&
  1608. (GFX.r2130 & 1);
  1609. if (PPU.BGMosaic [bg] && PPU.Mosaic > 1)
  1610. {
  1611. DrawBackgroundMosaic (BGMode, bg, Z1, Z2);
  1612. return;
  1613. }
  1614. switch (BGMode)
  1615. {
  1616. case 2:
  1617. if (Settings.WrestlemaniaArcade)
  1618. break;
  1619. case 4: // Used by Puzzle Bobble
  1620. DrawBackgroundOffset (BGMode, bg, Z1, Z2);
  1621. return;
  1622. case 5:
  1623. case 6: // XXX: is also offset per tile.
  1624. DrawBackgroundMode5 (BGMode, bg, Z1, Z2);
  1625. return;
  1626. }
  1627. CHECK_SOUND();
  1628. uint32 Tile;
  1629. uint16 *SC0;
  1630. uint16 *SC1;
  1631. uint16 *SC2;
  1632. uint16 *SC3;
  1633. uint32 Width;
  1634. uint8 depths [2] = {Z1, Z2};
  1635. if (BGMode == 0)
  1636. BG.StartPalette = bg << 5;
  1637. else
  1638. BG.StartPalette = 0;
  1639. SC0 = (uint16 *) &Memory.VRAM[PPU.BG[bg].SCBase << 1];
  1640. if (PPU.BG[bg].SCSize & 1)
  1641. SC1 = SC0 + 1024;
  1642. else
  1643. SC1 = SC0;
  1644. if (PPU.BG[bg].SCSize & 2)
  1645. SC2 = SC1 + 1024;
  1646. else
  1647. SC2 = SC0;
  1648. if (PPU.BG[bg].SCSize & 1)
  1649. SC3 = SC2 + 1024;
  1650. else
  1651. SC3 = SC2;
  1652. int Lines;
  1653. int OffsetMask;
  1654. int OffsetShift;
  1655. if (BG.TileSize == 16)
  1656. {
  1657. OffsetMask = 0x3ff;
  1658. OffsetShift = 4;
  1659. }
  1660. else
  1661. {
  1662. OffsetMask = 0x1ff;
  1663. OffsetShift = 3;
  1664. }
  1665. for (uint32 Y = GFX.StartY; Y <= GFX.EndY; Y += Lines)
  1666. {
  1667. uint32 VOffset = LineData [Y].BG[bg].VOffset;
  1668. uint32 HOffset = LineData [Y].BG[bg].HOffset;
  1669. int VirtAlign = (Y + VOffset) & 7;
  1670. for (Lines = 1; Lines < 8 - VirtAlign; Lines++)
  1671. if ((VOffset != LineData [Y + Lines].BG[bg].VOffset) ||
  1672. (HOffset != LineData [Y + Lines].BG[bg].HOffset))
  1673. break;
  1674. if (Y + Lines > GFX.EndY)
  1675. Lines = GFX.EndY + 1 - Y;
  1676. VirtAlign <<= 3;
  1677. uint32 ScreenLine = (VOffset + Y) >> OffsetShift;
  1678. uint32 t1;
  1679. uint32 t2;
  1680. if (((VOffset + Y) & 15) > 7)
  1681. {
  1682. t1 = 16;
  1683. t2 = 0;
  1684. }
  1685. else
  1686. {
  1687. t1 = 0;
  1688. t2 = 16;
  1689. }
  1690. uint16 *b1;
  1691. uint16 *b2;
  1692. if (ScreenLine & 0x20)
  1693. b1 = SC2, b2 = SC3;
  1694. else
  1695. b1 = SC0, b2 = SC1;
  1696. b1 += (ScreenLine & 0x1f) << 5;
  1697. b2 += (ScreenLine & 0x1f) << 5;
  1698. int clipcount = GFX.pCurrentClip->Count [bg];
  1699. if (!clipcount)
  1700. clipcount = 1;
  1701. for (int clip = 0; clip < clipcount; clip++)
  1702. {
  1703. uint32 Left;
  1704. uint32 Right;
  1705. if (!GFX.pCurrentClip->Count [bg])
  1706. {
  1707. Left = 0;
  1708. Right = 256;
  1709. }
  1710. else
  1711. {
  1712. Left = GFX.pCurrentClip->Left [clip][bg];
  1713. Right = GFX.pCurrentClip->Right [clip][bg];
  1714. if (Right <= Left)
  1715. continue;
  1716. }
  1717. uint32 s = Left * GFX.PixSize + Y * GFX.PPL;
  1718. uint32 HPos = (HOffset + Left) & OffsetMask;
  1719. uint32 Quot = HPos >> 3;
  1720. uint32 Count = 0;
  1721. uint16 *t;
  1722. if (BG.TileSize == 8)
  1723. {
  1724. if (Quot > 31)
  1725. t = b2 + (Quot & 0x1f);
  1726. else
  1727. t = b1 + Quot;
  1728. }
  1729. else
  1730. {
  1731. if (Quot > 63)
  1732. t = b2 + ((Quot >> 1) & 0x1f);
  1733. else
  1734. t = b1 + (Quot >> 1);
  1735. }
  1736. Width = Right - Left;
  1737. // Left hand edge clipped tile
  1738. if (HPos & 7)
  1739. {
  1740. uint32 Offset = (HPos & 7);
  1741. Count = 8 - Offset;
  1742. if (Count > Width)
  1743. Count = Width;
  1744. s -= Offset * GFX.PixSize;
  1745. Tile = READ_2BYTES(t);
  1746. GFX.Z1 = GFX.Z2 = depths [(Tile & 0x2000) >> 13];
  1747. if (BG.TileSize == 8)
  1748. {
  1749. (*DrawClippedTilePtr) (Tile, s, Offset, Count, VirtAlign,
  1750. Lines, &GFX);
  1751. }
  1752. else
  1753. {
  1754. if (!(Tile & (V_FLIP | H_FLIP)))
  1755. {
  1756. // Normal, unflipped
  1757. (*DrawClippedTilePtr) (Tile + t1 + (Quot & 1),
  1758. s, Offset, Count, VirtAlign, Lines, &GFX);
  1759. }
  1760. else
  1761. if (Tile & H_FLIP)
  1762. {
  1763. if (Tile & V_FLIP)
  1764. {
  1765. // H & V flip
  1766. (*DrawClippedTilePtr) (Tile + t2 + 1 - (Quot & 1),
  1767. s, Offset, Count, VirtAlign, Lines, &GFX);
  1768. }
  1769. else
  1770. {
  1771. // H flip only
  1772. (*DrawClippedTilePtr) (Tile + t1 + 1 - (Quot & 1),
  1773. s, Offset, Count, VirtAlign, Lines, &GFX);
  1774. }
  1775. }
  1776. else
  1777. {
  1778. // V flip only
  1779. (*DrawClippedTilePtr) (Tile + t2 + (Quot & 1), s,
  1780. Offset, Count, VirtAlign, Lines, &GFX);
  1781. }
  1782. }
  1783. if (BG.TileSize == 8)
  1784. {
  1785. t++;
  1786. if (Quot == 31)
  1787. t = b2;
  1788. else if (Quot == 63)
  1789. t = b1;
  1790. }
  1791. else
  1792. {
  1793. t += Quot & 1;
  1794. if (Quot == 63)
  1795. t = b2;
  1796. else if (Quot == 127)
  1797. t = b1;
  1798. }
  1799. Quot++;
  1800. s += 8 * GFX.PixSize;
  1801. }
  1802. // Middle, unclipped tiles
  1803. Count = Width - Count;
  1804. int Middle = Count >> 3;
  1805. Count &= 7;
  1806. for (int C = Middle; C > 0; s += 8 * GFX.PixSize, Quot++, C--)
  1807. {
  1808. Tile = READ_2BYTES(t);
  1809. GFX.Z1 = GFX.Z2 = depths [(Tile & 0x2000) >> 13];
  1810. if (BG.TileSize != 8)
  1811. {
  1812. if (Tile & H_FLIP)
  1813. {
  1814. // Horizontal flip, but what about vertical flip ?
  1815. if (Tile & V_FLIP)
  1816. {
  1817. // Both horzontal & vertical flip
  1818. (*DrawTilePtr) (Tile + t2 + 1 - (Quot & 1), s,
  1819. VirtAlign, Lines, &GFX);
  1820. }
  1821. else
  1822. {
  1823. // Horizontal flip only
  1824. (*DrawTilePtr) (Tile + t1 + 1 - (Quot & 1), s,
  1825. VirtAlign, Lines, &GFX);
  1826. }
  1827. }
  1828. else
  1829. {
  1830. // No horizontal flip, but is there a vertical flip ?
  1831. if (Tile & V_FLIP)
  1832. {
  1833. // Vertical flip only
  1834. (*DrawTilePtr) (Tile + t2 + (Quot & 1), s,
  1835. VirtAlign, Lines, &GFX);
  1836. }
  1837. else
  1838. {
  1839. // Normal unflipped
  1840. (*DrawTilePtr) (Tile + t1 + (Quot & 1), s,
  1841. VirtAlign, Lines, &GFX);
  1842. }
  1843. }
  1844. }
  1845. else
  1846. {
  1847. (*DrawTilePtr) (Tile, s, VirtAlign, Lines, &GFX);
  1848. }
  1849. if (BG.TileSize == 8)
  1850. {
  1851. t++;
  1852. if (Quot == 31)
  1853. t = b2;
  1854. else
  1855. if (Quot == 63)
  1856. t = b1;
  1857. }
  1858. else
  1859. {
  1860. t += Quot & 1;
  1861. if (Quot == 63)
  1862. t = b2;
  1863. else
  1864. if (Quot == 127)
  1865. t = b1;
  1866. }
  1867. }
  1868. // Right-hand edge clipped tiles
  1869. if (Count)
  1870. {
  1871. Tile = READ_2BYTES(t);
  1872. GFX.Z1 = GFX.Z2 = depths [(Tile & 0x2000) >> 13];
  1873. if (BG.TileSize == 8)
  1874. (*DrawClippedTilePtr) (Tile, s, 0, Count, VirtAlign,
  1875. Lines, &GFX);
  1876. else
  1877. {
  1878. if (!(Tile & (V_FLIP | H_FLIP)))
  1879. {
  1880. // Normal, unflipped
  1881. (*DrawClippedTilePtr) (Tile + t1 + (Quot & 1), s, 0,
  1882. Count, VirtAlign, Lines, &GFX);
  1883. }
  1884. else
  1885. if (Tile & H_FLIP)
  1886. {
  1887. if (Tile & V_FLIP)
  1888. {
  1889. // H & V flip
  1890. (*DrawClippedTilePtr) (Tile + t2 + 1 - (Quot & 1),
  1891. s, 0, Count, VirtAlign,
  1892. Lines, &GFX);
  1893. }
  1894. else
  1895. {
  1896. // H flip only
  1897. (*DrawClippedTilePtr) (Tile + t1 + 1 - (Quot & 1),
  1898. s, 0, Count, VirtAlign,
  1899. Lines, &GFX);
  1900. }
  1901. }
  1902. else
  1903. {
  1904. // V flip only
  1905. (*DrawClippedTilePtr) (Tile + t2 + (Quot & 1),
  1906. s, 0, Count, VirtAlign,
  1907. Lines, &GFX);
  1908. }
  1909. }
  1910. }
  1911. }
  1912. }
  1913. }
  1914. #define RENDER_BACKGROUND_MODE7(TYPE,FUNC) \
  1915. CHECK_SOUND(); \
  1916. \
  1917. uint8 *VRAM1 = Memory.VRAM + 1; \
  1918. if (GFX.r2130 & 1) \
  1919. { \
  1920. if (IPPU.DirectColourMapsNeedRebuild) \
  1921. S9xBuildDirectColourMaps (); \
  1922. GFX.ScreenColors = DirectColourMaps [0]; \
  1923. } \
  1924. else \
  1925. GFX.ScreenColors = IPPU.ScreenColors; \
  1926. \
  1927. int aa, cc; \
  1928. int dir; \
  1929. int startx, endx; \
  1930. uint32 Left = 0; \
  1931. uint32 Right = 256; \
  1932. uint32 ClipCount = GFX.pCurrentClip->Count [bg]; \
  1933. \
  1934. if (!ClipCount) \
  1935. ClipCount = 1; \
  1936. \
  1937. Screen += GFX.StartY * GFX.Pitch; \
  1938. uint8 *Depth = GFX.DB + GFX.StartY * GFX.PPL; \
  1939. struct SLineMatrixData *l = &LineMatrixData [GFX.StartY]; \
  1940. \
  1941. for (uint32 Line = GFX.StartY; Line <= GFX.EndY; Line++, Screen += GFX.Pitch, Depth += GFX.PPL, l++) \
  1942. { \
  1943. int yy; \
  1944. \
  1945. int32 HOffset = ((int32) LineData [Line].BG[0].HOffset << M7) >> M7; \
  1946. int32 VOffset = ((int32) LineData [Line].BG[0].VOffset << M7) >> M7; \
  1947. \
  1948. int32 CentreX = ((int32) l->CentreX << M7) >> M7; \
  1949. int32 CentreY = ((int32) l->CentreY << M7) >> M7; \
  1950. \
  1951. if (PPU.Mode7VFlip) \
  1952. yy = 261 - (int) Line; \
  1953. else \
  1954. yy = Line; \
  1955. \
  1956. if (PPU.Mode7Repeat == 0) \
  1957. yy += (VOffset - CentreY) % 1023; \
  1958. else \
  1959. yy += VOffset - CentreY; \
  1960. int BB = l->MatrixB * yy + (CentreX << 8); \
  1961. int DD = l->MatrixD * yy + (CentreY << 8); \
  1962. \
  1963. for (uint32 clip = 0; clip < ClipCount; clip++) \
  1964. { \
  1965. if (GFX.pCurrentClip->Count [bg]) \
  1966. { \
  1967. Left = GFX.pCurrentClip->Left [clip][bg]; \
  1968. Right = GFX.pCurrentClip->Right [clip][bg]; \
  1969. if (Right <= Left) \
  1970. continue; \
  1971. } \
  1972. TYPE *p = (TYPE *) Screen + Left; \
  1973. uint8 *d = Depth + Left; \
  1974. \
  1975. if (PPU.Mode7HFlip) \
  1976. { \
  1977. startx = Right - 1; \
  1978. endx = Left - 1; \
  1979. dir = -1; \
  1980. aa = -l->MatrixA; \
  1981. cc = -l->MatrixC; \
  1982. } \
  1983. else \
  1984. { \
  1985. startx = Left; \
  1986. endx = Right; \
  1987. dir = 1; \
  1988. aa = l->MatrixA; \
  1989. cc = l->MatrixC; \
  1990. } \
  1991. int xx; \
  1992. if (PPU.Mode7Repeat == 0) \
  1993. xx = startx + (HOffset - C

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