gen: two-cell vertical scroll mode
This commit is contained in:
parent
b7e8386af1
commit
64a04fd672
|
@ -25,8 +25,14 @@ namespace BizHawk.Emulation.Consoles.Sega
|
|||
// TODO: I would like to be able to render Scroll A before Scroll B, in order to minimize overdraw.
|
||||
// But at the moment it complicates priority stuff.
|
||||
|
||||
RenderScrollB();
|
||||
RenderScrollA();
|
||||
if (CellBasedVertScroll == false)
|
||||
{
|
||||
RenderScrollB();
|
||||
RenderScrollA();
|
||||
} else {
|
||||
RenderScrollBTwoCellVScroll();
|
||||
RenderScrollATwoCellVScroll();
|
||||
}
|
||||
|
||||
RenderSpritesScanline();
|
||||
}
|
||||
|
@ -88,6 +94,47 @@ namespace BizHawk.Emulation.Consoles.Sega
|
|||
}
|
||||
}
|
||||
|
||||
void RenderScrollAScanlineTwoCellVScroll(int xScroll, int nameTableBase, int startPixel, int endPixel, bool window)
|
||||
{
|
||||
const int lowPriority = 2;
|
||||
const int highPriority = 5;
|
||||
|
||||
int fineHScroll = xScroll & 15;
|
||||
int nameTableWidth = NameTableWidth;
|
||||
if (window)
|
||||
nameTableWidth = (DisplayWidth == 40) ? 64 : 32;
|
||||
|
||||
for (int x = startPixel; x < endPixel; x++)
|
||||
{
|
||||
int vsramUnitOffset = ((x - fineHScroll) / 16) % 40;
|
||||
int yScroll = VSRAM[vsramUnitOffset * 2] & 0x3FF;
|
||||
int yTile = ((ScanLine + yScroll) / 8) % NameTableHeight;
|
||||
|
||||
int xTile = Math.Abs(((x + (1024 - xScroll)) / 8) % nameTableWidth);
|
||||
int xOfs = Math.Abs((x + (1024 - xScroll)) & 7);
|
||||
int yOfs = (ScanLine + yScroll) % 8;
|
||||
int cellOfs = nameTableBase + (yTile * nameTableWidth * 2) + (xTile * 2);
|
||||
int nameTableEntry = VRAM[cellOfs] | (VRAM[cellOfs + 1] << 8);
|
||||
int patternNo = nameTableEntry & 0x7FF;
|
||||
bool hFlip = ((nameTableEntry >> 11) & 1) != 0;
|
||||
bool vFlip = ((nameTableEntry >> 12) & 1) != 0;
|
||||
bool priority = ((nameTableEntry >> 15) & 1) != 0;
|
||||
int palette = (nameTableEntry >> 13) & 3;
|
||||
|
||||
if (priority && PriorityBuffer[x] >= highPriority) continue;
|
||||
if (!priority && PriorityBuffer[x] >= lowPriority) continue;
|
||||
|
||||
if (vFlip) yOfs = 7 - yOfs;
|
||||
if (hFlip) xOfs = 7 - xOfs;
|
||||
|
||||
int texel = PatternBuffer[(patternNo * 64) + (yOfs * 8) + (xOfs)];
|
||||
if (texel == 0) continue;
|
||||
int pixel = Palette[(palette * 16) + texel];
|
||||
FrameBuffer[(ScanLine * FrameWidth) + x] = pixel;
|
||||
PriorityBuffer[x] = (byte)(priority ? highPriority : lowPriority);
|
||||
}
|
||||
}
|
||||
|
||||
void CalculateWindowScanlines(out int startScanline, out int endScanline)
|
||||
{
|
||||
int data = Registers[0x12];
|
||||
|
@ -182,6 +229,44 @@ namespace BizHawk.Emulation.Consoles.Sega
|
|||
}
|
||||
}
|
||||
|
||||
void RenderScrollATwoCellVScroll()
|
||||
{
|
||||
// Calculate scroll offsets
|
||||
|
||||
int hscroll = CalcHScrollPlaneA(ScanLine);
|
||||
|
||||
// Calculate window dimensions
|
||||
|
||||
int startWindowScanline, endWindowScanline;
|
||||
int startWindowPixel, endWindowPixel;
|
||||
CalculateWindowScanlines(out startWindowScanline, out endWindowScanline);
|
||||
CalculateWindowPosition(out startWindowPixel, out endWindowPixel);
|
||||
|
||||
// Render scanline
|
||||
|
||||
if (ScanLine >= startWindowScanline && ScanLine < endWindowScanline) // Window takes up whole scanline
|
||||
{
|
||||
RenderScrollAScanline(0, 0, NameTableAddrWindow, 0, FrameWidth, true);
|
||||
}
|
||||
else if (startWindowPixel != -1) // Window takes up partial scanline
|
||||
{
|
||||
if (startWindowPixel == 0) // Window grows from left side
|
||||
{
|
||||
RenderScrollAScanline(0, 0, NameTableAddrWindow, 0, endWindowPixel, true);
|
||||
RenderScrollAScanlineTwoCellVScroll(hscroll, NameTableAddrA, endWindowPixel, FrameWidth, false);
|
||||
}
|
||||
else // Window grows from right side
|
||||
{
|
||||
RenderScrollAScanlineTwoCellVScroll(hscroll, NameTableAddrA, 0, startWindowPixel, false);
|
||||
RenderScrollAScanline(0, 0, NameTableAddrWindow, startWindowPixel, FrameWidth, true);
|
||||
}
|
||||
}
|
||||
else // No window this scanline
|
||||
{
|
||||
RenderScrollAScanlineTwoCellVScroll(hscroll, NameTableAddrA, 0, FrameWidth, false);
|
||||
}
|
||||
}
|
||||
|
||||
void RenderScrollB()
|
||||
{
|
||||
int bgColor = BackgroundColor;
|
||||
|
@ -222,9 +307,51 @@ namespace BizHawk.Emulation.Consoles.Sega
|
|||
{
|
||||
FrameBuffer[(ScanLine * FrameWidth) + x] = pixel;
|
||||
PriorityBuffer[x] = (byte)(priority ? highPriority : lowPriority);
|
||||
} else {
|
||||
FrameBuffer[(ScanLine * FrameWidth) + x] = bgColor;
|
||||
}
|
||||
else
|
||||
}
|
||||
}
|
||||
|
||||
void RenderScrollBTwoCellVScroll()
|
||||
{
|
||||
int bgColor = BackgroundColor;
|
||||
int xScroll = CalcHScrollPlaneB(ScanLine);
|
||||
int fineHScroll = xScroll & 15;
|
||||
|
||||
const int lowPriority = 1;
|
||||
const int highPriority = 4;
|
||||
|
||||
for (int x = 0; x < FrameWidth; x++)
|
||||
{
|
||||
int vsramUnitOffset = ((x - fineHScroll) / 16) % 40;
|
||||
int yScroll = VSRAM[(vsramUnitOffset*2)+1] & 0x3FF;
|
||||
int yTile = ((ScanLine + yScroll) / 8) % NameTableHeight;
|
||||
|
||||
int xTile = Math.Abs(((x + (1024 - xScroll)) / 8) % NameTableWidth);
|
||||
int xOfs = Math.Abs((x + (1024 - xScroll)) & 7);
|
||||
int yOfs = (ScanLine + yScroll) % 8;
|
||||
int cellOfs = NameTableAddrB + (yTile * NameTableWidth * 2) + (xTile * 2);
|
||||
int nameTableEntry = VRAM[cellOfs] | (VRAM[cellOfs + 1] << 8);
|
||||
int patternNo = nameTableEntry & 0x7FF;
|
||||
bool hFlip = ((nameTableEntry >> 11) & 1) != 0;
|
||||
bool vFlip = ((nameTableEntry >> 12) & 1) != 0;
|
||||
bool priority = ((nameTableEntry >> 15) & 1) != 0;
|
||||
int palette = (nameTableEntry >> 13) & 3;
|
||||
|
||||
if (priority && PriorityBuffer[x] >= highPriority) continue;
|
||||
if (!priority && PriorityBuffer[x] >= lowPriority) continue;
|
||||
|
||||
if (vFlip) yOfs = 7 - yOfs;
|
||||
if (hFlip) xOfs = 7 - xOfs;
|
||||
|
||||
int texel = PatternBuffer[(patternNo * 64) + (yOfs * 8) + (xOfs)];
|
||||
int pixel = Palette[(palette * 16) + texel];
|
||||
if (texel != 0)
|
||||
{
|
||||
FrameBuffer[(ScanLine * FrameWidth) + x] = pixel;
|
||||
PriorityBuffer[x] = (byte)(priority ? highPriority : lowPriority);
|
||||
} else {
|
||||
FrameBuffer[(ScanLine * FrameWidth) + x] = bgColor;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -25,7 +25,7 @@ namespace BizHawk.Emulation.Consoles.Sega
|
|||
public bool DisplayEnabled { get { return (Registers[1] & 0x40) != 0; } }
|
||||
public bool VInterruptEnabled { get { return (Registers[1] & 0x20) != 0; } }
|
||||
public bool DmaEnabled { get { return (Registers[1] & 0x10) != 0; } }
|
||||
public bool CellBasedVertScroll { get { return (Registers[11] & 0x08) != 0; } }
|
||||
public bool CellBasedVertScroll { get { return (Registers[11] & 0x04) != 0; } }
|
||||
|
||||
public bool InDisplayPeriod { get { return ScanLine < 224 && DisplayEnabled; } }
|
||||
|
||||
|
|
Loading…
Reference in New Issue