mirror of
https://github.com/libretro/snes9x.git
synced 2024-11-23 08:19:46 +00:00
Improve interlace and OAM interlace support.
Interlace is now possible in every bg mode. OAM interlace no longer forces global interlace and properly switches between odd and even lines. Screen output can now be 256x448.
This commit is contained in:
parent
7c4d1566f7
commit
5e53e209b9
96
gfx.cpp
96
gfx.cpp
@ -329,9 +329,8 @@ void S9xStartScreenRefresh (void)
|
||||
{
|
||||
if (IPPU.RenderThisFrame)
|
||||
{
|
||||
if (GFX.DoInterlace && GFX.InterlaceFrame == 0)
|
||||
GFX.InterlaceFrame = 1;
|
||||
else
|
||||
GFX.InterlaceFrame = !GFX.InterlaceFrame;
|
||||
if (!GFX.DoInterlace || !GFX.InterlaceFrame)
|
||||
{
|
||||
if (!S9xInitUpdate())
|
||||
{
|
||||
@ -339,50 +338,45 @@ void S9xStartScreenRefresh (void)
|
||||
return;
|
||||
}
|
||||
|
||||
GFX.InterlaceFrame = 0;
|
||||
if (GFX.DoInterlace)
|
||||
GFX.DoInterlace--;
|
||||
|
||||
IPPU.MaxBrightness = PPU.Brightness;
|
||||
|
||||
IPPU.PseudoHires = Memory.FillRAM[0x2133] & 8;
|
||||
if (PPU.BGMode == 5 || PPU.BGMode == 6)
|
||||
{
|
||||
IPPU.Interlace = Memory.FillRAM[0x2133] & 1;
|
||||
IPPU.InterlaceOBJ = Memory.FillRAM[0x2133] & 2;
|
||||
}
|
||||
IPPU.Interlace = Memory.FillRAM[0x2133] & 1;
|
||||
IPPU.InterlaceOBJ = Memory.FillRAM[0x2133] & 2;
|
||||
IPPU.PseudoHires = Memory.FillRAM[0x2133] & 8;
|
||||
|
||||
if (Settings.SupportHiRes && (PPU.BGMode == 5 || PPU.BGMode == 6 || IPPU.PseudoHires || IPPU.Interlace || IPPU.InterlaceOBJ))
|
||||
if (Settings.SupportHiRes && (PPU.BGMode == 5 || PPU.BGMode == 6 || IPPU.PseudoHires))
|
||||
{
|
||||
GFX.RealPPL = GFX.Pitch >> 1;
|
||||
IPPU.DoubleWidthPixels = TRUE;
|
||||
IPPU.RenderedScreenWidth = SNES_WIDTH << 1;
|
||||
if (IPPU.Interlace || IPPU.InterlaceOBJ)
|
||||
{
|
||||
GFX.PPL = GFX.RealPPL << 1;
|
||||
IPPU.DoubleHeightPixels = TRUE;
|
||||
IPPU.RenderedScreenHeight = PPU.ScreenHeight << 1;
|
||||
GFX.DoInterlace++;
|
||||
}
|
||||
else
|
||||
{
|
||||
GFX.PPL = GFX.RealPPL;
|
||||
IPPU.DoubleHeightPixels = FALSE;
|
||||
IPPU.RenderedScreenHeight = PPU.ScreenHeight;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
IPPU.DoubleWidthPixels = FALSE;
|
||||
IPPU.DoubleHeightPixels = FALSE;
|
||||
IPPU.RenderedScreenWidth = SNES_WIDTH;
|
||||
IPPU.RenderedScreenHeight = PPU.ScreenHeight;
|
||||
#ifdef USE_OPENGL
|
||||
if (Settings.OpenGLEnable)
|
||||
GFX.RealPPL = GFX.PPL = SNES_WIDTH;
|
||||
GFX.RealPPL = SNES_WIDTH;
|
||||
else
|
||||
#endif
|
||||
GFX.RealPPL = GFX.PPL = GFX.Pitch >> 1;
|
||||
GFX.RealPPL = GFX.Pitch >> 1;
|
||||
IPPU.DoubleWidthPixels = FALSE;
|
||||
IPPU.RenderedScreenWidth = SNES_WIDTH;
|
||||
}
|
||||
|
||||
if (Settings.SupportHiRes && IPPU.Interlace)
|
||||
{
|
||||
GFX.PPL = GFX.RealPPL << 1;
|
||||
IPPU.DoubleHeightPixels = TRUE;
|
||||
IPPU.RenderedScreenHeight = PPU.ScreenHeight << 1;
|
||||
GFX.DoInterlace++;
|
||||
}
|
||||
else
|
||||
{
|
||||
GFX.PPL = GFX.RealPPL;
|
||||
IPPU.DoubleHeightPixels = FALSE;
|
||||
IPPU.RenderedScreenHeight = PPU.ScreenHeight;
|
||||
}
|
||||
|
||||
IPPU.RenderedFramesCount++;
|
||||
@ -652,7 +646,7 @@ static inline void RenderScreen (bool8 sub)
|
||||
|
||||
void S9xUpdateScreen (void)
|
||||
{
|
||||
if (IPPU.OBJChanged)
|
||||
if (IPPU.OBJChanged || IPPU.InterlaceOBJ)
|
||||
SetupOBJ();
|
||||
|
||||
// XXX: Check ForceBlank? Or anything else?
|
||||
@ -675,7 +669,7 @@ void S9xUpdateScreen (void)
|
||||
|
||||
if (Settings.SupportHiRes)
|
||||
{
|
||||
if (!IPPU.DoubleWidthPixels && (PPU.BGMode == 5 || PPU.BGMode == 6 || IPPU.PseudoHires || IPPU.Interlace || IPPU.InterlaceOBJ))
|
||||
if (!IPPU.DoubleWidthPixels && (PPU.BGMode == 5 || PPU.BGMode == 6 || IPPU.PseudoHires))
|
||||
{
|
||||
#ifdef USE_OPENGL
|
||||
if (Settings.OpenGLEnable && GFX.RealPPL == 256)
|
||||
@ -714,7 +708,7 @@ void S9xUpdateScreen (void)
|
||||
IPPU.RenderedScreenWidth = 512;
|
||||
}
|
||||
|
||||
if (!IPPU.DoubleHeightPixels && (IPPU.Interlace || IPPU.InterlaceOBJ))
|
||||
if (!IPPU.DoubleHeightPixels && IPPU.Interlace)
|
||||
{
|
||||
IPPU.DoubleHeightPixels = TRUE;
|
||||
IPPU.RenderedScreenHeight = PPU.ScreenHeight << 1;
|
||||
@ -803,6 +797,8 @@ static void SetupOBJ (void)
|
||||
|
||||
int inc = IPPU.InterlaceOBJ ? 2 : 1;
|
||||
|
||||
int startline = (IPPU.InterlaceOBJ && GFX.InterlaceFrame) ? 1 : 0;
|
||||
|
||||
// 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.
|
||||
@ -853,7 +849,7 @@ static void SetupOBJ (void)
|
||||
else
|
||||
GFX.OBJVisibleTiles[S] = GFX.OBJWidths[S] >> 3;
|
||||
|
||||
for (uint8 line = 0, Y = (uint8) (PPU.OBJ[S].VPos & 0xff); line < Height; Y++, line += inc)
|
||||
for (uint8 line = startline, Y = (uint8) (PPU.OBJ[S].VPos & 0xff); line < Height; Y++, line += inc)
|
||||
{
|
||||
if (Y >= SNES_HEIGHT_EXTENDED)
|
||||
continue;
|
||||
@ -919,7 +915,7 @@ static void SetupOBJ (void)
|
||||
else
|
||||
GFX.OBJVisibleTiles[S] = GFX.OBJWidths[S] >> 3;
|
||||
|
||||
for (uint8 line = 0, Y = (uint8) (PPU.OBJ[S].VPos & 0xff); line < Height; Y++, line += inc)
|
||||
for (uint8 line = startline, Y = (uint8) (PPU.OBJ[S].VPos & 0xff); line < Height; Y++, line += inc)
|
||||
{
|
||||
if (Y >= SNES_HEIGHT_EXTENDED)
|
||||
continue;
|
||||
@ -996,8 +992,6 @@ static void DrawOBJS (int D)
|
||||
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;
|
||||
if (IPPU.InterlaceOBJ)
|
||||
TileLine >>= 1;
|
||||
int TileInc = 1;
|
||||
|
||||
if (PPU.OBJ[S].HFlip)
|
||||
@ -1090,6 +1084,7 @@ static void DrawBackground (int bg, uint8 Zh, uint8 Zl)
|
||||
int OffsetMask = (BG.TileSizeH == 16) ? 0x3ff : 0x1ff;
|
||||
int OffsetShift = (BG.TileSizeV == 16) ? 4 : 3;
|
||||
int PixWidth = IPPU.DoubleWidthPixels ? 2 : 1;
|
||||
bool8 HiresInterlace = IPPU.Interlace && IPPU.DoubleWidthPixels;
|
||||
|
||||
void (*DrawTile) (uint32, uint32, uint32, uint32);
|
||||
void (*DrawClippedTile) (uint32, uint32, uint32, uint32, uint32, uint32);
|
||||
@ -1111,10 +1106,10 @@ static void DrawBackground (int bg, uint8 Zh, uint8 Zl)
|
||||
|
||||
for (uint32 Y = GFX.StartY; Y <= GFX.EndY; Y += Lines)
|
||||
{
|
||||
uint32 Y2 = IPPU.Interlace ? Y * 2 + GFX.InterlaceFrame : Y;
|
||||
uint32 VOffset = LineData[Y].BG[bg].VOffset + (IPPU.Interlace ? 1 : 0);
|
||||
uint32 Y2 = HiresInterlace ? Y * 2 + GFX.InterlaceFrame : Y;
|
||||
uint32 VOffset = LineData[Y].BG[bg].VOffset + (HiresInterlace ? 1 : 0);
|
||||
uint32 HOffset = LineData[Y].BG[bg].HOffset;
|
||||
int VirtAlign = ((Y2 + VOffset) & 7) >> (IPPU.Interlace ? 1 : 0);
|
||||
int VirtAlign = ((Y2 + VOffset) & 7) >> (HiresInterlace ? 1 : 0);
|
||||
|
||||
for (Lines = 1; Lines < GFX.LinesPerTile - VirtAlign; Lines++)
|
||||
{
|
||||
@ -1306,6 +1301,7 @@ static void DrawBackgroundMosaic (int bg, uint8 Zh, uint8 Zl)
|
||||
int OffsetMask = (BG.TileSizeH == 16) ? 0x3ff : 0x1ff;
|
||||
int OffsetShift = (BG.TileSizeV == 16) ? 4 : 3;
|
||||
int PixWidth = IPPU.DoubleWidthPixels ? 2 : 1;
|
||||
bool8 HiresInterlace = IPPU.Interlace && IPPU.DoubleWidthPixels;
|
||||
|
||||
void (*DrawPix) (uint32, uint32, uint32, uint32, uint32, uint32);
|
||||
|
||||
@ -1322,15 +1318,15 @@ static void DrawBackgroundMosaic (int bg, uint8 Zh, uint8 Zl)
|
||||
|
||||
for (uint32 Y = GFX.StartY - MosaicStart; Y <= GFX.EndY; Y += PPU.Mosaic)
|
||||
{
|
||||
uint32 Y2 = IPPU.Interlace ? Y * 2 : Y;
|
||||
uint32 VOffset = LineData[Y].BG[bg].VOffset + (IPPU.Interlace ? 1 : 0);
|
||||
uint32 Y2 = HiresInterlace ? Y * 2 : Y;
|
||||
uint32 VOffset = LineData[Y].BG[bg].VOffset + (HiresInterlace ? 1 : 0);
|
||||
uint32 HOffset = LineData[Y].BG[bg].HOffset;
|
||||
|
||||
Lines = PPU.Mosaic - MosaicStart;
|
||||
if (Y + MosaicStart + Lines > GFX.EndY)
|
||||
Lines = GFX.EndY - Y - MosaicStart + 1;
|
||||
|
||||
int VirtAlign = (((Y2 + VOffset) & 7) >> (IPPU.Interlace ? 1 : 0)) << 3;
|
||||
int VirtAlign = (((Y2 + VOffset) & 7) >> (HiresInterlace ? 1 : 0)) << 3;
|
||||
|
||||
uint32 t1, t2;
|
||||
uint32 TilemapRow = (VOffset + Y2) >> OffsetShift;
|
||||
@ -1485,6 +1481,7 @@ static void DrawBackgroundOffset (int bg, uint8 Zh, uint8 Zl, int VOffOff)
|
||||
int Offset2Shift = (BG.OffsetSizeV == 16) ? 4 : 3;
|
||||
int OffsetEnableMask = 0x2000 << bg;
|
||||
int PixWidth = IPPU.DoubleWidthPixels ? 2 : 1;
|
||||
bool8 HiresInterlace = IPPU.Interlace && IPPU.DoubleWidthPixels;
|
||||
|
||||
void (*DrawTile) (uint32, uint32, uint32, uint32);
|
||||
void (*DrawClippedTile) (uint32, uint32, uint32, uint32, uint32, uint32);
|
||||
@ -1506,7 +1503,7 @@ static void DrawBackgroundOffset (int bg, uint8 Zh, uint8 Zl, int VOffOff)
|
||||
|
||||
for (uint32 Y = GFX.StartY; Y <= GFX.EndY; Y++)
|
||||
{
|
||||
uint32 Y2 = IPPU.Interlace ? Y * 2 + GFX.InterlaceFrame : Y;
|
||||
uint32 Y2 = HiresInterlace ? Y * 2 + GFX.InterlaceFrame : Y;
|
||||
uint32 VOff = LineData[Y].BG[2].VOffset - 1;
|
||||
uint32 HOff = LineData[Y].BG[2].HOffset;
|
||||
uint32 HOffsetRow = VOff >> Offset2Shift;
|
||||
@ -1593,11 +1590,11 @@ static void DrawBackgroundOffset (int bg, uint8 Zh, uint8 Zl, int VOffOff)
|
||||
HOffset = LineHOffset;
|
||||
}
|
||||
|
||||
if (IPPU.Interlace)
|
||||
if (HiresInterlace)
|
||||
VOffset++;
|
||||
|
||||
uint32 t1, t2;
|
||||
int VirtAlign = (((Y2 + VOffset) & 7) >> (IPPU.Interlace ? 1 : 0)) << 3;
|
||||
int VirtAlign = (((Y2 + VOffset) & 7) >> (HiresInterlace ? 1 : 0)) << 3;
|
||||
int TilemapRow = (VOffset + Y2) >> OffsetShift;
|
||||
BG.InterlaceLine = ((VOffset + Y2) & 1) << 3;
|
||||
|
||||
@ -1716,6 +1713,7 @@ static void DrawBackgroundOffsetMosaic (int bg, uint8 Zh, uint8 Zl, int VOffOff)
|
||||
int Offset2Shift = (BG.OffsetSizeV == 16) ? 4 : 3;
|
||||
int OffsetEnableMask = 0x2000 << bg;
|
||||
int PixWidth = IPPU.DoubleWidthPixels ? 2 : 1;
|
||||
bool8 HiresInterlace = IPPU.Interlace && IPPU.DoubleWidthPixels;
|
||||
|
||||
void (*DrawPix) (uint32, uint32, uint32, uint32, uint32, uint32);
|
||||
|
||||
@ -1732,7 +1730,7 @@ static void DrawBackgroundOffsetMosaic (int bg, uint8 Zh, uint8 Zl, int VOffOff)
|
||||
|
||||
for (uint32 Y = GFX.StartY - MosaicStart; Y <= GFX.EndY; Y += PPU.Mosaic)
|
||||
{
|
||||
uint32 Y2 = IPPU.Interlace ? Y * 2 : Y;
|
||||
uint32 Y2 = HiresInterlace ? Y * 2 : Y;
|
||||
uint32 VOff = LineData[Y].BG[2].VOffset - 1;
|
||||
uint32 HOff = LineData[Y].BG[2].HOffset;
|
||||
|
||||
@ -1824,11 +1822,11 @@ static void DrawBackgroundOffsetMosaic (int bg, uint8 Zh, uint8 Zl, int VOffOff)
|
||||
HOffset = LineHOffset;
|
||||
}
|
||||
|
||||
if (IPPU.Interlace)
|
||||
if (HiresInterlace)
|
||||
VOffset++;
|
||||
|
||||
uint32 t1, t2;
|
||||
int VirtAlign = (((Y2 + VOffset) & 7) >> (IPPU.Interlace ? 1 : 0)) << 3;
|
||||
int VirtAlign = (((Y2 + VOffset) & 7) >> (HiresInterlace ? 1 : 0)) << 3;
|
||||
int TilemapRow = (VOffset + Y2) >> OffsetShift;
|
||||
BG.InterlaceLine = ((VOffset + Y2) & 1) << 3;
|
||||
|
||||
|
8
ppu.cpp
8
ppu.cpp
@ -454,10 +454,7 @@ void S9xSetPPU (uint8 Byte, uint16 Address)
|
||||
PPU.BGMode = Byte & 7;
|
||||
// BJ: BG3Priority only takes effect if BGMode == 1 and the bit is set
|
||||
PPU.BG3Priority = ((Byte & 0x0f) == 0x09);
|
||||
if (PPU.BGMode == 5 || PPU.BGMode == 6)
|
||||
IPPU.Interlace = Memory.FillRAM[0x2133] & 1;
|
||||
else
|
||||
IPPU.Interlace = 0;
|
||||
IPPU.Interlace = Memory.FillRAM[0x2133] & 1;
|
||||
#ifdef DEBUGGER
|
||||
missing.modes[PPU.BGMode] = 1;
|
||||
#endif
|
||||
@ -979,8 +976,7 @@ void S9xSetPPU (uint8 Byte, uint16 Address)
|
||||
FLUSH_REDRAW();
|
||||
if ((Memory.FillRAM[0x2133] ^ Byte) & 2)
|
||||
IPPU.OBJChanged = TRUE;
|
||||
if (PPU.BGMode == 5 || PPU.BGMode == 6)
|
||||
IPPU.Interlace = Byte & 1;
|
||||
IPPU.Interlace = Byte & 1;
|
||||
IPPU.InterlaceOBJ = Byte & 2;
|
||||
}
|
||||
#ifdef DEBUGGER
|
||||
|
38
tile.cpp
38
tile.cpp
@ -492,7 +492,10 @@ void S9xSelectTileRenderers (int BGMode, bool8 sub, bool8 obj)
|
||||
M7M1 = PPU.BGMosaic[0] && PPU.Mosaic > 1;
|
||||
M7M2 = PPU.BGMosaic[1] && PPU.Mosaic > 1;
|
||||
|
||||
if (!IPPU.DoubleWidthPixels)
|
||||
bool8 interlace = obj ? FALSE : IPPU.Interlace;
|
||||
bool8 hires = !sub && (BGMode == 5 || BGMode == 6 || IPPU.PseudoHires);
|
||||
|
||||
if (!IPPU.DoubleWidthPixels) // normal width
|
||||
{
|
||||
DT = Renderers_DrawTile16Normal1x1;
|
||||
DCT = Renderers_DrawClippedTile16Normal1x1;
|
||||
@ -502,31 +505,9 @@ void S9xSelectTileRenderers (int BGMode, bool8 sub, bool8 obj)
|
||||
DM7BG2 = M7M2 ? Renderers_DrawMode7MosaicBG2Normal1x1 : Renderers_DrawMode7BG2Normal1x1;
|
||||
GFX.LinesPerTile = 8;
|
||||
}
|
||||
else
|
||||
else if(hires) // hires double width
|
||||
{
|
||||
bool8 hires, interlace;
|
||||
|
||||
if (obj) // OBJ
|
||||
{
|
||||
hires = (BGMode == 5 || BGMode == 6 || IPPU.PseudoHires);
|
||||
interlace = IPPU.InterlaceOBJ;
|
||||
}
|
||||
else
|
||||
if (BGMode == 5 || BGMode == 6)
|
||||
{
|
||||
hires = TRUE;
|
||||
interlace = IPPU.Interlace;
|
||||
}
|
||||
else
|
||||
{
|
||||
hires = IPPU.PseudoHires;
|
||||
interlace = FALSE;
|
||||
}
|
||||
|
||||
if (sub)
|
||||
hires = FALSE;
|
||||
|
||||
if (hires && interlace)
|
||||
if (interlace)
|
||||
{
|
||||
DT = Renderers_DrawTile16HiresInterlace;
|
||||
DCT = Renderers_DrawClippedTile16HiresInterlace;
|
||||
@ -537,7 +518,6 @@ void S9xSelectTileRenderers (int BGMode, bool8 sub, bool8 obj)
|
||||
GFX.LinesPerTile = 4;
|
||||
}
|
||||
else
|
||||
if (hires)
|
||||
{
|
||||
DT = Renderers_DrawTile16Hires;
|
||||
DCT = Renderers_DrawClippedTile16Hires;
|
||||
@ -547,7 +527,9 @@ void S9xSelectTileRenderers (int BGMode, bool8 sub, bool8 obj)
|
||||
DM7BG2 = M7M2 ? Renderers_DrawMode7MosaicBG2Hires : Renderers_DrawMode7BG2Hires;
|
||||
GFX.LinesPerTile = 8;
|
||||
}
|
||||
else
|
||||
}
|
||||
else // normal double width
|
||||
{
|
||||
if (interlace)
|
||||
{
|
||||
DT = Renderers_DrawTile16Interlace;
|
||||
@ -1435,7 +1417,7 @@ extern struct SLineMatrixData LineMatrixData[240];
|
||||
#define DRAW_PIXEL(N, M) DRAW_PIXEL_N2x1(N, M)
|
||||
#define NAME2 Interlace
|
||||
|
||||
// Third-level include: Get the Interlace renderers.
|
||||
// Third-level include: Get the double width Interlace renderers.
|
||||
|
||||
#include "tile.cpp"
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user