PageRenderTime 83ms CodeModel.GetById 22ms RepoModel.GetById 0ms app.codeStats 1ms

/SNesoid/sneslib/gfx.cpp

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