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,9 +24,54 @@
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,
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
};
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,
@ -44,7 +88,10 @@
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
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,15 +35,21 @@ namespace BizHawk
while (reader.EndOfStream == false)
{
string line = reader.ReadLine();
if (line.Trim().Length == 0) continue;
string[] items = line.Split('\t');
var Game = new GameInfo();
Game.CRC32 = Int32.Parse(items[0], NumberStyles.HexNumber);
Game.Name = items[2];
Game.System = items[3];
Game.MetaData = items.Length >= 6 ? items[5] : null;
db[Game.CRC32] = Game;
try
{
if (line.Trim().Length == 0) continue;
string[] items = line.Split('\t');
var Game = new GameInfo();
Game.CRC32 = Int32.Parse(items[0], NumberStyles.HexNumber);
Game.Name = items[2];
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 }
}