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

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

  1. /*******************************************************************************
  2. Snes9x - Portable Super Nintendo Entertainment System (TM) emulator.
  3. (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 ti…

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