From 227007c07d6c379b288ef2f9eb3bb4bbe013f0df Mon Sep 17 00:00:00 2001 From: beirich Date: Mon, 17 Mar 2014 05:05:57 +0000 Subject: [PATCH] SMS: rework sprite render code, passing several additional VDP tests, and also fixing Fantastic Dizzy. --- .../Consoles/Sega/SMS/Compat.txt | 2 +- .../Consoles/Sega/SMS/VDP.Mode4.cs | 98 ++++++------------- .../Consoles/Sega/SMS/VDP.cs | 23 ++--- output/gamedb/gamedb_sega_gg.txt | 10 +- 4 files changed, 44 insertions(+), 89 deletions(-) diff --git a/BizHawk.Emulation.Cores/Consoles/Sega/SMS/Compat.txt b/BizHawk.Emulation.Cores/Consoles/Sega/SMS/Compat.txt index f4b0ad747b..ff77ae6971 100644 --- a/BizHawk.Emulation.Cores/Consoles/Sega/SMS/Compat.txt +++ b/BizHawk.Emulation.Cores/Consoles/Sega/SMS/Compat.txt @@ -1,6 +1,5 @@ ======= SMS compatibility issues ======= -Fantastic Dizzy (SMS and SMSGG) are freezing on boot. I swear I fixed this before, now it's re-broken. Sigh. Hopefully due to sprite collision thingy? Korean games currently not booting: @@ -24,6 +23,7 @@ Could probably stand to do another pass on SMS emulation after Genesis is workin ======= Game Gear compatibility issues ======= +* Ernie Els Golf has weird gfx corruption. Also in Cogwheel and Kega. Works in MEKA and Regen * Outrun has raster effect on the wrong line. I've been able to modify interrupt code to fix it, but so far, not without breaking other games. diff --git a/BizHawk.Emulation.Cores/Consoles/Sega/SMS/VDP.Mode4.cs b/BizHawk.Emulation.Cores/Consoles/Sega/SMS/VDP.Mode4.cs index 963762513a..b6d79f70e9 100644 --- a/BizHawk.Emulation.Cores/Consoles/Sega/SMS/VDP.Mode4.cs +++ b/BizHawk.Emulation.Cores/Consoles/Sega/SMS/VDP.Mode4.cs @@ -8,6 +8,9 @@ namespace BizHawk.Emulation.Cores.Sega.MasterSystem { internal void RenderBackgroundCurrentLine(bool show) { + if (ScanLine >= FrameHeight) + return; + if (DisplayOn == false) { for (int x = 0; x < 256; x++) @@ -105,7 +108,21 @@ namespace BizHawk.Emulation.Cores.Sega.MasterSystem internal void RenderSpritesCurrentLine(bool show) { - if (DisplayOn == false) return; + bool overflowHappens = true; + bool collisionHappens = true; + bool renderHappens = show; + + if (!DisplayOn) + { + renderHappens = false; + collisionHappens = false; + } + if (ScanLine >= FrameHeight) + { + renderHappens = false; + overflowHappens = false; + } + int SpriteBase = SpriteAttributeTableBase; int SpriteHeight = EnableLargeSprites ? 16 : 8; @@ -118,8 +135,11 @@ namespace BizHawk.Emulation.Cores.Sega.MasterSystem { if (SpritesDrawnThisScanline >= 8) { - StatusByte |= 0x40; // Set Overflow bit - if (SpriteLimit) break; + collisionHappens = false; // technically the VDP stops processing sprite past this so we would never set the collision bit for sprites past this + if (overflowHappens) + StatusByte |= 0x40; // Set Overflow bit + if (SpriteLimit) + renderHappens = false; // should be able to break/return, but to ensure this has no effect on sync we keep processing and disable rendering } int x = VRAM[SpriteBase + 0x80 + (i * 2)]; @@ -145,19 +165,22 @@ namespace BizHawk.Emulation.Cores.Sega.MasterSystem byte color = PatternBuffer[(tileNo * 64) + (ys * 8) + xs]; if (color != 0 && x + xs >= 0) { - if (SpriteCollisionBuffer[x + xs] != 0) - StatusByte |= 0x20; // Set Collision bit - else if (ScanlinePriorityBuffer[x + xs] == 0) + if (collisionHappens && SpriteCollisionBuffer[x + xs] != 0) { - if (show) FrameBuffer[(ys + y) * 256 + x + xs] = Palette[(color + 16)]; - SpriteCollisionBuffer[x + xs] = 1; + StatusByte |= 0x20; // Set Collision bit } + else if (renderHappens && ScanlinePriorityBuffer[x + xs] == 0) + { + FrameBuffer[(ys + y) * 256 + x + xs] = Palette[(color + 16)]; + } + SpriteCollisionBuffer[x + xs] = 1; } } SpritesDrawnThisScanline++; } } + // TODO apply enhancements from 1x renderer to 2x renderer. lets be consistent internal void RenderSpritesCurrentLineDoubleSize(bool show) { if (DisplayOn == false) return; @@ -213,65 +236,6 @@ namespace BizHawk.Emulation.Cores.Sega.MasterSystem } } - 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. internal void RenderBlankingRegions() diff --git a/BizHawk.Emulation.Cores/Consoles/Sega/SMS/VDP.cs b/BizHawk.Emulation.Cores/Consoles/Sega/SMS/VDP.cs index ea7ae471ac..86067678cc 100644 --- a/BizHawk.Emulation.Cores/Consoles/Sega/SMS/VDP.cs +++ b/BizHawk.Emulation.Cores/Consoles/Sega/SMS/VDP.cs @@ -370,37 +370,28 @@ namespace BizHawk.Emulation.Cores.Sega.MasterSystem internal void RenderCurrentScanline(bool render) { - if (ScanLine >= FrameHeight) - return; - + // only mode 4 supports frameskip. deal with it if (TmsMode == 4) { - if (render == false) - { - ProcessSpriteCollisionForFrameskip(); - return; - } - - RenderBackgroundCurrentLine(Sms.Settings.DispBG); + if (render) + RenderBackgroundCurrentLine(Sms.Settings.DispBG); if (EnableDoubledSprites) - RenderSpritesCurrentLineDoubleSize(Sms.Settings.DispOBJ); + RenderSpritesCurrentLineDoubleSize(Sms.Settings.DispOBJ & render); else - RenderSpritesCurrentLine(Sms.Settings.DispOBJ); + RenderSpritesCurrentLine(Sms.Settings.DispOBJ & render); } else if (TmsMode == 2) { - if (render == false) + if (ScanLine >= FrameHeight) // TODO fix this other way return; - RenderBackgroundM2(Sms.Settings.DispBG); RenderTmsSprites(Sms.Settings.DispOBJ); } else if (TmsMode == 0) { - if (render == false) + if (ScanLine >= FrameHeight) // TODO fix this other way return; - RenderBackgroundM0(Sms.Settings.DispBG); RenderTmsSprites(Sms.Settings.DispOBJ); } diff --git a/output/gamedb/gamedb_sega_gg.txt b/output/gamedb/gamedb_sega_gg.txt index 6c46d1c41a..3c1b04afda 100644 --- a/output/gamedb/gamedb_sega_gg.txt +++ b/output/gamedb/gamedb_sega_gg.txt @@ -72,7 +72,7 @@ DBEDE5C20828E3D251B05356D9176C79 Coca-Cola Kid (J) GG Japan 36B33D28235B4C9439AB0F62AB1C97C4 Columns (J) (En) (Rev 1) GG Japan 7F55C7E4696A9AD316E57C3F14A77F39 Cool Spot (U) GG USA 1EE49B56F0C349CC63EB0A60602F160E Cool Spot (E) GG Europe -0AD508B2A076990B49AE2BCDA0F1E9E7 Cosmic Spacehead (E) GG Europe +0AD508B2A076990B49AE2BCDA0F1E9E7 Cosmic Spacehead (E) GG CMMapper Europe 41EEC91E3C4E546D93053F2C234517A6 Crayon Shin-chan - Taiketsu! Kantam Panic!! (J) GG Japan 0336BD86C59096A6B9A069EC0DDD94B2 Crazy Faces (Unknown) (Proto) GG 35D3FC09FCF22E35DB4BAC8CEE9967F3 Crystal Warriors (UE) GG USA;Europe @@ -111,7 +111,7 @@ E35A0B3D9A4A3BB6B2E72FAB5A8C1712 Earthworm Jim (E) GG Europe E4E654AA1730565220120844DAD6B444 Ecco the Dolphin II (J) GG Japan CCD970B22303887734FAFB8E45B1E43F Ecco the Dolphin (UE) GG USA;Europe A506FC04C7A0DFAF37423FF0A38AEB2E Ecco the Dolphin (J) GG Japan -E97C20B86EA73248CC7AED602D46C3A4 Ernie Els Golf (E) (En,Fr,De,Es,It) GG Europe +E97C20B86EA73248CC7AED602D46C3A4 Ernie Els Golf (E) (En,Fr,De,Es,It) GG Sports;Golf CMMapper;SRAM=8192 Europe C58D6291DA8A4919328B8F42BE8640A7 Eternal Legend - Eien no Densetsu (J) GG Japan 4E63ABB36BE8D86B94B34846B16D9FA3 Evander Holyfield's 'Real Deal' Boxing (UE) GG USA;Europe 309ABE6822C52DF971856912C77A57CC F1 - World Championship Edition (E) GG Europe @@ -241,8 +241,8 @@ AAB2B02C831252F6A2EB369DF39F7C73 Megami Tensei Gaiden - Last Bible S (J) GG J AB54600E28D866558323381F74FE2749 Megami Tensei Gaiden - Last Bible (J) GG Japan D3A436B1FB64FD6295A30CC12BA6BED9 Mick & Mack as the Global Gladiators (UE) GG USA;Europe 66E41E9F596EEEC8127D12426F928791 Mickey's Ultimate Challenge (U) GG Disney USA -4ED897E5E2BD76CBE92CBBBD76AC8817 Micro Machines 2 - Turbo Tournament (E) GG Europe -C08B950E8AB836A737B07374F8235955 Micro Machines (E) GG Europe +4ED897E5E2BD76CBE92CBBBD76AC8817 Micro Machines 2 - Turbo Tournament (E) GG Racing CMMapper;GGLink Europe +C08B950E8AB836A737B07374F8235955 Micro Machines (E) GG Racind CMMapper;GGLink Europe F9ACD8F01CAA8D11150A53B37B435AA2 Mighty Morphin Power Rangers - The Movie (UE) GG USA;Europe 7FCB774AA2B207CF16D2DDFE618351C0 Mighty Morphin Power Rangers (UE) GG USA;Europe 465EAB01AB08A68A37C9C240DCA8A36C MLBPA Baseball (U) GG USA @@ -333,7 +333,7 @@ AE7121E6CE2831E1B700515B6060ACAF RoboCop 3 (W) GG World D19DC027E7AFF95A1ABFD0DB074E1CF2 RoboCop versus The Terminator (UE) GG USA;Europe C05B51EA07C8017A6D12BADAEA9DAF29 Royal Stone - Hirakareshi Toki no Tobira (J) GG Japan 5A43E20C816435A080A601B0DDACAA44 Ryuukyuu (J) GG Japan -D369DCC7C7317B88D401CD7DD54AD951 S.S. Lucifer - Man Overboard! (E) GG Europe +D369DCC7C7317B88D401CD7DD54AD951 S.S. Lucifer - Man Overboard! (E) GG CMMapper Europe 4898DB4B63C7024842E748FB81C95A55 Samurai Shodown (U) GG USA 71B53A4577065E11453928774A7B64B0 Samurai Spirits (J) GG Japan A469A38397A5D530313BEB549182558D Scratch Golf (U) GG USA