PageRenderTime 66ms CodeModel.GetById 18ms RepoModel.GetById 0ms app.codeStats 1ms

/snes9x_asm_optimized/gfx.cpp

http://github.com/Summeli/AntSnes
C++ | 4050 lines | 3510 code | 324 blank | 216 comment | 763 complexity | cb3f8250892c23834ad6082e7ec2e6f2 MD5 | raw file

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. //#define _TRANSP_SUPPORT_
  42. //#include <e32cmn.h>
  43. #include "snes9x.h"
  44. #include "memmap.h"
  45. #include "ppu.h"
  46. #include "cpuexec.h"
  47. #include "display.h"
  48. #include "gfx.h"
  49. #include "apu.h"
  50. #include "cheats.h"
  51. //#include "tile.h"
  52. #include "port.h"
  53. typedef unsigned int uint32_t;
  54. #define M7 19
  55. #define M8 19
  56. void ComputeClipWindows ();
  57. static void S9xDisplayFrameRate ();
  58. static void S9xDisplayString (const char *string);
  59. extern uint8 BitShifts[8][4];
  60. extern uint8 TileShifts[8][4];
  61. extern uint8 PaletteShifts[8][4];
  62. extern uint8 PaletteMasks[8][4];
  63. extern uint8 Depths[8][4];
  64. extern uint8 BGSizes [2];
  65. extern NormalTileRenderer DrawTilePtr;
  66. extern ClippedTileRenderer DrawClippedTilePtr;
  67. extern NormalTileRenderer DrawHiResTilePtr;
  68. extern ClippedTileRenderer DrawHiResClippedTilePtr;
  69. extern LargePixelRenderer DrawLargePixelPtr;
  70. extern struct SBG BG;
  71. extern struct SLineData LineData[240];
  72. extern struct SLineMatrixData LineMatrixData [240];
  73. extern uint8 Mode7Depths [2];
  74. #define ON_MAIN(N) \
  75. (GFX.r212c & (1 << (N)) && \
  76. !(PPU.BG_Forced & (1 << (N))))
  77. #define SUB_OR_ADD(N) \
  78. (GFX.r2131 & (1 << (N)))
  79. #define ON_SUB(N) \
  80. ((GFX.r2130 & 0x30) != 0x30 && \
  81. (GFX.r2130 & 2) && \
  82. (GFX.r212d & (1 << N)) && \
  83. !(PPU.BG_Forced & (1 << (N))))
  84. #define ANYTHING_ON_SUB \
  85. ((GFX.r2130 & 0x30) != 0x30 && \
  86. (GFX.r2130 & 2) && \
  87. (GFX.r212d & 0x1f))
  88. #define ADD_OR_SUB_ON_ANYTHING \
  89. (GFX.r2131 & 0x3f)
  90. #define BLACK BUILD_PIXEL(0,0,0)
  91. void DrawTile (uint32 Tile, uint32 Offset, uint32 StartLine,
  92. uint32 LineCount, struct SGFX * gfx);
  93. void DrawClippedTile (uint32 Tile, uint32 Offset,
  94. uint32 StartPixel, uint32 Width,
  95. uint32 StartLine, uint32 LineCount, struct SGFX * gfx);
  96. void DrawTilex2 (uint32 Tile, uint32 Offset, uint32 StartLine,
  97. uint32 LineCount, struct SGFX * gfx);
  98. void DrawClippedTilex2 (uint32 Tile, uint32 Offset,
  99. uint32 StartPixel, uint32 Width,
  100. uint32 StartLine, uint32 LineCount, struct SGFX * gfx);
  101. void DrawTilex2x2 (uint32 Tile, uint32 Offset, uint32 StartLine,
  102. uint32 LineCount, struct SGFX * gfx);
  103. void DrawClippedTilex2x2 (uint32 Tile, uint32 Offset,
  104. uint32 StartPixel, uint32 Width,
  105. uint32 StartLine, uint32 LineCount, struct SGFX * gfx);
  106. void DrawLargePixel (uint32 Tile, uint32 Offset,
  107. uint32 StartPixel, uint32 Pixels,
  108. uint32 StartLine, uint32 LineCount, struct SGFX * gfx);
  109. void DrawTile16 (uint32 Tile, uint32 Offset, uint32 StartLine,
  110. uint32 LineCount, struct SGFX * gfx);
  111. void DrawClippedTile16 (uint32 Tile, uint32 Offset,
  112. uint32 StartPixel, uint32 Width,
  113. uint32 StartLine, uint32 LineCount, struct SGFX * gfx);
  114. void DrawTile16x2 (uint32 Tile, uint32 Offset, uint32 StartLine,
  115. uint32 LineCount, struct SGFX * gfx);
  116. void DrawClippedTile16x2 (uint32 Tile, uint32 Offset,
  117. uint32 StartPixel, uint32 Width,
  118. uint32 StartLine, uint32 LineCount, struct SGFX * gfx);
  119. void DrawTile16x2x2 (uint32 Tile, uint32 Offset, uint32 StartLine,
  120. uint32 LineCount, struct SGFX * gfx);
  121. void DrawClippedTile16x2x2 (uint32 Tile, uint32 Offset,
  122. uint32 StartPixel, uint32 Width,
  123. uint32 StartLine, uint32 LineCount, struct SGFX * gfx);
  124. void DrawLargePixel16 (uint32 Tile, uint32 Offset,
  125. uint32 StartPixel, uint32 Pixels,
  126. uint32 StartLine, uint32 LineCount, struct SGFX * gfx);
  127. void DrawTile16Add (uint32 Tile, uint32 Offset, uint32 StartLine,
  128. uint32 LineCount, struct SGFX * gfx);
  129. void DrawClippedTile16Add (uint32 Tile, uint32 Offset,
  130. uint32 StartPixel, uint32 Width,
  131. uint32 StartLine, uint32 LineCount, struct SGFX * gfx);
  132. void DrawTile16Add1_2 (uint32 Tile, uint32 Offset, uint32 StartLine,
  133. uint32 LineCount, struct SGFX * gfx);
  134. void DrawClippedTile16Add1_2 (uint32 Tile, uint32 Offset,
  135. uint32 StartPixel, uint32 Width,
  136. uint32 StartLine, uint32 LineCount, struct SGFX * gfx);
  137. void DrawTile16FixedAdd1_2 (uint32 Tile, uint32 Offset, uint32 StartLine,
  138. uint32 LineCount, struct SGFX * gfx);
  139. void DrawClippedTile16FixedAdd1_2 (uint32 Tile, uint32 Offset,
  140. uint32 StartPixel, uint32 Width,
  141. uint32 StartLine, uint32 LineCount, struct SGFX * gfx);
  142. void DrawTile16Sub (uint32 Tile, uint32 Offset, uint32 StartLine,
  143. uint32 LineCount, struct SGFX * gfx);
  144. void DrawClippedTile16Sub (uint32 Tile, uint32 Offset,
  145. uint32 StartPixel, uint32 Width,
  146. uint32 StartLine, uint32 LineCount, struct SGFX * gfx);
  147. void DrawTile16Sub1_2 (uint32 Tile, uint32 Offset, uint32 StartLine,
  148. uint32 LineCount, struct SGFX * gfx);
  149. void DrawClippedTile16Sub1_2 (uint32 Tile, uint32 Offset,
  150. uint32 StartPixel, uint32 Width,
  151. uint32 StartLine, uint32 LineCount, struct SGFX * gfx);
  152. void DrawTile16FixedSub1_2 (uint32 Tile, uint32 Offset, uint32 StartLine,
  153. uint32 LineCount, struct SGFX * gfx);
  154. void DrawClippedTile16FixedSub1_2 (uint32 Tile, uint32 Offset,
  155. uint32 StartPixel, uint32 Width,
  156. uint32 StartLine, uint32 LineCount, struct SGFX * gfx);
  157. void DrawLargePixel16Add (uint32 Tile, uint32 Offset,
  158. uint32 StartPixel, uint32 Pixels,
  159. uint32 StartLine, uint32 LineCount, struct SGFX * gfx);
  160. void DrawLargePixel16Add1_2 (uint32 Tile, uint32 Offset,
  161. uint32 StartPixel, uint32 Pixels,
  162. uint32 StartLine, uint32 LineCount, struct SGFX * gfx);
  163. void DrawLargePixel16Sub (uint32 Tile, uint32 Offset,
  164. uint32 StartPixel, uint32 Pixels,
  165. uint32 StartLine, uint32 LineCount, struct SGFX * gfx);
  166. void DrawLargePixel16Sub1_2 (uint32 Tile, uint32 Offset,
  167. uint32 StartPixel, uint32 Pixels,
  168. uint32 StartLine, uint32 LineCount, struct SGFX * gfx);
  169. void DrawHiResClippedTile16 (uint32 Tile, uint32 Offset,
  170. uint32 StartPixel, uint32 Width,
  171. uint32 StartLine, uint32 LineCount, struct SGFX * gfx);
  172. void DrawHiResTile16 (uint32 Tile, uint32 Offset,
  173. uint32 StartLine, uint32 LineCount, struct SGFX * gfx);
  174. bool8 S9xGraphicsInit ()
  175. {
  176. register uint32 PixelOdd = 1;
  177. register uint32 PixelEven = 2;
  178. #ifdef GFX_MULTI_FORMAT
  179. if (GFX.BuildPixel == NULL)
  180. S9xSetRenderPixelFormat (RGB565);
  181. #endif
  182. for (uint8 bitshift = 0; bitshift < 4; bitshift++)
  183. {
  184. for (register char i = 0; i < 16; i++)
  185. {
  186. register uint32 h = 0;
  187. register uint32 l = 0;
  188. #if defined(LSB_FIRST)
  189. if (i & 8)
  190. h |= PixelOdd;
  191. if (i & 4)
  192. h |= PixelOdd << 8;
  193. if (i & 2)
  194. h |= PixelOdd << 16;
  195. if (i & 1)
  196. h |= PixelOdd << 24;
  197. if (i & 8)
  198. l |= PixelOdd;
  199. if (i & 4)
  200. l |= PixelOdd << 8;
  201. if (i & 2)
  202. l |= PixelOdd << 16;
  203. if (i & 1)
  204. l |= PixelOdd << 24;
  205. #else
  206. if (i & 8)
  207. h |= (PixelOdd << 24);
  208. if (i & 4)
  209. h |= (PixelOdd << 16);
  210. if (i & 2)
  211. h |= (PixelOdd << 8);
  212. if (i & 1)
  213. h |= PixelOdd;
  214. if (i & 8)
  215. l |= (PixelOdd << 24);
  216. if (i & 4)
  217. l |= (PixelOdd << 16);
  218. if (i & 2)
  219. l |= (PixelOdd << 8);
  220. if (i & 1)
  221. l |= PixelOdd;
  222. #endif
  223. odd_high[bitshift][(uint8)i] = h;
  224. odd_low[bitshift][(uint8)i] = l;
  225. h = l = 0;
  226. #if defined(LSB_FIRST)
  227. if (i & 8)
  228. h |= PixelEven;
  229. if (i & 4)
  230. h |= PixelEven << 8;
  231. if (i & 2)
  232. h |= PixelEven << 16;
  233. if (i & 1)
  234. h |= PixelEven << 24;
  235. if (i & 8)
  236. l |= PixelEven;
  237. if (i & 4)
  238. l |= PixelEven << 8;
  239. if (i & 2)
  240. l |= PixelEven << 16;
  241. if (i & 1)
  242. l |= PixelEven << 24;
  243. #else
  244. if (i & 8)
  245. h |= (PixelEven << 24);
  246. if (i & 4)
  247. h |= (PixelEven << 16);
  248. if (i & 2)
  249. h |= (PixelEven << 8);
  250. if (i & 1)
  251. h |= PixelEven;
  252. if (i & 8)
  253. l |= (PixelEven << 24);
  254. if (i & 4)
  255. l |= (PixelEven << 16);
  256. if (i & 2)
  257. l |= (PixelEven << 8);
  258. if (i & 1)
  259. l |= PixelEven;
  260. #endif
  261. even_high[bitshift][(uint8)i] = h;
  262. even_low[bitshift][(uint8)i] = l;
  263. }
  264. PixelEven <<= 2;
  265. PixelOdd <<= 2;
  266. }
  267. GFX.RealPitch = GFX.Pitch2 = GFX.Pitch;
  268. GFX.ZPitch = GFX.Pitch;
  269. if (Settings.SixteenBit)
  270. GFX.ZPitch >>= 1;
  271. GFX.Delta = (GFX.SubScreen - GFX.Screen) >> 1;
  272. GFX.DepthDelta = GFX.SubZBuffer - GFX.ZBuffer;
  273. //GFX.InfoStringTimeout = 0;
  274. //GFX.InfoString = NULL;
  275. PPU.BG_Forced = 0;
  276. IPPU.OBJChanged = TRUE;
  277. if (Settings.Transparency)
  278. Settings.SixteenBit = TRUE;
  279. IPPU.DirectColourMapsNeedRebuild = TRUE;
  280. GFX.PixSize = 1;
  281. if (Settings.SixteenBit)
  282. {
  283. DrawTilePtr = DrawTile16;
  284. DrawClippedTilePtr = DrawClippedTile16;
  285. DrawLargePixelPtr = DrawLargePixel16;
  286. DrawHiResTilePtr= DrawHiResTile16;
  287. DrawHiResClippedTilePtr = DrawHiResClippedTile16;
  288. GFX.PPL = GFX.Pitch >> 1;
  289. GFX.PPLx2 = GFX.Pitch;
  290. }
  291. else
  292. {
  293. DrawTilePtr = DrawTile;
  294. DrawClippedTilePtr = DrawClippedTile;
  295. DrawLargePixelPtr = DrawLargePixel;
  296. DrawHiResTilePtr = DrawTile;
  297. DrawHiResClippedTilePtr = DrawClippedTile;
  298. GFX.PPL = GFX.Pitch;
  299. GFX.PPLx2 = GFX.Pitch * 2;
  300. }
  301. S9xFixColourBrightness ();
  302. if (Settings.SixteenBit)
  303. {
  304. if (!(GFX.X2 = (uint16 *) malloc (sizeof (uint16) * 0x10000)))
  305. return (FALSE);
  306. if (!(GFX.ZERO_OR_X2 = (uint16 *) malloc (sizeof (uint16) * 0x10000)) ||
  307. !(GFX.ZERO = (uint16 *) malloc (sizeof (uint16) * 0x10000)))
  308. {
  309. if (GFX.ZERO_OR_X2)
  310. {
  311. free ((char *) GFX.ZERO_OR_X2);
  312. GFX.ZERO_OR_X2 = NULL;
  313. }
  314. if (GFX.X2)
  315. {
  316. free ((char *) GFX.X2);
  317. GFX.X2 = NULL;
  318. }
  319. return (FALSE);
  320. }
  321. uint32 r, g, b;
  322. // Build a lookup table that multiplies a packed RGB value by 2 with
  323. // saturation.
  324. for (r = 0; r <= MAX_RED; r++)
  325. {
  326. uint32 r2 = r << 1;
  327. if (r2 > MAX_RED)
  328. r2 = MAX_RED;
  329. for (g = 0; g <= MAX_GREEN; g++)
  330. {
  331. uint32 g2 = g << 1;
  332. if (g2 > MAX_GREEN)
  333. g2 = MAX_GREEN;
  334. for (b = 0; b <= MAX_BLUE; b++)
  335. {
  336. uint32 b2 = b << 1;
  337. if (b2 > MAX_BLUE)
  338. b2 = MAX_BLUE;
  339. GFX.X2 [BUILD_PIXEL2 (r, g, b)] = BUILD_PIXEL2 (r2, g2, b2);
  340. GFX.X2 [BUILD_PIXEL2 (r, g, b) & ~ALPHA_BITS_MASK] = BUILD_PIXEL2 (r2, g2, b2);
  341. }
  342. }
  343. }
  344. ZeroMemory (GFX.ZERO, 0x10000 * sizeof (uint16));
  345. ZeroMemory (GFX.ZERO_OR_X2, 0x10000 * sizeof (uint16));
  346. // Build a lookup table that if the top bit of the color value is zero
  347. // then the value is zero, otherwise multiply the value by 2. Used by
  348. // the color subtraction code.
  349. #if defined(OLD_COLOUR_BLENDING)
  350. for (r = 0; r <= MAX_RED; r++)
  351. {
  352. uint32 r2 = r;
  353. if ((r2 & 0x10) == 0)
  354. r2 = 0;
  355. else
  356. r2 = (r2 << 1) & MAX_RED;
  357. for (g = 0; g <= MAX_GREEN; g++)
  358. {
  359. uint32 g2 = g;
  360. if ((g2 & GREEN_HI_BIT) == 0)
  361. g2 = 0;
  362. else
  363. g2 = (g2 << 1) & MAX_GREEN;
  364. for (b = 0; b <= MAX_BLUE; b++)
  365. {
  366. uint32 b2 = b;
  367. if ((b2 & 0x10) == 0)
  368. b2 = 0;
  369. else
  370. b2 = (b2 << 1) & MAX_BLUE;
  371. GFX.ZERO_OR_X2 [BUILD_PIXEL2 (r, g, b)] = BUILD_PIXEL2 (r2, g2, b2);
  372. GFX.ZERO_OR_X2 [BUILD_PIXEL2 (r, g, b) & ~ALPHA_BITS_MASK] = BUILD_PIXEL2 (r2, g2, b2);
  373. }
  374. }
  375. }
  376. #else
  377. for (r = 0; r <= MAX_RED; r++)
  378. {
  379. uint32 r2 = r;
  380. if ((r2 & 0x10) == 0)
  381. r2 = 0;
  382. else
  383. r2 = (r2 << 1) & MAX_RED;
  384. if (r2 == 0)
  385. r2 = 1;
  386. for (g = 0; g <= MAX_GREEN; g++)
  387. {
  388. uint32 g2 = g;
  389. if ((g2 & GREEN_HI_BIT) == 0)
  390. g2 = 0;
  391. else
  392. g2 = (g2 << 1) & MAX_GREEN;
  393. if (g2 == 0)
  394. g2 = 1;
  395. for (b = 0; b <= MAX_BLUE; b++)
  396. {
  397. uint32 b2 = b;
  398. if ((b2 & 0x10) == 0)
  399. b2 = 0;
  400. else
  401. b2 = (b2 << 1) & MAX_BLUE;
  402. if (b2 == 0)
  403. b2 = 1;
  404. GFX.ZERO_OR_X2 [BUILD_PIXEL2 (r, g, b)] = BUILD_PIXEL2 (r2, g2, b2);
  405. GFX.ZERO_OR_X2 [BUILD_PIXEL2 (r, g, b) & ~ALPHA_BITS_MASK] = BUILD_PIXEL2 (r2, g2, b2);
  406. }
  407. }
  408. }
  409. #endif
  410. // Build a lookup table that if the top bit of the color value is zero
  411. // then the value is zero, otherwise its just the value.
  412. for (r = 0; r <= MAX_RED; r++)
  413. {
  414. uint32 r2 = r;
  415. if ((r2 & 0x10) == 0)
  416. r2 = 0;
  417. else
  418. r2 &= ~0x10;
  419. for (g = 0; g <= MAX_GREEN; g++)
  420. {
  421. uint32 g2 = g;
  422. if ((g2 & GREEN_HI_BIT) == 0)
  423. g2 = 0;
  424. else
  425. g2 &= ~GREEN_HI_BIT;
  426. for (b = 0; b <= MAX_BLUE; b++)
  427. {
  428. uint32 b2 = b;
  429. if ((b2 & 0x10) == 0)
  430. b2 = 0;
  431. else
  432. b2 &= ~0x10;
  433. GFX.ZERO [BUILD_PIXEL2 (r, g, b)] = BUILD_PIXEL2 (r2, g2, b2);
  434. GFX.ZERO [BUILD_PIXEL2 (r, g, b) & ~ALPHA_BITS_MASK] = BUILD_PIXEL2 (r2, g2, b2);
  435. }
  436. }
  437. }
  438. }
  439. else
  440. {
  441. GFX.X2 = NULL;
  442. GFX.ZERO_OR_X2 = NULL;
  443. GFX.ZERO = NULL;
  444. }
  445. return (TRUE);
  446. }
  447. void S9xGraphicsDeinit (void)
  448. {
  449. // Free any memory allocated in S9xGraphicsInit
  450. if (GFX.X2)
  451. {
  452. free ((char *) GFX.X2);
  453. GFX.X2 = NULL;
  454. }
  455. if (GFX.ZERO_OR_X2)
  456. {
  457. free ((char *) GFX.ZERO_OR_X2);
  458. GFX.ZERO_OR_X2 = NULL;
  459. }
  460. if (GFX.ZERO)
  461. {
  462. free ((char *) GFX.ZERO);
  463. GFX.ZERO = NULL;
  464. }
  465. }
  466. void S9xBuildDirectColourMaps ()
  467. {
  468. for (uint32 p = 0; p < 8; p++)
  469. {
  470. for (uint32 c = 0; c < 256; c++)
  471. {
  472. // XXX: Brightness
  473. DirectColourMaps [p][c] = BUILD_PIXEL (((c & 7) << 2) | ((p & 1) << 1),
  474. ((c & 0x38) >> 1) | (p & 2),
  475. ((c & 0xc0) >> 3) | (p & 4));
  476. }
  477. }
  478. IPPU.DirectColourMapsNeedRebuild = FALSE;
  479. }
  480. void S9xStartScreenRefresh ()
  481. {
  482. if (GFX.InfoStringTimeout > 0 && --GFX.InfoStringTimeout == 0)
  483. GFX.InfoString = NULL;
  484. if (IPPU.RenderThisFrame)
  485. {
  486. #ifndef _SNESPPC
  487. if (!S9xInitUpdate ())
  488. {
  489. IPPU.RenderThisFrame = FALSE;
  490. return;
  491. }
  492. #endif
  493. IPPU.RenderedFramesCount++;
  494. IPPU.PreviousLine = IPPU.CurrentLine = 0;
  495. IPPU.MaxBrightness = PPU.Brightness;
  496. IPPU.LatchedBlanking = PPU.ForcedBlanking;
  497. IPPU.LatchedInterlace = (Memory.FillRAM[0x2133] & 1);
  498. IPPU.RenderedScreenWidth = 256;
  499. IPPU.RenderedScreenHeight = PPU.ScreenHeight;
  500. IPPU.DoubleWidthPixels = FALSE;
  501. GFX.Pitch2 = GFX.Pitch = GFX.RealPitch;
  502. GFX.PPL = GFX.PPLx2 >> 1;
  503. GFX.ZPitch = GFX.RealPitch;
  504. if (Settings.SixteenBit)
  505. GFX.ZPitch >>= 1;
  506. PPU.RecomputeClipWindows = TRUE;
  507. GFX.DepthDelta = GFX.SubZBuffer - GFX.ZBuffer;
  508. GFX.Delta = (GFX.SubScreen - GFX.Screen) >> 1;
  509. }
  510. if (++IPPU.FrameCount % Memory.ROMFramesPerSecond == 0)
  511. {
  512. IPPU.DisplayedRenderedFrameCount = IPPU.RenderedFramesCount;
  513. IPPU.RenderedFramesCount = 0;
  514. IPPU.FrameCount = 0;
  515. }
  516. }
  517. void RenderLine (uint8 C)
  518. {
  519. if (IPPU.RenderThisFrame)
  520. {
  521. LineData[C].BG[0].VOffset = PPU.BG[0].VOffset + 1;
  522. LineData[C].BG[0].HOffset = PPU.BG[0].HOffset;
  523. LineData[C].BG[1].VOffset = PPU.BG[1].VOffset + 1;
  524. LineData[C].BG[1].HOffset = PPU.BG[1].HOffset;
  525. if (PPU.BGMode == 7)
  526. {
  527. struct SLineMatrixData *p = &LineMatrixData [C];
  528. p->MatrixA = PPU.MatrixA;
  529. p->MatrixB = PPU.MatrixB;
  530. p->MatrixC = PPU.MatrixC;
  531. p->MatrixD = PPU.MatrixD;
  532. p->CentreX = PPU.CentreX;
  533. p->CentreY = PPU.CentreY;
  534. }
  535. else
  536. {
  537. if (Settings.StarfoxHack && PPU.BG[2].VOffset == 0 &&
  538. PPU.BG[2].HOffset == 0xe000)
  539. {
  540. LineData[C].BG[2].VOffset = 0xe1;
  541. LineData[C].BG[2].HOffset = 0;
  542. }
  543. else
  544. {
  545. LineData[C].BG[2].VOffset = PPU.BG[2].VOffset + 1;
  546. LineData[C].BG[2].HOffset = PPU.BG[2].HOffset;
  547. LineData[C].BG[3].VOffset = PPU.BG[3].VOffset + 1;
  548. LineData[C].BG[3].HOffset = PPU.BG[3].HOffset;
  549. }
  550. }
  551. IPPU.CurrentLine = C + 1;
  552. }
  553. }
  554. void S9xEndScreenRefresh ()
  555. {
  556. IPPU.HDMAStarted = FALSE;
  557. if (IPPU.RenderThisFrame)
  558. {
  559. FLUSH_REDRAW ();
  560. if (IPPU.ColorsChanged)
  561. {
  562. uint32 saved = PPU.CGDATA[0];
  563. if (!Settings.SixteenBit)
  564. {
  565. // Hack for Super Mario World - to get its sky blue
  566. // (It uses Fixed colour addition on the backdrop colour)
  567. if (!(Memory.FillRAM [0x2131] & 0x80) &&
  568. (Memory.FillRAM[0x2131] & 0x20) &&
  569. (PPU.FixedColourRed || PPU.FixedColourGreen ||
  570. PPU.FixedColourBlue))
  571. {
  572. PPU.CGDATA[0] = PPU.FixedColourRed |
  573. (PPU.FixedColourGreen << 5) |
  574. (PPU.FixedColourBlue << 10);
  575. }
  576. }
  577. IPPU.ColorsChanged = FALSE;
  578. S9xSetPalette ();
  579. PPU.CGDATA[0] = saved;
  580. }
  581. GFX.Pitch = GFX.Pitch2 = GFX.RealPitch;
  582. GFX.PPL = GFX.PPLx2 >> 1;
  583. if (Settings.DisplayFrameRate)
  584. S9xDisplayFrameRate ();
  585. if (GFX.InfoString)
  586. S9xDisplayString (GFX.InfoString);
  587. S9xDeinitUpdate (IPPU.RenderedScreenWidth, IPPU.RenderedScreenHeight,
  588. Settings.SixteenBit);
  589. }
  590. #ifndef RC_OPTIMIZED
  591. S9xApplyCheats ();
  592. #endif
  593. #ifdef DEBUGGER
  594. if (CPU.Flags & FRAME_ADVANCE_FLAG)
  595. {
  596. if (ICPU.FrameAdvanceCount)
  597. {
  598. ICPU.FrameAdvanceCount--;
  599. IPPU.RenderThisFrame = TRUE;
  600. IPPU.FrameSkip = 0;
  601. }
  602. else
  603. {
  604. CPU.Flags &= ~FRAME_ADVANCE_FLAG;
  605. CPU.Flags |= DEBUG_MODE_FLAG;
  606. }
  607. }
  608. #endif
  609. /*
  610. SRAM autosaves cause too noticeable slowdown in Symbian..
  611. if (CPU.SRAMModified)
  612. {
  613. if (!CPU.AutoSaveTimer)
  614. {
  615. if (!(CPU.AutoSaveTimer = Settings.AutoSaveDelay * Memory.ROMFramesPerSecond))
  616. CPU.SRAMModified = FALSE;
  617. }
  618. else
  619. {
  620. if (!--CPU.AutoSaveTimer)
  621. {
  622. S9xAutoSaveSRAM ();
  623. CPU.SRAMModified = FALSE;
  624. }
  625. }
  626. }
  627. */
  628. }
  629. void S9xSetInfoString (const char *string)
  630. {
  631. GFX.InfoString = string;
  632. GFX.InfoStringTimeout = 120;
  633. }
  634. INLINE void SelectTileRenderer (bool8_32 normal)
  635. {
  636. if (normal)
  637. {
  638. DrawTilePtr = DrawTile16;
  639. DrawClippedTilePtr = DrawClippedTile16;
  640. DrawLargePixelPtr = DrawLargePixel16;
  641. }
  642. else
  643. {
  644. if (GFX.r2131 & 0x80)
  645. {
  646. if (GFX.r2131 & 0x40)
  647. {
  648. if (GFX.r2130 & 2)
  649. {
  650. DrawTilePtr = DrawTile16Sub1_2;
  651. DrawClippedTilePtr = DrawClippedTile16Sub1_2;
  652. }
  653. else
  654. {
  655. // Fixed colour substraction
  656. DrawTilePtr = DrawTile16FixedSub1_2;
  657. DrawClippedTilePtr = DrawClippedTile16FixedSub1_2;
  658. }
  659. DrawLargePixelPtr = DrawLargePixel16Sub1_2;
  660. }
  661. else
  662. {
  663. DrawTilePtr = DrawTile16Sub;
  664. DrawClippedTilePtr = DrawClippedTile16Sub;
  665. DrawLargePixelPtr = DrawLargePixel16Sub;
  666. }
  667. }
  668. else
  669. {
  670. if (GFX.r2131 & 0x40)
  671. {
  672. if (GFX.r2130 & 2)
  673. {
  674. DrawTilePtr = DrawTile16Add1_2;
  675. DrawClippedTilePtr = DrawClippedTile16Add1_2;
  676. }
  677. else
  678. {
  679. // Fixed colour addition
  680. DrawTilePtr = DrawTile16FixedAdd1_2;
  681. DrawClippedTilePtr = DrawClippedTile16FixedAdd1_2;
  682. }
  683. DrawLargePixelPtr = DrawLargePixel16Add1_2;
  684. }
  685. else
  686. {
  687. DrawTilePtr = DrawTile16Add;
  688. DrawClippedTilePtr = DrawClippedTile16Add;
  689. DrawLargePixelPtr = DrawLargePixel16Add;
  690. }
  691. }
  692. }
  693. }
  694. void S9xSetupOBJ ()
  695. {
  696. int SmallSize;
  697. int LargeSize;
  698. switch (PPU.OBJSizeSelect)
  699. {
  700. case 0:
  701. SmallSize = 8;
  702. LargeSize = 16;
  703. break;
  704. case 1:
  705. SmallSize = 8;
  706. LargeSize = 32;
  707. break;
  708. case 2:
  709. SmallSize = 8;
  710. LargeSize = 64;
  711. break;
  712. case 3:
  713. SmallSize = 16;
  714. LargeSize = 32;
  715. break;
  716. case 4:
  717. SmallSize = 16;
  718. LargeSize = 64;
  719. break;
  720. case 5:
  721. default:
  722. SmallSize = 32;
  723. LargeSize = 64;
  724. break;
  725. }
  726. int C = 0;
  727. int FirstSprite = PPU.FirstSprite & 0x7f;
  728. int S = FirstSprite;
  729. do
  730. {
  731. int Size;
  732. if (PPU.OBJ [S].Size)
  733. Size = LargeSize;
  734. else
  735. Size = SmallSize;
  736. long VPos = PPU.OBJ [S].VPos;
  737. if (VPos >= PPU.ScreenHeight)
  738. VPos -= 256;
  739. if (PPU.OBJ [S].HPos < 256 && PPU.OBJ [S].HPos > -Size &&
  740. VPos < PPU.ScreenHeight && VPos > -Size)
  741. {
  742. GFX.OBJList [C++] = S;
  743. GFX.Sizes[S] = Size;
  744. GFX.VPositions[S] = VPos;
  745. }
  746. S = (S + 1) & 0x7f;
  747. } while (S != FirstSprite);
  748. // Terminate the list
  749. GFX.OBJList [C] = -1;
  750. IPPU.OBJChanged = FALSE;
  751. }
  752. void DrawOBJS (bool8_32 OnMain = FALSE, uint8 D = 0)
  753. {
  754. uint32 O;
  755. uint32 BaseTile, Tile;
  756. CHECK_SOUND();
  757. BG.BitShift = 4;
  758. BG.TileShift = 5;
  759. BG.TileAddress = PPU.OBJNameBase;
  760. BG.StartPalette = 128;
  761. BG.PaletteShift = 4;
  762. BG.PaletteMask = 7;
  763. BG.Buffer = IPPU.TileCache [TILE_4BIT];
  764. BG.Buffered = IPPU.TileCached [TILE_4BIT];
  765. BG.NameSelect = PPU.OBJNameSelect;
  766. BG.DirectColourMode = FALSE;
  767. GFX.PixSize = 1;
  768. GFX.Z1 = D + 2;
  769. int I = 0;
  770. for (int S = GFX.OBJList [I++]; S >= 0; S = GFX.OBJList [I++])
  771. {
  772. int VPos = GFX.VPositions [S];
  773. int Size = GFX.Sizes[S];
  774. int TileInc = 1;
  775. int Offset;
  776. if (VPos + Size <= (int) GFX.StartY || VPos > (int) GFX.EndY)
  777. continue;
  778. if (OnMain && SUB_OR_ADD(4))
  779. {
  780. SelectTileRenderer (!GFX.Pseudo && PPU.OBJ [S].Palette < 4);
  781. }
  782. BaseTile = PPU.OBJ[S].Name | (PPU.OBJ[S].Palette << 10);
  783. if (PPU.OBJ[S].HFlip)
  784. {
  785. BaseTile += ((Size >> 3) - 1) | H_FLIP;
  786. TileInc = -1;
  787. }
  788. if (PPU.OBJ[S].VFlip)
  789. BaseTile |= V_FLIP;
  790. int clipcount = GFX.pCurrentClip->Count [4];
  791. if (!clipcount)
  792. clipcount = 1;
  793. GFX.Z2 = (PPU.OBJ[S].Priority + 1) * 4 + D;
  794. for (int clip = 0; clip < clipcount; clip++)
  795. {
  796. int Left;
  797. int Right;
  798. if (!GFX.pCurrentClip->Count [4])
  799. {
  800. Left = 0;
  801. Right = 256;
  802. }
  803. else
  804. {
  805. Left = GFX.pCurrentClip->Left [clip][4];
  806. Right = GFX.pCurrentClip->Right [clip][4];
  807. }
  808. if (Right <= Left || PPU.OBJ[S].HPos + Size <= Left ||
  809. PPU.OBJ[S].HPos >= Right)
  810. continue;
  811. for (int Y = 0; Y < Size; Y += 8)
  812. {
  813. if (VPos + Y + 7 >= (int) GFX.StartY && VPos + Y <= (int) GFX.EndY)
  814. {
  815. int StartLine;
  816. int TileLine;
  817. int LineCount;
  818. int Last;
  819. if ((StartLine = VPos + Y) < (int) GFX.StartY)
  820. {
  821. StartLine = GFX.StartY - StartLine;
  822. LineCount = 8 - StartLine;
  823. }
  824. else
  825. {
  826. StartLine = 0;
  827. LineCount = 8;
  828. }
  829. if ((Last = VPos + Y + 7 - GFX.EndY) > 0)
  830. if ((LineCount -= Last) <= 0)
  831. break;
  832. TileLine = StartLine << 3;
  833. O = (VPos + Y + StartLine) * GFX.PPL;
  834. if (!PPU.OBJ[S].VFlip)
  835. Tile = BaseTile + (Y << 1);
  836. else
  837. Tile = BaseTile + ((Size - Y - 8) << 1);
  838. int Middle = Size >> 3;
  839. if (PPU.OBJ[S].HPos < Left)
  840. {
  841. Tile += ((Left - PPU.OBJ[S].HPos) >> 3) * TileInc;
  842. Middle -= (Left - PPU.OBJ[S].HPos) >> 3;
  843. O += Left * GFX.PixSize;
  844. if ((Offset = (Left - PPU.OBJ[S].HPos) & 7))
  845. {
  846. O -= Offset * GFX.PixSize;
  847. int W = 8 - Offset;
  848. int Width = Right - Left;
  849. if (W > Width)
  850. W = Width;
  851. (*DrawClippedTilePtr) (Tile, O, Offset, W,
  852. TileLine, LineCount, &GFX);
  853. if (W >= Width)
  854. continue;
  855. Tile += TileInc;
  856. Middle--;
  857. O += 8 * GFX.PixSize;
  858. }
  859. }
  860. else
  861. O += PPU.OBJ[S].HPos * GFX.PixSize;
  862. if (PPU.OBJ[S].HPos + Size >= Right)
  863. {
  864. Middle -= ((PPU.OBJ[S].HPos + Size + 7) -
  865. Right) >> 3;
  866. Offset = (Right - (PPU.OBJ[S].HPos + Size)) & 7;
  867. }
  868. else
  869. Offset = 0;
  870. for (int X = 0; X < Middle; X++, O += 8 * GFX.PixSize,
  871. Tile += TileInc)
  872. {
  873. (*DrawTilePtr) (Tile, O, TileLine, LineCount, &GFX);
  874. }
  875. if (Offset)
  876. {
  877. (*DrawClippedTilePtr) (Tile, O, 0, Offset,
  878. TileLine, LineCount, &GFX);
  879. }
  880. }
  881. }
  882. }
  883. }
  884. }
  885. void DrawBackgroundMosaic (uint32 BGMode, uint32 bg, uint8 Z1, uint8 Z2)
  886. {
  887. CHECK_SOUND();
  888. uint32 Tile;
  889. uint16 *SC0;
  890. uint16 *SC1;
  891. uint16 *SC2;
  892. uint16 *SC3;
  893. uint8 depths [2] = {Z1, Z2};
  894. if (BGMode == 0)
  895. BG.StartPalette = bg << 5;
  896. else
  897. BG.StartPalette = 0;
  898. SC0 = (uint16 *) &Memory.VRAM[PPU.BG[bg].SCBase << 1];
  899. if (PPU.BG[bg].SCSize & 1)
  900. SC1 = SC0 + 1024;
  901. else
  902. SC1 = SC0;
  903. if (PPU.BG[bg].SCSize & 2)
  904. SC2 = SC1 + 1024;
  905. else
  906. SC2 = SC0;
  907. if (PPU.BG[bg].SCSize & 1)
  908. SC3 = SC2 + 1024;
  909. else
  910. SC3 = SC2;
  911. uint32 Lines;
  912. uint32 OffsetMask;
  913. uint32 OffsetShift;
  914. if (BG.TileSize == 16)
  915. {
  916. OffsetMask = 0x3ff;
  917. OffsetShift = 4;
  918. }
  919. else
  920. {
  921. OffsetMask = 0x1ff;
  922. OffsetShift = 3;
  923. }
  924. for (uint32 Y = GFX.StartY; Y <= GFX.EndY; Y += Lines)
  925. {
  926. uint32 VOffset = LineData [Y].BG[bg].VOffset;
  927. uint32 HOffset = LineData [Y].BG[bg].HOffset;
  928. uint32 MosaicOffset = Y % PPU.Mosaic;
  929. for (Lines = 1; Lines < PPU.Mosaic - MosaicOffset; Lines++)
  930. if ((VOffset != LineData [Y + Lines].BG[bg].VOffset) ||
  931. (HOffset != LineData [Y + Lines].BG[bg].HOffset))
  932. break;
  933. uint32 MosaicLine = VOffset + Y - MosaicOffset;
  934. if (Y + Lines > GFX.EndY)
  935. Lines = GFX.EndY + 1 - Y;
  936. uint32 VirtAlign = (MosaicLine & 7) << 3;
  937. uint16 *b1;
  938. uint16 *b2;
  939. uint32 ScreenLine = MosaicLine >> OffsetShift;
  940. uint32 Rem16 = MosaicLine & 15;
  941. if (ScreenLine & 0x20)
  942. b1 = SC2, b2 = SC3;
  943. else
  944. b1 = SC0, b2 = SC1;
  945. b1 += (ScreenLine & 0x1f) << 5;
  946. b2 += (ScreenLine & 0x1f) << 5;
  947. uint16 *t;
  948. uint32 Left = 0;
  949. uint32 Right = 256;
  950. uint32 ClipCount = GFX.pCurrentClip->Count [bg];
  951. uint32 HPos = HOffset;
  952. uint32 PixWidth = PPU.Mosaic;
  953. if (!ClipCount)
  954. ClipCount = 1;
  955. for (uint32 clip = 0; clip < ClipCount; clip++)
  956. {
  957. if (GFX.pCurrentClip->Count [bg])
  958. {
  959. Left = GFX.pCurrentClip->Left [clip][bg];
  960. Right = GFX.pCurrentClip->Right [clip][bg];
  961. uint32 r = Left % PPU.Mosaic;
  962. HPos = HOffset + Left;
  963. PixWidth = PPU.Mosaic - r;
  964. }
  965. uint32 s = Y * GFX.PPL + Left * GFX.PixSize;
  966. for (uint32 x = Left; x < Right; x += PixWidth,
  967. s += PixWidth * GFX.PixSize,
  968. HPos += PixWidth, PixWidth = PPU.Mosaic)
  969. {
  970. uint32 Quot = (HPos & OffsetMask) >> 3;
  971. if (x + PixWidth >= Right)
  972. PixWidth = Right - x;
  973. if (BG.TileSize == 8)
  974. {
  975. if (Quot > 31)
  976. t = b2 + (Quot & 0x1f);
  977. else
  978. t = b1 + Quot;
  979. }
  980. else
  981. {
  982. if (Quot > 63)
  983. t = b2 + ((Quot >> 1) & 0x1f);
  984. else
  985. t = b1 + (Quot >> 1);
  986. }
  987. Tile = READ_2BYTES (t);
  988. GFX.Z1 = GFX.Z2 = depths [(Tile & 0x2000) >> 13];
  989. // Draw tile...
  990. if (BG.TileSize != 8)
  991. {
  992. if (Tile & H_FLIP)
  993. {
  994. // Horizontal flip, but what about vertical flip ?
  995. if (Tile & V_FLIP)
  996. {
  997. // Both horzontal & vertical flip
  998. if (Rem16 < 8)
  999. {
  1000. (*DrawLargePixelPtr) (Tile + 17 - (Quot & 1), s,
  1001. HPos & 7, PixWidth,
  1002. VirtAlign, Lines, &GFX);
  1003. }
  1004. else
  1005. {
  1006. (*DrawLargePixelPtr) (Tile + 1 - (Quot & 1), s,
  1007. HPos & 7, PixWidth,
  1008. VirtAlign, Lines, &GFX);
  1009. }
  1010. }
  1011. else
  1012. {
  1013. // Horizontal flip only
  1014. if (Rem16 > 7)
  1015. {
  1016. (*DrawLargePixelPtr) (Tile + 17 - (Quot & 1), s,
  1017. HPos & 7, PixWidth,
  1018. VirtAlign, Lines, &GFX);
  1019. }
  1020. else
  1021. {
  1022. (*DrawLargePixelPtr) (Tile + 1 - (Quot & 1), s,
  1023. HPos & 7, PixWidth,
  1024. VirtAlign, Lines, &GFX);
  1025. }
  1026. }
  1027. }
  1028. else
  1029. {
  1030. // No horizontal flip, but is there a vertical flip ?
  1031. if (Tile & V_FLIP)
  1032. {
  1033. // Vertical flip only
  1034. if (Rem16 < 8)
  1035. {
  1036. (*DrawLargePixelPtr) (Tile + 16 + (Quot & 1), s,
  1037. HPos & 7, PixWidth,
  1038. VirtAlign, Lines, &GFX);
  1039. }
  1040. else
  1041. {
  1042. (*DrawLargePixelPtr) (Tile + (Quot & 1), s,
  1043. HPos & 7, PixWidth,
  1044. VirtAlign, Lines, &GFX);
  1045. }
  1046. }
  1047. else
  1048. {
  1049. // Normal unflipped
  1050. if (Rem16 > 7)
  1051. {
  1052. (*DrawLargePixelPtr) (Tile + 16 + (Quot & 1), s,
  1053. HPos & 7, PixWidth,
  1054. VirtAlign, Lines, &GFX);
  1055. }
  1056. else
  1057. {
  1058. (*DrawLargePixelPtr) (Tile + (Quot & 1), s,
  1059. HPos & 7, PixWidth,
  1060. VirtAlign, Lines, &GFX);
  1061. }
  1062. }
  1063. }
  1064. }
  1065. else
  1066. (*DrawLargePixelPtr) (Tile, s, HPos & 7, PixWidth,
  1067. VirtAlign, Lines, &GFX);
  1068. }
  1069. }
  1070. }
  1071. }
  1072. void DrawBackgroundOffset (uint32 BGMode, uint32 bg, uint8 Z1, uint8 Z2)
  1073. {
  1074. CHECK_SOUND();
  1075. uint32 Tile;
  1076. uint16 *SC0;
  1077. uint16 *SC1;
  1078. uint16 *SC2;
  1079. uint16 *SC3;
  1080. uint16 *BPS0;
  1081. uint16 *BPS1;
  1082. uint16 *BPS2;
  1083. uint16 *BPS3;
  1084. uint32 Width;
  1085. int VOffsetOffset = BGMode == 4 ? 0 : 32;
  1086. uint8 depths [2] = {Z1, Z2};
  1087. BG.StartPalette = 0;
  1088. BPS0 = (uint16 *) &Memory.VRAM[PPU.BG[2].SCBase << 1];
  1089. if (PPU.BG[2].SCSize & 1)
  1090. BPS1 = BPS0 + 1024;
  1091. else
  1092. BPS1 = BPS0;
  1093. if (PPU.BG[2].SCSize & 2)
  1094. BPS2 = BPS1 + 1024;
  1095. else
  1096. BPS2 = BPS0;
  1097. if (PPU.BG[2].SCSize & 1)
  1098. BPS3 = BPS2 + 1024;
  1099. else
  1100. BPS3 = BPS2;
  1101. SC0 = (uint16 *) &Memory.VRAM[PPU.BG[bg].SCBase << 1];
  1102. if (PPU.BG[bg].SCSize & 1)
  1103. SC1 = SC0 + 1024;
  1104. else
  1105. SC1 = SC0;
  1106. if (PPU.BG[bg].SCSize & 2)
  1107. SC2 = SC1 + 1024;
  1108. else
  1109. SC2 = SC0;
  1110. if (PPU.BG[bg].SCSize & 1)
  1111. SC3 = SC2 + 1024;
  1112. else
  1113. SC3 = SC2;
  1114. static const int Lines = 1;
  1115. int OffsetMask;
  1116. int OffsetShift;
  1117. int OffsetEnableMask = 1 << (bg + 13);
  1118. if (BG.TileSize == 16)
  1119. {
  1120. OffsetMask = 0x3ff;
  1121. OffsetShift = 4;
  1122. }
  1123. else
  1124. {
  1125. OffsetMask = 0x1ff;
  1126. OffsetShift = 3;
  1127. }
  1128. for (uint32 Y = GFX.StartY; Y <= GFX.EndY; Y++)
  1129. {
  1130. uint32 VOff = LineData [Y].BG[2].VOffset;
  1131. uint32 HOff = LineData [Y].BG[2].HOffset;
  1132. int VirtAlign;
  1133. int ScreenLine = VOff >> 3;
  1134. int t1;
  1135. int t2;
  1136. uint16 *s0;
  1137. uint16 *s1;
  1138. uint16 *s2;
  1139. if (ScreenLine & 0x20)
  1140. s1 = BPS2, s2 = BPS3;
  1141. else
  1142. s1 = BPS0, s2 = BPS1;
  1143. s1 += (ScreenLine & 0x1f) << 5;
  1144. s2 += (ScreenLine & 0x1f) << 5;
  1145. int clipcount = GFX.pCurrentClip->Count [bg];
  1146. if (!clipcount)
  1147. clipcount = 1;
  1148. for (int clip = 0; clip < clipcount; clip++)
  1149. {
  1150. uint32 Left;
  1151. uint32 Right;
  1152. if (!GFX.pCurrentClip->Count [bg])
  1153. {
  1154. Left = 0;
  1155. Right = 256;
  1156. }
  1157. else
  1158. {
  1159. Left = GFX.pCurrentClip->Left [clip][bg];
  1160. Right = GFX.pCurrentClip->Right [clip][bg];
  1161. if (Right <= Left)
  1162. continue;
  1163. }
  1164. uint32 VOffset;
  1165. uint32 HOffset;
  1166. uint32 LineHOffset=LineData [Y].BG[bg].HOffset;
  1167. uint32 Offset;
  1168. uint32 HPos;
  1169. uint32 Quot;
  1170. uint32 Count;
  1171. uint16 *t;
  1172. uint32 Quot2;
  1173. uint32 VCellOffset;
  1174. uint32 HCellOffset;
  1175. uint16 *b1;
  1176. uint16 *b2;
  1177. uint32 TotalCount = 0;
  1178. uint32 MaxCount = 8;
  1179. uint32 s = Left * GFX.PixSize + Y * GFX.PPL;
  1180. bool8_32 left_hand_edge = (Left == 0);
  1181. Width = Right - Left;
  1182. if (Left & 7)
  1183. MaxCount = 8 - (Left & 7);
  1184. while (Left < Right)
  1185. {
  1186. if (left_hand_edge)
  1187. {
  1188. // The SNES offset-per-tile background mode has a
  1189. // hardware limitation that the offsets cannot be set
  1190. // for the tile at the left-hand edge of the screen.
  1191. VOffset = LineData [Y].BG[bg].VOffset;
  1192. HOffset = LineHOffset;
  1193. left_hand_edge = FALSE;
  1194. }
  1195. else
  1196. {
  1197. // All subsequent offset tile data is shifted left by one,
  1198. // hence the - 1 below.
  1199. Quot2 = ((HOff + Left - 1) & OffsetMask) >> 3;
  1200. if (Quot2 > 31)
  1201. s0 = s2 + (Quot2 & 0x1f);
  1202. else
  1203. s0 = s1 + Quot2;
  1204. HCellOffset = READ_2BYTES (s0);
  1205. if (BGMode == 4)
  1206. {
  1207. VOffset = LineData [Y].BG[bg].VOffset;
  1208. HOffset=LineHOffset;
  1209. if ((HCellOffset & OffsetEnableMask))
  1210. {
  1211. if (HCellOffset & 0x8000)
  1212. VOffset = HCellOffset + 1;
  1213. else
  1214. HOffset = HCellOffset;
  1215. }
  1216. }
  1217. else
  1218. {
  1219. VCellOffset = READ_2BYTES (s0 + VOffsetOffset);
  1220. if ((VCellOffset & OffsetEnableMask))
  1221. VOffset = VCellOffset + 1;
  1222. else
  1223. VOffset = LineData [Y].BG[bg].VOffset;
  1224. if ((HCellOffset & OffsetEnableMask))
  1225. HOffset = (HCellOffset & ~7)|(LineHOffset&7);
  1226. else
  1227. HOffset=LineHOffset;
  1228. }
  1229. }
  1230. VirtAlign = ((Y + VOffset) & 7) << 3;
  1231. ScreenLine = (VOffset + Y) >> OffsetShift;
  1232. if (((VOffset + Y) & 15) > 7)
  1233. {
  1234. t1 = 16;
  1235. t2 = 0;
  1236. }
  1237. else
  1238. {
  1239. t1 = 0;
  1240. t2 = 16;
  1241. }
  1242. if (ScreenLine & 0x20)
  1243. b1 = SC2, b2 = SC3;
  1244. else
  1245. b1 = SC0, b2 = SC1;
  1246. b1 += (ScreenLine & 0x1f) << 5;
  1247. b2 += (ScreenLine & 0x1f) << 5;
  1248. HPos = (HOffset + Left) & OffsetMask;
  1249. Quot = HPos >> 3;
  1250. if (BG.TileSize == 8)
  1251. {
  1252. if (Quot > 31)
  1253. t = b2 + (Quot & 0x1f);
  1254. else
  1255. t = b1 + Quot;
  1256. }
  1257. else
  1258. {
  1259. if (Quot > 63)
  1260. t = b2 + ((Quot >> 1) & 0x1f);
  1261. else
  1262. t = b1 + (Quot >> 1);
  1263. }
  1264. if (MaxCount + TotalCount > Width)
  1265. MaxCount = Width - TotalCount;
  1266. Offset = HPos & 7;
  1267. Count = 8 - Offset;
  1268. if (Count > MaxCount)
  1269. Count = MaxCount;
  1270. s -= Offset * GFX.PixSize;
  1271. Tile = READ_2BYTES(t);
  1272. GFX.Z1 = GFX.Z2 = depths [(Tile & 0x2000) >> 13];
  1273. if (BG.TileSize == 8)
  1274. (*DrawClippedTilePtr) (Tile, s, Offset, Count, VirtAlign, Lines, &GFX);
  1275. else
  1276. {
  1277. if (!(Tile & (V_FLIP | H_FLIP)))
  1278. {
  1279. // Normal, unflipped
  1280. (*DrawClippedTilePtr) (Tile + t1 + (Quot & 1),
  1281. s, Offset, Count, VirtAlign, Lines, &GFX);
  1282. }
  1283. else
  1284. if (Tile & H_FLIP)
  1285. {
  1286. if (Tile & V_FLIP)
  1287. {
  1288. // H & V flip
  1289. (*DrawClippedTilePtr) (Tile + t2 + 1 - (Quot & 1),
  1290. s, Offset, Count, VirtAlign, Lines, &GFX);
  1291. }
  1292. else
  1293. {
  1294. // H flip only
  1295. (*DrawClippedTilePtr) (Tile + t1 + 1 - (Quot & 1),
  1296. s, Offset, Count, VirtAlign, Lines, &GFX);
  1297. }
  1298. }
  1299. else
  1300. {
  1301. // V flip only
  1302. (*DrawClippedTilePtr) (Tile + t2 + (Quot & 1),
  1303. s, Offset, Count, VirtAlign, Lines, &GFX);
  1304. }
  1305. }
  1306. Left += Count;
  1307. TotalCount += Count;
  1308. s += (Offset + Count) * GFX.PixSize;
  1309. MaxCount = 8;
  1310. }
  1311. }
  1312. }
  1313. }
  1314. void DrawBackgroundMode5 (uint32 /* BGMODE */, uint32 bg, uint8 Z1, uint8 Z2)
  1315. {
  1316. CHECK_SOUND();
  1317. GFX.Pitch = GFX.RealPitch;
  1318. GFX.PPL = GFX.PPLx2 >> 1;
  1319. GFX.PixSize = 1;
  1320. uint8 depths [2] = {Z1, Z2};
  1321. uint32 Tile;
  1322. uint16 *SC0;
  1323. uint16 *SC1;
  1324. uint16 *SC2;
  1325. uint16 *SC3;
  1326. uint32 Width;
  1327. BG.StartPalette = 0;
  1328. SC0 = (uint16 *) &Memory.VRAM[PPU.BG[bg].SCBase << 1];
  1329. if ((PPU.BG[bg].SCSize & 1))
  1330. SC1 = SC0 + 1024;
  1331. else
  1332. SC1 = SC0;
  1333. if ((PPU.BG[bg].SCSize & 2))
  1334. SC2 = SC1 + 1024;
  1335. else
  1336. SC2 = SC0;
  1337. if ((PPU.BG[bg].SCSize & 1))
  1338. SC3 = SC2 + 1024;
  1339. else
  1340. SC3 = SC2;
  1341. int Lines;
  1342. int VOffsetMask;
  1343. int VOffsetShift;
  1344. if (BG.TileSize == 16)
  1345. {
  1346. VOffsetMask = 0x3ff;
  1347. VOffsetShift = 4;
  1348. }
  1349. else
  1350. {
  1351. VOffsetMask = 0x1ff;
  1352. VOffsetShift = 3;
  1353. }
  1354. // int endy = IPPU.LatchedInterlace ? GFX.EndY << 1 : GFX.EndY;
  1355. int endy = GFX.EndY;
  1356. // for (int Y = IPPU.LatchedInterlace ? GFX.StartY << 1 : GFX.StartY; Y <= endy; Y += Lines)
  1357. for (int Y = GFX.StartY; Y <= endy; Y += Lines)
  1358. {
  1359. // int y = IPPU.LatchedInterlace ? (Y >> 1) : Y;
  1360. int y = Y;
  1361. uint32 VOffset = LineData [y].BG[bg].VOffset;
  1362. uint32 HOffset = LineData [y].BG[bg].HOffset;
  1363. int VirtAlign = (Y + VOffset) & 7;
  1364. for (Lines = 1; Lines < 8 - VirtAlign; Lines++)
  1365. if ((VOffset != LineData [y + Lines].BG[bg].VOffset) ||
  1366. (HOffset != LineData [y + Lines].BG[bg].HOffset))
  1367. break;
  1368. HOffset <<= 1;
  1369. if (Y + Lines > endy)
  1370. Lines = endy + 1 - Y;
  1371. // VirtAlign <<= 3;
  1372. int ScreenLine = (VOffset + Y) >> VOffsetShift;
  1373. int t1;
  1374. int t2;
  1375. if (((VOffset + Y) & 15) > 7)
  1376. {
  1377. t1 = 16;
  1378. t2 = 0;
  1379. }
  1380. else
  1381. {
  1382. t1 = 0;
  1383. t2 = 16;
  1384. }
  1385. uint16 *b1;
  1386. uint16 *b2;
  1387. if (ScreenLine & 0x20)
  1388. b1 = SC2, b2 = SC3;
  1389. else
  1390. b1 = SC0, b2 = SC1;
  1391. b1 += (ScreenLine & 0x1f) << 5;
  1392. b2 += (ScreenLine & 0x1f) << 5;
  1393. int clipcount = GFX.pCurrentClip->Count [bg];
  1394. if (!clipcount)
  1395. clipcount = 1;
  1396. for (int clip = 0; clip < clipcount; clip++)
  1397. {
  1398. int Left;
  1399. int Right;
  1400. if (!GFX.pCurrentClip->Count [bg])
  1401. {
  1402. Left = 0;
  1403. Right = 512;
  1404. }
  1405. else
  1406. {
  1407. Left = GFX.pCurrentClip->Left [clip][bg] * 2;
  1408. Right = GFX.pCurrentClip->Right [clip][bg] * 2;
  1409. if (Right <= Left)
  1410. continue;
  1411. }
  1412. uint32 s = (Left>>1) * GFX.PixSize + Y * GFX.PPL;
  1413. uint32 HPos = (HOffset + Left * GFX.PixSize) & 0x3ff;
  1414. uint32 Quot = HPos >> 3;
  1415. uint32 Count = 0;
  1416. uint16 *t;
  1417. if (Quot > 63)
  1418. t = b2 + ((Quot >> 1) & 0x1f);
  1419. else
  1420. t = b1 + (Quot >> 1);
  1421. Width = Right - Left;
  1422. // Left hand edge clipped tile
  1423. if (HPos & 7)
  1424. {
  1425. int Offset = (HPos & 7);
  1426. Count = 8 - Offset;
  1427. if (Count > Width)
  1428. Count = Width;
  1429. s -= (Offset>>1);
  1430. Tile = READ_2BYTES (t);
  1431. GFX.Z1 = GFX.Z2 = depths [(Tile & 0x2000) >> 13];
  1432. if (BG.TileSize == 8)
  1433. {
  1434. if (!(Tile & H_FLIP))
  1435. {
  1436. // Normal, unflipped
  1437. (*DrawHiResClippedTilePtr) (Tile + (Quot & 1),
  1438. s, Offset, Count, VirtAlign, Lines, &GFX);
  1439. }
  1440. else
  1441. {
  1442. // H flip
  1443. (*DrawHiResClippedTilePtr) (Tile + 1 - (Quot & 1),
  1444. s, Offset, Count, VirtAlign, Lines, &GFX);
  1445. }
  1446. }
  1447. else
  1448. {
  1449. if (!(Tile & (V_FLIP | H_FLIP)))
  1450. {
  1451. // Normal, unflipped
  1452. (*DrawHiResClippedTilePtr) (Tile + t1 + (Quot & 1),
  1453. s, Offset, Count, VirtAlign, Lines, &GFX);
  1454. }
  1455. else
  1456. if (Tile & H_FLIP)
  1457. {
  1458. if (Tile & V_FLIP)
  1459. {
  1460. // H & V flip
  1461. (*DrawHiResClippedTilePtr) (Tile + t2 + 1 - (Quot & 1),
  1462. s, Offset, Count, VirtAlign, Lines, &GFX);
  1463. }
  1464. else
  1465. {
  1466. // H flip only
  1467. (*DrawHiResClippedTilePtr) (Tile + t1 + 1 - (Quot & 1),
  1468. s, Offset, Count, VirtAlign, Lines, &GFX);
  1469. }
  1470. }
  1471. else
  1472. {
  1473. // V flip only
  1474. (*DrawHiResClippedTilePtr) (Tile + t2 + (Quot & 1),
  1475. s, Offset, Count, VirtAlign, Lines, &GFX);
  1476. }
  1477. }
  1478. t += Quot & 1;
  1479. if (Quot == 63)
  1480. t = b2;
  1481. else if (Quot == 127)
  1482. t = b1;
  1483. Quot++;
  1484. s += 4;
  1485. }
  1486. // Middle, unclipped tiles
  1487. Count = Width - Count;
  1488. int Middle = Count >> 3;
  1489. Count &= 7;
  1490. for (int C = Middle; C > 0; s += 4, Quot++, C--)
  1491. {
  1492. Tile = READ_2BYTES(t);
  1493. GFX.Z1 = GFX.Z2 = depths [(Tile & 0x2000) >> 13];
  1494. if (BG.TileSize == 8)
  1495. {
  1496. if (!(Tile & H_FLIP))
  1497. {
  1498. // Normal, unflipped
  1499. (*DrawHiResTilePtr) (Tile + (Quot & 1),
  1500. s, VirtAlign, Lines, &GFX);
  1501. }
  1502. else
  1503. {
  1504. // H flip
  1505. (*DrawHiResTilePtr) (Tile + 1 - (Quot & 1),
  1506. s, VirtAlign, Lines, &GFX);
  1507. }
  1508. }
  1509. else
  1510. {
  1511. if (!(Tile & (V_FLIP | H_FLIP)))
  1512. {
  1513. // Normal, unflipped
  1514. (*DrawHiResTilePtr) (Tile + t1 + (Quot & 1),
  1515. s, VirtAlign, Lines, &GFX);
  1516. }
  1517. else
  1518. if (Tile & H_FLIP)
  1519. {
  1520. if (Tile & V_FLIP)
  1521. {
  1522. // H & V flip
  1523. (*DrawHiResTilePtr) (Tile + t2 + 1 - (Quot & 1),
  1524. s, VirtAlign, Lines, &GFX);
  1525. }
  1526. else
  1527. {
  1528. // H flip only
  1529. (*DrawHiResTilePtr) (Tile + t1 + 1 - (Quot & 1),
  1530. s, VirtAlign, Lines, &GFX);
  1531. }
  1532. }
  1533. else
  1534. {
  1535. // V flip only
  1536. (*DrawHiResTilePtr) (Tile + t2 + (Quot & 1),
  1537. s, VirtAlign, Lines, &GFX);
  1538. }
  1539. }
  1540. t += Quot & 1;
  1541. if (Quot == 63)
  1542. t = b2;
  1543. else
  1544. if (Quot == 127)
  1545. t = b1;
  1546. }
  1547. // Right-hand edge clipped tiles
  1548. if (Count)
  1549. {
  1550. Tile = READ_2BYTES(t);
  1551. GFX.Z1 = GFX.Z2 = depths [(Tile & 0x2000) >> 13];
  1552. if (BG.TileSize == 8)
  1553. {
  1554. if (!(Tile & H_FLIP))
  1555. {
  1556. // Normal, unflipped
  1557. (*DrawHiResClippedTilePtr) (Tile + (Quot & 1),
  1558. s, 0, Count, VirtAlign, Lines, &GFX);
  1559. }
  1560. else
  1561. {
  1562. // H flip
  1563. (*DrawHiResClippedTilePtr) (Tile + 1 - (Quot & 1),
  1564. s, 0, Count, VirtAlign, Lines, &GFX);
  1565. }
  1566. }
  1567. else
  1568. {
  1569. if (!(Tile & (V_FLIP | H_FLIP)))
  1570. {
  1571. // Normal, unflipped
  1572. (*DrawHiResClippedTilePtr) (Tile + t1 + (Quot & 1),
  1573. s, 0, Count, VirtAlign, Lines, &GFX);
  1574. }
  1575. else
  1576. if (Tile & H_FLIP)
  1577. {
  1578. if (Tile & V_FLIP)
  1579. {
  1580. // H & V flip
  1581. (*DrawHiResClippedTilePtr) (Tile + t2 + 1 - (Quot & 1),
  1582. s, 0, Count, VirtAlign, Lines, &GFX);
  1583. }
  1584. else
  1585. {
  1586. // H flip only
  1587. (*DrawHiResClippedTilePtr) (Tile + t1 + 1 - (Quot & 1),
  1588. s, 0, Count, VirtAlign, Lines, &GFX);
  1589. }
  1590. }
  1591. else
  1592. {
  1593. // V flip only
  1594. (*DrawHiResClippedTilePtr) (Tile + t2 + (Quot & 1),
  1595. s, 0, Count, VirtAlign, Lines, &GFX);
  1596. }
  1597. }
  1598. }
  1599. }
  1600. }
  1601. }
  1602. void DrawBackground (uint32 BGMode, uint32 bg, uint8 Z1, uint8 Z2)
  1603. {
  1604. GFX.PixSize = 1;
  1605. BG.TileSize = BGSizes [PPU.BG[bg].BGSize];
  1606. BG.BitShift = BitShifts[BGMode][bg];
  1607. BG.TileShift = TileShifts[BGMode][bg];
  1608. BG.TileAddress = PPU.BG[bg].NameBase << 1;
  1609. BG.NameSelect = 0;
  1610. BG.Buffer = IPPU.TileCache [Depths [BGMode][bg]];
  1611. BG.Buffered = IPPU.TileCached [Depths [BGMode][bg]];
  1612. BG.PaletteShift = PaletteShifts[BGMode][bg];
  1613. BG.PaletteMask = PaletteMasks[BGMode][bg];
  1614. BG.DirectColourMode = (BGMode == 3 || BGMode == 4) && bg == 0 &&
  1615. (GFX.r2130 & 1);
  1616. if (PPU.BGMosaic [bg] && PPU.Mosaic > 1)
  1617. {
  1618. DrawBackgroundMosaic (BGMode, bg, Z1, Z2);
  1619. return;
  1620. }
  1621. switch (BGMode)
  1622. {
  1623. case 2:
  1624. if (Settings.WrestlemaniaArcade)
  1625. break;
  1626. case 4: // Used by Puzzle Bobble
  1627. DrawBackgroundOffset (BGMode, bg, Z1, Z2);
  1628. return;
  1629. case 5:
  1630. case 6: // XXX: is also offset per tile.
  1631. DrawBackgroundMode5 (BGMode, bg, Z1, Z2);
  1632. return;
  1633. }
  1634. CHECK_SOUND();
  1635. uint32 Tile;
  1636. uint16 *SC0;
  1637. uint16 *SC1;
  1638. uint16 *SC2;
  1639. uint16 *SC3;
  1640. uint32 Width;
  1641. uint8 depths [2] = {Z1, Z2};
  1642. if (BGMode == 0)
  1643. BG.StartPalette = bg << 5;
  1644. else
  1645. BG.StartPalette = 0;
  1646. SC0 = (uint16 *) &Memory.VRAM[PPU.BG[bg].SCBase << 1];
  1647. if (PPU.BG[bg].SCSize & 1)
  1648. SC1 = SC0 + 1024;
  1649. else
  1650. SC1 = SC0;
  1651. if (PPU.BG[bg].SCSize & 2)
  1652. SC2 = SC1 + 1024;
  1653. else
  1654. SC2 = SC0;
  1655. if (PPU.BG[bg].SCSize & 1)
  1656. SC3 = SC2 + 1024;
  1657. else
  1658. SC3 = SC2;
  1659. int Lines;
  1660. int OffsetMask;
  1661. int OffsetShift;
  1662. if (BG.TileSize == 16)
  1663. {
  1664. OffsetMask = 0x3ff;
  1665. OffsetShift = 4;
  1666. }
  1667. else
  1668. {
  1669. OffsetMask = 0x1ff;
  1670. OffsetShift = 3;
  1671. }
  1672. // outermost loop
  1673. for (uint32 Y = GFX.StartY; Y <= GFX.EndY; Y += Lines)
  1674. {
  1675. uint32 VOffset = LineData [Y].BG[bg].VOffset;
  1676. uint32 HOffset = LineData [Y].BG[bg].HOffset;
  1677. int VirtAlign = (Y + VOffset) & 7;
  1678. for (Lines = 1; Lines < 8 - VirtAlign; Lines++)
  1679. if ((VOffset != LineData [Y + Lines].BG[bg].VOffset) ||
  1680. (HOffset != LineData [Y + Lines].BG[bg].HOffset))
  1681. break;
  1682. if (Y + Lines > GFX.EndY)
  1683. Lines = GFX.EndY + 1 - Y;
  1684. VirtAlign <<= 3;
  1685. uint32 ScreenLine = (VOffset + Y) >> OffsetShift;
  1686. uint32 t1;
  1687. uint32 t2;
  1688. if (((VOffset + Y) & 15) > 7)
  1689. {
  1690. t1 = 16;
  1691. t2 = 0;
  1692. }
  1693. else
  1694. {
  1695. t1 = 0;
  1696. t2 = 16;
  1697. }
  1698. uint16 *b1;
  1699. uint16 *b2;
  1700. if (ScreenLine & 0x20)
  1701. b1 = SC2, b2 = SC3;
  1702. else
  1703. b1 = SC0, b2 = SC1;
  1704. b1 += (ScreenLine & 0x1f) << 5;
  1705. b2 += (ScreenLine & 0x1f) << 5;
  1706. int clipcount = GFX.pCurrentClip->Count [bg];
  1707. if (!clipcount)
  1708. clipcount = 1;
  1709. for (int clip = 0; clip < clipcount; clip++)
  1710. {
  1711. uint32 Left;
  1712. uint32 Right;
  1713. if (!GFX.pCurrentClip->Count [bg])
  1714. {
  1715. Left = 0;
  1716. Right = 256;
  1717. }
  1718. else
  1719. {
  1720. Left = GFX.pCurrentClip->Left [clip][bg];
  1721. Right = GFX.pCurrentClip->Right [clip][bg];
  1722. if (Right <= Left)
  1723. continue;
  1724. }
  1725. uint32 s = Left * GFX.PixSize + Y * GFX.PPL;
  1726. uint32 HPos = (HOffset + Left) & OffsetMask;
  1727. uint32 Quot = HPos >> 3;
  1728. uint32 Count = 0;
  1729. uint16 *t;
  1730. if (BG.TileSize == 8)
  1731. {
  1732. if (Quot > 31)
  1733. t = b2 + (Quot & 0x1f);
  1734. else
  1735. t = b1 + Quot;
  1736. }
  1737. else
  1738. {
  1739. if (Quot > 63)
  1740. t = b2 + ((Quot >> 1) & 0x1f);
  1741. else
  1742. t = b1 + (Quot >> 1);
  1743. }
  1744. Width = Right - Left;
  1745. // Left hand edge clipped tile
  1746. if (HPos & 7)
  1747. {
  1748. uint32 Offset = (HPos & 7);
  1749. Count = 8 - Offset;
  1750. if (Count > Width)
  1751. Count = Width;
  1752. s -= Offset * GFX.PixSize;
  1753. Tile = READ_2BYTES(t);
  1754. GFX.Z1 = GFX.Z2 = depths [(Tile & 0x2000) >> 13];
  1755. if (BG.TileSize == 8)
  1756. {
  1757. (*DrawClippedTilePtr) (Tile, s, Offset, Count, VirtAlign,
  1758. Lines, &GFX);
  1759. }
  1760. else
  1761. {
  1762. if (!(Tile & (V_FLIP | H_FLIP)))
  1763. {
  1764. // Normal, unflipped
  1765. (*DrawClippedTilePtr) (Tile + t1 + (Quot & 1),
  1766. s, Offset, Count, VirtAlign, Lines, &GFX);
  1767. }
  1768. else
  1769. if (Tile & H_FLIP)
  1770. {
  1771. if (Tile & V_FLIP)
  1772. {
  1773. // H & V flip
  1774. (*DrawClippedTilePtr) (Tile + t2 + 1 - (Quot & 1),
  1775. s, Offset, Count, VirtAlign, Lines, &GFX);
  1776. }
  1777. else
  1778. {
  1779. // H flip only
  1780. (*DrawClippedTilePtr) (Tile + t1 + 1 - (Quot & 1),
  1781. s, Offset, Count, VirtAlign, Lines, &GFX);
  1782. }
  1783. }
  1784. else
  1785. {
  1786. // V flip only
  1787. (*DrawClippedTilePtr) (Tile + t2 + (Quot & 1), s,
  1788. Offset, Count, VirtAlign, Lines, &GFX);
  1789. }
  1790. }
  1791. if (BG.TileSize == 8)
  1792. {
  1793. t++;
  1794. if (Quot == 31)
  1795. t = b2;
  1796. else if (Quot == 63)
  1797. t = b1;
  1798. }
  1799. else
  1800. {
  1801. t += Quot & 1;
  1802. if (Quot == 63)
  1803. t = b2;
  1804. else if (Quot == 127)
  1805. t = b1;
  1806. }
  1807. Quot++;
  1808. s += 8 * GFX.PixSize;
  1809. }
  1810. // Middle, unclipped tiles
  1811. Count = Width - Count;
  1812. int Middle = Count >> 3;
  1813. Count &= 7;
  1814. for (int C = Middle; C > 0; s += 8 * GFX.PixSize, Quot++, C--)
  1815. {
  1816. Tile = READ_2BYTES(t);
  1817. GFX.Z1 = GFX.Z2 = depths [(Tile & 0x2000) >> 13];
  1818. if (BG.TileSize != 8)
  1819. {
  1820. if (Tile & H_FLIP)
  1821. {
  1822. // Horizontal flip, but what about vertical flip ?
  1823. if (Tile & V_FLIP)
  1824. {
  1825. // Both horzontal & vertical flip
  1826. (*DrawTilePtr) (Tile + t2 + 1 - (Quot & 1), s,
  1827. VirtAlign, Lines, &GFX);
  1828. }
  1829. else
  1830. {
  1831. // Horizontal flip only
  1832. (*DrawTilePtr) (Tile + t1 + 1 - (Quot & 1), s,
  1833. VirtAlign, Lines, &GFX);
  1834. }
  1835. }
  1836. else
  1837. {
  1838. // No horizontal flip, but is there a vertical flip ?
  1839. if (Tile & V_FLIP)
  1840. {
  1841. // Vertical flip only
  1842. (*DrawTilePtr) (Tile + t2 + (Quot & 1), s,
  1843. VirtAlign, Lines, &GFX);
  1844. }
  1845. else
  1846. {
  1847. // Normal unflipped
  1848. (*DrawTilePtr) (Tile + t1 + (Quot & 1), s,
  1849. VirtAlign, Lines, &GFX);
  1850. }
  1851. }
  1852. }
  1853. else
  1854. {
  1855. (*DrawTilePtr) (Tile, s, VirtAlign, Lines, &GFX);
  1856. }
  1857. if (BG.TileSize == 8)
  1858. {
  1859. t++;
  1860. if (Quot == 31)
  1861. t = b2;
  1862. else
  1863. if (Quot == 63)
  1864. t = b1;
  1865. }
  1866. else
  1867. {
  1868. t += Quot & 1;
  1869. if (Quot == 63)
  1870. t = b2;
  1871. else
  1872. if (Quot == 127)
  1873. t = b1;
  1874. }
  1875. }
  1876. // Right-hand edge clipped tiles
  1877. if (Count)
  1878. {
  1879. Tile = READ_2BYTES(t);
  1880. GFX.Z1 = GFX.Z2 = depths [(Tile & 0x2000) >> 13];
  1881. if (BG.TileSize == 8)
  1882. (*DrawClippedTilePtr) (Tile, s, 0, Count, VirtAlign,
  1883. Lines, &GFX);
  1884. else
  1885. {
  1886. if (!(Tile & (V_FLIP | H_FLIP)))

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