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

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

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

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