/SNesoid/sneslib_comp/gfx.cpp
C++ | 4282 lines | 3685 code | 357 blank | 240 comment | 855 complexity | a70f938ac4d189ad4013406102c294dd MD5 | raw file
Large files files are truncated, but you can click here to view the full file
- /*******************************************************************************
- Snes9x - Portable Super Nintendo Entertainment System (TM) emulator.
-
- (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com) and
- Jerremy Koot (jkoot@snes9x.com)
- (c) Copyright 2001 - 2004 John Weidman (jweidman@slip.net)
- (c) Copyright 2002 - 2004 Brad Jorsch (anomie@users.sourceforge.net),
- funkyass (funkyass@spam.shaw.ca),
- Joel Yliluoma (http://iki.fi/bisqwit/)
- Kris Bleakley (codeviolation@hotmail.com),
- Matthew Kendora,
- Nach (n-a-c-h@users.sourceforge.net),
- Peter Bortas (peter@bortas.org) and
- zones (kasumitokoduck@yahoo.com)
- C4 x86 assembler and some C emulation code
- (c) Copyright 2000 - 2003 zsKnight (zsknight@zsnes.com),
- _Demo_ (_demo_@zsnes.com), and Nach
- C4 C++ code
- (c) Copyright 2003 Brad Jorsch
- DSP-1 emulator code
- (c) Copyright 1998 - 2004 Ivar (ivar@snes9x.com), _Demo_, Gary Henderson,
- John Weidman, neviksti (neviksti@hotmail.com),
- Kris Bleakley, Andreas Naive
- DSP-2 emulator code
- (c) Copyright 2003 Kris Bleakley, John Weidman, neviksti, Matthew Kendora, and
- Lord Nightmare (lord_nightmare@users.sourceforge.net
- OBC1 emulator code
- (c) Copyright 2001 - 2004 zsKnight, pagefault (pagefault@zsnes.com) and
- Kris Bleakley
- Ported from x86 assembler to C by sanmaiwashi
- SPC7110 and RTC C++ emulator code
- (c) Copyright 2002 Matthew Kendora with research by
- zsKnight, John Weidman, and Dark Force
- S-DD1 C emulator code
- (c) Copyright 2003 Brad Jorsch with research by
- Andreas Naive and John Weidman
-
- S-RTC C emulator code
- (c) Copyright 2001 John Weidman
-
- ST010 C++ emulator code
- (c) Copyright 2003 Feather, Kris Bleakley, John Weidman and Matthew Kendora
- Super FX x86 assembler emulator code
- (c) Copyright 1998 - 2003 zsKnight, _Demo_, and pagefault
- Super FX C emulator code
- (c) Copyright 1997 - 1999 Ivar, Gary Henderson and John Weidman
- SH assembler code partly based on x86 assembler code
- (c) Copyright 2002 - 2004 Marcus Comstedt (marcus@mc.pp.se)
-
- Specific ports contains the works of other authors. See headers in
- individual files.
-
- Snes9x homepage: http://www.snes9x.com
-
- Permission to use, copy, modify and distribute Snes9x in both binary and
- source form, for non-commercial purposes, is hereby granted without fee,
- providing that this license information and copyright notice appear with
- all copies and any derived work.
-
- This software is provided 'as-is', without any express or implied
- warranty. In no event shall the authors be held liable for any damages
- arising from the use of this software.
-
- Snes9x is freeware for PERSONAL USE only. Commercial users should
- seek permission of the copyright holders first. Commercial use includes
- charging money for Snes9x or software derived from Snes9x.
-
- The copyright holders request that bug fixes and improvements to the code
- should be forwarded to them so everyone can benefit from the modifications
- in future versions.
-
- Super NES and Super Nintendo Entertainment System are trademarks of
- Nintendo Co., Limited and its subsidiary companies.
- *******************************************************************************/
- #include "snes9x.h"
- #include "memmap.h"
- #include "ppu.h"
- #include "cpuexec.h"
- #include "display.h"
- #include "gfx.h"
- #include "apu.h"
- #include "cheats.h"
- #include "screenshot.h"
- #define M7 19
- #define M8 19
- void output_png();
- void ComputeClipWindows ();
- static void S9xDisplayFrameRate ();
- static void S9xDisplayString (const char *string);
- extern uint8 BitShifts[8][4];
- extern uint8 TileShifts[8][4];
- extern uint8 PaletteShifts[8][4];
- extern uint8 PaletteMasks[8][4];
- extern uint8 Depths[8][4];
- extern uint8 BGSizes [2];
- extern NormalTileRenderer DrawTilePtr;
- extern ClippedTileRenderer DrawClippedTilePtr;
- extern NormalTileRenderer DrawHiResTilePtr;
- extern ClippedTileRenderer DrawHiResClippedTilePtr;
- extern LargePixelRenderer DrawLargePixelPtr;
- extern struct SBG BG;
- extern struct SLineData LineData[240];
- extern struct SLineMatrixData LineMatrixData [240];
- extern uint8 Mode7Depths [2];
- #define CLIP_10_BIT_SIGNED(a) \
- ((a) & ((1 << 10) - 1)) + (((((a) & (1 << 13)) ^ (1 << 13)) - (1 << 13)) >> 3)
- #define ON_MAIN(N) \
- (GFX.r212c & (1 << (N)) && \
- !(PPU.BG_Forced & (1 << (N))))
- #define SUB_OR_ADD(N) \
- (GFX.r2131 & (1 << (N)))
- #define ON_SUB(N) \
- ((GFX.r2130 & 0x30) != 0x30 && \
- (GFX.r2130 & 2) && \
- (GFX.r212d & (1 << N)) && \
- !(PPU.BG_Forced & (1 << (N))))
- #define ANYTHING_ON_SUB \
- ((GFX.r2130 & 0x30) != 0x30 && \
- (GFX.r2130 & 2) && \
- (GFX.r212d & 0x1f))
- #define ADD_OR_SUB_ON_ANYTHING \
- (GFX.r2131 & 0x3f)
- #define FIX_INTERLACE(SCREEN, DO_DEPTH, DEPTH) \
- if (IPPU.DoubleHeightPixels && ((PPU.BGMode != 5 && PPU.BGMode != 6) || !IPPU.Interlace)) \
- for (uint32 y = GFX.StartY; y <= GFX.EndY; y++) \
- { \
- memmove (SCREEN + (y * 2 + 1) * GFX.Pitch2, \
- SCREEN + y * 2 * GFX.Pitch2, \
- GFX.Pitch2); \
- if(DO_DEPTH){ \
- memmove (DEPTH + (y * 2 + 1) * (GFX.PPLx2>>1), \
- DEPTH + y * GFX.PPL, \
- GFX.PPLx2>>1); \
- } \
- }
- #define BLACK BUILD_PIXEL(0,0,0)
- void DrawTile (uint32 Tile, uint32 Offset, uint32 StartLine,
- uint32 LineCount);
- void DrawClippedTile (uint32 Tile, uint32 Offset,
- uint32 StartPixel, uint32 Width,
- uint32 StartLine, uint32 LineCount);
- void DrawTilex2 (uint32 Tile, uint32 Offset, uint32 StartLine,
- uint32 LineCount);
- void DrawClippedTilex2 (uint32 Tile, uint32 Offset,
- uint32 StartPixel, uint32 Width,
- uint32 StartLine, uint32 LineCount);
- void DrawTilex2x2 (uint32 Tile, uint32 Offset, uint32 StartLine,
- uint32 LineCount);
- void DrawClippedTilex2x2 (uint32 Tile, uint32 Offset,
- uint32 StartPixel, uint32 Width,
- uint32 StartLine, uint32 LineCount);
- void DrawLargePixel (uint32 Tile, uint32 Offset,
- uint32 StartPixel, uint32 Pixels,
- uint32 StartLine, uint32 LineCount);
- void DrawTile16 (uint32 Tile, uint32 Offset, uint32 StartLine,
- uint32 LineCount);
- void DrawClippedTile16 (uint32 Tile, uint32 Offset,
- uint32 StartPixel, uint32 Width,
- uint32 StartLine, uint32 LineCount);
- void DrawTile16x2 (uint32 Tile, uint32 Offset, uint32 StartLine,
- uint32 LineCount);
- void DrawClippedTile16x2 (uint32 Tile, uint32 Offset,
- uint32 StartPixel, uint32 Width,
- uint32 StartLine, uint32 LineCount);
- void DrawTile16x2x2 (uint32 Tile, uint32 Offset, uint32 StartLine,
- uint32 LineCount);
- void DrawClippedTile16x2x2 (uint32 Tile, uint32 Offset,
- uint32 StartPixel, uint32 Width,
- uint32 StartLine, uint32 LineCount);
- void DrawLargePixel16 (uint32 Tile, uint32 Offset,
- uint32 StartPixel, uint32 Pixels,
- uint32 StartLine, uint32 LineCount);
- void DrawTile16Add (uint32 Tile, uint32 Offset, uint32 StartLine,
- uint32 LineCount);
- void DrawClippedTile16Add (uint32 Tile, uint32 Offset,
- uint32 StartPixel, uint32 Width,
- uint32 StartLine, uint32 LineCount);
- void DrawTile16Add1_2 (uint32 Tile, uint32 Offset, uint32 StartLine,
- uint32 LineCount);
- void DrawClippedTile16Add1_2 (uint32 Tile, uint32 Offset,
- uint32 StartPixel, uint32 Width,
- uint32 StartLine, uint32 LineCount);
- void DrawTile16FixedAdd1_2 (uint32 Tile, uint32 Offset, uint32 StartLine,
- uint32 LineCount);
- void DrawClippedTile16FixedAdd1_2 (uint32 Tile, uint32 Offset,
- uint32 StartPixel, uint32 Width,
- uint32 StartLine, uint32 LineCount);
- void DrawTile16Sub (uint32 Tile, uint32 Offset, uint32 StartLine,
- uint32 LineCount);
- void DrawClippedTile16Sub (uint32 Tile, uint32 Offset,
- uint32 StartPixel, uint32 Width,
- uint32 StartLine, uint32 LineCount);
- void DrawTile16Sub1_2 (uint32 Tile, uint32 Offset, uint32 StartLine,
- uint32 LineCount);
- void DrawClippedTile16Sub1_2 (uint32 Tile, uint32 Offset,
- uint32 StartPixel, uint32 Width,
- uint32 StartLine, uint32 LineCount);
- void DrawTile16FixedSub1_2 (uint32 Tile, uint32 Offset, uint32 StartLine,
- uint32 LineCount);
- void DrawClippedTile16FixedSub1_2 (uint32 Tile, uint32 Offset,
- uint32 StartPixel, uint32 Width,
- uint32 StartLine, uint32 LineCount);
- void DrawLargePixel16Add (uint32 Tile, uint32 Offset,
- uint32 StartPixel, uint32 Pixels,
- uint32 StartLine, uint32 LineCount);
- void DrawLargePixel16Add1_2 (uint32 Tile, uint32 Offset,
- uint32 StartPixel, uint32 Pixels,
- uint32 StartLine, uint32 LineCount);
- void DrawLargePixel16Sub (uint32 Tile, uint32 Offset,
- uint32 StartPixel, uint32 Pixels,
- uint32 StartLine, uint32 LineCount);
- void DrawLargePixel16Sub1_2 (uint32 Tile, uint32 Offset,
- uint32 StartPixel, uint32 Pixels,
- uint32 StartLine, uint32 LineCount);
- bool8 S9xGraphicsInit ()
- {
- register uint32 PixelOdd = 1;
- register uint32 PixelEven = 2;
- #ifdef GFX_MULTI_FORMAT
- if (GFX.BuildPixel == NULL)
- S9xSetRenderPixelFormat (RGB565);
- #endif
- for (uint8 bitshift = 0; bitshift < 4; bitshift++)
- {
- for (register int i = 0; i < 16; i++)
- {
- register uint32 h = 0;
- register uint32 l = 0;
- #if defined(LSB_FIRST)
- if (i & 8)
- h |= PixelOdd;
- if (i & 4)
- h |= PixelOdd << 8;
- if (i & 2)
- h |= PixelOdd << 16;
- if (i & 1)
- h |= PixelOdd << 24;
- if (i & 8)
- l |= PixelOdd;
- if (i & 4)
- l |= PixelOdd << 8;
- if (i & 2)
- l |= PixelOdd << 16;
- if (i & 1)
- l |= PixelOdd << 24;
- #else
- if (i & 8)
- h |= (PixelOdd << 24);
- if (i & 4)
- h |= (PixelOdd << 16);
- if (i & 2)
- h |= (PixelOdd << 8);
- if (i & 1)
- h |= PixelOdd;
- if (i & 8)
- l |= (PixelOdd << 24);
- if (i & 4)
- l |= (PixelOdd << 16);
- if (i & 2)
- l |= (PixelOdd << 8);
- if (i & 1)
- l |= PixelOdd;
- #endif
- odd_high[bitshift][i] = h;
- odd_low[bitshift][i] = l;
- h = l = 0;
- #if defined(LSB_FIRST)
- if (i & 8)
- h |= PixelEven;
- if (i & 4)
- h |= PixelEven << 8;
- if (i & 2)
- h |= PixelEven << 16;
- if (i & 1)
- h |= PixelEven << 24;
- if (i & 8)
- l |= PixelEven;
- if (i & 4)
- l |= PixelEven << 8;
- if (i & 2)
- l |= PixelEven << 16;
- if (i & 1)
- l |= PixelEven << 24;
- #else
- if (i & 8)
- h |= (PixelEven << 24);
- if (i & 4)
- h |= (PixelEven << 16);
- if (i & 2)
- h |= (PixelEven << 8);
- if (i & 1)
- h |= PixelEven;
- if (i & 8)
- l |= (PixelEven << 24);
- if (i & 4)
- l |= (PixelEven << 16);
- if (i & 2)
- l |= (PixelEven << 8);
- if (i & 1)
- l |= PixelEven;
- #endif
- even_high[bitshift][i] = h;
- even_low[bitshift][i] = l;
- }
- PixelEven <<= 2;
- PixelOdd <<= 2;
- }
- GFX.RealPitch = GFX.Pitch2 = GFX.Pitch;
- GFX.ZPitch = GFX.Pitch;
- if (Settings.SixteenBit)
- GFX.ZPitch >>= 1;
- GFX.Delta = (GFX.SubScreen - GFX.Screen) >> 1;
- GFX.DepthDelta = GFX.SubZBuffer - GFX.ZBuffer;
- //GFX.InfoStringTimeout = 0;
- //GFX.InfoString = NULL;
- PPU.BG_Forced = 0;
- IPPU.OBJChanged = TRUE;
- if (Settings.Transparency)
- Settings.SixteenBit = TRUE;
- IPPU.DirectColourMapsNeedRebuild = TRUE;
- GFX.PixSize = 1;
- if (Settings.SixteenBit)
- {
- DrawTilePtr = DrawTile16;
- DrawClippedTilePtr = DrawClippedTile16;
- DrawLargePixelPtr = DrawLargePixel16;
- DrawHiResTilePtr= DrawTile16;
- DrawHiResClippedTilePtr = DrawClippedTile16;
- GFX.PPL = GFX.Pitch >> 1;
- GFX.PPLx2 = GFX.Pitch;
- }
- else
- {
- DrawTilePtr = DrawTile;
- DrawClippedTilePtr = DrawClippedTile;
- DrawLargePixelPtr = DrawLargePixel;
- DrawHiResTilePtr = DrawTile;
- DrawHiResClippedTilePtr = DrawClippedTile;
- GFX.PPL = GFX.Pitch;
- GFX.PPLx2 = GFX.Pitch * 2;
- }
- S9xFixColourBrightness ();
- if (Settings.SixteenBit)
- {
- if (!(GFX.X2 = (uint16 *) malloc (sizeof (uint16) * 0x10000)))
- return (FALSE);
- if (!(GFX.ZERO_OR_X2 = (uint16 *) malloc (sizeof (uint16) * 0x10000)) ||
- !(GFX.ZERO = (uint16 *) malloc (sizeof (uint16) * 0x10000)))
- {
- if (GFX.ZERO_OR_X2)
- {
- free ((char *) GFX.ZERO_OR_X2);
- GFX.ZERO_OR_X2 = NULL;
- }
- if (GFX.X2)
- {
- free ((char *) GFX.X2);
- GFX.X2 = NULL;
- }
- return (FALSE);
- }
- uint32 r, g, b;
- // Build a lookup table that multiplies a packed RGB value by 2 with
- // saturation.
- for (r = 0; r <= MAX_RED; r++)
- {
- uint32 r2 = r << 1;
- if (r2 > MAX_RED)
- r2 = MAX_RED;
- for (g = 0; g <= MAX_GREEN; g++)
- {
- uint32 g2 = g << 1;
- if (g2 > MAX_GREEN)
- g2 = MAX_GREEN;
- for (b = 0; b <= MAX_BLUE; b++)
- {
- uint32 b2 = b << 1;
- if (b2 > MAX_BLUE)
- b2 = MAX_BLUE;
- GFX.X2 [BUILD_PIXEL2 (r, g, b)] = BUILD_PIXEL2 (r2, g2, b2);
- GFX.X2 [BUILD_PIXEL2 (r, g, b) & ~ALPHA_BITS_MASK] = BUILD_PIXEL2 (r2, g2, b2);
- }
- }
- }
- ZeroMemory (GFX.ZERO, 0x10000 * sizeof (uint16));
- ZeroMemory (GFX.ZERO_OR_X2, 0x10000 * sizeof (uint16));
- // Build a lookup table that if the top bit of the color value is zero
- // then the value is zero, otherwise multiply the value by 2. Used by
- // the color subtraction code.
- #if defined(OLD_COLOUR_BLENDING)
- for (r = 0; r <= MAX_RED; r++)
- {
- uint32 r2 = r;
- if ((r2 & 0x10) == 0)
- r2 = 0;
- else
- r2 = (r2 << 1) & MAX_RED;
- for (g = 0; g <= MAX_GREEN; g++)
- {
- uint32 g2 = g;
- if ((g2 & GREEN_HI_BIT) == 0)
- g2 = 0;
- else
- g2 = (g2 << 1) & MAX_GREEN;
- for (b = 0; b <= MAX_BLUE; b++)
- {
- uint32 b2 = b;
- if ((b2 & 0x10) == 0)
- b2 = 0;
- else
- b2 = (b2 << 1) & MAX_BLUE;
- GFX.ZERO_OR_X2 [BUILD_PIXEL2 (r, g, b)] = BUILD_PIXEL2 (r2, g2, b2);
- GFX.ZERO_OR_X2 [BUILD_PIXEL2 (r, g, b) & ~ALPHA_BITS_MASK] = BUILD_PIXEL2 (r2, g2, b2);
- }
- }
- }
- #else
- for (r = 0; r <= MAX_RED; r++)
- {
- uint32 r2 = r;
- if ((r2 & 0x10) == 0)
- r2 = 0;
- else
- r2 = (r2 << 1) & MAX_RED;
- if (r2 == 0)
- r2 = 1;
- for (g = 0; g <= MAX_GREEN; g++)
- {
- uint32 g2 = g;
- if ((g2 & GREEN_HI_BIT) == 0)
- g2 = 0;
- else
- g2 = (g2 << 1) & MAX_GREEN;
- if (g2 == 0)
- g2 = 1;
- for (b = 0; b <= MAX_BLUE; b++)
- {
- uint32 b2 = b;
- if ((b2 & 0x10) == 0)
- b2 = 0;
- else
- b2 = (b2 << 1) & MAX_BLUE;
- if (b2 == 0)
- b2 = 1;
- GFX.ZERO_OR_X2 [BUILD_PIXEL2 (r, g, b)] = BUILD_PIXEL2 (r2, g2, b2);
- GFX.ZERO_OR_X2 [BUILD_PIXEL2 (r, g, b) & ~ALPHA_BITS_MASK] = BUILD_PIXEL2 (r2, g2, b2);
- }
- }
- }
- #endif
- // Build a lookup table that if the top bit of the color value is zero
- // then the value is zero, otherwise its just the value.
- for (r = 0; r <= MAX_RED; r++)
- {
- uint32 r2 = r;
- if ((r2 & 0x10) == 0)
- r2 = 0;
- else
- r2 &= ~0x10;
- for (g = 0; g <= MAX_GREEN; g++)
- {
- uint32 g2 = g;
- if ((g2 & GREEN_HI_BIT) == 0)
- g2 = 0;
- else
- g2 &= ~GREEN_HI_BIT;
- for (b = 0; b <= MAX_BLUE; b++)
- {
- uint32 b2 = b;
- if ((b2 & 0x10) == 0)
- b2 = 0;
- else
- b2 &= ~0x10;
- GFX.ZERO [BUILD_PIXEL2 (r, g, b)] = BUILD_PIXEL2 (r2, g2, b2);
- GFX.ZERO [BUILD_PIXEL2 (r, g, b) & ~ALPHA_BITS_MASK] = BUILD_PIXEL2 (r2, g2, b2);
- }
- }
- }
- }
- else
- {
- GFX.X2 = NULL;
- GFX.ZERO_OR_X2 = NULL;
- GFX.ZERO = NULL;
- }
- return (TRUE);
- }
- void S9xGraphicsDeinit (void)
- {
- // Free any memory allocated in S9xGraphicsInit
- if (GFX.X2)
- {
- free ((char *) GFX.X2);
- GFX.X2 = NULL;
- }
- if (GFX.ZERO_OR_X2)
- {
- free ((char *) GFX.ZERO_OR_X2);
- GFX.ZERO_OR_X2 = NULL;
- }
- if (GFX.ZERO)
- {
- free ((char *) GFX.ZERO);
- GFX.ZERO = NULL;
- }
- }
- void S9xBuildDirectColourMaps ()
- {
- for (uint32 p = 0; p < 8; p++)
- {
- for (uint32 c = 0; c < 256; c++)
- {
- // XXX: Brightness
- DirectColourMaps [p][c] = BUILD_PIXEL (((c & 7) << 2) | ((p & 1) << 1),
- ((c & 0x38) >> 1) | (p & 2),
- ((c & 0xc0) >> 3) | (p & 4));
- }
- }
- IPPU.DirectColourMapsNeedRebuild = FALSE;
- }
- void S9xStartScreenRefresh ()
- {
- if (GFX.InfoStringTimeout > 0 && --GFX.InfoStringTimeout == 0)
- GFX.InfoString = NULL;
- if (IPPU.RenderThisFrame)
- {
- if (!S9xInitUpdate ())
- {
- IPPU.RenderThisFrame = FALSE;
- return;
- }
- IPPU.RenderedFramesCount++;
- IPPU.PreviousLine = IPPU.CurrentLine = 0;
- IPPU.MaxBrightness = PPU.Brightness;
- IPPU.LatchedBlanking = PPU.ForcedBlanking;
- if(PPU.BGMode == 5 || PPU.BGMode == 6)
- IPPU.Interlace = (Memory.FillRAM[0x2133] & 1);
- if (Settings.SupportHiRes && (PPU.BGMode == 5 || PPU.BGMode == 6 ||
- IPPU.Interlace))
- {
- if (PPU.BGMode == 5 || PPU.BGMode == 6 || IPPU.Interlace)
- {
- IPPU.RenderedScreenWidth = 512;
- IPPU.DoubleWidthPixels = TRUE;
- }
- else
- {
- IPPU.RenderedScreenWidth = 256;
- IPPU.DoubleWidthPixels = FALSE;
- }
- if (IPPU.Interlace)
- {
- IPPU.RenderedScreenHeight = PPU.ScreenHeight << 1;
- IPPU.DoubleHeightPixels = TRUE;
- GFX.Pitch2 = GFX.RealPitch;
- GFX.Pitch = GFX.RealPitch * 2;
- if (Settings.SixteenBit)
- GFX.PPL = GFX.PPLx2 = GFX.RealPitch;
- else
- GFX.PPL = GFX.PPLx2 = GFX.RealPitch << 1;
- }
- else
- {
- IPPU.RenderedScreenHeight = PPU.ScreenHeight;
- GFX.Pitch2 = GFX.Pitch = GFX.RealPitch;
- IPPU.DoubleHeightPixels = FALSE;
- if (Settings.SixteenBit)
- GFX.PPL = GFX.Pitch >> 1;
- else
- GFX.PPL = GFX.Pitch;
- GFX.PPLx2 = GFX.PPL << 1;
- }
- #if defined(USE_GLIDE) || defined(USE_OPENGL)
- GFX.ZPitch = GFX.RealPitch;
- if (Settings.SixteenBit)
- GFX.ZPitch >>= 1;
- #endif
- }
- else
- {
- IPPU.RenderedScreenWidth = 256;
- IPPU.RenderedScreenHeight = PPU.ScreenHeight;
- IPPU.DoubleWidthPixels = FALSE;
- IPPU.DoubleHeightPixels = FALSE;
- #ifdef USE_GLIDE
- if (Settings.GlideEnable)
- {
- // Speed up hack for Glide: render low res. SNES images
- // into a handy 256x256 sized buffer that can be uploaded into
- // texture memory with one Glide call without having to copy it
- // into a second, suitably sized buffer first.
- GFX.Pitch2 = GFX.Pitch = 256 * sizeof (uint16);
- GFX.PPL = 256;
- GFX.PPLx2 = GFX.Pitch;
- GFX.ZPitch = 256;
- }
- else
- #endif
- #ifdef USE_OPENGL
- if (Settings.OpenGLEnable)
- {
- GFX.Pitch2 = GFX.Pitch = 256 * sizeof (uint16);
- GFX.PPL = 256;
- GFX.PPLx2 = GFX.Pitch;
- GFX.ZPitch = 256;
- }
- else
- #endif
- {
- GFX.Pitch2 = GFX.Pitch = GFX.RealPitch;
- GFX.PPL = GFX.PPLx2 >> 1;
- GFX.ZPitch = GFX.RealPitch;
- if (Settings.SixteenBit)
- GFX.ZPitch >>= 1;
- }
- }
- PPU.RecomputeClipWindows = TRUE;
- GFX.DepthDelta = GFX.SubZBuffer - GFX.ZBuffer;
- GFX.Delta = (GFX.SubScreen - GFX.Screen) >> 1;
- }
- if (++IPPU.FrameCount % Memory.ROMFramesPerSecond == 0)
- {
- IPPU.DisplayedRenderedFrameCount = IPPU.RenderedFramesCount;
- IPPU.RenderedFramesCount = 0;
- IPPU.FrameCount = 0;
- }
- }
- void RenderLine (uint8 C)
- {
- if (IPPU.RenderThisFrame)
- {
- LineData[C].BG[0].VOffset = PPU.BG[0].VOffset + 1;
- LineData[C].BG[0].HOffset = PPU.BG[0].HOffset;
- LineData[C].BG[1].VOffset = PPU.BG[1].VOffset + 1;
- LineData[C].BG[1].HOffset = PPU.BG[1].HOffset;
- if (PPU.BGMode == 7)
- {
- struct SLineMatrixData *p = &LineMatrixData [C];
- p->MatrixA = PPU.MatrixA;
- p->MatrixB = PPU.MatrixB;
- p->MatrixC = PPU.MatrixC;
- p->MatrixD = PPU.MatrixD;
- p->CentreX = PPU.CentreX;
- p->CentreY = PPU.CentreY;
- }
- else
- {
- if (Settings.StarfoxHack && PPU.BG[2].VOffset == 0 &&
- PPU.BG[2].HOffset == 0xe000)
- {
- LineData[C].BG[2].VOffset = 0xe1;
- LineData[C].BG[2].HOffset = 0;
- }
- else
- {
- LineData[C].BG[2].VOffset = PPU.BG[2].VOffset + 1;
- LineData[C].BG[2].HOffset = PPU.BG[2].HOffset;
- LineData[C].BG[3].VOffset = PPU.BG[3].VOffset + 1;
- LineData[C].BG[3].HOffset = PPU.BG[3].HOffset;
- }
- }
- IPPU.CurrentLine = C + 1;
- } else {
- /* if we're not rendering this frame, we still need to update this */
- // XXX: Check ForceBlank? Or anything else?
- if(IPPU.OBJChanged) S9xSetupOBJ();
- PPU.RangeTimeOver |= GFX.OBJLines[C].RTOFlags;
- }
- }
- void S9xEndScreenRefresh ()
- {
- IPPU.HDMAStarted = FALSE;
- if (IPPU.RenderThisFrame)
- {
- FLUSH_REDRAW ();
- if (IPPU.ColorsChanged)
- {
- uint32 saved = PPU.CGDATA[0];
- if (!Settings.SixteenBit)
- {
- // Hack for Super Mario World - to get its sky blue
- // (It uses Fixed colour addition on the backdrop colour)
- if (!(Memory.FillRAM [0x2131] & 0x80) &&
- (Memory.FillRAM[0x2131] & 0x20) &&
- (PPU.FixedColourRed || PPU.FixedColourGreen ||
- PPU.FixedColourBlue))
- {
- PPU.CGDATA[0] = PPU.FixedColourRed |
- (PPU.FixedColourGreen << 5) |
- (PPU.FixedColourBlue << 10);
- }
- }
- IPPU.ColorsChanged = FALSE;
- S9xSetPalette ();
- PPU.CGDATA[0] = saved;
- }
- if (
- #ifdef USE_GLIDE
- !Settings.GlideEnable &&
- #endif
- #ifdef USE_OPENGL
- !Settings.OpenGLEnable &&
- #endif
- TRUE)
- {
- GFX.Pitch = GFX.Pitch2 = GFX.RealPitch;
- GFX.PPL = GFX.PPLx2 >> 1;
- }
- //take screenshot here.
- #if 0
- if(Settings.TakeScreenshot)
- S9xDoScreenshot(IPPU.RenderedScreenWidth, IPPU.RenderedScreenHeight);
- #endif
- if (Settings.DisplayFrameRate)
- S9xDisplayFrameRate ();
- if (GFX.InfoString)
- S9xDisplayString (GFX.InfoString);
- S9xDeinitUpdate (IPPU.RenderedScreenWidth, IPPU.RenderedScreenHeight,
- Settings.SixteenBit);
- }
- S9xApplyCheats ();
- #ifdef DEBUGGER
- if (CPU.Flags & FRAME_ADVANCE_FLAG)
- {
- if (ICPU.FrameAdvanceCount)
- {
- ICPU.FrameAdvanceCount--;
- IPPU.RenderThisFrame = TRUE;
- IPPU.FrameSkip = 0;
- }
- else
- {
- CPU.Flags &= ~FRAME_ADVANCE_FLAG;
- CPU.Flags |= DEBUG_MODE_FLAG;
- }
- }
- #endif
- if (CPU.SRAMModified)
- {
- if (!CPU.AutoSaveTimer)
- {
- if (!(CPU.AutoSaveTimer = Settings.AutoSaveDelay * Memory.ROMFramesPerSecond))
- CPU.SRAMModified = FALSE;
- }
- else
- {
- if (!--CPU.AutoSaveTimer)
- {
- S9xAutoSaveSRAM ();
- CPU.SRAMModified = FALSE;
- }
- }
- }
- }
- void S9xSetInfoString (const char *string)
- {
- GFX.InfoString = string;
- GFX.InfoStringTimeout = 120;
- }
- inline void SelectTileRenderer (bool8 normal)
- {
- if (normal)
- {
- DrawTilePtr = DrawTile16;
- DrawClippedTilePtr = DrawClippedTile16;
- DrawLargePixelPtr = DrawLargePixel16;
- }
- else
- {
- if (GFX.r2131 & 0x80)
- {
- if (GFX.r2131 & 0x40)
- {
- if (GFX.r2130 & 2)
- {
- DrawTilePtr = DrawTile16Sub1_2;
- DrawClippedTilePtr = DrawClippedTile16Sub1_2;
- }
- else
- {
- // Fixed colour substraction
- DrawTilePtr = DrawTile16FixedSub1_2;
- DrawClippedTilePtr = DrawClippedTile16FixedSub1_2;
- }
- DrawLargePixelPtr = DrawLargePixel16Sub1_2;
- }
- else
- {
- DrawTilePtr = DrawTile16Sub;
- DrawClippedTilePtr = DrawClippedTile16Sub;
- DrawLargePixelPtr = DrawLargePixel16Sub;
- }
- }
- else
- {
- if (GFX.r2131 & 0x40)
- {
- if (GFX.r2130 & 2)
- {
- DrawTilePtr = DrawTile16Add1_2;
- DrawClippedTilePtr = DrawClippedTile16Add1_2;
- }
- else
- {
- // Fixed colour addition
- DrawTilePtr = DrawTile16FixedAdd1_2;
- DrawClippedTilePtr = DrawClippedTile16FixedAdd1_2;
- }
- DrawLargePixelPtr = DrawLargePixel16Add1_2;
- }
- else
- {
- DrawTilePtr = DrawTile16Add;
- DrawClippedTilePtr = DrawClippedTile16Add;
- DrawLargePixelPtr = DrawLargePixel16Add;
- }
- }
- }
- }
- void S9xSetupOBJ ()
- {
- #ifdef MK_DEBUG_RTO
- if(Settings.BGLayering) fprintf(stderr, "Entering SetupOBJS()\n");
- #endif
- int SmallWidth, SmallHeight;
- int LargeWidth, LargeHeight;
- switch (PPU.OBJSizeSelect)
- {
- case 0:
- SmallWidth = SmallHeight = 8;
- LargeWidth = LargeHeight = 16;
- break;
- case 1:
- SmallWidth = SmallHeight = 8;
- LargeWidth = LargeHeight = 32;
- break;
- case 2:
- SmallWidth = SmallHeight = 8;
- LargeWidth = LargeHeight = 64;
- break;
- case 3:
- SmallWidth = SmallHeight = 16;
- LargeWidth = LargeHeight = 32;
- break;
- case 4:
- SmallWidth = SmallHeight = 16;
- LargeWidth = LargeHeight = 64;
- break;
- default:
- case 5:
- SmallWidth = SmallHeight = 32;
- LargeWidth = LargeHeight = 64;
- break;
- case 6:
- SmallWidth = 16; SmallHeight = 32;
- LargeWidth = 32; LargeHeight = 64;
- break;
- case 7:
- SmallWidth = 16; SmallHeight = 32;
- LargeWidth = LargeHeight = 32;
- break;
- }
- if(IPPU.InterlaceSprites)
- {
- SmallHeight>>=1; LargeHeight>>=1;
- }
- #ifdef MK_DEBUG_RTO
- if(Settings.BGLayering) fprintf(stderr, "Sizes are %dx%d and %dx%d\n", SmallWidth, SmallHeight, LargeWidth, LargeHeight);
- #endif
- /* OK, we have three cases here. Either there's no priority, priority is
- * normal FirstSprite, or priority is FirstSprite+Y. The first two are
- * easy, the last is somewhat more ... interesting. So we split them up. */
- int Height;
- uint8 S;
- #ifdef MK_DEBUG_RTO
- if(Settings.BGLayering) fprintf(stderr, "Priority rotation=%d, OAMAddr=%d -> ", PPU.OAMPriorityRotation, PPU.OAMAddr*2 | (PPU.OAMFlip&1));
- #endif
- if(!PPU.OAMPriorityRotation || !(PPU.OAMFlip&PPU.OAMAddr&1)){
- #ifdef MK_DEBUG_RTO
- if(Settings.BGLayering) fprintf(stderr, "normal FirstSprite = %02x\n", PPU.FirstSprite);
- #endif
- /* normal case */
- uint8 LineOBJ[SNES_HEIGHT_EXTENDED];
- memset(LineOBJ, 0, sizeof(LineOBJ));
- for(int i=0; i<SNES_HEIGHT_EXTENDED; i++){
- GFX.OBJLines[i].RTOFlags=0;
- GFX.OBJLines[i].Tiles=34;
- for(int j=0; j<32; j++){ GFX.OBJLines[i].OBJ[j].Sprite=-1; }
- }
- uint8 FirstSprite=PPU.FirstSprite;
- S=FirstSprite;
- do {
- if(PPU.OBJ[S].Size){
- GFX.OBJWidths[S]=LargeWidth; Height=LargeHeight;
- } else {
- GFX.OBJWidths[S]=SmallWidth; Height=SmallHeight;
- }
- int HPos=PPU.OBJ[S].HPos; if(HPos==-256) HPos=256;
- if(HPos>-GFX.OBJWidths[S] && HPos<=256)
- {
- if(HPos<0){
- GFX.OBJVisibleTiles[S]=(GFX.OBJWidths[S]+HPos+7)>>3;
- } else if(HPos+GFX.OBJWidths[S]>=257){
- GFX.OBJVisibleTiles[S]=(257-HPos+7)>>3;
- } else {
- GFX.OBJVisibleTiles[S]=GFX.OBJWidths[S]>>3;
- }
- for(uint8 line=0, Y=(uint8)(PPU.OBJ[S].VPos&0xff); line<Height; Y++, line++){
- if(Y>=SNES_HEIGHT_EXTENDED) continue;
- if(LineOBJ[Y]>=32){
- GFX.OBJLines[Y].RTOFlags|=0x40;
- #ifdef MK_DEBUG_RTO
- if(Settings.BGLayering) fprintf(stderr, "%d: OBJ %02x ranged over\n", Y, S);
- #endif
- continue;
- }
- GFX.OBJLines[Y].Tiles-=GFX.OBJVisibleTiles[S];
- if(GFX.OBJLines[Y].Tiles<0) GFX.OBJLines[Y].RTOFlags|=0x80;
- GFX.OBJLines[Y].OBJ[LineOBJ[Y]].Sprite=S;
- if(PPU.OBJ[S].VFlip){
- // Yes, Width not Height. It so happens that the
- // sprites with H=2*W flip as two WxW sprites.
- GFX.OBJLines[Y].OBJ[LineOBJ[Y]].Line=line^(GFX.OBJWidths[S]-1);
- } else {
- GFX.OBJLines[Y].OBJ[LineOBJ[Y]].Line=line;
- }
- LineOBJ[Y]++;
- }
- }
- S=(S+1)&0x7F;
- } while(S!=FirstSprite);
- for(int Y=1; Y<SNES_HEIGHT_EXTENDED; Y++){
- GFX.OBJLines[Y].RTOFlags |= GFX.OBJLines[Y-1].RTOFlags;
- }
- } else {
- /* evil FirstSprite+Y case */
- #ifdef MK_DEBUG_RTO
- if(Settings.BGLayering) fprintf(stderr, "FirstSprite+Y\n");
- #endif
- /* First, find out which sprites are on which lines */
- uint8 OBJOnLine[SNES_HEIGHT_EXTENDED][128];
- memset(OBJOnLine, 0, sizeof(OBJOnLine));
- for(S=0; S<128; S++){
- if(PPU.OBJ[S].Size){
- GFX.OBJWidths[S]=LargeWidth; Height=LargeHeight;
- } else {
- GFX.OBJWidths[S]=SmallWidth; Height=SmallHeight;
- }
- int HPos=PPU.OBJ[S].HPos; if(HPos==-256) HPos=256;
- if(HPos>-GFX.OBJWidths[S] && HPos<=256)
- {
- if(HPos<0){
- GFX.OBJVisibleTiles[S]=(GFX.OBJWidths[S]+HPos+7)>>3;
- } else if(HPos+GFX.OBJWidths[S]>=257){
- GFX.OBJVisibleTiles[S]=(257-HPos+7)>>3;
- } else {
- GFX.OBJVisibleTiles[S]=GFX.OBJWidths[S]>>3;
- }
- for(uint8 line=0, Y=(uint8)(PPU.OBJ[S].VPos&0xff); line<Height; Y++, line++){
- if(Y>=SNES_HEIGHT_EXTENDED) continue;
- if(PPU.OBJ[S].VFlip){
- // Yes, Width not Height. It so happens that the
- // sprites with H=2*W flip as two WxW sprites.
- OBJOnLine[Y][S]=(line^(GFX.OBJWidths[S]-1)) | 0x80;
- } else {
- OBJOnLine[Y][S]=line | 0x80;
- }
- }
- }
- }
- /* Now go through and pull out those OBJ that are actually visible. */
- int j;
- for(int Y=0; Y<SNES_HEIGHT_EXTENDED; Y++){
- GFX.OBJLines[Y].RTOFlags=Y?0:GFX.OBJLines[Y-1].RTOFlags;
- GFX.OBJLines[Y].Tiles=34;
- uint8 FirstSprite=(PPU.FirstSprite+Y)&0x7F;
- S=FirstSprite; j=0;
- do {
- if(OBJOnLine[Y][S]){
- if(j>=32){
- GFX.OBJLines[Y].RTOFlags|=0x40;
- #ifdef MK_DEBUG_RTO
- if(Settings.BGLayering) fprintf(stderr, "%d: OBJ %02x ranged over\n", Y, S);
- #endif
- break;
- }
- GFX.OBJLines[Y].Tiles-=GFX.OBJVisibleTiles[S];
- if(GFX.OBJLines[Y].Tiles<0) GFX.OBJLines[Y].RTOFlags|=0x80;
- GFX.OBJLines[Y].OBJ[j].Sprite=S;
- GFX.OBJLines[Y].OBJ[j++].Line=OBJOnLine[Y][S]&~0x80;
- }
- S=(S+1)&0x7F;
- } while(S!=FirstSprite);
- if(j<32) GFX.OBJLines[Y].OBJ[j].Sprite=-1;
- }
- }
- #ifdef MK_DEBUG_RTO
- if(Settings.BGLayering) {
- fprintf(stderr, "Sprites per line:\n");
- for(int xxx=0; xxx<SNES_HEIGHT_EXTENDED; xxx++){
- fprintf(stderr, "Line %d: RTO=%02x Tiles=%d", xxx, GFX.OBJLines[xxx].RTOFlags, 34-GFX.OBJLines[xxx].Tiles);
- for(int j=0; j<32 && GFX.OBJLines[xxx].OBJ[j].Sprite>=0; j++){
- fprintf(stderr, " %02x.%d", GFX.OBJLines[xxx].OBJ[j].Sprite, GFX.OBJLines[xxx].OBJ[j].Line);
- }
- fprintf(stderr, "\n");
- }
- fprintf(stderr, "Exiting SetupObj()\n");
- }
- #endif
- IPPU.OBJChanged = FALSE;
- }
- void DrawOBJS (bool8 OnMain = FALSE, uint8 D = 0)
- {
- #ifdef MK_DEBUG_RTO
- if(Settings.BGLayering) fprintf(stderr, "Entering DrawOBJS() for %d-%d\n", GFX.StartY, GFX.EndY);
- #endif
- CHECK_SOUND();
- BG.BitShift = 4;
- BG.TileShift = 5;
- BG.TileAddress = PPU.OBJNameBase;
- BG.StartPalette = 128;
- BG.PaletteShift = 4;
- BG.PaletteMask = 7;
- BG.Buffer = IPPU.TileCache [TILE_4BIT];
- BG.Buffered = IPPU.TileCached [TILE_4BIT];
- BG.NameSelect = PPU.OBJNameSelect;
- BG.DirectColourMode = FALSE;
- GFX.PixSize = 1;
- struct {
- uint16 Pos;
- bool8 Value;
- } Windows[7];
- int clipcount = GFX.pCurrentClip->Count [4];
- if (!clipcount){
- Windows[0].Pos=0;
- Windows[0].Value=TRUE;
- Windows[1].Pos=256;
- Windows[1].Value=FALSE;
- Windows[2].Pos=1000;
- Windows[2].Value=FALSE;
- } else {
- Windows[0].Pos=1000;
- Windows[0].Value=FALSE;
- for(int clip=0, i=1; clip<clipcount; clip++){
- if(GFX.pCurrentClip->Right[clip][4]<=GFX.pCurrentClip->Left[clip][4]) continue;
- int j;
- for(j=0; j<i && Windows[j].Pos<GFX.pCurrentClip->Left[clip][4]; j++);
- if(j<i && Windows[j].Pos==GFX.pCurrentClip->Left[clip][4]){
- Windows[j].Value = TRUE;
- } else {
- if(j<i) memmove(&Windows[j+1], &Windows[j], sizeof(Windows[0])*(i-j));
- Windows[j].Pos = GFX.pCurrentClip->Left[clip][4];
- Windows[j].Value = TRUE;
- i++;
- }
- for(j=0; j<i && Windows[j].Pos<GFX.pCurrentClip->Right[clip][4]; j++);
- if(j>=i || Windows[j].Pos!=GFX.pCurrentClip->Right[clip][4]){
- if(j<i) memmove(&Windows[j+1], &Windows[j], sizeof(Windows[0])*(i-j));
- Windows[j].Pos = GFX.pCurrentClip->Right[clip][4];
- Windows[j].Value = FALSE;
- i++;
- }
- }
- }
- #ifdef MK_DEBUG_RTO
- if(Settings.BGLayering) {
- fprintf(stderr, "Windows:\n");
- for(int xxx=0; xxx<6; xxx++){ fprintf(stderr, "%d: %d = %d\n", xxx, Windows[xxx].Pos, Windows[xxx].Value); }
- }
- #endif
- if (Settings.SupportHiRes)
- {
- if (PPU.BGMode == 5 || PPU.BGMode == 6)
- {
- // Bah, OnMain is never used except to determine if calling
- // SelectTileRenderer is necessary. So let's hack it to false here
- // to stop SelectTileRenderer from being called when it causes
- // problems.
- OnMain = FALSE;
- GFX.PixSize = 2;
- if (IPPU.DoubleHeightPixels)
- {
- if (Settings.SixteenBit)
- {
- DrawTilePtr = DrawTile16x2x2;
- DrawClippedTilePtr = DrawClippedTile16x2x2;
- }
- else
- {
- DrawTilePtr = DrawTilex2x2;
- DrawClippedTilePtr = DrawClippedTilex2x2;
- }
- }
- else
- {
- if (Settings.SixteenBit)
- {
- DrawTilePtr = DrawTile16x2;
- DrawClippedTilePtr = DrawClippedTile16x2;
- }
- else
- {
- DrawTilePtr = DrawTilex2;
- DrawClippedTilePtr = DrawClippedTilex2;
- }
- }
- }
- else
- {
- if (Settings.SixteenBit)
- {
- DrawTilePtr = DrawTile16;
- DrawClippedTilePtr = DrawClippedTile16;
- }
- else
- {
- DrawTilePtr = DrawTile;
- DrawClippedTilePtr = DrawClippedTile;
- }
- }
- }
- GFX.Z1 = D + 2;
- for(uint32 Y=GFX.StartY, Offset=Y*GFX.PPL; Y<=GFX.EndY; Y++, Offset+=GFX.PPL){
- #ifdef MK_DEBUG_RTO
- bool8 Flag=0;
- #endif
- int I = 0;
- #ifdef MK_DISABLE_TIME_OVER
- int tiles=0;
- #else
- int tiles=GFX.OBJLines[Y].Tiles;
- #endif
- for (int S = GFX.OBJLines[Y].OBJ[I].Sprite; S >= 0 && I<32; S = GFX.OBJLines[Y].OBJ[++I].Sprite)
- {
- tiles+=GFX.OBJVisibleTiles[S];
- if(tiles<=0){
- #ifdef MK_DEBUG_RTO
- if(Settings.BGLayering) {
- if(!Flag){ Flag=1; fprintf(stderr, "Line %d:", Y); }
- fprintf(stderr, " [%02x]", S);
- }
- #endif
- continue;
- }
- #ifdef MK_DEBUG_RTO
- if(Settings.BGLayering) {
- if(!Flag){ Flag=1; fprintf(stderr, "Line %d:", Y); }
- fprintf(stderr, " %02x", S);
- }
- #endif
- if (OnMain && SUB_OR_ADD(4))
- {
- SelectTileRenderer (!GFX.Pseudo && PPU.OBJ [S].Palette < 4);
- }
- int BaseTile = (((GFX.OBJLines[Y].OBJ[I].Line<<1) + (PPU.OBJ[S].Name&0xf0))&0xf0) | (PPU.OBJ[S].Name&0x100) | (PPU.OBJ[S].Palette << 10);
- int TileX = PPU.OBJ[S].Name&0x0f;
- int TileLine = (GFX.OBJLines[Y].OBJ[I].Line&7)*8;
- int TileInc = 1;
- if (PPU.OBJ[S].HFlip)
- {
- TileX = (TileX + (GFX.OBJWidths[S] >> 3) - 1) & 0x0f;
- BaseTile |= H_FLIP;
- TileInc = -1;
- }
- GFX.Z2 = (PPU.OBJ[S].Priority + 1) * 4 + D;
- bool8 WinStat=TRUE;
- int WinIdx=0, NextPos=-1000;
- int X=PPU.OBJ[S].HPos; if(X==-256) X=256;
- for(int t=tiles, O=Offset+X*GFX.PixSize; X<=256 && X<PPU.OBJ[S].HPos+GFX.OBJWidths[S]; TileX=(TileX+TileInc)&0x0f, X+=8, O+=8*GFX.PixSize){
- #ifdef MK_DEBUG_RTO
- if(Settings.BGLayering) {
- if(X<-7) continue;
- if((t-1)<0) fprintf(stderr, "-[%d]", 35-t);
- else fprintf(stderr, "-%d", 35-t);
- }
- #endif
- if(X<-7 || --t<0 || X==256) continue;
- if(X>=NextPos){
- for(; WinIdx<7 && Windows[WinIdx].Pos<=X; WinIdx++);
- if(WinIdx==0) WinStat=FALSE;
- else WinStat=Windows[WinIdx-1].Value;
- NextPos=(WinIdx<7)?Windows[WinIdx].Pos:1000;
- }
- if(X+8<NextPos){
- if(WinStat) (*DrawTilePtr) (BaseTile|TileX, O, TileLine, 1);
- } else {
- int x=X;
- while(x<X+8){
- if(WinStat) (*DrawClippedTilePtr) (BaseTile|TileX, O, x-X, NextPos-x, TileLine, 1);
- x=NextPos;
- for(; WinIdx<7 && Windows[WinIdx].Pos<=x; WinIdx++);
- if(WinIdx==0) WinStat=FALSE;
- else WinStat=Windows[WinIdx-1].Value;
- NextPos=(WinIdx<7)?Windows[WinIdx].Pos:1000;
- if(NextPos>X+8) NextPos=X+8;
- }
- }
- }
- }
- #ifdef MK_DEBUG_RTO
- if(Settings.BGLayering) if(Flag) fprintf(stderr, "\n");
- #endif
- }
- #ifdef MK_DEBUG_RTO
- if(Settings.BGLayering) fprintf(stderr, "Exiting DrawOBJS() for %d-%d\n", GFX.StartY, GFX.EndY);
- #endif
- }
- void DrawBackgroundMosaic (uint32 BGMode, uint32 bg, uint8 Z1, uint8 Z2)
- {
- CHECK_SOUND();
- uint32 Tile;
- uint16 *SC0;
- uint16 *SC1;
- uint16 *SC2;
- uint16 *SC3;
- uint8 depths [2] = {Z1, Z2};
-
- if (BGMode == 0)
- BG.StartPalette = bg << 5;
- else
- BG.StartPalette = 0;
- SC0 = (uint16 *) &Memory.VRAM[PPU.BG[bg].SCBase << 1];
- if (PPU.BG[bg].SCSize & 1)
- SC1 = SC0 + 1024;
- else
- SC1 = SC0;
- if(((uint8*)SC1-Memory.VRAM)>=0x10000)
- SC1-=0x08000;
- if (PPU.BG[bg].SCSize & 2)
- SC2 = SC1 + 1024;
- else
- SC2 = SC0;
- if(((uint8*)SC2-Memory.VRAM)>=0x10000)
- SC2-=0x08000;
- if (PPU.BG[bg].SCSize & 1)
- SC3 = SC2 + 1024;
- else
- SC3 = SC2;
- if(((uint8*)SC3-Memory.VRAM)>=0x10000)
- SC3-=0x08000;
- uint32 Lines;
- uint32 OffsetMask;
- uint32 OffsetShift;
- if (BG.TileSize == 16)
- {
- OffsetMask = 0x3ff;
- OffsetShift = 4;
- }
- else
- {
- OffsetMask = 0x1ff;
- OffsetShift = 3;
- }
- int m5 = (BGMode == 5 || BGMode == 6) ? 1 : 0;
- for (uint32 Y = GFX.StartY; Y <= GFX.EndY; Y += Lines)
- {
- uint32 VOffset = LineData [Y].BG[bg].VOffset;
- uint32 HOffset = LineData [Y].BG[bg].HOffset;
- uint32 MosaicOffset = Y % PPU.Mosaic;
- for (Lines = 1; Lines < PPU.Mosaic - MosaicOffset; Lines++)
- if ((VOffset != LineData [Y + Lines].BG[bg].VOffset) ||
- (HOffset != LineData [Y + Lines].BG[bg].HOffset))
- break;
-
- uint32 MosaicLine = VOffset + Y - MosaicOffset;
- if (Y + Lines > GFX.EndY)
- Lines = GFX.EndY + 1 - Y;
- uint32 VirtAlign = (MosaicLine & 7) << 3;
-
- uint16 *b1;
- uint16 *b2;
- uint32 ScreenLine = MosaicLine >> OffsetShift;
- uint32 Rem16 = MosaicLine & 15;
- if (ScreenLine & 0x20)
- b1 = SC2, b2 = SC3;
- else
- b1 = SC0, b2 = SC1;
- b1 += (ScreenLine & 0x1f) << 5;
- b2 += (ScreenLine & 0x1f) << 5;
- uint16 *t;
- uint32 Left = 0;
- uint32 Right = 256 << m5;
- HOffset <<= m5;
- uint32 ClipCount = GFX.pCurrentClip->Count [bg];
- uint32 HPos = HOffset;
- uint32 PixWidth = (PPU.Mosaic << m5);
- if (!ClipCount)
- ClipCount = 1;
- for (uint32 clip = 0; clip < ClipCount; clip++)
- {
- if (GFX.pCurrentClip->Count [bg])
- {
- Left = GFX.pCurrentClip->Left [clip][bg] << m5;
- Right = GFX.pCurrentClip->Right [clip][bg] << m5;
- uint32 r = Left % (PPU.Mosaic << m5);
- HPos = HOffset + Left;
- PixWidth = (PPU.Mosaic << m5) - r;
- }
- uint32 s = Y * GFX.PPL + Left * GFX.PixSize;
- for (uint32 x = Left; x < Right; x += PixWidth,
- s += PixWidth * GFX.PixSize,
- HPos += PixWidth, PixWidth = (PPU.Mosaic << m5))
- {
- uint32 Quot = (HPos & OffsetMask) >> 3;
- if (x + PixWidth >= Right)
- PixWidth = Right - x;
- if (BG.TileSize == 8 && !m5)
- {
- if (Quot > 31)
- t = b2 + (Quot & 0x1f);
- else
- t = b1 + Quot;
- }
- else
- {
- if (Quot > 63)
- t = b2 + ((Quot >> 1) & 0x1f);
- else
- t = b1 + (Quot >> 1);
- }
- Tile = READ_2BYTES (t);
- GFX.Z1 = GFX.Z2 = depths [(Tile & 0x2000) >> 13];
- // Draw tile...
- if (BG.TileSize != 8)
- {
- if (Tile & H_FLIP)
- {
- // Horizontal flip, but what about vertical flip ?
- if (Tile & V_FLIP)
- {
- // Both horzontal & vertical flip
- if (Rem16 < 8)
- {
- (*DrawLargePixelPtr) (Tile + 17 - (Quot & 1), s,
- HPos & 7, PixWidth,
- VirtAlign, Lines);
- }
- else
- {
- (*DrawLargePixelPtr) (Tile + 1 - (Quot & 1), s,
- HPos & 7, PixWidth,
- VirtAlign, Lines);
- }
- }
- else
- {
- // Horizontal flip only
- if (Rem16 > 7)
- {
- (*DrawLargePixelPtr) (Tile + 17 - (Quot & 1), s,
- HPos & 7, PixWidth,
- VirtAlign, Lines);
- }
- else
- {
- (*DrawLargePixelPtr) (Tile + 1 - (Quot & 1), s,
- HPos & 7, PixWidth,
- VirtAlign, Lines);
- }
- }
- }
- else
- {
- // No horizontal flip, but is there a vertical flip ?
- if (Tile & V_FLIP)
- {
- // Vertical flip only
- if (Rem16 < 8)
- {
- (*DrawLargePixelPtr) (Tile + 16 + (Quot & 1), s,
- HPos & 7, PixWidth,
- VirtAlign, Lines);
- }
- else
- {
- (*DrawLargePixelPtr) (Tile + (Quot & 1), s,
- HPos & 7, PixWidth,
- VirtAlign, Lines);
- }
- }
- else
- {
- // Normal unflipped
- if (Rem16 > 7)
- {
- (*DrawLargePixelPtr) (Tile + 16 + (Quot & 1), s,
- HPos & 7, PixWidth,
- VirtAlign, Lines);
- }
- else
- {
- (*DrawLargePixelPtr) (Tile + (Quot & 1), s,
- HPos & 7, PixWidth,
- VirtAlign, Lines);
- }
- }
- }
- }
- else
- (*DrawLargePixelPtr) (Tile + (Quot & 1) * m5, s, HPos & 7, PixWidth,
- VirtAlign, Lines);
- }
- }
- }
- }
- void DrawBackgroundOffset (uint32 BGMode, uint32 bg, uint8 Z1, uint8 Z2)
- {
- CHECK_SOUND();
-
- uint32 Tile;
- uint16 *SC0;
- uint16 *SC1;
- uint16 *SC2;
- uint16 *SC3;
- uint16 *BPS0;
- uint16 *BPS1;
- uint16 *BPS2;
- uint16 *BPS3;
- uint32 Width;
- int VOffsetOffset = BGMode == 4 ? 0 : 32;
- uint8 depths [2] = {Z1, Z2};
-
- BG.StartPalette = 0;
-
- BPS0 = (uint16 *) &Memory.VRAM[PPU.BG[2].SCBase << 1];
-
- if (PPU.BG[2].SCSize & 1)
- BPS1 = BPS0 + 1024;
- else
- BPS1 = BPS0;
-
- if (PPU.BG[2].SCSize & 2)
- BPS2 = BPS1 + 1024;
- else
- BPS2 = BPS0;
-
- if (PPU.BG[2].SCSize & 1)
- BPS3 = BPS2 + 1024;
- else
- BPS3 = BPS2;
-
- SC0 = (uint16 *) &Memory.VRAM[PPU.BG[bg].SCBase << 1];
-
- if (PPU.BG[bg].SCSize & 1)
- SC1 = SC0 + 1024;
- else
- SC1 = SC0;
-
- if(((uint8*)SC1-Memory.VRAM)>=0x10000)
- SC1-=0x08000;
- if (PPU.BG[bg].SCSize & 2)
- SC2 = SC1 + 1024;
- else
- SC2 = SC0;
- if(((uint8*)SC2-Memory.VRAM)>=0x10000)
- SC2-=0x08000;
- if (PPU.BG[bg].SCSize & 1)
- SC3 = SC2 + 1024;
- else
- SC3 = SC2;
-
- if(((uint8*)SC3-Memory.VRAM)>=0x10000)
- SC3-=0x08000;
- static const int Lines = 1;
- int OffsetMask;
- int OffsetShift;
- int OffsetEnableMask = 1 << (bg + 13);
-
- if (BG.TileSize == 16)
- {
- OffsetMask = 0x3ff;
- OffsetShift = 4;
- }
- else
- {
- OffsetMask = 0x1ff;
- OffsetShift = 3;
- }
-
- for (uint32 Y = GFX.StartY; Y <= GFX.EndY; Y++)
- {
- uint32 VOff = LineData [Y].BG[2].VOffset - 1;
- // uint32 VOff = LineData [Y].BG[2].VOffset;
- uint32 HOff = LineData [Y].BG[2].HOffset;
- int VirtAlign;
- int ScreenLine = VOff >> 3;
- int t1;
- int t2;
- uint16 *s0;
- uint16 *s1;
- uint16 *s2;
-
- if (ScreenLine & 0x20)
- s1 = BPS2, s2 = BPS3;
- else
- s1 = BPS0, s2 = BPS1;
-
- s1 += (ScreenLine & 0x1f) << 5;
- s2 += (ScreenLine & 0x1f) << 5;
-
- if(BGMode != 4)
- {
- if((ScreenLine & 0x1f) == 0x1f)
- {
- if(ScreenLine & 0x20)
- VOffsetOffset = BPS0 - BPS2 - 0x1f*32;
- else
- VOffsetOffset = BPS2 - BPS0 - 0x1f*32;
- }
- else
- {
- VOffsetOffset = 32;
- }
- }
-
- int clipcount = GFX.pCurrentClip->Count [bg];
- if (!clipcount)
- clipcount = 1;
-
- for (int clip = 0; clip < clipcount; clip++)
- {
- uint32 Left;
- uint32 Right;
-
- if (!GFX.pCurrentClip->Count [bg])
- {
- Left = 0;
- Right = 256;
- }
- else
- {
- Left = GFX.pCurrentClip->Left [clip][bg];
- Right = GFX.pCurrentClip->Right [clip][bg];
-
- if (Right <= Left)
- continue;
- }
-
- uint32 VOffset;
- uint32 HOffset;
- //added:
- uint32 LineHOffset=LineData [Y].BG[bg].HOffset;
-
- uint32 Offset;
- uint32 HPos;
- uint32 Quot;
- uint32 Count;
- uint16 *t;
- uint32 Quot2;
- uint32 VCellOffset;
- uint32 HCellOffset;
- uint16 *b1;
- uint16 *b2;
- uint32 TotalCount = 0;
- uint32 MaxCount = 8;
-
- uint32 s = Left * GFX.PixSize + Y * GFX.PPL;
- bool8 left_hand_edge = (Left == 0);
- Width = Right - Left;
-
- if (Left & 7)
- MaxCount = 8 - (Left & 7);
-
- while (Left < Right)
- {
- if (left_hand_edge)
- {
- // The SNES offset-per-tile background mode has a
- // hardware limitation that the offsets cannot be set
- // for the tile at the left-hand edge of the screen.
- VOffset = LineData [Y].BG[bg].VOffset;
- //MKendora; use temp var to reduce memory accesses
- //HOffset = LineData [Y].BG[bg].HOffset;
- HOffset = LineHOffset;
- //End MK
- left_hand_edge = FALSE;
- }
- else
- {
- // All subsequent offset tile data is shifted left by one,
- // hence the - 1 below.
- Quot2 = ((HOff + Left - 1) & OffsetMask) >> 3;
-
- if (Quot2 > 31)
- s0 = s2 + (Quot2 & 0x1f);
- else
- s0 = s1 + Quot2;
-
- HCellOffset = READ_2BYTES (s0);
-
- if (BGMode == 4)
- {
- VOffset = LineData [Y].BG[bg].VOffset;
-
- //MKendora another mem access hack
- //HOffset = LineData [Y].BG[bg].HOffset;
- HOffset=LineHOffset;
- //end MK
- if ((HCellOffset & OffsetEnableMask))
- {
- if (HCellOffset & 0x8000)
- VOffset = HCellOffset + 1;
- else
- HOffset = HCellOffset;
- }
- }
- else
- {
- VCellOffset = READ_2BYTES (s0 + VOffsetOffset);
- if ((VCellOffset & OffsetEnableMask))
- VOffset = VCellOffset + 1;
- else
- VOffset = LineData [Y].BG[bg].VOffset;
- //MKendora Strike Gunner fix
- if ((HCellOffset & OffsetEnableMask))
- {
- //HOffset= HCellOffset;
-
- HOffset = (HCellOffset & ~7)|(LineHOffset&7);
- //HOffset |= LineData [Y].BG[bg].HOffset&7;
- }
- else
- HOffset=LineHOffset;
- //HOffset = LineData [Y].BG[bg].HOffset -
- //Settings.StrikeGunnerOffsetHack;
- //HOffset &= (~7);
- //end MK
- }
- }
- VirtAlign = ((Y + VOffset) & 7) << 3;
- ScreenLine = (VOffset + Y) >> OffsetShift;
-
- if (((VOffset + Y) & 15) > 7)
- {
- t1 = 16;
- t2 = 0;
- }
- else
- {
- t1 = 0;
- t2 = 16;
- }
-
- if (ScreenLine & 0x20)
- b1 = SC2, b2 = SC3;
- else
- b1 = SC0, b2 = SC1;
-
- b1 += (ScreenLine & 0x1f) << 5;
- b2 += (ScreenLine & 0x1f) << 5;
-
- HPos = (HOffset + Left) & OffsetMask;
-
- Quot = HPos >> 3;
-
- if (BG.TileSize == 8)
- {
- if (Quot > 31)
- t = b2 + (Quot & 0x1f);
- else
- t = b1 + Quot;
- }
- else
- {
- if (Quot > 63)
- t = b2 + ((Quot >> 1) & 0x1f);
- else
- t = b1 + (Quot >> 1);
- }
-
- if (MaxCount + TotalCount > Width)
- MaxCount = Width - TotalCount;
-
- Offset = HPos & 7;
-
- //Count =1;
- Count = 8 - Offset;
- if (Count > MaxCount)
- Count = MaxCount;
-
- s -= Offset * GFX.PixSize;
- Tile = READ_2BYTES(t);
- GFX.Z1 = GFX.Z2 = depths [(Tile & 0x2000) >> 13];
-
- if (BG.TileSize == 8)
- (*DrawClippedTilePtr) (Tile, s, Offset, Count, VirtAlign, Lines);
- else
- {
- if (!(Tile & (V_FLIP | H_FLIP)))
- {
- // Normal, unflipped
- (*DrawClippedTilePtr) (Tile + t1 + (Quot & 1),
- s, Offset, Count, VirtAlign, Lines);
- }
- else
- if (Tile & H_FLIP)
- {
- if (Tile & V_FLIP)
- {
- // H & V flip
- (*DrawClippedTilePtr) (Tile + t2 + 1 - (Quot & 1),
- s, Offset, Count, VirtAlign, Lines);
- }
- else
- {
- // H flip only
- (*DrawClippedTilePtr) (Tile + t1 + 1 - (Quot & 1),
- s, Offset, Count, VirtAlign, Lines);
- }
- }
- else
- {
- // V flip only
- (*DrawClippedTilePtr) (Tile + t2 + (Quot & 1),
- s, Offset, Count, VirtAlign, Lines);
- }
- }
-
- Left += Count;
- TotalCount += Count;
- s += (Offset + Count) * GFX.PixSize;
- MaxCount = 8;
- }
- }
- }
- }
- void DrawBackgroundMode5 (uint32 /* BGMODE */, uint32 bg, uint8 Z1, uint8 Z2)
- {
- CHECK_SOUND();
- if(IPPU.Interlace)
- {
- GFX.Pitch = GFX.RealPitch;
- GFX.PPL = GFX.PPLx2 >> 1;
- }
- GFX.PixSize = 1;
- uint8 depths [2] = {Z1, Z2};
-
- uint32 Tile;
- uint16 *SC0;
- uint16 *SC1;
- uint16 *SC2;
- uint16 *SC3;
- uint32 Width;
-
- BG.StartPalette = 0;
-
- SC0 = (uint16 *) &Memory.VRAM[PPU.BG[bg].SCBase << 1];
-
- if ((PPU.BG[bg].SCSize & 1))
- SC1 = SC0 + 1024;
- else
- SC1 = SC0;
-
- if((SC1-(unsigned short*)Memory.VRAM)>0x10000)
- SC1=(uint16*)&Memory.VRAM[(((uint8*)SC1)-Memory.VRAM)%0x10000];
-
- if ((PPU.BG[bg].SCSize & 2))
- SC2 = SC1 + 1024;
- else SC2 = SC0;
-
- if(((uint8*)SC2-Memory.VRAM)>=0x10000)
- SC2-=0x08000;
-
-
- if ((PPU.BG[bg].SCSize & 1))
- SC3 = SC2 + 1024;
- else
- SC3 = SC2;
-
- if(((uint8*)SC3-Memory.VRAM)>=0x10000)
- SC3-=0x08000;
-
-
- int Lines;
- int VOffsetMask;
- int VOffsetShift;
-
- if (BG.TileSize == 16)
- {
- VOffsetMask = 0x3ff;
- VOffsetShift = 4;
- }
- else
- {
- VOffsetMask = 0x1ff;
- VOffsetShift = 3;
- }
- int endy = IPPU.Interlace ? 1 + (GFX.EndY << 1) : GFX.EndY;
-
- for (int Y = IPPU.Interlace ? GFX.StartY << 1 : GFX.StartY; Y <= endy; Y += Lines)
- {
- int y = IPPU.Interlace ? (Y >> 1) : Y;
- uint32 VOffset = LineData [y].BG[bg].VOffset;
- uint32 HOffset = LineData [y].BG[bg].HOffset;
- int VirtAlign = (Y + VOffset) & 7;
-
- for (Lines = 1; Lines < 8 - VirtAlign; Lines++)
- if ((VOffset != LineData [y + Lines].BG[bg].VOffset) ||
- (HOffset != LineData [y + Lines].BG[bg].HOffset))
- break;
-
- HOffset <<= 1;
- if (Y + Lines > endy)
- Lines = endy + 1 - Y;
- VirtAlign <<= 3;
-
- int ScreenLine = (VOffset + Y) >> VOffsetShift;
- int t1;
- int t2;
- if (((VOffset + Y) & 15) > 7)
- {
- t1 = 16;
- t2 = 0;
- }
- else
- {
- t1 = 0;
- t2 = 16;
- }
- uint16 *b1;
- uint16 *b2;
-
- if (ScreenLine & 0x20)
- b1 = SC2, b2 = SC3;
- else
- b1 = SC0, b2 = SC1;
-
- b1 += (ScreenLine & 0x1f) << 5;
- b2 += (ScreenLine & 0x1f) << 5;
-
- int clipcount = GFX.pCurrentClip->Count [bg];
- if (!clipcount)
- clipcount = 1;
- for (int clip = 0; clip < clipcount; clip++)
- {
- int Left;
- int Right;
-
- if (!GFX.pCurrentClip->Count [bg])
- {
- Left = 0;
- Right = 512;
- }
- else
- {
- Left = GFX.pCurrentClip->Left [clip][bg] * 2;
- Right = GFX.pCurrentClip->Right [clip][bg] * 2;
-
- if (Right <= Left)
- continue;
- }
-
- uint32 s = Left * GFX.PixSize + Y * GFX.PPL;
- uint32 HPos = (HOffset + Left * GFX.PixSize) & 0x3ff;
-
- uint32 Quot = HPos >> 3;
- uint32 Count = 0;
-
- uint16 *t;
- if (Quot > 63)
- t = b2 + ((Quot >> 1) & 0x1f);
- else
- t = b1 + (Quot >> 1);
-
- Width = Right - Left;
- // Left hand edge clipped ti…
Large files files are truncated, but you can click here to view the full file