PageRenderTime 75ms CodeModel.GetById 33ms RepoModel.GetById 0ms app.codeStats 1ms

/src/snes4iphone_src/gfx_org.cpp

https://github.com/zodttd/snes4iphone
C++ | 3857 lines | 3184 code | 389 blank | 284 comment | 701 complexity | e8cacd20ca038d02b25e241d1d8fe3dd MD5 | raw file

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

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