PageRenderTime 71ms CodeModel.GetById 15ms RepoModel.GetById 0ms app.codeStats 1ms

/snes9x_asm_optimized/gfx.cpp

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