From 3c019b9e963219b9fcfe14d3f614f1a677a8e946 Mon Sep 17 00:00:00 2001 From: beirich Date: Wed, 19 Jan 2011 07:06:14 +0000 Subject: [PATCH] SG-1000 progress (try doki doki penguin land) --- .../Consoles/Sega/SMS/VDP.Mode4.cs | 12 +-- .../Consoles/Sega/SMS/VDP.ModeTMS.cs | 91 ++++++++++++++++++- BizHawk.Emulation/Consoles/Sega/SMS/VDP.cs | 12 ++- BizHawk.MultiClient/RomGame.cs | 8 ++ 4 files changed, 112 insertions(+), 11 deletions(-) diff --git a/BizHawk.Emulation/Consoles/Sega/SMS/VDP.Mode4.cs b/BizHawk.Emulation/Consoles/Sega/SMS/VDP.Mode4.cs index 81568c0acb..21d6386834 100644 --- a/BizHawk.Emulation/Consoles/Sega/SMS/VDP.Mode4.cs +++ b/BizHawk.Emulation/Consoles/Sega/SMS/VDP.Mode4.cs @@ -107,7 +107,7 @@ namespace BizHawk.Emulation.Consoles.Sega { if (DisplayOn == false) return; int SpriteBase = SpriteAttributeTableBase; - int SpriteHeight = Enable8x16Sprites ? 16 : 8; + int SpriteHeight = EnableLargeSprites ? 16 : 8; // Clear the sprite collision buffer for this scanline Array.Clear(SpriteCollisionBuffer, 0, 256); @@ -136,13 +136,13 @@ namespace BizHawk.Emulation.Consoles.Sega x -= 8; int y = VRAM[SpriteBase + i] + 1; - if (y >= (Enable8x16Sprites ? 240 : 248)) y -= 256; + if (y >= (EnableLargeSprites ? 240 : 248)) y -= 256; if (y + SpriteHeight <= ScanLine || y > ScanLine) continue; int tileNo = VRAM[SpriteBase + 0x80 + (i * 2) + 1]; - if (Enable8x16Sprites) + if (EnableLargeSprites) tileNo &= 0xFE; tileNo += SpriteTileBase; @@ -167,7 +167,7 @@ namespace BizHawk.Emulation.Consoles.Sega { if (DisplayOn == false) return; int SpriteBase = SpriteAttributeTableBase; - int SpriteHeight = Enable8x16Sprites ? 16 : 8; + int SpriteHeight = EnableLargeSprites ? 16 : 8; // Clear the sprite collision buffer for this scanline Array.Clear(SpriteCollisionBuffer, 0, 256); @@ -196,13 +196,13 @@ namespace BizHawk.Emulation.Consoles.Sega x -= 8; int y = VRAM[SpriteBase + i] + 1; - if (y >= (Enable8x16Sprites ? 240 : 248)) y -= 256; + if (y >= (EnableLargeSprites ? 240 : 248)) y -= 256; if (y + (SpriteHeight*2) <= ScanLine || y > ScanLine) continue; int tileNo = VRAM[SpriteBase + 0x80 + (i * 2) + 1]; - if (Enable8x16Sprites) + if (EnableLargeSprites) tileNo &= 0xFE; tileNo += SpriteTileBase; diff --git a/BizHawk.Emulation/Consoles/Sega/SMS/VDP.ModeTMS.cs b/BizHawk.Emulation/Consoles/Sega/SMS/VDP.ModeTMS.cs index 301ac0d3a5..3f3197dc9e 100644 --- a/BizHawk.Emulation/Consoles/Sega/SMS/VDP.ModeTMS.cs +++ b/BizHawk.Emulation/Consoles/Sega/SMS/VDP.ModeTMS.cs @@ -1,5 +1,7 @@ // Contains rendering functions for legacy TMS9918 modes. +using System; + namespace BizHawk.Emulation.Consoles.Sega { public partial class VDP @@ -29,8 +31,8 @@ namespace BizHawk.Emulation.Consoles.Sega int yc = ScanLine/8; int yofs = ScanLine%8; int FrameBufferOffset = ScanLine*256; - int PatternNameOffset = mystery_pn + (yc*32); - + int PatternNameOffset = TmsPatternNameTableBase + (yc*32); + for (int xc=0; xc<32; xc++) { int pn = VRAM[PatternNameOffset++]; @@ -49,5 +51,90 @@ namespace BizHawk.Emulation.Consoles.Sega FrameBuffer[FrameBufferOffset++] = ((pv & 0x01) > 0) ? fgColor : bgColor; } } + + private void RenderBackgroundM2() + { + int yrow = ScanLine/8; + int yofs = ScanLine%8; + int FrameBufferOffset = ScanLine*256; + int PatternNameOffset = TmsPatternNameTableBase + (yrow*32); + int PatternGeneratorOffset = (((Registers[4] & 4) << 11) & 0x2000);// +((yrow / 8) * 0x100); + int ColorOffset = (ColorTableBase & 0x2000);// +((yrow / 8) * 0x100); + + for (int xc=0; xc<32; xc++) + { + int pn = VRAM[PatternNameOffset++]; + int pv = VRAM[PatternGeneratorOffset + (pn * 8) + yofs]; + int colorEntry = VRAM[ColorOffset + (pn * 8) + yofs]; + int fgColor = PaletteTMS9918[(colorEntry >> 4 & 0x0F)]; + int bgColor = PaletteTMS9918[(colorEntry & 0x0F)]; + + FrameBuffer[FrameBufferOffset++] = ((pv & 0x80) > 0) ? fgColor : bgColor; + FrameBuffer[FrameBufferOffset++] = ((pv & 0x40) > 0) ? fgColor : bgColor; + FrameBuffer[FrameBufferOffset++] = ((pv & 0x20) > 0) ? fgColor : bgColor; + FrameBuffer[FrameBufferOffset++] = ((pv & 0x10) > 0) ? fgColor : bgColor; + FrameBuffer[FrameBufferOffset++] = ((pv & 0x08) > 0) ? fgColor : bgColor; + FrameBuffer[FrameBufferOffset++] = ((pv & 0x04) > 0) ? fgColor : bgColor; + FrameBuffer[FrameBufferOffset++] = ((pv & 0x02) > 0) ? fgColor : bgColor; + FrameBuffer[FrameBufferOffset++] = ((pv & 0x01) > 0) ? fgColor : bgColor; + } + } + + private void RenderTmsSprites() + { + Array.Clear(ScanlinePriorityBuffer, 0, 256); + Array.Clear(SpriteCollisionBuffer, 0, 256); + + bool Double = EnableDoubledSprites; + bool LargeSprites = EnableLargeSprites; + + int SpriteSize = 8; + if (LargeSprites) SpriteSize *= 2; + if (Double) SpriteSize *= 2; + int OneCellSize = Double ? 16 : 8; + + int NumSpritesOnScanline = 0; + for (int i=0; i<32; i++) + { + int SpriteBase = TmsSpriteAttributeBase + (i*4); + int y = VRAM[SpriteBase++]; + int x = VRAM[SpriteBase++]; + int Pattern = VRAM[SpriteBase++]; + int Color = VRAM[SpriteBase]; + + if (y == 208) break; // terminator sprite + if (y > 224) y -= 256; // sprite Y wrap + y++; // inexplicably, sprites start on Y+1 + if (y > ScanLine || y + SpriteSize <= ScanLine) continue; // sprite is not on this scanline + if ((Color & 0x80) > 0) x -= 32; // Early Clock adjustment + + if (++NumSpritesOnScanline == 5) + { + StatusByte |= (byte) i; // set 5th sprite index + StatusByte |= 0x40; // set overflow bit + break; + } + + if (LargeSprites) Pattern &= 0xFC; // 16x16 sprites forced to 4-byte alignment + int SpriteLine = ScanLine - y; + if (Double) SpriteLine /= 2; + + byte pv = VRAM[SpritePatternGeneratorBase + (Pattern*8) + SpriteLine]; + + for (int xp = 0; xp < SpriteSize && x + xp < 256; xp++) + { + if (x+xp < 0) continue; + if (LargeSprites && xp == OneCellSize) + pv = VRAM[SpritePatternGeneratorBase + (Pattern * 8) + SpriteLine + 16]; + + if ((pv & (1 << (7 - (xp & 7)))) > 0) + { + if (Color != 0) + FrameBuffer[(ScanLine * 256) + x + xp] = PaletteTMS9918[Color & 0x0F]; + } + + } + } + } } } \ No newline at end of file diff --git a/BizHawk.Emulation/Consoles/Sega/SMS/VDP.cs b/BizHawk.Emulation/Consoles/Sega/SMS/VDP.cs index 9ab6d4a93e..3f47063ffb 100644 --- a/BizHawk.Emulation/Consoles/Sega/SMS/VDP.cs +++ b/BizHawk.Emulation/Consoles/Sega/SMS/VDP.cs @@ -48,7 +48,7 @@ namespace BizHawk.Emulation.Consoles.Sega public bool HorizScrollLock { get { return (Registers[0] & 64) > 0; } } public bool VerticalScrollLock { get { return (Registers[0] & 128) > 0; } } public bool EnableDoubledSprites { get { return (Registers[1] & 1) > 0; } } - public bool Enable8x16Sprites { get { return (Registers[1] & 2) > 0; } } + public bool EnableLargeSprites { get { return (Registers[1] & 2) > 0; } } public bool EnableFrameInterrupts { get { return (Registers[1] & 32) > 0; } } public bool DisplayOn { get { return (Registers[1] & 64) > 0; } } public int SpriteAttributeTableBase { get { return ((Registers[5] >> 1) << 8) & 0x3FFF; } } @@ -59,7 +59,8 @@ namespace BizHawk.Emulation.Consoles.Sega private int ColorTableBase; private int PatternGeneratorBase; private int SpritePatternGeneratorBase; - private int mystery_pn; + private int TmsPatternNameTableBase; + private int TmsSpriteAttributeBase; // preprocessed state assist stuff. public int[] Palette = new int[32]; @@ -288,7 +289,7 @@ namespace BizHawk.Emulation.Consoles.Sega break; case 2: // Name Table Base Address NameTableBase = CalcNameTableBase(); - mystery_pn = (Registers[2] << 10) & 0x3C00; + TmsPatternNameTableBase = (Registers[2] << 10) & 0x3C00; break; case 3: // Color Table Base Address ColorTableBase = (Registers[3] << 6) & 0x3FC0; @@ -298,6 +299,7 @@ namespace BizHawk.Emulation.Consoles.Sega break; case 5: // Sprite Attribute Table Base Address // ??? should I move from my property to precalculated? + TmsSpriteAttributeBase = (Registers[5] << 7) & 0x3F80; break; case 6: // Sprite Pattern Generator Base Adderss SpritePatternGeneratorBase = (Registers[6] << 11) & 0x3800; @@ -369,6 +371,7 @@ namespace BizHawk.Emulation.Consoles.Sega RenderBlankingRegions(); } } + internal void RenderCurrentScanline(bool render) { if (ScanLine >= FrameHeight) @@ -383,6 +386,9 @@ namespace BizHawk.Emulation.Consoles.Sega RenderSpritesCurrentLineDoubleSize(); else RenderSpritesCurrentLine(); + } else if (TmsMode == 2) { + RenderBackgroundM2(); + RenderTmsSprites(); } else if (TmsMode == 0) { RenderBackgroundM0(); } diff --git a/BizHawk.MultiClient/RomGame.cs b/BizHawk.MultiClient/RomGame.cs index c8d69bf491..be905003da 100644 --- a/BizHawk.MultiClient/RomGame.cs +++ b/BizHawk.MultiClient/RomGame.cs @@ -80,6 +80,8 @@ namespace BizHawk.MultiClient { case "SMS": return "SMS/SaveRAM/" + Name + ".SaveRAM"; case "GG": return "Game Gear/SaveRAM/" + Name + ".SaveRAM"; + case "SG": return "SG-1000/SaveRAM/" + Name + ".SaveRAM"; + case "SGX": return "TurboGrafx/SaveRAM/" + Name + ".SaveRAM"; case "PCE": return "TurboGrafx/SaveRAM/" + Name + ".SaveRAM"; case "GB": return "Gameboy/SaveRAM/" + Name + ".SaveRAM"; case "GEN": return "Genesis/SaveRAM/" + Name + ".SaveRAM"; @@ -97,7 +99,9 @@ namespace BizHawk.MultiClient { case "SMS": return "SMS/State/" + Name; case "GG": return "Game Gear/State/" + Name; + case "SG": return "SG-1000/State/" + Name; case "PCE": return "TurboGrafx/State/" + Name; + case "SGX": return "TurboGrafx/State/" + Name; case "GB": return "Gameboy/State/" + Name; case "GEN": return "Genesis/State/" + Name; case "NES": return "NES/State/" + Name; @@ -115,7 +119,9 @@ namespace BizHawk.MultiClient { case "SMS": return "SMS/Movie/" + Name; case "GG": return "Game Gear/Movie/" + Name; + case "SG": return "SG-1000/Movie/" + Name; case "PCE": return "TurboGrafx/Movie/" + Name; + case "SGX": return "TurboGrafx/Movie/" + Name; case "GB": return "Gameboy/Movie/" + Name; case "GEN": return "Genesis/Movie/" + Name; case "NES": return "NES/Movie/" + Name; @@ -132,7 +138,9 @@ namespace BizHawk.MultiClient { case "SMS": return "SMS/Screenshot/" + Name; case "GG": return "Game Gear/Screenshot/" + Name; + case "SG": return "SG-1000/Screenshot/" + Name; case "PCE": return "TurboGrafx/Screenshot/" + Name; + case "SGX": return "TurboGrafx/Screenshot/" + Name; case "GB": return "Gameboy/Screenshot/" + Name; case "GEN": return "Genesis/Screenshot/" + Name; case "NES": return "NES/Screenshot/" + Name;