PageRenderTime 71ms CodeModel.GetById 21ms RepoModel.GetById 1ms app.codeStats 1ms

/src/snes4iphone_src/gfx_org.cpp

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