PageRenderTime 75ms CodeModel.GetById 17ms RepoModel.GetById 0ms app.codeStats 1ms

/SNesoid/sneslib_comp/gfx.cpp

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