SMS: Add "external cart ram" mapper for SG1000, fixes The Castle and Othello. Fortunately, both games are somewhat interesting and playable. SG1000 compat now 100% minus games requiring exotic peripherals

This commit is contained in:
beirich 2014-03-06 04:43:36 +00:00
parent d2d6d00938
commit 7e77c5a116
6 changed files with 82 additions and 1934 deletions

View File

@ -435,6 +435,7 @@
<Compile Include="Consoles\Sega\Saturn\FilePiping.cs" />
<Compile Include="Consoles\Sega\Saturn\LibYabause.cs" />
<Compile Include="Consoles\Sega\Saturn\Yabause.cs" />
<Compile Include="Consoles\Sega\SMS\MemoryMap.ExtRam.cs" />
<Compile Include="Consoles\Sega\SMS\MemoryMap.CodeMasters.cs" />
<Compile Include="Consoles\Sega\SMS\MemoryMap.Sega.cs" />
<Compile Include="Consoles\Sega\SMS\VDP.ModeTMS.cs" />
@ -503,7 +504,6 @@
<Compile Include="Consoles\Sega\Genesis\IO.cs" />
<Compile Include="Consoles\Sega\Genesis\MemoryMap.68000.cs" />
<Compile Include="Consoles\Sega\Genesis\MemoryMap.Z80.cs" />
<Compile Include="Consoles\Sega\SMS\BIOS.cs" />
<Compile Include="Consoles\Sega\SMS\Input.cs" />
<Compile Include="Consoles\Sega\SMS\SMS.cs" />
<Compile Include="Consoles\Sega\SMS\VDP.cs" />

File diff suppressed because it is too large Load Diff

View File

@ -7,7 +7,6 @@
but don't really consider it super-high priority since it works correctly in PAL mode.
* Desert Strike - you can enter the map screen but cannot leave.
* Korean mapper needs to be implemented for SG-1000 games.
Could probably stand to do another pass on SMS emulation after Genesis is working.
@ -18,6 +17,4 @@ Could probably stand to do another pass on SMS emulation after Genesis is workin
======= SG-1000 compatibility checklist =======
The Castle Dies, mapper issue
Othello Doesnt boot
Terebi Oekaki Req Graphic Board peripheral

View File

@ -0,0 +1,41 @@
namespace BizHawk.Emulation.Cores.Sega.MasterSystem
{
public partial class SMS
{
byte[] ExtRam;
int ExtRamMask;
byte ReadMemoryExt(ushort address)
{
byte ret;
if (address < 0x8000)
ret = RomData[address];
else if (address < 0xC000)
ret = ExtRam[address & ExtRamMask];
else
ret = SystemRam[address & RamSizeMask];
CoreComm.MemoryCallbackSystem.CallRead(address);
return ret;
}
void WriteMemoryExt(ushort address, byte value)
{
if (address < 0xC000 && address >= 0x8000)
ExtRam[address & ExtRamMask] = value;
else if (address >= 0xC000)
SystemRam[address & RamSizeMask] = value;
CoreComm.MemoryCallbackSystem.CallWrite((uint)address);
}
void InitExt2kMapper(int size)
{
ExtRam = new byte[size];
ExtRamMask = size - 1;
Cpu.ReadMemory = ReadMemoryExt;
Cpu.WriteMemory = WriteMemoryExt;
}
}
}

View File

