From 023fb0897adabb76d5431a7a0fc97e453e8491ea Mon Sep 17 00:00:00 2001 From: beirich Date: Thu, 24 Feb 2011 04:39:52 +0000 Subject: [PATCH] [SMS] Frameskip actually skip frames --- .../Consoles/Sega/SMS/VDP.Mode4.cs | 59 +++++++++++++++++++ BizHawk.Emulation/Consoles/Sega/SMS/VDP.cs | 21 ++++++- 2 files changed, 77 insertions(+), 3 deletions(-) diff --git a/BizHawk.Emulation/Consoles/Sega/SMS/VDP.Mode4.cs b/BizHawk.Emulation/Consoles/Sega/SMS/VDP.Mode4.cs index be42303c74..d3dd77cfb1 100644 --- a/BizHawk.Emulation/Consoles/Sega/SMS/VDP.Mode4.cs +++ b/BizHawk.Emulation/Consoles/Sega/SMS/VDP.Mode4.cs @@ -224,6 +224,65 @@ namespace BizHawk.Emulation.Consoles.Sega } } + internal void ProcessSpriteCollisionForFrameskip() + { + if (DisplayOn == false) return; + int SpriteBase = SpriteAttributeTableBase; + int SpriteHeight = EnableLargeSprites ? 16 : 8; + + // Clear the sprite collision buffer for this scanline + Array.Clear(SpriteCollisionBuffer, 0, 256); + + // 208 is a special terminator sprite (in 192-line mode). Lets find it... + int TerminalSprite = 64; + if (FrameHeight == 192) + for (int i = 0; i < 64; i++) + { + if (VRAM[SpriteBase + i] == 208) + { + TerminalSprite = i; + break; + } + } + + // Loop through these sprites and render the current scanline + int SpritesDrawnThisScanline = 0; + for (int i = TerminalSprite - 1; i >= 0; i--) + { + if (SpritesDrawnThisScanline >= 8) + StatusByte |= 0x40; // Set Overflow bit + + int x = VRAM[SpriteBase + 0x80 + (i * 2)]; + if (ShiftSpritesLeft8Pixels) + x -= 8; + + int y = VRAM[SpriteBase + i] + 1; + if (y >= (EnableLargeSprites ? 240 : 248)) y -= 256; + + if (y + SpriteHeight <= ScanLine || y > ScanLine) + continue; + + int tileNo = VRAM[SpriteBase + 0x80 + (i * 2) + 1]; + if (EnableLargeSprites) + tileNo &= 0xFE; + tileNo += SpriteTileBase; + + int ys = ScanLine - y; + + for (int xs = 0; xs < 8 && x + xs < 256; xs++) + { + byte color = PatternBuffer[(tileNo * 64) + (ys * 8) + xs]; + if (color != 0 && x + xs >= 0) + { + if (SpriteCollisionBuffer[x + xs] != 0) + StatusByte |= 0x20; // Set Collision bit + SpriteCollisionBuffer[x + xs] = 1; + } + } + SpritesDrawnThisScanline++; + } + } + /// /// Performs render buffer blanking. This includes the left-column blanking as well as Game Gear blanking if requested. /// Should be called at the end of the frame. diff --git a/BizHawk.Emulation/Consoles/Sega/SMS/VDP.cs b/BizHawk.Emulation/Consoles/Sega/SMS/VDP.cs index 0b511d7890..e65f9ed194 100644 --- a/BizHawk.Emulation/Consoles/Sega/SMS/VDP.cs +++ b/BizHawk.Emulation/Consoles/Sega/SMS/VDP.cs @@ -364,17 +364,32 @@ namespace BizHawk.Emulation.Consoles.Sega if (TmsMode == 4) { - // TODO: make frameskip actually skip rendering + if (render == false) + { + ProcessSpriteCollisionForFrameskip(); + return; + } + RenderBackgroundCurrentLine(); if (EnableDoubledSprites) RenderSpritesCurrentLineDoubleSize(); else RenderSpritesCurrentLine(); - } else if (TmsMode == 2) { + } + else if (TmsMode == 2) + { + if (render == false) + return; + RenderBackgroundM2(); RenderTmsSprites(); - } else if (TmsMode == 0) { + } + else if (TmsMode == 0) + { + if (render == false) + return; + RenderBackgroundM0(); RenderTmsSprites(); }