PageRenderTime 33ms CodeModel.GetById 7ms RepoModel.GetById 0ms app.codeStats 1ms

/src/snes4iphone_src/gfx.cpp

https://github.com/tandrup/snes4iphone
C++ | 4061 lines | 3527 code | 337 blank | 197 comment | 752 complexity | 55d65387bc7e8439071bf4c21ba6cdf5 MD5 | raw file
  1. /*
  2. * Snes9x - Portable Super Nintendo Entertainment System (TM) emulator.
  3. *
  4. * (c) Copyright 1996 - 2001 Gary Henderson (gary.henderson@ntlworld.com) and
  5. * Jerremy Koot (jkoot@snes9x.com)
  6. *
  7. * Super FX C emulator code
  8. * (c) Copyright 1997 - 1999 Ivar (ivar@snes9x.com) and
  9. * Gary Henderson.
  10. * Super FX assembler emulator code (c) Copyright 1998 zsKnight and _Demo_.
  11. *
  12. * DSP1 emulator code (c) Copyright 1998 Ivar, _Demo_ and Gary Henderson.
  13. * C4 asm and some C emulation code (c) Copyright 2000 zsKnight and _Demo_.
  14. * C4 C code (c) Copyright 2001 Gary Henderson (gary.henderson@ntlworld.com).
  15. *
  16. * DOS port code contains the works of other authors. See headers in
  17. * individual files.
  18. *
  19. * Snes9x homepage: http://www.snes9x.com
  20. *
  21. * Permission to use, copy, modify and distribute Snes9x in both binary and
  22. * source form, for non-commercial purposes, is hereby granted without fee,
  23. * providing that this license information and copyright notice appear with
  24. * all copies and any derived work.
  25. *
  26. * This software is provided 'as-is', without any express or implied
  27. * warranty. In no event shall the authors be held liable for any damages
  28. * arising from the use of this software.
  29. *
  30. * Snes9x is freeware for PERSONAL USE only. Commercial users should
  31. * seek permission of the copyright holders first. Commercial use includes
  32. * charging money for Snes9x or software derived from Snes9x.
  33. *
  34. * The copyright holders request that bug fixes and improvements to the code
  35. * should be forwarded to them so everyone can benefit from the modifications
  36. * in future versions.
  37. *
  38. * Super NES and Super Nintendo Entertainment System are trademarks of
  39. * Nintendo Co., Limited and its subsidiary companies.
  40. */
  41. #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 - CentreX) % 1023; \
  1994. else \
  1995. xx = startx + HOffset - CentreX; \
  1996. int AA = l->MatrixA * xx; \
  1997. int CC = l->MatrixC * xx; \
  1998. \
  1999. if (!PPU.Mode7Repeat) \
  2000. { \
  2001. for (int x = startx; x != endx; x += dir, AA += aa, CC += cc, p++, d++) \
  2002. { \
  2003. int X = ((AA + BB) >> 8) & 0x3ff; \
  2004. int Y = ((CC + DD) >> 8) & 0x3ff; \
  2005. uint8 *TileData = VRAM1 + (Memory.VRAM[((Y & ~7) << 5) + ((X >> 2) & ~1)] << 7); \
  2006. uint32 b = *(TileData + ((Y & 7) << 4) + ((X & 7) << 1)); \
  2007. GFX.Z1 = Mode7Depths [(b & GFX.Mode7PriorityMask) >> 7]; \
  2008. if (GFX.Z1 > *d && b) \
  2009. { \
  2010. *p = (FUNC); \
  2011. *d = GFX.Z1; \
  2012. } \
  2013. } \
  2014. } \
  2015. else \
  2016. { \
  2017. for (int x = startx; x != endx; x += dir, AA += aa, CC += cc, p++, d++) \
  2018. { \
  2019. int X = ((AA + BB) >> 8); \
  2020. int Y = ((CC + DD) >> 8); \
  2021. \
  2022. if (Settings.Dezaemon && PPU.Mode7Repeat == 2) \
  2023. { \
  2024. X &= 0x7ff; \
  2025. Y &= 0x7ff; \
  2026. } \
  2027. \
  2028. if (((X | Y) & ~0x3ff) == 0) \
  2029. { \
  2030. uint8 *TileData = VRAM1 + (Memory.VRAM[((Y & ~7) << 5) + ((X >> 2) & ~1)] << 7); \
  2031. uint32 b = *(TileData + ((Y & 7) << 4) + ((X & 7) << 1)); \
  2032. GFX.Z1 = Mode7Depths [(b & GFX.Mode7PriorityMask) >> 7]; \
  2033. if (GFX.Z1 > *d && b) \
  2034. { \
  2035. *p = (FUNC); \
  2036. *d = GFX.Z1; \
  2037. } \
  2038. } \
  2039. else \
  2040. { \
  2041. if (PPU.Mode7Repeat == 3) \
  2042. { \
  2043. X = (x + HOffset) & 7; \
  2044. Y = (yy + CentreY) & 7; \
  2045. uint32 b = *(VRAM1 + ((Y & 7) << 4) + ((X & 7) << 1)); \
  2046. GFX.Z1 = Mode7Depths [(b & GFX.Mode7PriorityMask) >> 7]; \
  2047. if (GFX.Z1 > *d && b) \
  2048. { \
  2049. *p = (FUNC); \
  2050. *d = GFX.Z1; \
  2051. } \
  2052. } \
  2053. } \
  2054. } \
  2055. } \
  2056. } \
  2057. }
  2058. void DrawBGMode7Background (uint8 *Screen, int bg)
  2059. {
  2060. RENDER_BACKGROUND_MODE7 (uint8, (uint8) (b & GFX.Mode7Mask))
  2061. }
  2062. void DrawBGMode7Background16 (uint8 *Screen, int bg)
  2063. {
  2064. RENDER_BACKGROUND_MODE7 (uint16, GFX.ScreenColors [b & GFX.Mode7Mask]);
  2065. }
  2066. void DrawBGMode7Background16Add (uint8 *Screen, int bg)
  2067. {
  2068. RENDER_BACKGROUND_MODE7 (uint16, *(d + GFX.DepthDelta) ?
  2069. (*(d + GFX.DepthDelta) != 1 ?
  2070. COLOR_ADD (GFX.ScreenColors [b & GFX.Mode7Mask],
  2071. p [GFX.Delta]) :
  2072. COLOR_ADD (GFX.ScreenColors [b & GFX.Mode7Mask],
  2073. GFX.FixedColour)) :
  2074. GFX.ScreenColors [b & GFX.Mode7Mask]);
  2075. }
  2076. void DrawBGMode7Background16Add1_2 (uint8 *Screen, int bg)
  2077. {
  2078. RENDER_BACKGROUND_MODE7 (uint16, *(d + GFX.DepthDelta) ?
  2079. (*(d + GFX.DepthDelta) != 1 ?
  2080. COLOR_ADD1_2 (GFX.ScreenColors [b & GFX.Mode7Mask],
  2081. p [GFX.Delta]) :
  2082. COLOR_ADD (GFX.ScreenColors [b & GFX.Mode7Mask],
  2083. GFX.FixedColour)) :
  2084. GFX.ScreenColors [b & GFX.Mode7Mask]);
  2085. }
  2086. void DrawBGMode7Background16Sub (uint8 *Screen, int bg)
  2087. {
  2088. RENDER_BACKGROUND_MODE7 (uint16, *(d + GFX.DepthDelta) ?
  2089. (*(d + GFX.DepthDelta) != 1 ?
  2090. COLOR_SUB (GFX.ScreenColors [b & GFX.Mode7Mask],
  2091. p [GFX.Delta]) :
  2092. COLOR_SUB (GFX.ScreenColors [b & GFX.Mode7Mask],
  2093. GFX.FixedColour)) :
  2094. GFX.ScreenColors [b & GFX.Mode7Mask]);
  2095. }
  2096. void DrawBGMode7Background16Sub1_2 (uint8 *Screen, int bg)
  2097. {
  2098. RENDER_BACKGROUND_MODE7 (uint16, *(d + GFX.DepthDelta) ?
  2099. (*(d + GFX.DepthDelta) != 1 ?
  2100. COLOR_SUB1_2 (GFX.ScreenColors [b & GFX.Mode7Mask],
  2101. p [GFX.Delta]) :
  2102. COLOR_SUB (GFX.ScreenColors [b & GFX.Mode7Mask],
  2103. GFX.FixedColour)) :
  2104. GFX.ScreenColors [b & GFX.Mode7Mask]);
  2105. }
  2106. #define RENDER_BACKGROUND_MODE7_i(TYPE,FUNC,COLORFUNC) \
  2107. CHECK_SOUND(); \
  2108. \
  2109. uint8 *VRAM1 = Memory.VRAM + 1; \
  2110. if (GFX.r2130 & 1) \
  2111. { \
  2112. if (IPPU.DirectColourMapsNeedRebuild) \
  2113. S9xBuildDirectColourMaps (); \
  2114. GFX.ScreenColors = DirectColourMaps [0]; \
  2115. } \
  2116. else \
  2117. GFX.ScreenColors = IPPU.ScreenColors; \
  2118. \
  2119. int aa, cc; \
  2120. int dir; \
  2121. int startx, endx; \
  2122. uint32 Left = 0; \
  2123. uint32 Right = 256; \
  2124. uint32 ClipCount = GFX.pCurrentClip->Count [bg]; \
  2125. \
  2126. if (!ClipCount) \
  2127. ClipCount = 1; \
  2128. \
  2129. Screen += GFX.StartY * GFX.Pitch; \
  2130. uint8 *Depth = GFX.DB + GFX.StartY * GFX.PPL; \
  2131. struct SLineMatrixData *l = &LineMatrixData [GFX.StartY]; \
  2132. bool8_32 allowSimpleCase = FALSE; \
  2133. if (!l->MatrixB && !l->MatrixC && (l->MatrixA == 0x0100) && (l->MatrixD == 0x0100) \
  2134. && !LineMatrixData[GFX.EndY].MatrixB && !LineMatrixData[GFX.EndY].MatrixC \
  2135. && (LineMatrixData[GFX.EndY].MatrixA == 0x0100) && (LineMatrixData[GFX.EndY].MatrixD == 0x0100) \
  2136. ) \
  2137. allowSimpleCase = TRUE; \
  2138. \
  2139. for (uint32 Line = GFX.StartY; Line <= GFX.EndY; Line++, Screen += GFX.Pitch, Depth += GFX.PPL, l++) \
  2140. { \
  2141. int yy; \
  2142. \
  2143. int HOffset = ((int) LineData [Line].BG[0].HOffset << M7) >> M7; \
  2144. int VOffset = ((int) LineData [Line].BG[0].VOffset << M7) >> M7; \
  2145. \
  2146. int CentreX = ((int) l->CentreX << M7) >> M7; \
  2147. int CentreY = ((int) l->CentreY << M7) >> M7; \
  2148. \
  2149. if (PPU.Mode7VFlip) \
  2150. yy = 261 - (int) Line; \
  2151. else \
  2152. yy = Line; \
  2153. \
  2154. if (PPU.Mode7Repeat == 0) \
  2155. yy += (VOffset - CentreY) % 1023; \
  2156. else \
  2157. yy += VOffset - CentreY; \
  2158. bool8_32 simpleCase = FALSE; \
  2159. int BB; \
  2160. int DD; \
  2161. /* Make a special case for the identity matrix, since it's a common case and */ \
  2162. /* can be done much more quickly without special effects */ \
  2163. if (allowSimpleCase && !l->MatrixB && !l->MatrixC && (l->MatrixA == 0x0100) && (l->MatrixD == 0x0100)) \
  2164. { \
  2165. BB = CentreX << 8; \
  2166. DD = (yy + CentreY) << 8; \
  2167. simpleCase = TRUE; \
  2168. } \
  2169. else \
  2170. { \
  2171. BB = l->MatrixB * yy + (CentreX << 8); \
  2172. DD = l->MatrixD * yy + (CentreY << 8); \
  2173. } \
  2174. \
  2175. for (uint32 clip = 0; clip < ClipCount; clip++) \
  2176. { \
  2177. if (GFX.pCurrentClip->Count [bg]) \
  2178. { \
  2179. Left = GFX.pCurrentClip->Left [clip][bg]; \
  2180. Right = GFX.pCurrentClip->Right [clip][bg]; \
  2181. if (Right <= Left) \
  2182. continue; \
  2183. } \
  2184. TYPE *p = (TYPE *) Screen + Left; \
  2185. uint8 *d = Depth + Left; \
  2186. \
  2187. if (PPU.Mode7HFlip) \
  2188. { \
  2189. startx = Right - 1; \
  2190. endx = Left - 1; \
  2191. dir = -1; \
  2192. aa = -l->MatrixA; \
  2193. cc = -l->MatrixC; \
  2194. } \
  2195. else \
  2196. { \
  2197. startx = Left; \
  2198. endx = Right; \
  2199. dir = 1; \
  2200. aa = l->MatrixA; \
  2201. cc = l->MatrixC; \
  2202. } \
  2203. int xx; \
  2204. if (PPU.Mode7Repeat == 0) \
  2205. xx = startx + (HOffset - CentreX) % 1023; \
  2206. else \
  2207. xx = startx + HOffset - CentreX; \
  2208. int AA, CC = 0; \
  2209. if (simpleCase) \
  2210. { \
  2211. AA = xx << 8; \
  2212. } \
  2213. else \
  2214. { \
  2215. AA = l->MatrixA * xx; \
  2216. CC = l->MatrixC * xx; \
  2217. } \
  2218. if (simpleCase) \
  2219. { \
  2220. if (!PPU.Mode7Repeat) \
  2221. { \
  2222. int x = startx; \
  2223. do \
  2224. { \
  2225. int X = ((AA + BB) >> 8) & 0x3ff; \
  2226. int Y = (DD >> 8) & 0x3ff; \
  2227. uint8 *TileData = VRAM1 + (Memory.VRAM[((Y & ~7) << 5) + ((X >> 2) & ~1)] << 7); \
  2228. uint32 b = *(TileData + ((Y & 7) << 4) + ((X & 7) << 1)); \
  2229. GFX.Z1 = Mode7Depths [(b & GFX.Mode7PriorityMask) >> 7]; \
  2230. if (GFX.Z1 > *d && b) \
  2231. { \
  2232. TYPE theColor = COLORFUNC; \
  2233. *p = (FUNC) | ALPHA_BITS_MASK; \
  2234. *d = GFX.Z1; \
  2235. } \
  2236. AA += aa, p++, d++; \
  2237. x += dir; \
  2238. } while (x != endx); \
  2239. } \
  2240. else \
  2241. { \
  2242. int x = startx; \
  2243. do { \
  2244. int X = (AA + BB) >> 8; \
  2245. int Y = DD >> 8; \
  2246. \
  2247. if(Settings.Dezaemon && PPU.Mode7Repeat == 2) \
  2248. { \
  2249. X &= 0x7ff; \
  2250. Y &= 0x7ff; \
  2251. } \
  2252. \
  2253. if (((X | Y) & ~0x3ff) == 0) \
  2254. { \
  2255. uint8 *TileData = VRAM1 + (Memory.VRAM[((Y & ~7) << 5) + ((X >> 2) & ~1)] << 7); \
  2256. uint32 b = *(TileData + ((Y & 7) << 4) + ((X & 7) << 1)); \
  2257. GFX.Z1 = Mode7Depths [(b & GFX.Mode7PriorityMask) >> 7]; \
  2258. if (GFX.Z1 > *d && b) \
  2259. { \
  2260. TYPE theColor = COLORFUNC; \
  2261. *p = (FUNC) | ALPHA_BITS_MASK; \
  2262. *d = GFX.Z1; \
  2263. } \
  2264. } \
  2265. else if (PPU.Mode7Repeat == 3) \
  2266. { \
  2267. X = (x + HOffset) & 7; \
  2268. Y = (yy + CentreY) & 7; \
  2269. uint8 *TileData = VRAM1 + (Memory.VRAM[((Y & ~7) << 5) + ((X >> 2) & ~1)] << 7); \
  2270. uint32 b = *(TileData + ((Y & 7) << 4) + ((X & 7) << 1)); \
  2271. GFX.Z1 = Mode7Depths [(b & GFX.Mode7PriorityMask) >> 7]; \
  2272. if (GFX.Z1 > *d && b) \
  2273. { \
  2274. TYPE theColor = COLORFUNC; \
  2275. *p = (FUNC) | ALPHA_BITS_MASK; \
  2276. *d = GFX.Z1; \
  2277. } \
  2278. } \
  2279. AA += aa; p++; d++; \
  2280. x += dir; \
  2281. } while (x != endx); \
  2282. } \
  2283. } \
  2284. else if (!PPU.Mode7Repeat) \
  2285. { \
  2286. /* The bilinear interpolator: get the colors at the four points surrounding */ \
  2287. /* the location of one point in the _sampled_ image, and weight them according */ \
  2288. /* to their (city block) distance. It's very smooth, but blurry with "close up" */ \
  2289. /* points. */ \
  2290. \
  2291. /* 460 (slightly less than 2 source pixels per displayed pixel) is an educated */ \
  2292. /* guess for where bilinear filtering will become a poor method for averaging. */ \
  2293. /* (When reducing the image, the weighting used by a bilinear filter becomes */ \
  2294. /* arbitrary, and a simple mean is a better way to represent the source image.) */ \
  2295. /* You can think of this as a kind of mipmapping. */ \
  2296. if ((aa < 460 && aa > -460) && (cc < 460 && cc > -460)) \
  2297. {\
  2298. for (int x = startx; x != endx; x += dir, AA += aa, CC += cc, p++, d++) \
  2299. { \
  2300. uint32 xPos = AA + BB; \
  2301. uint32 xPix = xPos >> 8; \
  2302. uint32 yPos = CC + DD; \
  2303. uint32 yPix = yPos >> 8; \
  2304. uint32 X = xPix & 0x3ff; \
  2305. uint32 Y = yPix & 0x3ff; \
  2306. uint8 *TileData = VRAM1 + (Memory.VRAM[((Y & ~7) << 5) + ((X >> 2) & ~1)] << 7); \
  2307. uint32 b = *(TileData + ((Y & 7) << 4) + ((X & 7) << 1)); \
  2308. GFX.Z1 = Mode7Depths [(b & GFX.Mode7PriorityMask) >> 7]; \
  2309. if (GFX.Z1 > *d && b) \
  2310. { \
  2311. /* X10 and Y01 are the X and Y coordinates of the next source point over. */ \
  2312. uint32 X10 = (xPix + dir) & 0x3ff; \
  2313. uint32 Y01 = (yPix + dir) & 0x3ff; \
  2314. uint8 *TileData10 = VRAM1 + (Memory.VRAM[((Y & ~7) << 5) + ((X10 >> 2) & ~1)] << 7); \
  2315. uint8 *TileData11 = VRAM1 + (Memory.VRAM[((Y01 & ~7) << 5) + ((X10 >> 2) & ~1)] << 7); \
  2316. uint8 *TileData01 = VRAM1 + (Memory.VRAM[((Y01 & ~7) << 5) + ((X >> 2) & ~1)] << 7); \
  2317. uint32 p1 = COLORFUNC; \
  2318. p1 = (p1 & FIRST_THIRD_COLOR_MASK) | ((p1 & SECOND_COLOR_MASK) << 16); \
  2319. b = *(TileData10 + ((Y & 7) << 4) + ((X10 & 7) << 1)); \
  2320. uint32 p2 = COLORFUNC; \
  2321. p2 = (p2 & FIRST_THIRD_COLOR_MASK) | ((p2 & SECOND_COLOR_MASK) << 16); \
  2322. b = *(TileData11 + ((Y01 & 7) << 4) + ((X10 & 7) << 1)); \
  2323. uint32 p4 = COLORFUNC; \
  2324. p4 = (p4 & FIRST_THIRD_COLOR_MASK) | ((p4 & SECOND_COLOR_MASK) << 16); \
  2325. b = *(TileData01 + ((Y01 & 7) << 4) + ((X & 7) << 1)); \
  2326. uint32 p3 = COLORFUNC; \
  2327. p3 = (p3 & FIRST_THIRD_COLOR_MASK) | ((p3 & SECOND_COLOR_MASK) << 16); \
  2328. /* Xdel, Ydel: position (in 1/32nds) between the points */ \
  2329. uint32 Xdel = (xPos >> 3) & 0x1F; \
  2330. uint32 Ydel = (yPos >> 3) & 0x1F; \
  2331. uint32 XY = (Xdel*Ydel) >> 5; \
  2332. uint32 area1 = 0x20 + XY - Xdel - Ydel; \
  2333. uint32 area2 = Xdel - XY; \
  2334. uint32 area3 = Ydel - XY; \
  2335. uint32 area4 = XY; \
  2336. uint32 tempColor = ((area1 * p1) + \
  2337. (area2 * p2) + \
  2338. (area3 * p3) + \
  2339. (area4 * p4)) >> 5; \
  2340. TYPE theColor = (tempColor & FIRST_THIRD_COLOR_MASK) | ((tempColor >> 16) & SECOND_COLOR_MASK); \
  2341. *p = (FUNC) | ALPHA_BITS_MASK; \
  2342. *d = GFX.Z1; \
  2343. } \
  2344. } \
  2345. } \
  2346. else \
  2347. /* The oversampling method: get the colors at four corners of a square */ \
  2348. /* in the _displayed_ image, and average them. It's sharp and clean, but */ \
  2349. /* gives the usual huge pixels when the source image gets "close." */ \
  2350. { \
  2351. /* Find the dimensions of the square in the source image whose corners will be examined. */ \
  2352. uint32 aaDelX = aa >> 1; \
  2353. uint32 ccDelX = cc >> 1; \
  2354. uint32 bbDelY = l->MatrixB >> 1; \
  2355. uint32 ddDelY = l->MatrixD >> 1; \
  2356. /* Offset the location within the source image so that the four sampled points */ \
  2357. /* center around where the single point would otherwise have been drawn. */ \
  2358. BB -= (bbDelY >> 1); \
  2359. DD -= (ddDelY >> 1); \
  2360. AA -= (aaDelX >> 1); \
  2361. CC -= (ccDelX >> 1); \
  2362. uint32 BB10 = BB + aaDelX; \
  2363. uint32 BB01 = BB + bbDelY; \
  2364. uint32 BB11 = BB + aaDelX + bbDelY; \
  2365. uint32 DD10 = DD + ccDelX; \
  2366. uint32 DD01 = DD + ddDelY; \
  2367. uint32 DD11 = DD + ccDelX + ddDelY; \
  2368. for (int x = startx; x != endx; x += dir, AA += aa, CC += cc, p++, d++) \
  2369. { \
  2370. uint32 X = ((AA + BB) >> 8) & 0x3ff; \
  2371. uint32 Y = ((CC + DD) >> 8) & 0x3ff; \
  2372. uint8 *TileData = VRAM1 + (Memory.VRAM[((Y & ~7) << 5) + ((X >> 2) & ~1)] << 7); \
  2373. uint32 b = *(TileData + ((Y & 7) << 4) + ((X & 7) << 1)); \
  2374. GFX.Z1 = Mode7Depths [(b & GFX.Mode7PriorityMask) >> 7]; \
  2375. if (GFX.Z1 > *d && b) \
  2376. { \
  2377. /* X, Y, X10, Y10, etc. are the coordinates of the four pixels within the */ \
  2378. /* source image that we're going to examine. */ \
  2379. uint32 X10 = ((AA + BB10) >> 8) & 0x3ff; \
  2380. uint32 Y10 = ((CC + DD10) >> 8) & 0x3ff; \
  2381. uint32 X01 = ((AA + BB01) >> 8) & 0x3ff; \
  2382. uint32 Y01 = ((CC + DD01) >> 8) & 0x3ff; \
  2383. uint32 X11 = ((AA + BB11) >> 8) & 0x3ff; \
  2384. uint32 Y11 = ((CC + DD11) >> 8) & 0x3ff; \
  2385. uint8 *TileData10 = VRAM1 + (Memory.VRAM[((Y10 & ~7) << 5) + ((X10 >> 2) & ~1)] << 7); \
  2386. uint8 *TileData01 = VRAM1 + (Memory.VRAM[((Y01 & ~7) << 5) + ((X01 >> 2) & ~1)] << 7); \
  2387. uint8 *TileData11 = VRAM1 + (Memory.VRAM[((Y11 & ~7) << 5) + ((X11 >> 2) & ~1)] << 7); \
  2388. TYPE p1 = COLORFUNC; \
  2389. b = *(TileData10 + ((Y10 & 7) << 4) + ((X10 & 7) << 1)); \
  2390. TYPE p2 = COLORFUNC; \
  2391. b = *(TileData01 + ((Y01 & 7) << 4) + ((X01 & 7) << 1)); \
  2392. TYPE p3 = COLORFUNC; \
  2393. b = *(TileData11 + ((Y11 & 7) << 4) + ((X11 & 7) << 1)); \
  2394. TYPE p4 = COLORFUNC; \
  2395. TYPE theColor = Q_INTERPOLATE(p1, p2, p3, p4); \
  2396. *p = (FUNC) | ALPHA_BITS_MASK; \
  2397. *d = GFX.Z1; \
  2398. } \
  2399. } \
  2400. } \
  2401. } \
  2402. else \
  2403. { \
  2404. for (int x = startx; x != endx; x += dir, AA += aa, CC += cc, p++, d++) \
  2405. { \
  2406. uint32 xPos = AA + BB; \
  2407. uint32 xPix = xPos >> 8; \
  2408. uint32 yPos = CC + DD; \
  2409. uint32 yPix = yPos >> 8; \
  2410. uint32 X = xPix; \
  2411. uint32 Y = yPix; \
  2412. \
  2413. \
  2414. if(Settings.Dezaemon && PPU.Mode7Repeat == 2) \
  2415. { \
  2416. X &= 0x7ff; \
  2417. Y &= 0x7ff; \
  2418. } \
  2419. \
  2420. if (((X | Y) & ~0x3ff) == 0) \
  2421. { \
  2422. uint8 *TileData = VRAM1 + (Memory.VRAM[((Y & ~7) << 5) + ((X >> 2) & ~1)] << 7); \
  2423. uint32 b = *(TileData + ((Y & 7) << 4) + ((X & 7) << 1)); \
  2424. GFX.Z1 = Mode7Depths [(b & GFX.Mode7PriorityMask) >> 7]; \
  2425. if (GFX.Z1 > *d && b) \
  2426. { \
  2427. /* X10 and Y01 are the X and Y coordinates of the next source point over. */ \
  2428. uint32 X10 = (xPix + dir) & 0x3ff; \
  2429. uint32 Y01 = (yPix + dir) & 0x3ff; \
  2430. uint8 *TileData10 = VRAM1 + (Memory.VRAM[((Y & ~7) << 5) + ((X10 >> 2) & ~1)] << 7); \
  2431. uint8 *TileData11 = VRAM1 + (Memory.VRAM[((Y01 & ~7) << 5) + ((X10 >> 2) & ~1)] << 7); \
  2432. uint8 *TileData01 = VRAM1 + (Memory.VRAM[((Y01 & ~7) << 5) + ((X >> 2) & ~1)] << 7); \
  2433. uint32 p1 = COLORFUNC; \
  2434. p1 = (p1 & FIRST_THIRD_COLOR_MASK) | ((p1 & SECOND_COLOR_MASK) << 16); \
  2435. b = *(TileData10 + ((Y & 7) << 4) + ((X10 & 7) << 1)); \
  2436. uint32 p2 = COLORFUNC; \
  2437. p2 = (p2 & FIRST_THIRD_COLOR_MASK) | ((p2 & SECOND_COLOR_MASK) << 16); \
  2438. b = *(TileData11 + ((Y01 & 7) << 4) + ((X10 & 7) << 1)); \
  2439. uint32 p4 = COLORFUNC; \
  2440. p4 = (p4 & FIRST_THIRD_COLOR_MASK) | ((p4 & SECOND_COLOR_MASK) << 16); \
  2441. b = *(TileData01 + ((Y01 & 7) << 4) + ((X & 7) << 1)); \
  2442. uint32 p3 = COLORFUNC; \
  2443. p3 = (p3 & FIRST_THIRD_COLOR_MASK) | ((p3 & SECOND_COLOR_MASK) << 16); \
  2444. /* Xdel, Ydel: position (in 1/32nds) between the points */ \
  2445. uint32 Xdel = (xPos >> 3) & 0x1F; \
  2446. uint32 Ydel = (yPos >> 3) & 0x1F; \
  2447. uint32 XY = (Xdel*Ydel) >> 5; \
  2448. uint32 area1 = 0x20 + XY - Xdel - Ydel; \
  2449. uint32 area2 = Xdel - XY; \
  2450. uint32 area3 = Ydel - XY; \
  2451. uint32 area4 = XY; \
  2452. uint32 tempColor = ((area1 * p1) + \
  2453. (area2 * p2) + \
  2454. (area3 * p3) + \
  2455. (area4 * p4)) >> 5; \
  2456. TYPE theColor = (tempColor & FIRST_THIRD_COLOR_MASK) | ((tempColor >> 16) & SECOND_COLOR_MASK); \
  2457. *p = (FUNC) | ALPHA_BITS_MASK; \
  2458. *d = GFX.Z1; \
  2459. } \
  2460. } \
  2461. else \
  2462. { \
  2463. if (PPU.Mode7Repeat == 3) \
  2464. { \
  2465. X = (x + HOffset) & 7; \
  2466. Y = (yy + CentreY) & 7; \
  2467. uint32 b = *(VRAM1 + ((Y & 7) << 4) + ((X & 7) << 1)); \
  2468. GFX.Z1 = Mode7Depths [(b & GFX.Mode7PriorityMask) >> 7]; \
  2469. if (GFX.Z1 > *d && b) \
  2470. { \
  2471. TYPE theColor = COLORFUNC; \
  2472. *p = (FUNC) | ALPHA_BITS_MASK; \
  2473. *d = GFX.Z1; \
  2474. } \
  2475. } \
  2476. } \
  2477. } \
  2478. } \
  2479. } \
  2480. }
  2481. STATIC uint32 Q_INTERPOLATE(uint32 A, uint32 B, uint32 C, uint32 D)
  2482. {
  2483. register uint32 x = ((A >> 2) & HIGH_BITS_SHIFTED_TWO_MASK) +
  2484. ((B >> 2) & HIGH_BITS_SHIFTED_TWO_MASK) +
  2485. ((C >> 2) & HIGH_BITS_SHIFTED_TWO_MASK) +
  2486. ((D >> 2) & HIGH_BITS_SHIFTED_TWO_MASK);
  2487. register uint32 y = (A & TWO_LOW_BITS_MASK) +
  2488. (B & TWO_LOW_BITS_MASK) +
  2489. (C & TWO_LOW_BITS_MASK) +
  2490. (D & TWO_LOW_BITS_MASK);
  2491. y = (y>>2) & TWO_LOW_BITS_MASK;
  2492. return x+y;
  2493. }
  2494. void DrawBGMode7Background16_i (uint8 *Screen, int bg)
  2495. {
  2496. RENDER_BACKGROUND_MODE7_i (uint16, theColor, (GFX.ScreenColors[b & GFX.Mode7Mask]));
  2497. }
  2498. void DrawBGMode7Background16Add_i (uint8 *Screen, int bg)
  2499. {
  2500. RENDER_BACKGROUND_MODE7_i (uint16, *(d + GFX.DepthDelta) ?
  2501. (*(d + GFX.DepthDelta) != 1 ?
  2502. (COLOR_ADD (theColor,
  2503. p [GFX.Delta])) :
  2504. (COLOR_ADD (theColor,
  2505. GFX.FixedColour))) :
  2506. theColor, (GFX.ScreenColors[b & GFX.Mode7Mask]));
  2507. }
  2508. void DrawBGMode7Background16Add1_2_i (uint8 *Screen, int bg)
  2509. {
  2510. RENDER_BACKGROUND_MODE7_i (uint16, *(d + GFX.DepthDelta) ?
  2511. (*(d + GFX.DepthDelta) != 1 ?
  2512. COLOR_ADD1_2 (theColor,
  2513. p [GFX.Delta]) :
  2514. COLOR_ADD (theColor,
  2515. GFX.FixedColour)) :
  2516. theColor, (GFX.ScreenColors[b & GFX.Mode7Mask]));
  2517. }
  2518. void DrawBGMode7Background16Sub_i (uint8 *Screen, int bg)
  2519. {
  2520. RENDER_BACKGROUND_MODE7_i (uint16, *(d + GFX.DepthDelta) ?
  2521. (*(d + GFX.DepthDelta) != 1 ?
  2522. COLOR_SUB (theColor,
  2523. p [GFX.Delta]) :
  2524. COLOR_SUB (theColor,
  2525. GFX.FixedColour)) :
  2526. theColor, (GFX.ScreenColors[b & GFX.Mode7Mask]));
  2527. }
  2528. void DrawBGMode7Background16Sub1_2_i (uint8 *Screen, int bg)
  2529. {
  2530. RENDER_BACKGROUND_MODE7_i (uint16, *(d + GFX.DepthDelta) ?
  2531. (*(d + GFX.DepthDelta) != 1 ?
  2532. COLOR_SUB1_2 (theColor,
  2533. p [GFX.Delta]) :
  2534. COLOR_SUB (theColor,
  2535. GFX.FixedColour)) :
  2536. theColor, (GFX.ScreenColors[b & GFX.Mode7Mask]));
  2537. }
  2538. #define _BUILD_SETUP(F) \
  2539. GFX.BuildPixel = BuildPixel##F; \
  2540. GFX.BuildPixel2 = BuildPixel2##F; \
  2541. GFX.DecomposePixel = DecomposePixel##F; \
  2542. RED_LOW_BIT_MASK = RED_LOW_BIT_MASK_##F; \
  2543. GREEN_LOW_BIT_MASK = GREEN_LOW_BIT_MASK_##F; \
  2544. BLUE_LOW_BIT_MASK = BLUE_LOW_BIT_MASK_##F; \
  2545. RED_HI_BIT_MASK = RED_HI_BIT_MASK_##F; \
  2546. GREEN_HI_BIT_MASK = GREEN_HI_BIT_MASK_##F; \
  2547. BLUE_HI_BIT_MASK = BLUE_HI_BIT_MASK_##F; \
  2548. MAX_RED = MAX_RED_##F; \
  2549. MAX_GREEN = MAX_GREEN_##F; \
  2550. MAX_BLUE = MAX_BLUE_##F; \
  2551. GREEN_HI_BIT = ((MAX_GREEN_##F + 1) >> 1); \
  2552. SPARE_RGB_BIT_MASK = SPARE_RGB_BIT_MASK_##F; \
  2553. RGB_LOW_BITS_MASK = (RED_LOW_BIT_MASK_##F | \
  2554. GREEN_LOW_BIT_MASK_##F | \
  2555. BLUE_LOW_BIT_MASK_##F); \
  2556. RGB_HI_BITS_MASK = (RED_HI_BIT_MASK_##F | \
  2557. GREEN_HI_BIT_MASK_##F | \
  2558. BLUE_HI_BIT_MASK_##F); \
  2559. RGB_HI_BITS_MASKx2 = ((RED_HI_BIT_MASK_##F | \
  2560. GREEN_HI_BIT_MASK_##F | \
  2561. BLUE_HI_BIT_MASK_##F) << 1); \
  2562. RGB_REMOVE_LOW_BITS_MASK = ~RGB_LOW_BITS_MASK; \
  2563. FIRST_COLOR_MASK = FIRST_COLOR_MASK_##F; \
  2564. SECOND_COLOR_MASK = SECOND_COLOR_MASK_##F; \
  2565. THIRD_COLOR_MASK = THIRD_COLOR_MASK_##F; \
  2566. ALPHA_BITS_MASK = ALPHA_BITS_MASK_##F; \
  2567. FIRST_THIRD_COLOR_MASK = FIRST_COLOR_MASK | THIRD_COLOR_MASK; \
  2568. TWO_LOW_BITS_MASK = RGB_LOW_BITS_MASK | (RGB_LOW_BITS_MASK << 1); \
  2569. HIGH_BITS_SHIFTED_TWO_MASK = (( (FIRST_COLOR_MASK | SECOND_COLOR_MASK | THIRD_COLOR_MASK) & \
  2570. ~TWO_LOW_BITS_MASK ) >> 2);
  2571. void RenderScreen (uint8 *Screen, bool8_32 sub, bool8_32 force_no_add, uint8 D)
  2572. {
  2573. bool8_32 BG0;
  2574. bool8_32 BG1;
  2575. bool8_32 BG2;
  2576. bool8_32 BG3;
  2577. bool8_32 OB;
  2578. GFX.S = Screen;
  2579. if (!sub)
  2580. {
  2581. GFX.pCurrentClip = &IPPU.Clip [0];
  2582. BG0 = ON_MAIN (0);
  2583. BG1 = ON_MAIN (1);
  2584. BG2 = ON_MAIN (2);
  2585. BG3 = ON_MAIN (3);
  2586. OB = ON_MAIN (4);
  2587. }
  2588. else
  2589. {
  2590. GFX.pCurrentClip = &IPPU.Clip [1];
  2591. BG0 = ON_SUB (0);
  2592. BG1 = ON_SUB (1);
  2593. BG2 = ON_SUB (2);
  2594. BG3 = ON_SUB (3);
  2595. OB = ON_SUB (4);
  2596. }
  2597. sub |= force_no_add;
  2598. if (PPU.BGMode <= 1)
  2599. {
  2600. if (OB)
  2601. {
  2602. SelectTileRenderer (sub || !SUB_OR_ADD(4));
  2603. DrawOBJS (!sub, D);
  2604. }
  2605. if (BG0)
  2606. {
  2607. SelectTileRenderer (sub || !SUB_OR_ADD(0));
  2608. DrawBackground (PPU.BGMode, 0, D + 10, D + 14);
  2609. }
  2610. if (BG1)
  2611. {
  2612. SelectTileRenderer (sub || !SUB_OR_ADD(1));
  2613. DrawBackground (PPU.BGMode, 1, D + 9, D + 13);
  2614. }
  2615. if (BG2)
  2616. {
  2617. SelectTileRenderer (sub || !SUB_OR_ADD(2));
  2618. DrawBackground (PPU.BGMode, 2, D + 3,
  2619. (Memory.FillRAM [0x2105] & 8) == 0 ? D + 6 : D + 17);
  2620. }
  2621. if (BG3 && PPU.BGMode == 0)
  2622. {
  2623. SelectTileRenderer (sub || !SUB_OR_ADD(3));
  2624. DrawBackground (PPU.BGMode, 3, D + 2, D + 5);
  2625. }
  2626. }
  2627. else if (PPU.BGMode != 7)
  2628. {
  2629. if (OB)
  2630. {
  2631. SelectTileRenderer (sub || !SUB_OR_ADD(4));
  2632. DrawOBJS (!sub, D);
  2633. }
  2634. if (BG0)
  2635. {
  2636. SelectTileRenderer (sub || !SUB_OR_ADD(0));
  2637. DrawBackground (PPU.BGMode, 0, D + 5, D + 13);
  2638. }
  2639. if (PPU.BGMode != 6 && BG1)
  2640. {
  2641. SelectTileRenderer (sub || !SUB_OR_ADD(1));
  2642. DrawBackground (PPU.BGMode, 1, D + 2, D + 9);
  2643. }
  2644. }
  2645. else
  2646. {
  2647. if (OB)
  2648. {
  2649. SelectTileRenderer (sub || !SUB_OR_ADD(4));
  2650. DrawOBJS (!sub, D);
  2651. }
  2652. if (BG0 || ((Memory.FillRAM [0x2133] & 0x40) && BG1))
  2653. {
  2654. int bg;
  2655. if (Memory.FillRAM [0x2133] & 0x40)
  2656. {
  2657. GFX.Mode7Mask = 0x7f;
  2658. GFX.Mode7PriorityMask = 0x80;
  2659. Mode7Depths [0] = 5 + D;
  2660. Mode7Depths [1] = 9 + D;
  2661. bg = 1;
  2662. }
  2663. else
  2664. {
  2665. GFX.Mode7Mask = 0xff;
  2666. GFX.Mode7PriorityMask = 0;
  2667. Mode7Depths [0] = 5 + D;
  2668. Mode7Depths [1] = 5 + D;
  2669. bg = 0;
  2670. }
  2671. if (sub || !SUB_OR_ADD(0))
  2672. {
  2673. if (!Settings.Mode7Interpolate)
  2674. DrawBGMode7Background16 (Screen, bg);
  2675. else
  2676. DrawBGMode7Background16_i (Screen, bg);
  2677. }
  2678. else
  2679. {
  2680. if (GFX.r2131 & 0x80)
  2681. {
  2682. if (GFX.r2131 & 0x40)
  2683. {
  2684. if (!Settings.Mode7Interpolate)
  2685. DrawBGMode7Background16Sub1_2 (Screen, bg);
  2686. else
  2687. DrawBGMode7Background16Sub1_2_i (Screen, bg);
  2688. }
  2689. else
  2690. {
  2691. if (!Settings.Mode7Interpolate)
  2692. DrawBGMode7Background16Sub (Screen, bg);
  2693. else
  2694. DrawBGMode7Background16Sub_i (Screen, bg);
  2695. }
  2696. }
  2697. else
  2698. {
  2699. if (GFX.r2131 & 0x40)
  2700. {
  2701. if (!Settings.Mode7Interpolate)
  2702. DrawBGMode7Background16Add1_2 (Screen, bg);
  2703. else
  2704. DrawBGMode7Background16Add1_2_i (Screen, bg);
  2705. }
  2706. else
  2707. {
  2708. if (!Settings.Mode7Interpolate)
  2709. DrawBGMode7Background16Add (Screen, bg);
  2710. else
  2711. DrawBGMode7Background16Add_i (Screen, bg);
  2712. }
  2713. }
  2714. }
  2715. }
  2716. }
  2717. }
  2718. #include "font.h"
  2719. void DisplayChar (uint8 *Screen, uint8 c)
  2720. {
  2721. int line = (((c & 0x7f) - 32) >> 4) * font_height;
  2722. int offset = (((c & 0x7f) - 32) & 15) * font_width;
  2723. #ifndef _SNESPPC
  2724. if (Settings.SixteenBit)
  2725. #endif
  2726. {
  2727. int h, w;
  2728. uint16 *s = (uint16 *) Screen;
  2729. for (h = 0; h < font_height; h++, line++,
  2730. s += GFX.PPL - font_width)
  2731. {
  2732. for (w = 0; w < font_width; w++, s++)
  2733. {
  2734. uint8 p = font [line][offset + w];
  2735. if (p == '#')
  2736. *s = 0xffff;
  2737. else
  2738. if (p == '.')
  2739. *s = BLACK;
  2740. }
  2741. }
  2742. }
  2743. #ifndef _SNESPPC
  2744. else
  2745. {
  2746. int h, w;
  2747. uint8 *s = Screen;
  2748. for (h = 0; h < font_height; h++, line++,
  2749. s += GFX.PPL - font_width)
  2750. {
  2751. for (w = 0; w < font_width; w++, s++)
  2752. {
  2753. uint8 p = font [line][offset + w];
  2754. if (p == '#')
  2755. *s = 255;
  2756. else
  2757. if (p == '.')
  2758. *s = BLACK;
  2759. }
  2760. }
  2761. }
  2762. #endif
  2763. }
  2764. static void S9xDisplayFrameRate ()
  2765. {
  2766. uint8 *Screen = GFX.Screen + 2 +
  2767. (IPPU.RenderedScreenHeight - font_height - 1) * GFX.Pitch2;
  2768. char string [10];
  2769. int len = 5;
  2770. sprintf (string, "%02d/%02d", IPPU.DisplayedRenderedFrameCount,
  2771. (int) Memory.ROMFramesPerSecond);
  2772. int i;
  2773. #ifdef _SNESPPC
  2774. Screen += (font_width - 1) * sizeof(uint16);
  2775. #endif
  2776. for (i = 0; i < len; i++)
  2777. {
  2778. DisplayChar (Screen, string [i]);
  2779. Screen += Settings.SixteenBit ? (font_width - 1) * sizeof (uint16) :
  2780. (font_width - 1);
  2781. }
  2782. }
  2783. static void S9xDisplayString (const char *string)
  2784. {
  2785. uint8 *Screen = GFX.Screen + 2 +
  2786. (IPPU.RenderedScreenHeight - font_height * 5) * GFX.Pitch2;
  2787. int len = strlen (string);
  2788. int max_chars = IPPU.RenderedScreenWidth / (font_width - 1);
  2789. int char_count = 0;
  2790. int i;
  2791. for (i = 0; i < len; i++, char_count++)
  2792. {
  2793. if (char_count >= max_chars || string [i] < 32)
  2794. {
  2795. Screen -= Settings.SixteenBit ?
  2796. (font_width - 1) * sizeof (uint16) * max_chars :
  2797. (font_width - 1) * max_chars;
  2798. Screen += font_height * GFX.Pitch;
  2799. if (Screen >= GFX.Screen + GFX.Pitch * IPPU.RenderedScreenHeight)
  2800. break;
  2801. char_count -= max_chars;
  2802. }
  2803. if (string [i] < 32)
  2804. continue;
  2805. DisplayChar (Screen, string [i]);
  2806. Screen += Settings.SixteenBit ? (font_width - 1) * sizeof (uint16) :
  2807. (font_width - 1);
  2808. }
  2809. }
  2810. void S9xUpdateScreen () // ~30-50ms! (called from FLUSH_REDRAW())
  2811. {
  2812. int32 x2 = 1;
  2813. GFX.S = GFX.Screen;
  2814. unsigned char *memoryfillram = Memory.FillRAM;
  2815. // get local copies of vid registers to be used later
  2816. GFX.r2131 = memoryfillram [0x2131]; // ADDITION/SUBTRACTION & SUBTRACTION DESIGNATION FOR EACH SCREEN
  2817. GFX.r212c = memoryfillram [0x212c]; // MAIN SCREEN, DESIGNATION - used to enable BGS
  2818. GFX.r212d = memoryfillram [0x212d]; // SUB SCREEN DESIGNATION - used to enable sub BGS
  2819. GFX.r2130 = memoryfillram [0x2130]; // INITIAL SETTINGS FOR FIXED COLOR ADDITION OR SCREEN ADDITION
  2820. // If external sync is off and
  2821. // main screens have not been configured the same as the sub screen and
  2822. // color addition and subtraction has been diabled then
  2823. // Pseudo is 1
  2824. // anything else it is 0
  2825. GFX.Pseudo = (memoryfillram [0x2133] & 8) != 0 && // Use EXTERNAL SYNCHRONIZATION?
  2826. (GFX.r212c & 15) != (GFX.r212d & 15) && // Are the main screens different from the sub screens?
  2827. (GFX.r2131 & 0x3f) == 0; // Is colour data addition/subtraction disabled on all BGS?
  2828. // If sprite data has been changed then go through and
  2829. // refresh the sprites.
  2830. if (IPPU.OBJChanged)
  2831. {
  2832. S9xSetupOBJ ();
  2833. }
  2834. if (PPU.RecomputeClipWindows)
  2835. {
  2836. ComputeClipWindows ();
  2837. PPU.RecomputeClipWindows = FALSE;
  2838. }
  2839. GFX.StartY = IPPU.PreviousLine;
  2840. if ((GFX.EndY = IPPU.CurrentLine - 1) >= PPU.ScreenHeight)
  2841. GFX.EndY = PPU.ScreenHeight - 1;
  2842. uint32 starty = GFX.StartY;
  2843. uint32 endy = GFX.EndY;
  2844. #ifndef RC_OPTIMIZED
  2845. if (Settings.SupportHiRes &&
  2846. (PPU.BGMode == 5 || PPU.BGMode == 6 || IPPU.LatchedInterlace))
  2847. {
  2848. if (PPU.BGMode == 5 || PPU.BGMode == 6)
  2849. {
  2850. IPPU.RenderedScreenWidth = 512;
  2851. x2 = 2;
  2852. }
  2853. if (IPPU.LatchedInterlace)
  2854. {
  2855. starty = GFX.StartY * 2;
  2856. endy = GFX.EndY * 2 + 1;
  2857. }
  2858. if (!IPPU.DoubleWidthPixels)
  2859. {
  2860. // The game has switched from lo-res to hi-res mode part way down
  2861. // the screen. Scale any existing lo-res pixels on screen
  2862. #ifndef _SNESPPC
  2863. if (Settings.SixteenBit)
  2864. #endif
  2865. {
  2866. #if defined (USE_GLIDE) || defined (USE_OPENGL)
  2867. if (
  2868. #ifdef USE_GLIDE
  2869. (Settings.GlideEnable && GFX.Pitch == 512) ||
  2870. #endif
  2871. #ifdef USE_OPENGL
  2872. (Settings.OpenGLEnable && GFX.Pitch == 512) ||
  2873. #endif
  2874. 0)
  2875. {
  2876. // Have to back out of the speed up hack where the low res.
  2877. // SNES image was rendered into a 256x239 sized buffer,
  2878. // ignoring the true, larger size of the buffer.
  2879. for (register int32 y = (int32) GFX.StartY - 1; y >= 0; y--)
  2880. {
  2881. register uint16 *p = (uint16 *) (GFX.Screen + y * GFX.Pitch) + 255;
  2882. register uint16 *q = (uint16 *) (GFX.Screen + y * GFX.RealPitch) + 510;
  2883. for (register int x = 255; x >= 0; x--, p--, q -= 2)
  2884. *q = *(q + 1) = *p;
  2885. }
  2886. GFX.Pitch = GFX.Pitch2 = GFX.RealPitch;
  2887. GFX.PPL = GFX.Pitch >> 1;
  2888. GFX.PPLx2 = GFX.Pitch;
  2889. GFX.ZPitch = GFX.PPL;
  2890. }
  2891. else
  2892. #endif
  2893. for (register uint32 y = 0; y < GFX.StartY; y++)
  2894. {
  2895. register uint16 *p = (uint16 *) (GFX.Screen + y * GFX.Pitch) + 255;
  2896. register uint16 *q = (uint16 *) (GFX.Screen + y * GFX.Pitch) + 510;
  2897. for (register int x = 255; x >= 0; x--, p--, q -= 2)
  2898. *q = *(q + 1) = *p;
  2899. }
  2900. }
  2901. #ifndef _SNESPPC
  2902. else
  2903. {
  2904. for (register uint32 y = 0; y < GFX.StartY; y++)
  2905. {
  2906. register uint8 *p = GFX.Screen + y * GFX.Pitch + 255;
  2907. register uint8 *q = GFX.Screen + y * GFX.Pitch + 510;
  2908. for (register int x = 255; x >= 0; x--, p--, q -= 2)
  2909. *q = *(q + 1) = *p;
  2910. }
  2911. }
  2912. #endif
  2913. IPPU.DoubleWidthPixels = TRUE;
  2914. }
  2915. }
  2916. #endif //RC_OPTIMIZED (DONT DO ABOVE)
  2917. uint32 black = BLACK | (BLACK << 16);
  2918. // Are we worrying about transparencies?
  2919. if (Settings.Transparency && Settings.SixteenBit)
  2920. {
  2921. if (GFX.Pseudo)
  2922. {
  2923. GFX.r2131 = 0x5f; //0101 1111 - enable addition/subtraction on all BGS and sprites and "1/2 OF COLOR DATA" DESIGNATION
  2924. GFX.r212d = (Memory.FillRAM [0x212c] ^ // any BGS which are set as main and as sub then switch off the sub
  2925. Memory.FillRAM [0x212d]) & 15;
  2926. GFX.r212c &= ~GFX.r212d; // make sure the main BG reg is the reverse of the sub BG reg
  2927. GFX.r2130 |= 2; // enable ADDITION/SUBTRACTION FOR SUB SCREEN
  2928. }
  2929. // Check to see if any transparency effects are currently in use
  2930. if (!PPU.ForcedBlanking && ADD_OR_SUB_ON_ANYTHING &&
  2931. (GFX.r2130 & 0x30) != 0x30 &&
  2932. !((GFX.r2130 & 0x30) == 0x10 && IPPU.Clip[1].Count[5] == 0))
  2933. {
  2934. // transparency effects in use, so lets get busy!
  2935. struct ClipData *pClip;
  2936. uint32 fixedColour;
  2937. GFX.FixedColour = BUILD_PIXEL (IPPU.XB [PPU.FixedColourRed],
  2938. IPPU.XB [PPU.FixedColourGreen],
  2939. IPPU.XB [PPU.FixedColourBlue]);
  2940. fixedColour = (GFX.FixedColour<<16|GFX.FixedColour);
  2941. // Clear the z-buffer, marking areas 'covered' by the fixed
  2942. // colour as depth 1.
  2943. pClip = &IPPU.Clip [1];
  2944. // Clear the z-buffer
  2945. if (pClip->Count [5])
  2946. {
  2947. // Colour window enabled.
  2948. #ifdef RC_OPTIMIZED
  2949. for (uint32 y = starty; y <= endy; y++)
  2950. {
  2951. ZeroMemory (GFX.SubZBuffer + y * GFX.ZPitch,
  2952. IPPU.RenderedScreenWidth);
  2953. ZeroMemory (GFX.ZBuffer + y * GFX.ZPitch,
  2954. IPPU.RenderedScreenWidth);
  2955. if (IPPU.Clip [0].Count [5])
  2956. {
  2957. memset ((GFX.SubScreen + y * GFX.Pitch2), black, IPPU.RenderedScreenWidth);
  2958. }
  2959. for (uint32 c = 0; c < pClip->Count [5]; c++)
  2960. {
  2961. if (pClip->Right [c][5] > pClip->Left [c][5])
  2962. {
  2963. memset (GFX.SubZBuffer + y * GFX.ZPitch + pClip->Left [c][5] * x2,
  2964. 1, (pClip->Right [c][5] - pClip->Left [c][5]) * x2);
  2965. if (IPPU.Clip [0].Count [5])
  2966. {
  2967. // Blast, have to clear the sub-screen to the fixed-colour
  2968. // because there is a colour window in effect clipping
  2969. // the main screen that will allow the sub-screen
  2970. // 'underneath' to show through.
  2971. memset ((GFX.SubScreen + y * GFX.Pitch2) + pClip->Left [c][5] * x2,
  2972. GFX.FixedColour,
  2973. pClip->Right[c][5]*x2 - pClip->Left [c][5] * x2);
  2974. }
  2975. }
  2976. }
  2977. }
  2978. #else // NOT RC_OPTIMIZED
  2979. // loop around all of the lines being updated
  2980. for (uint32 y = starty; y <= endy; y++)
  2981. {
  2982. // Clear the subZbuffer
  2983. memset32 ((uint32_t*)(GFX.SubZBuffer + y * GFX.ZPitch),0,
  2984. IPPU.RenderedScreenWidth>>2);
  2985. // Clear the Zbuffer
  2986. memset32 ((uint32_t*)(GFX.ZBuffer + y * GFX.ZPitch),0,
  2987. IPPU.RenderedScreenWidth>>2);
  2988. // if there is clipping then clear subscreen to a black color
  2989. if (IPPU.Clip [0].Count [5])
  2990. {
  2991. memset32 ((uint32_t*)(GFX.SubScreen + y * GFX.Pitch2), black, IPPU.RenderedScreenWidth>>1);
  2992. }
  2993. // loop through all window clippings
  2994. for (uint32 c = 0; c < pClip->Count [5]; c++)
  2995. {
  2996. if (pClip->Right [c][5] > pClip->Left [c][5])
  2997. {
  2998. memset (GFX.SubZBuffer + y * GFX.ZPitch + pClip->Left [c][5] * x2,
  2999. 1, (pClip->Right [c][5] - pClip->Left [c][5]) * x2);
  3000. if (IPPU.Clip [0].Count [5])
  3001. {
  3002. // Blast, have to clear the sub-screen to the fixed-colour
  3003. // because there is a colour window in effect clipping
  3004. // the main screen that will allow the sub-screen
  3005. // 'underneath' to show through.
  3006. register uint16 *p = (uint16 *) (GFX.SubScreen + y * GFX.Pitch2);
  3007. register uint16 *q = p + pClip->Right [c][5] * x2;
  3008. p += pClip->Left [c][5] * x2;
  3009. while (p < q)
  3010. *p++ = (uint16) GFX.FixedColour;
  3011. }
  3012. }
  3013. }
  3014. }
  3015. #endif
  3016. //#undef RC_OPTIMIZED
  3017. }
  3018. else
  3019. {
  3020. // No windows are clipping the main screen
  3021. // this simplifies the screen clearing process
  3022. #ifdef RC_OPTIMIZED
  3023. if (GFX.ZPitch == (uint32)IPPU.RenderedScreenWidth)
  3024. {
  3025. memset (GFX.ZBuffer + starty * GFX.ZPitch, 0, GFX.ZPitch * (endy - starty - 1));
  3026. memset (GFX.SubZBuffer + starty * GFX.ZPitch, 1, GFX.ZPitch * (endy - starty - 1));
  3027. }
  3028. else
  3029. {
  3030. for (uint32 y = starty; y <= endy; y++)
  3031. {
  3032. ZeroMemory (GFX.ZBuffer + y * GFX.ZPitch,
  3033. IPPU.RenderedScreenWidth);
  3034. memset (GFX.SubZBuffer + y * GFX.ZPitch, 1,
  3035. IPPU.RenderedScreenWidth);
  3036. }
  3037. }
  3038. if (IPPU.Clip [0].Count [5])
  3039. {
  3040. // Blast, have to clear the sub-screen to the fixed-colour
  3041. // because there is a colour window in effect clipping
  3042. // the main screen that will allow the sub-screen
  3043. // 'underneath' to show through.
  3044. if (GFX.Pitch2 == (uint32)IPPU.RenderedScreenWidth)
  3045. {
  3046. memset ((GFX.SubScreen + starty * GFX.Pitch2),
  3047. GFX.FixedColour | (GFX.FixedColour << 16),
  3048. GFX.Pitch2 * (endy - starty - 1));
  3049. }
  3050. else
  3051. {
  3052. for (uint32 y = starty; y <= endy; y++)
  3053. {
  3054. memset ((GFX.SubScreen + y * GFX.Pitch2),
  3055. GFX.FixedColour | (GFX.FixedColour << 16),
  3056. IPPU.RenderedScreenWidth);
  3057. }
  3058. }
  3059. }
  3060. #else // NOT RC_OPTIMIZED
  3061. // loop through all of the lines to be updated
  3062. for (uint32 y = starty; y <= endy; y++)
  3063. {
  3064. // Clear the Zbuffer
  3065. memset32 ((uint32_t*)(GFX.ZBuffer + y * GFX.ZPitch),0,
  3066. IPPU.RenderedScreenWidth>>2);
  3067. // clear the sub Zbuffer to 1
  3068. memset32 ((uint32_t*)(GFX.SubZBuffer + y * GFX.ZPitch), 0x01010101,
  3069. IPPU.RenderedScreenWidth>>2);
  3070. if (IPPU.Clip [0].Count [5])
  3071. {
  3072. // Blast, have to clear the sub-screen to the fixed-colour
  3073. // because there is a colour window in effect clipping
  3074. // the main screen that will allow the sub-screen
  3075. // 'underneath' to show through.
  3076. memset32 ((uint32_t*)(GFX.SubScreen + y * GFX.Pitch2), fixedColour,
  3077. IPPU.RenderedScreenWidth>>1);
  3078. }
  3079. }
  3080. #endif
  3081. }
  3082. if (ANYTHING_ON_SUB)
  3083. {
  3084. GFX.DB = GFX.SubZBuffer;
  3085. RenderScreen (GFX.SubScreen, TRUE, TRUE, SUB_SCREEN_DEPTH);
  3086. }
  3087. if (IPPU.Clip [0].Count [5])
  3088. {
  3089. for (uint32 y = starty; y <= endy; y++)
  3090. {
  3091. register uint16 *p = (uint16 *) (GFX.Screen + y * GFX.Pitch2);
  3092. register uint8 *d = GFX.SubZBuffer + y * GFX.ZPitch ;
  3093. register uint8 *e = d + SNES_WIDTH;
  3094. while (d < e)
  3095. {
  3096. if (*d > 1)
  3097. *p = *(p + GFX.Delta);
  3098. else
  3099. *p = BLACK;
  3100. d++;
  3101. p++;
  3102. }
  3103. }
  3104. }
  3105. GFX.DB = GFX.ZBuffer;
  3106. RenderScreen (GFX.Screen, FALSE, FALSE, MAIN_SCREEN_DEPTH);
  3107. if (SUB_OR_ADD(5))
  3108. {
  3109. uint32 back = IPPU.ScreenColors [0];
  3110. uint32 Left = 0;
  3111. uint32 Right = 256;
  3112. uint32 Count;
  3113. pClip = &IPPU.Clip [0];
  3114. for (uint32 y = starty; y <= endy; y++)
  3115. {
  3116. if (!(Count = pClip->Count [5]))
  3117. {
  3118. Left = 0;
  3119. Right = 256 * x2;
  3120. Count = 1;
  3121. }
  3122. for (uint32 b = 0; b < Count; b++)
  3123. {
  3124. if (pClip->Count [5])
  3125. {
  3126. Left = pClip->Left [b][5] * x2;
  3127. Right = pClip->Right [b][5] * x2;
  3128. if (Right <= Left)
  3129. continue;
  3130. }
  3131. if (GFX.r2131 & 0x80)
  3132. {
  3133. if (GFX.r2131 & 0x40)
  3134. {
  3135. // Subtract, halving the result.
  3136. register uint16 *p = (uint16 *) (GFX.Screen + y * GFX.Pitch2) + Left;
  3137. register uint8 *d = GFX.ZBuffer + y * GFX.ZPitch;
  3138. register uint8 *s = GFX.SubZBuffer + y * GFX.ZPitch + Left;
  3139. register uint8 *e = d + Right;
  3140. uint16 back_fixed = COLOR_SUB (back, GFX.FixedColour);
  3141. d += Left;
  3142. while (d < e)
  3143. {
  3144. if (*d == 0)
  3145. {
  3146. if (*s)
  3147. {
  3148. if (*s != 1)
  3149. *p = COLOR_SUB1_2 (back, *(p + GFX.Delta));
  3150. else
  3151. *p = back_fixed;
  3152. }
  3153. else
  3154. *p = (uint16) back;
  3155. }
  3156. d++;
  3157. p++;
  3158. s++;
  3159. }
  3160. }
  3161. else
  3162. {
  3163. // Subtract
  3164. register uint16 *p = (uint16 *) (GFX.Screen + y * GFX.Pitch2) + Left;
  3165. register uint8 *s = GFX.SubZBuffer + y * GFX.ZPitch + Left;
  3166. register uint8 *d = GFX.ZBuffer + y * GFX.ZPitch;
  3167. register uint8 *e = d + Right;
  3168. uint16 back_fixed = COLOR_SUB (back, GFX.FixedColour);
  3169. d += Left;
  3170. while (d < e)
  3171. {
  3172. if (*d == 0)
  3173. {
  3174. if (*s)
  3175. {
  3176. if (*s != 1)
  3177. *p = COLOR_SUB (back, *(p + GFX.Delta));
  3178. else
  3179. *p = back_fixed;
  3180. }
  3181. else
  3182. *p = (uint16) back;
  3183. }
  3184. d++;
  3185. p++;
  3186. s++;
  3187. }
  3188. }
  3189. }
  3190. else
  3191. if (GFX.r2131 & 0x40)
  3192. {
  3193. register uint16 *p = (uint16 *) (GFX.Screen + y * GFX.Pitch2) + Left;
  3194. register uint8 *d = GFX.ZBuffer + y * GFX.ZPitch;
  3195. register uint8 *s = GFX.SubZBuffer + y * GFX.ZPitch + Left;
  3196. register uint8 *e = d + Right;
  3197. uint16 back_fixed = COLOR_ADD (back, GFX.FixedColour);
  3198. d += Left;
  3199. while (d < e)
  3200. {
  3201. if (*d == 0)
  3202. {
  3203. if (*s)
  3204. {
  3205. if (*s != 1)
  3206. *p = COLOR_ADD1_2 (back, *(p + GFX.Delta));
  3207. else
  3208. *p = back_fixed;
  3209. }
  3210. else
  3211. *p = (uint16) back;
  3212. }
  3213. d++;
  3214. p++;
  3215. s++;
  3216. }
  3217. }
  3218. else
  3219. if (back != 0)
  3220. {
  3221. register uint16 *p = (uint16 *) (GFX.Screen + y * GFX.Pitch2) + Left;
  3222. register uint8 *d = GFX.ZBuffer + y * GFX.ZPitch;
  3223. register uint8 *s = GFX.SubZBuffer + y * GFX.ZPitch + Left;
  3224. register uint8 *e = d + Right;
  3225. uint16 back_fixed = COLOR_ADD (back, GFX.FixedColour);
  3226. d += Left;
  3227. while (d < e)
  3228. {
  3229. if (*d == 0)
  3230. {
  3231. if (*s)
  3232. {
  3233. if (*s != 1)
  3234. *p = COLOR_ADD (back, *(p + GFX.Delta));
  3235. else
  3236. *p = back_fixed;
  3237. }
  3238. else
  3239. *p = (uint16) back;
  3240. }
  3241. d++;
  3242. p++;
  3243. s++;
  3244. }
  3245. }
  3246. else
  3247. {
  3248. if (!pClip->Count [5])
  3249. {
  3250. // The backdrop has not been cleared yet - so
  3251. // copy the sub-screen to the main screen
  3252. // or fill it with the back-drop colour if the
  3253. // sub-screen is clear.
  3254. register uint16 *p = (uint16 *) (GFX.Screen + y * GFX.Pitch2) + Left;
  3255. register uint8 *d = GFX.ZBuffer + y * GFX.ZPitch;
  3256. register uint8 *s = GFX.SubZBuffer + y * GFX.ZPitch + Left;
  3257. register uint8 *e = d + Right;
  3258. d += Left;
  3259. while (d < e)
  3260. {
  3261. if (*d == 0)
  3262. {
  3263. if (*s)
  3264. {
  3265. if (*s != 1)
  3266. *p = *(p + GFX.Delta);
  3267. else
  3268. *p = GFX.FixedColour;
  3269. }
  3270. else
  3271. *p = (uint16) back;
  3272. }
  3273. d++;
  3274. p++;
  3275. s++;
  3276. }
  3277. }
  3278. }
  3279. }
  3280. }
  3281. }
  3282. else
  3283. {
  3284. // Subscreen not being added to back
  3285. uint32 back = IPPU.ScreenColors [0] | (IPPU.ScreenColors [0] << 16);
  3286. pClip = &IPPU.Clip [0];
  3287. if (pClip->Count [5])
  3288. {
  3289. for (uint32 y = starty; y <= endy; y++)
  3290. {
  3291. for (uint32 b = 0; b < pClip->Count [5]; b++)
  3292. {
  3293. uint32 Left = pClip->Left [b][5] * x2;
  3294. uint32 Right = pClip->Right [b][5] * x2;
  3295. register uint16 *p = (uint16 *) (GFX.Screen + y * GFX.Pitch2) + Left;
  3296. register uint8 *d = GFX.ZBuffer + y * GFX.ZPitch;
  3297. register uint8 *e = d + Right;
  3298. d += Left;
  3299. while (d < e)
  3300. {
  3301. if (*d++ == 0)
  3302. *p = (int16) back;
  3303. p++;
  3304. }
  3305. }
  3306. }
  3307. }
  3308. else
  3309. {
  3310. for (uint32 y = starty; y <= endy; y++)
  3311. {
  3312. register uint16 *p = (uint16 *) (GFX.Screen + y * GFX.Pitch2);
  3313. register uint8 *d = GFX.ZBuffer + y * GFX.ZPitch;
  3314. register uint8 *e = d + 256 * x2;
  3315. while (d < e)
  3316. {
  3317. if (*d == 0)
  3318. #ifdef RC_OPTIMIZED
  3319. *p++ = back;
  3320. d++;
  3321. #else
  3322. *p = (int16) back;
  3323. d++;
  3324. p++;
  3325. #endif
  3326. }
  3327. }
  3328. }
  3329. }
  3330. }
  3331. else
  3332. {
  3333. // 16bit and transparency but currently no transparency effects in
  3334. // operation.
  3335. // get the back colour of the current screen
  3336. uint32 back = IPPU.ScreenColors [0] |
  3337. (IPPU.ScreenColors [0] << 16);
  3338. // if forceblanking in use then use black instead of the back color
  3339. if (PPU.ForcedBlanking)
  3340. back = black;
  3341. // not sure what Clip is used for yet
  3342. // could be a check to see if there is any clipping present?
  3343. if (IPPU.Clip [0].Count[5])
  3344. {
  3345. #ifdef RC_OPTIMIZED
  3346. if (GFX.Pitch2 == (uint32)IPPU.RenderedScreenWidth)
  3347. {
  3348. memset (GFX.Screen + starty * GFX.Pitch2, black,
  3349. GFX.Pitch2 * (endy - starty - 1));
  3350. }
  3351. else
  3352. {
  3353. for (uint32 y = starty; y <= endy; y++)
  3354. {
  3355. memset (GFX.Screen + y * GFX.Pitch2, black,
  3356. GFX.Pitch2);
  3357. }
  3358. }
  3359. for (uint32 y = starty; y <= endy; y++)
  3360. {
  3361. for (uint32 c = 0; c < IPPU.Clip [0].Count [5]; c++)
  3362. {
  3363. if (IPPU.Clip [0].Right [c][5] > IPPU.Clip [0].Left [c][5])
  3364. {
  3365. memset ((GFX.Screen + y * GFX.Pitch2) + IPPU.Clip [0].Left [c][5] * x2,
  3366. back,
  3367. IPPU.Clip [0].Right [c][5] * x2 - IPPU.Clip [0].Left [c][5] * x2);
  3368. }
  3369. }
  3370. }
  3371. #else
  3372. // loop through all of the lines that are going to be updated as part of this screen update
  3373. for (uint32 y = starty; y <= endy; y++)
  3374. {
  3375. memset32 ((uint32_t*)(GFX.Screen + y * GFX.Pitch2), black,
  3376. IPPU.RenderedScreenWidth>>1);
  3377. if (black!=back)
  3378. {
  3379. for (uint32 c = 0; c < IPPU.Clip [0].Count [5]; c++)
  3380. {
  3381. if (IPPU.Clip [0].Right [c][5] > IPPU.Clip [0].Left [c][5])
  3382. {
  3383. register uint16 *p = (uint16 *) (GFX.Screen + y * GFX.Pitch2); // get pointer to current line in screen buffer
  3384. register uint16 *q = p + IPPU.Clip [0].Right [c][5] * x2; // get pointer to end of line
  3385. p += IPPU.Clip [0].Left [c][5] * x2;
  3386. while (p < q)
  3387. *p++ = (uint16) back; // fill all pixels in clipped section with the back colour
  3388. }
  3389. }
  3390. }
  3391. }
  3392. #endif
  3393. }
  3394. else
  3395. {
  3396. #ifdef RC_OPTIMIZED
  3397. if (GFX.Pitch2 == (uint32)IPPU.RenderedScreenWidth)
  3398. {
  3399. memset (GFX.Screen + starty * GFX.Pitch2, back,
  3400. GFX.Pitch2 * (endy - starty - 1));
  3401. }
  3402. else
  3403. {
  3404. for (uint32 y = starty; y <= endy; y++)
  3405. {
  3406. memset (GFX.Screen + y * GFX.Pitch2, back,
  3407. GFX.Pitch2);
  3408. }
  3409. }
  3410. #else
  3411. // there is no clipping to worry about so just fill with the back colour
  3412. for (uint32 y = starty; y <= endy; y++)
  3413. {
  3414. memset32 ((uint32_t*)(GFX.Screen + y * GFX.Pitch2), back,
  3415. IPPU.RenderedScreenWidth>>1);
  3416. }
  3417. #endif
  3418. }
  3419. // If Forced blanking is not in effect
  3420. if (!PPU.ForcedBlanking)
  3421. {
  3422. #ifdef RC_OPTIMIZED
  3423. if (GFX.ZPitch == (uint32)IPPU.RenderedScreenWidth)
  3424. {
  3425. memset (GFX.ZBuffer + starty * GFX.ZPitch, 0,
  3426. GFX.ZPitch * (endy - starty - 1));
  3427. }
  3428. else
  3429. {
  3430. for (uint32 y = starty; y <= endy; y++)
  3431. {
  3432. memset (GFX.ZBuffer + y * GFX.ZPitch, 0,
  3433. GFX.ZPitch);
  3434. }
  3435. }
  3436. #else
  3437. // Clear the Zbuffer for each of the lines which are going to be updated
  3438. for (uint32 y = starty; y <= endy; y++)
  3439. {
  3440. memset32 ((uint32_t*)(GFX.ZBuffer + y * GFX.ZPitch), 0,
  3441. IPPU.RenderedScreenWidth>>2);
  3442. }
  3443. #endif
  3444. GFX.DB = GFX.ZBuffer; // save pointer to Zbuffer in GFX object
  3445. RenderScreen (GFX.Screen, FALSE, TRUE, SUB_SCREEN_DEPTH);
  3446. }
  3447. }
  3448. }
  3449. else // Transparencys are disabled, ahh lovely ... nice and easy.
  3450. {
  3451. #ifndef _SNESPPC
  3452. if (Settings.SixteenBit)
  3453. #endif
  3454. {
  3455. // get back colour to be used in clearing the screen
  3456. register uint32 back;
  3457. if (!(Memory.FillRAM [0x2131] & 0x80) &&(Memory.FillRAM[0x2131] & 0x20) &&
  3458. (PPU.FixedColourRed || PPU.FixedColourGreen || PPU.FixedColourBlue))
  3459. {
  3460. back = (IPPU.XB[PPU.FixedColourRed]<<11) |
  3461. (IPPU.XB[PPU.FixedColourGreen] << 6) |
  3462. (IPPU.XB[PPU.FixedColourBlue] << 1) | 1;
  3463. back = (back << 16) | back;
  3464. }
  3465. else
  3466. {
  3467. back = IPPU.ScreenColors [0] | (IPPU.ScreenColors [0] << 16);
  3468. }
  3469. // if Forcedblanking in use then back colour becomes black
  3470. if (PPU.ForcedBlanking)
  3471. back = black;
  3472. else
  3473. {
  3474. SelectTileRenderer (TRUE); //selects the tile renderers to be used
  3475. // TRUE means to use the default
  3476. // FALSE means use best renderer based on current
  3477. // graphics register settings
  3478. }
  3479. // now clear all graphics lines which are being updated using the back colour
  3480. for (register uint32 y = starty; y <= endy; y++)
  3481. {
  3482. memset32 ((uint32_t*)(GFX.Screen + y * GFX.Pitch2), back,
  3483. IPPU.RenderedScreenWidth>>1);
  3484. }
  3485. }
  3486. #ifndef _SNESPPC
  3487. else // Settings.SixteenBit == false
  3488. {
  3489. // because we are in 8 bit we can just use 0 to clear the screen
  3490. // this means we can use the Zero Memory function
  3491. // Loop through all lines being updated and clear the pixels to 0
  3492. for (uint32 y = starty; y <= endy; y++)
  3493. {
  3494. ZeroMemory (GFX.Screen + y * GFX.Pitch2,
  3495. IPPU.RenderedScreenWidth);
  3496. }
  3497. }
  3498. #endif
  3499. if (!PPU.ForcedBlanking)
  3500. {
  3501. // Loop through all lines being updated and clear the
  3502. // zbuffer for each of the lines
  3503. for (uint32 y = starty; y <= endy; y++)
  3504. {
  3505. memset32 ((uint32_t*)(GFX.ZBuffer + y * GFX.ZPitch), 0,
  3506. IPPU.RenderedScreenWidth>>2);
  3507. }
  3508. GFX.DB = GFX.ZBuffer; // save pointer to Zbuffer in GFX object
  3509. GFX.pCurrentClip = &IPPU.Clip [0];
  3510. // Define an inline function to handle clipping
  3511. #define FIXCLIP(n) \
  3512. if (GFX.r212c & (1 << (n))) \
  3513. GFX.pCurrentClip = &IPPU.Clip [0]; \
  3514. else \
  3515. GFX.pCurrentClip = &IPPU.Clip [1]
  3516. // Define an inline function to handle which BGs are being displayed
  3517. #define DISPLAY(n) \
  3518. (!(PPU.BG_Forced & n) && \
  3519. (GFX.r212c & n) || \
  3520. ((GFX.r212d & n) && subadd))
  3521. uint8 subadd = GFX.r2131 & 0x3f;
  3522. // go through all BGS are check if they need to be displayed
  3523. bool8_32 BG0 = DISPLAY(1);
  3524. bool8_32 BG1 = DISPLAY(2);
  3525. bool8_32 BG2 = DISPLAY(4);
  3526. bool8_32 BG3 = DISPLAY(8);
  3527. bool8_32 OB = DISPLAY(16);
  3528. if (PPU.BGMode <= 1)
  3529. {
  3530. // screen modes 0 and 1
  3531. if (OB)
  3532. {
  3533. FIXCLIP(4);
  3534. DrawOBJS ();
  3535. }
  3536. if (BG0)
  3537. {
  3538. FIXCLIP(0);
  3539. DrawBackground (PPU.BGMode, 0, 10, 14);
  3540. }
  3541. if (BG1)
  3542. {
  3543. FIXCLIP(1);
  3544. DrawBackground (PPU.BGMode, 1, 9, 13);
  3545. }
  3546. if (BG2)
  3547. {
  3548. FIXCLIP(2);
  3549. DrawBackground (PPU.BGMode, 2, 3,
  3550. (Memory.FillRAM [0x2105] & 8) == 0 ? 6 : 17);
  3551. }
  3552. if (BG3 && PPU.BGMode == 0)
  3553. {
  3554. FIXCLIP(3);
  3555. DrawBackground (PPU.BGMode, 3, 2, 5);
  3556. }
  3557. }
  3558. else if (PPU.BGMode != 7)
  3559. {
  3560. // screen modes 2 and up but not mode 7
  3561. if (OB)
  3562. {
  3563. FIXCLIP(4);
  3564. DrawOBJS ();
  3565. }
  3566. if (BG0)
  3567. {
  3568. FIXCLIP(0);
  3569. DrawBackground (PPU.BGMode, 0, 5, 13);
  3570. }
  3571. if (BG1 && PPU.BGMode != 6)
  3572. {
  3573. FIXCLIP(1);
  3574. DrawBackground (PPU.BGMode, 1, 2, 9);
  3575. }
  3576. }
  3577. else
  3578. {
  3579. // screen mode 7
  3580. if (OB)
  3581. {
  3582. FIXCLIP(4);
  3583. DrawOBJS ();
  3584. }
  3585. if (BG0 || ((Memory.FillRAM [0x2133] & 0x40) && BG1))
  3586. {
  3587. int bg;
  3588. FIXCLIP(0);
  3589. if (Memory.FillRAM [0x2133] & 0x40)
  3590. {
  3591. GFX.Mode7Mask = 0x7f;
  3592. GFX.Mode7PriorityMask = 0x80;
  3593. Mode7Depths [0] = 5;
  3594. Mode7Depths [1] = 9;
  3595. bg = 1;
  3596. }
  3597. else
  3598. {
  3599. GFX.Mode7Mask = 0xff;
  3600. GFX.Mode7PriorityMask = 0;
  3601. Mode7Depths [0] = 5;
  3602. Mode7Depths [1] = 5;
  3603. bg = 0;
  3604. }
  3605. #ifndef _SNESPPC
  3606. if (!Settings.SixteenBit)
  3607. DrawBGMode7Background (GFX.Screen, bg);
  3608. else
  3609. #endif
  3610. {
  3611. if (!Settings.Mode7Interpolate)
  3612. {
  3613. DrawBGMode7Background16 (GFX.Screen, bg);
  3614. }
  3615. else
  3616. {
  3617. DrawBGMode7Background16_i (GFX.Screen, bg);
  3618. }
  3619. }
  3620. }
  3621. }
  3622. }
  3623. }
  3624. #ifndef RC_OPTIMIZE // no hi res
  3625. if (Settings.SupportHiRes && PPU.BGMode != 5 && PPU.BGMode != 6)
  3626. {
  3627. if (IPPU.DoubleWidthPixels)
  3628. {
  3629. // Mixure of background modes used on screen - scale width
  3630. // of all non-mode 5 and 6 pixels.
  3631. #ifndef _SNESPPC
  3632. if (Settings.SixteenBit)
  3633. #endif
  3634. {
  3635. for (register uint32 y = GFX.StartY; y <= GFX.EndY; y++)
  3636. {
  3637. register uint16 *p = (uint16 *) (GFX.Screen + y * GFX.Pitch) + 255;
  3638. register uint16 *q = (uint16 *) (GFX.Screen + y * GFX.Pitch) + 510;
  3639. for (register int x = 255; x >= 0; x--, p--, q -= 2)
  3640. *q = *(q + 1) = *p;
  3641. }
  3642. }
  3643. #ifndef _SNESPPC
  3644. else
  3645. {
  3646. for (register uint32 y = GFX.StartY; y <= GFX.EndY; y++)
  3647. {
  3648. register uint8 *p = GFX.Screen + y * GFX.Pitch + 255;
  3649. register uint8 *q = GFX.Screen + y * GFX.Pitch + 510;
  3650. for (register int x = 255; x >= 0; x--, p--, q -= 2)
  3651. *q = *(q + 1) = *p;
  3652. }
  3653. }
  3654. #endif
  3655. }
  3656. if (IPPU.LatchedInterlace)
  3657. {
  3658. // Interlace is enabled - double the height of all non-mode 5 and 6
  3659. // pixels.
  3660. for (uint32 y = GFX.StartY; y <= GFX.EndY; y++)
  3661. {
  3662. memcpy32 ((uint32_t*)(GFX.Screen + (y * 2 + 1) * GFX.Pitch2),
  3663. (uint32_t*)(GFX.Screen + y * 2 * GFX.Pitch2),
  3664. GFX.Pitch2>>2);
  3665. }
  3666. }
  3667. }
  3668. #endif
  3669. IPPU.PreviousLine = IPPU.CurrentLine;
  3670. }
  3671. #ifdef GFX_MULTI_FORMAT
  3672. #define _BUILD_PIXEL(F) \
  3673. uint32 BuildPixel##F(uint32 R, uint32 G, uint32 B) \
  3674. { \
  3675. return (BUILD_PIXEL_##F(R,G,B)); \
  3676. }\
  3677. uint32 BuildPixel2##F(uint32 R, uint32 G, uint32 B) \
  3678. { \
  3679. return (BUILD_PIXEL2_##F(R,G,B)); \
  3680. } \
  3681. void DecomposePixel##F(uint32 pixel, uint32 &R, uint32 &G, uint32 &B) \
  3682. { \
  3683. DECOMPOSE_PIXEL_##F(pixel,R,G,B); \
  3684. }
  3685. _BUILD_PIXEL(RGB565)
  3686. _BUILD_PIXEL(RGB555)
  3687. _BUILD_PIXEL(BGR565)
  3688. _BUILD_PIXEL(BGR555)
  3689. _BUILD_PIXEL(GBR565)
  3690. _BUILD_PIXEL(GBR555)
  3691. _BUILD_PIXEL(RGB5551)
  3692. bool8_32 S9xSetRenderPixelFormat (int format)
  3693. {
  3694. extern uint32 current_graphic_format;
  3695. current_graphic_format = format;
  3696. switch (format)
  3697. {
  3698. case RGB565:
  3699. _BUILD_SETUP(RGB565)
  3700. return (TRUE);
  3701. case RGB555:
  3702. _BUILD_SETUP(RGB555)
  3703. return (TRUE);
  3704. case BGR565:
  3705. _BUILD_SETUP(BGR565)
  3706. return (TRUE);
  3707. case BGR555:
  3708. _BUILD_SETUP(BGR555)
  3709. return (TRUE);
  3710. case GBR565:
  3711. _BUILD_SETUP(GBR565)
  3712. return (TRUE);
  3713. case GBR555:
  3714. _BUILD_SETUP(GBR555)
  3715. return (TRUE);
  3716. case RGB5551:
  3717. _BUILD_SETUP(RGB5551)
  3718. return (TRUE);
  3719. default:
  3720. break;
  3721. }
  3722. return (FALSE);
  3723. }
  3724. #endif