@ -130,10 +130,10 @@ namespace BizHawk.Emulation.Cores.Sega.MasterSystem
public DisplayType DisplayType { get; set; }
public bool DeterministicEmulation { get { return true; } }
public SMS(CoreComm comm, GameInfo game, byte[] rom, object Settings, object SyncSettings)
public SMS(CoreComm comm, GameInfo game, byte[] rom, object settings, object syncSettings)
{
this.Settings = (SMSSettings)Settings ?? new SMSSettings();
this.SyncSettings = (SMSSyncSettings)SyncSettings ?? new SMSSyncSettings();
Settings = (SMSSettings)settings ?? new SMSSettings();
SyncSettings = (SMSSyncSettings)syncSettings ?? new SMSSyncSettings();
CoreComm = comm;
@ -151,7 +151,7 @@ namespace BizHawk.Emulation.Cores.Sega.MasterSystem
CoreComm.VsyncDen = 1;
if (game["Japan"]) Region = "Japan";
if (game.NotInDatabase || game["FM"] && this.SyncSettings.EnableFM && !IsGameGear)
if (game.NotInDatabase || game["FM"] && SyncSettings.EnableFM && !IsGameGear)
HasYM2413 = true;
if (Controller == null)
@ -171,12 +171,15 @@ namespace BizHawk.Emulation.Cores.Sega.MasterSystem
ActiveSoundProvider = HasYM2413 ? (ISoundProvider)SoundMixer : PSG;
SystemRam = new byte[0x2000];
if (game["CMMapper"] == false)
InitSegaMapper();
else
InitCodeMastersMapper();
if (this.Settings.ForceStereoSeparation && !IsGameGear)
if (game["CMMapper"])
InitCodeMastersMapper();
else if (game["ExtRam"])
InitExt2kMapper(int.Parse(game.OptionValue("ExtRam")));
else
InitSegaMapper();
if (Settings.ForceStereoSeparation && !IsGameGear)
{
if (game["StereoByte"])
{
@ -185,10 +188,10 @@ namespace BizHawk.Emulation.Cores.Sega.MasterSystem
PSG.StereoPanning = ForceStereoByte;
}
if (this.SyncSettings.AllowOverlock && game["OverclockSafe"])
if (SyncSettings.AllowOverlock && game["OverclockSafe"])
Vdp.IPeriod = 512;
if (this.Settings.SpriteLimit)
if (Settings.SpriteLimit)
Vdp.SpriteLimit = true;
if (game["3D"])
@ -303,6 +306,7 @@ namespace BizHawk.Emulation.Cores.Sega.MasterSystem
SystemRam.SaveAsHex(writer);
writer.WriteLine("Port01 {0:X2}", Port01);
writer.WriteLine("Port02 {0:X2}", Port02);
writer.WriteLine("Port3E {0:X2}", Port3E);
writer.WriteLine("Port3F {0:X2}", Port3F);
int SaveRamLen = Util.SaveRamBytesUsed(SaveRAM);
if (SaveRamLen > 0)
@ -310,6 +314,11 @@ namespace BizHawk.Emulation.Cores.Sega.MasterSystem
writer.Write("SaveRAM ");
SaveRAM.SaveAsHex(writer, SaveRamLen);
}
if (ExtRam != null)
{
writer.Write("ExtRAM ");
ExtRam.SaveAsHex(writer, ExtRam.Length);
}
if (HasYM2413)
{
writer.Write("FMRegs ");
@ -345,6 +354,11 @@ namespace BizHawk.Emulation.Cores.Sega.MasterSystem
for (int i = 0; i < SaveRAM.Length; i++) SaveRAM[i] = 0;
SaveRAM.ReadFromHex(args[1]);
}
else if (args[0] == "ExtRAM")
{
for (int i = 0; i < ExtRam.Length; i++) ExtRam[i] = 0;
ExtRam.ReadFromHex(args[1]);
}
else if (args[0] == "FMRegs")
{
byte[] regs = new byte[YM2413.opll.reg.Length];
@ -356,6 +370,8 @@ namespace BizHawk.Emulation.Cores.Sega.MasterSystem
Port01 = byte.Parse(args[1], NumberStyles.HexNumber);
else if (args[0] == "Port02")
Port02 = byte.Parse(args[1], NumberStyles.HexNumber);
else if (args[0] == "Port3E")
Port3E = byte.Parse(args[1], NumberStyles.HexNumber);
else if (args[0] == "Port3F")
Port3F = byte.Parse(args[1], NumberStyles.HexNumber);
else if (args[0] == "[Z80]")
@ -371,7 +387,10 @@ namespace BizHawk.Emulation.Cores.Sega.MasterSystem
public byte[] SaveStateBinary()
{
var buf = new byte[24806 + 1 + 16384 + 16384];
int buflen = 24808 + 16384 + 16384;
if (ExtRam != null)
buflen += ExtRam.Length;
var buf = new byte[buflen];
var stream = new MemoryStream(buf);
var writer = new BinaryWriter(stream);
SaveStateBinary(writer);
@ -399,7 +418,10 @@ namespace BizHawk.Emulation.Cores.Sega.MasterSystem
writer.Write(SaveRAM);
writer.Write(Port01);
writer.Write(Port02);
writer.Write(Port3E);
writer.Write(Port3F);
if (ExtRam != null)
writer.Write(ExtRam);
writer.Write(YM2413.opll.reg);
}
@ -419,7 +441,10 @@ namespace BizHawk.Emulation.Cores.Sega.MasterSystem
reader.Read(SaveRAM, 0, SaveRAM.Length);
Port01 = reader.ReadByte();
Port02 = reader.ReadByte();
Port3E = reader.ReadByte();
Port3F = reader.ReadByte();
if (ExtRam != null)
reader.Read(ExtRam, 0, ExtRam.Length);
if (HasYM2413)
{
byte[] regs = new byte[YM2413.opll.reg.Length];

View File

@ -1914,7 +1914,7 @@ D8A87095 Bank Panic SG
EA0F2691 Bomb Jack SG
0B4BCA74 Borderline SG
BE7ED0EB C_So! (JP) SG
092F29D6 The Castle SG
092F29D6 The Castle SG ExtRam=8192
D37BDA49 Chack'n Pop SG
5970A12B Champion Baseball SG
62B21E31 Champion Billiards SG
@ -1960,7 +1960,8 @@ BA09A0FD Hyper Sports (Konami no) SG
3B912408 Ninja Princess SG
09196FC5 N-Sub [1988] SG
F4F78B76 Orguss SG
AF4F14BC Othello (JP) SG
AF4F14BC Othello (JP) SG ExtRam=2048
1D1A0CA3 Othello (TW) SG ExtRam=2048
30C52E5E Pacar SG
326587E1 Pachinko (JP) SG
FD7CB50A Pachinko II SG