SMS: rework sprite render code, passing several additional VDP tests, and also fixing Fantastic Dizzy.

This commit is contained in:
beirich 2014-03-17 05:05:57 +00:00
parent eeeb71dfe0
commit 227007c07d
4 changed files with 44 additions and 89 deletions

View File

@ -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.

View File

@ -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()

View File

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

View File

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