PAL support for SMS

This commit is contained in:
beirich 2011-01-13 06:10:50 +00:00
parent aa784295d8
commit 3c8236fd32
8 changed files with 94 additions and 51 deletions

View File

@ -1,6 +1,4 @@
using System;
namespace BizHawk.Emulation.CPUs.Z80
namespace BizHawk.Emulation.CPUs.Z80
{
public partial class Z80A
{

View File

@ -36,7 +36,6 @@ namespace BizHawk.Emulation.CPUs.Z80
totalExecutedCycles += 4; pendingCycles -= 4;
} else {
++RegR;
//System.Console.WriteLine(State());
switch (ReadMemory(RegPC.Word++))
{

View File

@ -1,9 +1,6 @@
======= Sega MasterSystem Compatibility Issues =======
* CodeMasters games use a custom mapper and special video modes (both implemented)
+ Cosmic Spacehead and Micro Machines are playable but suffer from a graphic glitch on the
top part of the frame. In my defense, Kega, Cogwheel, and other emulators do the precise
same thing.
+ Fantastic Dizzy crashes shortly after starting a new game. Investigating.
* F16 Fighting Falcon uses old SG-1000 video mode, and doesn't work on a GG/Genesis either.

View File

@ -10,19 +10,18 @@ using BizHawk.Emulation.Sound;
VDP:
+ Double Size Sprites
+ HCounter
+ Possibly work on VDP tests, but they don't really affect games.
- Other video modes / CodeMasters 224 lines / old SG-1000 video modes.
+ Old TMS video modes (SG-1000)
GENERAL:
+ Debug some GameGear game issues.
+ Port 3F emulation (Japanese BIOS)
+ Try to clean up the organization of the source code.
+ SG-1000 support
**********************************************************/
namespace BizHawk.Emulation.Consoles.Sega
{
public enum DisplayType { NTSC, PAL }
public sealed partial class SMS : IEmulator
{
@ -59,7 +58,6 @@ namespace BizHawk.Emulation.Consoles.Sega
private byte Port02 = 0xFF;
private byte Port3F = 0xFF;
private int framesPerSecond;
private int scanlinesPerFrame;
private DisplayType displayType;
@ -69,15 +67,7 @@ namespace BizHawk.Emulation.Consoles.Sega
set
{
displayType = value;
if (displayType == DisplayType.NTSC)
{
framesPerSecond = 60;
scanlinesPerFrame = 262;
} else // PAL
{
framesPerSecond = 50;
scanlinesPerFrame = 313;
}
scanlinesPerFrame = displayType == DisplayType.NTSC ? 262 : 313;
}
}
@ -85,7 +75,6 @@ namespace BizHawk.Emulation.Consoles.Sega
public void Init()
{
DisplayType = DisplayType.NTSC;
if (Controller == null)
Controller = NullController.GetNullController();
@ -93,21 +82,23 @@ namespace BizHawk.Emulation.Consoles.Sega
Cpu.ReadHardware = ReadPort;
Cpu.WriteHardware = WritePort;
Vdp = new VDP(IsGameGear ? VdpMode.GameGear : VdpMode.SMS);
Vdp = new VDP(IsGameGear ? VdpMode.GameGear : VdpMode.SMS, DisplayType);
PSG = new SN76489();
YM2413 = new YM2413();
SoundMixer = new SoundMixer(PSG, YM2413);
if (HasYM2413 && Options.Contains("WhenFMDisablePSG"))
SoundMixer.DisableSource(PSG);
ActiveSoundProvider = PSG;
HardReset();
//PSG.StereoPanning = 0xDA;
}
public void HardReset()
{
Cpu.Reset();
Cpu.RegisterSP = 0xDFF0;
Vdp = new VDP(Vdp.VdpMode);
Vdp = new VDP(Vdp.VdpMode, DisplayType);
PSG.Reset();
YM2413.Reset();
SystemRam = new byte[0x2000];
@ -123,26 +114,17 @@ namespace BizHawk.Emulation.Consoles.Sega
RomData = game.GetRomData();
RomBanks = (byte)(RomData.Length/BankSize);
Options = game.GetOptions();
DisplayType = DisplayType.NTSC;
foreach (string option in Options)
{
var args = option.Split('=');
if (option == "FM") HasYM2413 = true;
else if (args[0] == "IPeriod") IPeriod = int.Parse(args[1]);
else if (args[0] == "Japan") Region = "Japan";
else if (args[0] == "PAL") DisplayType = DisplayType.PAL;
}
Init();
// In Outrun FM mode, when you start a race, the PSG noise channel is left on until a "wheel squeeling"
// sound effect occurs, and this happens again every "extended play" checkpoint. Every emulator I have tested
// does this; if it's a bug, it is a bug that no emulator gets right.
// In any case, it is annoying, so this turns it off.
// My view is that because I believe it to be a game bug (not an emulation bug), this doesn't count as a game-specific hack :)
if (HasYM2413 && game.Name.StartsWith("OutRun", StringComparison.InvariantCultureIgnoreCase))
SoundMixer.DisableSource(PSG);
// TODO: at some point we need a proper Game Library construct with various metadata about emulation hints and options for games and roms.
}
public byte ReadPort(ushort port)

View File

@ -2,8 +2,7 @@
{
public partial class VDP
{
// TODO: PAL video modes, HCounter
// TODO: HCounter
private readonly byte[] VLineCounterTableNTSC192 =
{
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
@ -25,7 +24,6 @@
0xF0, 0xF1, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF7, 0xF8, 0xF9, 0xFA, 0xFB, 0xFC, 0xFD, 0xFE, 0xFF,
};
private readonly byte[] VLineCounterTableNTSC240 =
{
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
@ -46,5 +44,54 @@
0xF0, 0xF1, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF7, 0xF8, 0xF9, 0xFA, 0xFB, 0xFC, 0xFD, 0xFE, 0xFF,
0x00, 0x01, 0x02, 0x03, 0x04, 0x05
};
private readonly byte[] VLineCounterTablePAL192 =
{
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F,
0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, 0x2F,
0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A, 0x3B, 0x3C, 0x3D, 0x3E, 0x3F,
0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F,
0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5A, 0x5B, 0x5C, 0x5D, 0x5E, 0x5F,
0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6A, 0x6B, 0x6C, 0x6D, 0x6E, 0x6F,
0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7A, 0x7B, 0x7C, 0x7D, 0x7E, 0x7F,
0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8A, 0x8B, 0x8C, 0x8D, 0x8E, 0x8F,
0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9A, 0x9B, 0x9C, 0x9D, 0x9E, 0x9F,
0xA0, 0xA1, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6, 0xA7, 0xA8, 0xA9, 0xAA, 0xAB, 0xAC, 0xAD, 0xAE, 0xAF,
0xB0, 0xB1, 0xB2, 0xB3, 0xB4, 0xB5, 0xB6, 0xB7, 0xB8, 0xB9, 0xBA, 0xBB, 0xBC, 0xBD, 0xBE, 0xBF,
0xC0, 0xC1, 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7, 0xC8, 0xC9, 0xCA, 0xCB, 0xCC, 0xCD, 0xCE, 0xCF,
0xD0, 0xD1, 0xD2, 0xD3, 0xD4, 0xD5, 0xD6, 0xD7, 0xD8, 0xD9, 0xDA, 0xDB, 0xDC, 0xDD, 0xDE, 0xDF,
0xE0, 0xE1, 0xE2, 0xE3, 0xE4, 0xE5, 0xE6, 0xE7, 0xE8, 0xE9, 0xEA, 0xEB, 0xEC, 0xED, 0xEE, 0xEF,
0xF0, 0xF1, 0xF2,
0xBA, 0xBB, 0xBC, 0xBD, 0xBE, 0xBF,
0xC0, 0xC1, 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7, 0xC8, 0xC9, 0xCA, 0xCB, 0xCC, 0xCD, 0xCE, 0xCF,
0xD0, 0xD1, 0xD2, 0xD3, 0xD4, 0xD5, 0xD6, 0xD7, 0xD8, 0xD9, 0xDA, 0xDB, 0xDC, 0xDD, 0xDE, 0xDF,
0xE0, 0xE1, 0xE2, 0xE3, 0xE4, 0xE5, 0xE6, 0xE7, 0xE8, 0xE9, 0xEA, 0xEB, 0xEC, 0xED, 0xEE, 0xEF,
0xF0, 0xF1, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF7, 0xF8, 0xF9, 0xFA, 0xFB, 0xFC, 0xFD, 0xFE, 0xFF
};
private readonly byte[] VLineCounterTablePAL240 =
{
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F,
0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, 0x2F,
0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A, 0x3B, 0x3C, 0x3D, 0x3E, 0x3F,
0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F,
0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5A, 0x5B, 0x5C, 0x5D, 0x5E, 0x5F,
0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6A, 0x6B, 0x6C, 0x6D, 0x6E, 0x6F,
0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7A, 0x7B, 0x7C, 0x7D, 0x7E, 0x7F,
0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8A, 0x8B, 0x8C, 0x8D, 0x8E, 0x8F,
0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9A, 0x9B, 0x9C, 0x9D, 0x9E, 0x9F,
0xA0, 0xA1, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6, 0xA7, 0xA8, 0xA9, 0xAA, 0xAB, 0xAC, 0xAD, 0xAE, 0xAF,
0xB0, 0xB1, 0xB2, 0xB3, 0xB4, 0xB5, 0xB6, 0xB7, 0xB8, 0xB9, 0xBA, 0xBB, 0xBC, 0xBD, 0xBE, 0xBF,
0xC0, 0xC1, 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7, 0xC8, 0xC9, 0xCA, 0xCB, 0xCC, 0xCD, 0xCE, 0xCF,
0xD0, 0xD1, 0xD2, 0xD3, 0xD4, 0xD5, 0xD6, 0xD7, 0xD8, 0xD9, 0xDA, 0xDB, 0xDC, 0xDD, 0xDE, 0xDF,
0xE0, 0xE1, 0xE2, 0xE3, 0xE4, 0xE5, 0xE6, 0xE7, 0xE8, 0xE9, 0xEA, 0xEB, 0xEC, 0xED, 0xEE, 0xEF,
0xF0, 0xF1, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF7, 0xF8, 0xF9, 0xFA, 0xFB, 0xFC, 0xFD, 0xFE, 0xFF,
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A,
0xD2, 0xD3, 0xD4, 0xD5, 0xD6, 0xD7, 0xD8, 0xD9, 0xDA, 0xDB, 0xDC, 0xDD, 0xDE, 0xDF,
0xE0, 0xE1, 0xE2, 0xE3, 0xE4, 0xE5, 0xE6, 0xE7, 0xE8, 0xE9, 0xEA, 0xEB, 0xEC, 0xED, 0xEE, 0xEF,
0xF0, 0xF1, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF7, 0xF8, 0xF9, 0xFA, 0xFB, 0xFC, 0xFD, 0xFE, 0xFF
};
}
}

View File

@ -19,7 +19,7 @@ namespace BizHawk.Emulation.Consoles.Sega
}
/// <summary>
/// Emulates the Texas Instruments TMS9918 VDP.
/// Emulates the Texas Instruments TMS9918(A) VDP.
/// </summary>
public sealed partial class VDP : IVideoProvider
{
@ -46,6 +46,8 @@ namespace BizHawk.Emulation.Consoles.Sega
public int[] FrameBuffer = new int[256*192];
public int[] GameGearFrameBuffer = new int[160*144];
private DisplayType DisplayType = DisplayType.NTSC;
// preprocessed state assist stuff.
public int[] Palette = new int[32];
@ -79,11 +81,12 @@ namespace BizHawk.Emulation.Consoles.Sega
private byte[] ScanlinePriorityBuffer = new byte[256];
private byte[] SpriteCollisionBuffer = new byte[256];
public VDP(VdpMode mode)
public VDP(VdpMode mode, DisplayType displayType)
{
this.mode = mode;
if (mode == VdpMode.SMS) CRAM = new byte[32];
if (mode == VdpMode.GameGear) CRAM = new byte[64];
DisplayType = displayType;
}
public byte ReadVram()
@ -105,7 +108,16 @@ namespace BizHawk.Emulation.Consoles.Sega
public byte ReadVLineCounter()
{
return FrameHeight == 240 ? VLineCounterTableNTSC240[ScanLine] : VLineCounterTableNTSC192[ScanLine];
if (DisplayType == DisplayType.NTSC)
{
if (FrameHeight == 240)
return VLineCounterTableNTSC240[ScanLine];
return VLineCounterTableNTSC192[ScanLine];
} else { // PAL
if (FrameHeight == 240)
return VLineCounterTablePAL240[ScanLine];
return VLineCounterTablePAL192[ScanLine];
}
}
public void WriteVdpRegister(byte value)

View File

@ -35,6 +35,8 @@ namespace BizHawk
while (reader.EndOfStream == false)
{
string line = reader.ReadLine();
try
{
if (line.Trim().Length == 0) continue;
string[] items = line.Split('\t');
@ -44,6 +46,10 @@ namespace BizHawk
Game.System = items[3];
Game.MetaData = items.Length >= 6 ? items[5] : null;
db[Game.CRC32] = Game;
} catch (Exception e)
{
Console.WriteLine("Error parsing database entry: "+line);
}
}
}
}

View File

@ -29,4 +29,6 @@ namespace BizHawk
void LoadStateBinary(BinaryReader reader);
byte[] SaveStateBinary();
}
public enum DisplayType { NTSC, PAL }
}