gen: two-cell vertical scroll mode

This commit is contained in:
beirich 2012-09-22 04:46:44 +00:00
parent b7e8386af1
commit 64a04fd672
2 changed files with 131 additions and 4 deletions

View File

@ -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;
}
}

View File

@ -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; } }