some implementations necessary for the gameboy controller
This commit is contained in:
parent
6c6929b625
commit
52215061aa
|
@ -6,6 +6,11 @@ namespace BizHawk.Emulation.Consoles.Gameboy
|
|||
{
|
||||
public partial class Gameboy : IEmulator
|
||||
{
|
||||
|
||||
private int _lagcount = 0;
|
||||
private bool lagged = true;
|
||||
private bool islag = false;
|
||||
|
||||
public interface IDebuggerAPI
|
||||
{
|
||||
void DoEvents();
|
||||
|
@ -326,8 +331,28 @@ namespace BizHawk.Emulation.Consoles.Gameboy
|
|||
Registers = new TRegisters(this);
|
||||
|
||||
Registers.LCDC.Poke(0x91);
|
||||
SetupMemoryDomains();
|
||||
}
|
||||
|
||||
private IList<MemoryDomain> memoryDomains;
|
||||
|
||||
private void SetupMemoryDomains()
|
||||
{
|
||||
//TODO: WRAM (0 & 1? or both?)
|
||||
//TODO: VRAM
|
||||
//TODO: OAM
|
||||
//TODO: HRAM
|
||||
var domains = new List<MemoryDomain>(1);
|
||||
var SystemBusDomain = new MemoryDomain("System Bus", 0x10000, Endian.Little,
|
||||
addr => Cpu.ReadMemory((ushort)addr),
|
||||
(addr, value) => Cpu.WriteMemory((ushort)addr, value));
|
||||
domains.Add(SystemBusDomain);
|
||||
memoryDomains = domains.AsReadOnly();
|
||||
}
|
||||
|
||||
public IList<MemoryDomain> MemoryDomains { get { return memoryDomains; } }
|
||||
public MemoryDomain MainMemory { get { return memoryDomains[0]; } }
|
||||
|
||||
public byte ReadMemoryBios(ushort addr)
|
||||
{
|
||||
//we speculate that the bios unmaps itself after the first read of 0x100
|
||||
|
@ -651,9 +676,18 @@ namespace BizHawk.Emulation.Consoles.Gameboy
|
|||
|
||||
public void FrameAdvance(bool render)
|
||||
{
|
||||
lagged = true;
|
||||
Controller.UpdateControls(Frame++);
|
||||
Cpu.ExecuteCycles(4096);
|
||||
}
|
||||
|
||||
if (lagged)
|
||||
{
|
||||
_lagcount++;
|
||||
islag = true;
|
||||
}
|
||||
else
|
||||
islag = false;
|
||||
}
|
||||
|
||||
public CoreInputComm CoreInputComm { get; set; }
|
||||
public CoreOutputComm CoreOutputComm { get; private set; }
|
||||
|
@ -668,14 +702,10 @@ namespace BizHawk.Emulation.Consoles.Gameboy
|
|||
get { return new NullEmulator(); }
|
||||
}
|
||||
|
||||
public int Frame
|
||||
{
|
||||
get { return 0; }
|
||||
//get { throw new NotImplementedException(); }
|
||||
}
|
||||
public int Frame { get; set; }
|
||||
|
||||
public int LagCount { get { return -1; } set { return; } } //TODO: implement
|
||||
public bool IsLagFrame { get { return false; } } //TODO: implement
|
||||
public int LagCount { get { return _lagcount; } set { _lagcount = value; } }
|
||||
public bool IsLagFrame { get { return islag; } }
|
||||
|
||||
public byte[] SaveRam
|
||||
{
|
||||
|
@ -869,9 +899,6 @@ namespace BizHawk.Emulation.Consoles.Gameboy
|
|||
public bool DeterministicEmulation { get; set; }
|
||||
public string SystemId { get { return "GB"; } }
|
||||
|
||||
public IList<MemoryDomain> MemoryDomains { get { throw new NotImplementedException(); } }
|
||||
public MemoryDomain MainMemory { get { throw new NotImplementedException(); } }
|
||||
|
||||
public void Dispose() { }
|
||||
}
|
||||
}
|
|
@ -16,370 +16,370 @@ using BizHawk.Emulation.Sound;
|
|||
|
||||
namespace BizHawk.Emulation.Consoles.Sega
|
||||
{
|
||||
public sealed partial class SMS : IEmulator
|
||||
{
|
||||
// Constants
|
||||
public const int BankSize = 16384;
|
||||
public sealed partial class SMS : IEmulator
|
||||
{
|
||||
// Constants
|
||||
public const int BankSize = 16384;
|
||||
|
||||
// ROM
|
||||
public byte[] RomData;
|
||||
public byte RomBank0, RomBank1, RomBank2;
|
||||
public byte RomBanks;
|
||||
public IList<string> Options;
|
||||
// ROM
|
||||
public byte[] RomData;
|
||||
public byte RomBank0, RomBank1, RomBank2;
|
||||
public byte RomBanks;
|
||||
public IList<string> Options;
|
||||
|
||||
// SaveRAM
|
||||
public byte[] SaveRAM = new byte[BankSize*2];
|
||||
public byte SaveRamBank;
|
||||
// SaveRAM
|
||||
public byte[] SaveRAM = new byte[BankSize * 2];
|
||||
public byte SaveRamBank;
|
||||
|
||||
public byte[] SaveRam { get { return SaveRAM; } }
|
||||
public bool SaveRamModified { get; set; }
|
||||
public byte[] SaveRam { get { return SaveRAM; } }
|
||||
public bool SaveRamModified { get; set; }
|
||||
|
||||
// Machine resources
|
||||
public Z80A Cpu;
|
||||
public byte[] SystemRam;
|
||||
public VDP Vdp;
|
||||
public SN76489 PSG;
|
||||
public YM2413 YM2413;
|
||||
public SoundMixer SoundMixer;
|
||||
public bool IsGameGear = false;
|
||||
public bool HasYM2413 = false;
|
||||
// Machine resources
|
||||
public Z80A Cpu;
|
||||
public byte[] SystemRam;
|
||||
public VDP Vdp;
|
||||
public SN76489 PSG;
|
||||
public YM2413 YM2413;
|
||||
public SoundMixer SoundMixer;
|
||||
public bool IsGameGear = false;
|
||||
public bool HasYM2413 = false;
|
||||
|
||||
private int _lagcount = 0;
|
||||
private bool lagged = true;
|
||||
private bool islag = false;
|
||||
public int Frame { get; set; }
|
||||
public int LagCount { get { return _lagcount; } set { _lagcount = value; } }
|
||||
public bool IsLagFrame { get { return islag; } }
|
||||
private byte Port01 = 0xFF;
|
||||
private byte Port02 = 0xFF;
|
||||
private byte Port3E = 0xAF;
|
||||
private byte Port3F = 0xFF;
|
||||
private int _lagcount = 0;
|
||||
private bool lagged = true;
|
||||
private bool islag = false;
|
||||
public int Frame { get; set; }
|
||||
public int LagCount { get { return _lagcount; } set { _lagcount = value; } }
|
||||
public bool IsLagFrame { get { return islag; } }
|
||||
private byte Port01 = 0xFF;
|
||||
private byte Port02 = 0xFF;
|
||||
private byte Port3E = 0xAF;
|
||||
private byte Port3F = 0xFF;
|
||||
|
||||
public DisplayType DisplayType { get; set; }
|
||||
public bool DeterministicEmulation { get; set; }
|
||||
public DisplayType DisplayType { get; set; }
|
||||
public bool DeterministicEmulation { get; set; }
|
||||
|
||||
public SMS()
|
||||
{
|
||||
CoreOutputComm = new CoreOutputComm();
|
||||
}
|
||||
|
||||
public void Init()
|
||||
{
|
||||
if (Controller == null)
|
||||
Controller = NullController.GetNullController();
|
||||
public void Init()
|
||||
{
|
||||
if (Controller == null)
|
||||
Controller = NullController.GetNullController();
|
||||
|
||||
Cpu = new Z80A();
|
||||
Cpu.RegisterSP = 0xDFF0;
|
||||
Cpu.ReadHardware = ReadPort;
|
||||
Cpu.WriteHardware = WritePort;
|
||||
Cpu = new Z80A();
|
||||
Cpu.RegisterSP = 0xDFF0;
|
||||
Cpu.ReadHardware = ReadPort;
|
||||
Cpu.WriteHardware = WritePort;
|
||||
|
||||
Vdp = new VDP(Cpu, IsGameGear ? VdpMode.GameGear : VdpMode.SMS, DisplayType);
|
||||
PSG = new SN76489();
|
||||
YM2413 = new YM2413();
|
||||
SoundMixer = new SoundMixer(YM2413, PSG);
|
||||
if (HasYM2413 && Options.Contains("WhenFMDisablePSG"))
|
||||
SoundMixer.DisableSource(PSG);
|
||||
ActiveSoundProvider = HasYM2413 ? (ISoundProvider) SoundMixer : PSG;
|
||||
Vdp = new VDP(Cpu, IsGameGear ? VdpMode.GameGear : VdpMode.SMS, DisplayType);
|
||||
PSG = new SN76489();
|
||||
YM2413 = new YM2413();
|
||||
SoundMixer = new SoundMixer(YM2413, PSG);
|
||||
if (HasYM2413 && Options.Contains("WhenFMDisablePSG"))
|
||||
SoundMixer.DisableSource(PSG);
|
||||
ActiveSoundProvider = HasYM2413 ? (ISoundProvider)SoundMixer : PSG;
|
||||
|
||||
SystemRam = new byte[0x2000];
|
||||
if (Options.Contains("CMMapper") == false)
|
||||
InitSegaMapper();
|
||||
else
|
||||
InitCodeMastersMapper();
|
||||
SystemRam = new byte[0x2000];
|
||||
if (Options.Contains("CMMapper") == false)
|
||||
InitSegaMapper();
|
||||
else
|
||||
InitCodeMastersMapper();
|
||||
|
||||
if (Options.Contains("ForceStereo"))
|
||||
{
|
||||
byte stereoByte = 0xAD;
|
||||
if (Options.ContainsStartsWith("StereoByte"))
|
||||
{
|
||||
stereoByte = byte.Parse(Options.GetOptionValue("StereoByte"));
|
||||
}
|
||||
PSG.StereoPanning = stereoByte;
|
||||
}
|
||||
if (Options.Contains("ForceStereo"))
|
||||
{
|
||||
byte stereoByte = 0xAD;
|
||||
if (Options.ContainsStartsWith("StereoByte"))
|
||||
{
|
||||
stereoByte = byte.Parse(Options.GetOptionValue("StereoByte"));
|
||||
}
|
||||
PSG.StereoPanning = stereoByte;
|
||||
}
|
||||
|
||||
if (Options.Contains("AllowOverclock") && Options.Contains("OverclockSafe"))
|
||||
Vdp.IPeriod = 512;
|
||||
if (Options.Contains("AllowOverclock") && Options.Contains("OverclockSafe"))
|
||||
Vdp.IPeriod = 512;
|
||||
|
||||
if (Options.Contains("BIOS"))
|
||||
{
|
||||
Port3E = 0xF7; // Disable cartridge, enable BIOS rom
|
||||
InitBiosMapper();
|
||||
}
|
||||
SetupMemoryDomains();
|
||||
}
|
||||
if (Options.Contains("BIOS"))
|
||||
{
|
||||
Port3E = 0xF7; // Disable cartridge, enable BIOS rom
|
||||
InitBiosMapper();
|
||||
}
|
||||
SetupMemoryDomains();
|
||||
}
|
||||
|
||||
public void LoadGame(IGame game)
|
||||
{
|
||||
RomData = game.GetRomData();
|
||||
if (RomData.Length % BankSize != 0)
|
||||
Array.Resize(ref RomData, ((RomData.Length/BankSize) + 1)*BankSize);
|
||||
RomBanks = (byte)(RomData.Length/BankSize);
|
||||
Options = game.GetOptions();
|
||||
DisplayType = DisplayType.NTSC;
|
||||
public void LoadGame(IGame game)
|
||||
{
|
||||
RomData = game.GetRomData();
|
||||
if (RomData.Length % BankSize != 0)
|
||||
Array.Resize(ref RomData, ((RomData.Length / BankSize) + 1) * BankSize);
|
||||
RomBanks = (byte)(RomData.Length / BankSize);
|
||||
Options = game.GetOptions();
|
||||
DisplayType = DisplayType.NTSC;
|
||||
CoreOutputComm.VsyncRate = DisplayType == DisplayType.NTSC ? 60d : 50d;
|
||||
foreach (string option in Options)
|
||||
{
|
||||
var args = option.Split('=');
|
||||
if (args[0] == "Japan") Region = "Japan";
|
||||
else if (args[0] == "PAL") DisplayType = DisplayType.PAL;
|
||||
}
|
||||
foreach (string option in Options)
|
||||
{
|
||||
var args = option.Split('=');
|
||||
if (args[0] == "Japan") Region = "Japan";
|
||||
else if (args[0] == "PAL") DisplayType = DisplayType.PAL;
|
||||
}
|
||||
|
||||
if (Options.Contains("NotInDatabase") || (Options.Contains("FM") && Options.Contains("UseFM")))
|
||||
HasYM2413 = true;
|
||||
if (Options.Contains("NotInDatabase") || (Options.Contains("FM") && Options.Contains("UseFM")))
|
||||
HasYM2413 = true;
|
||||
|
||||
Init();
|
||||
}
|
||||
Init();
|
||||
}
|
||||
|
||||
public byte ReadPort(ushort port)
|
||||
{
|
||||
switch (port & 0xFF)
|
||||
{
|
||||
case 0x00: return ReadPort0();
|
||||
case 0x01: return Port01;
|
||||
case 0x02: return Port02;
|
||||
case 0x03: return 0x00;
|
||||
case 0x04: return 0xFF;
|
||||
case 0x05: return 0x00;
|
||||
case 0x06: return 0xFF;
|
||||
case 0x3E: return Port3E;
|
||||
case 0x7E: return Vdp.ReadVLineCounter();
|
||||
case 0x7F: break; // hline counter TODO
|
||||
case 0xBE: return Vdp.ReadData();
|
||||
case 0xBF: return Vdp.ReadVdpStatus();
|
||||
case 0xC0:
|
||||
case 0xDC: return ReadControls1();
|
||||
case 0xC1:
|
||||
case 0xDD: return ReadControls2();
|
||||
case 0xF2: return HasYM2413 ? YM2413.DetectionValue : (byte) 0xFF;
|
||||
}
|
||||
return 0xFF;
|
||||
}
|
||||
public byte ReadPort(ushort port)
|
||||
{
|
||||
switch (port & 0xFF)
|
||||
{
|
||||
case 0x00: return ReadPort0();
|
||||
case 0x01: return Port01;
|
||||
case 0x02: return Port02;
|
||||
case 0x03: return 0x00;
|
||||
case 0x04: return 0xFF;
|
||||
case 0x05: return 0x00;
|
||||
case 0x06: return 0xFF;
|
||||
case 0x3E: return Port3E;
|
||||
case 0x7E: return Vdp.ReadVLineCounter();
|
||||
case 0x7F: break; // hline counter TODO
|
||||
case 0xBE: return Vdp.ReadData();
|
||||
case 0xBF: return Vdp.ReadVdpStatus();
|
||||
case 0xC0:
|
||||
case 0xDC: return ReadControls1();
|
||||
case 0xC1:
|
||||
case 0xDD: return ReadControls2();
|
||||
case 0xF2: return HasYM2413 ? YM2413.DetectionValue : (byte)0xFF;
|
||||
}
|
||||
return 0xFF;
|
||||
}
|
||||
|
||||
public void WritePort(ushort port, byte value)
|
||||
{
|
||||
switch (port & 0xFF)
|
||||
{
|
||||
case 0x01: Port01 = value; break;
|
||||
case 0x02: Port02 = value; break;
|
||||
case 0x06: PSG.StereoPanning = value; break;
|
||||
case 0x3E: Port3E = value; break;
|
||||
case 0x3F: Port3F = value; break;
|
||||
case 0x7E:
|
||||
case 0x7F: PSG.WritePsgData(value, Cpu.TotalExecutedCycles); break;
|
||||
case 0xBE: Vdp.WriteVdpData(value); break;
|
||||
case 0xBD:
|
||||
case 0xBF: Vdp.WriteVdpControl(value); break;
|
||||
case 0xF0: if (HasYM2413) YM2413.RegisterLatch = value; break;
|
||||
case 0xF1: if (HasYM2413) YM2413.Write(value); break;
|
||||
case 0xF2: if (HasYM2413) YM2413.DetectionValue = value; break;
|
||||
}
|
||||
}
|
||||
public void WritePort(ushort port, byte value)
|
||||
{
|
||||
switch (port & 0xFF)
|
||||
{
|
||||
case 0x01: Port01 = value; break;
|
||||
case 0x02: Port02 = value; break;
|
||||
case 0x06: PSG.StereoPanning = value; break;
|
||||
case 0x3E: Port3E = value; break;
|
||||
case 0x3F: Port3F = value; break;
|
||||
case 0x7E:
|
||||
case 0x7F: PSG.WritePsgData(value, Cpu.TotalExecutedCycles); break;
|
||||
case 0xBE: Vdp.WriteVdpData(value); break;
|
||||
case 0xBD:
|
||||
case 0xBF: Vdp.WriteVdpControl(value); break;
|
||||
case 0xF0: if (HasYM2413) YM2413.RegisterLatch = value; break;
|
||||
case 0xF1: if (HasYM2413) YM2413.Write(value); break;
|
||||
case 0xF2: if (HasYM2413) YM2413.DetectionValue = value; break;
|
||||
}
|
||||
}
|
||||
|
||||
public void FrameAdvance(bool render)
|
||||
{
|
||||
lagged = true;
|
||||
Controller.UpdateControls(Frame++);
|
||||
PSG.BeginFrame(Cpu.TotalExecutedCycles);
|
||||
public void FrameAdvance(bool render)
|
||||
{
|
||||
lagged = true;
|
||||
Controller.UpdateControls(Frame++);
|
||||
PSG.BeginFrame(Cpu.TotalExecutedCycles);
|
||||
|
||||
if (IsGameGear == false)
|
||||
Cpu.NonMaskableInterrupt = Controller["Pause"];
|
||||
if (IsGameGear == false)
|
||||
Cpu.NonMaskableInterrupt = Controller["Pause"];
|
||||
|
||||
Vdp.ExecFrame(render);
|
||||
PSG.EndFrame(Cpu.TotalExecutedCycles);
|
||||
if (lagged)
|
||||
{
|
||||
_lagcount++;
|
||||
islag = true;
|
||||
}
|
||||
else
|
||||
islag = false;
|
||||
}
|
||||
Vdp.ExecFrame(render);
|
||||
PSG.EndFrame(Cpu.TotalExecutedCycles);
|
||||
if (lagged)
|
||||
{
|
||||
_lagcount++;
|
||||
islag = true;
|
||||
}
|
||||
else
|
||||
islag = false;
|
||||
}
|
||||
|
||||
public void SaveStateText(TextWriter writer)
|
||||
{
|
||||
writer.WriteLine("[SMS]\n");
|
||||
Cpu.SaveStateText(writer);
|
||||
PSG.SaveStateText(writer);
|
||||
Vdp.SaveStateText(writer);
|
||||
public void SaveStateText(TextWriter writer)
|
||||
{
|
||||
writer.WriteLine("[SMS]\n");
|
||||
Cpu.SaveStateText(writer);
|
||||
PSG.SaveStateText(writer);
|
||||
Vdp.SaveStateText(writer);
|
||||
|
||||
writer.WriteLine("Frame {0}", Frame);
|
||||
writer.WriteLine("Lag {0}", _lagcount);
|
||||
writer.WriteLine("Bank0 {0}", RomBank0);
|
||||
writer.WriteLine("Bank1 {0}", RomBank1);
|
||||
writer.WriteLine("Bank2 {0}", RomBank2);
|
||||
writer.Write("RAM ");
|
||||
SystemRam.SaveAsHex(writer);
|
||||
writer.WriteLine("Port01 {0:X2}", Port01);
|
||||
writer.WriteLine("Port02 {0:X2}", Port02);
|
||||
writer.WriteLine("Port3F {0:X2}", Port3F);
|
||||
int SaveRamLen = Util.SaveRamBytesUsed(SaveRAM);
|
||||
if (SaveRamLen > 0)
|
||||
{
|
||||
writer.Write("SaveRAM ");
|
||||
SaveRAM.SaveAsHex(writer, SaveRamLen);
|
||||
}
|
||||
if (HasYM2413)
|
||||
{
|
||||
writer.Write("FMRegs " );
|
||||
YM2413.opll.reg.SaveAsHex(writer);
|
||||
}
|
||||
writer.WriteLine("[/SMS]");
|
||||
}
|
||||
writer.WriteLine("Frame {0}", Frame);
|
||||
writer.WriteLine("Lag {0}", _lagcount);
|
||||
writer.WriteLine("Bank0 {0}", RomBank0);
|
||||
writer.WriteLine("Bank1 {0}", RomBank1);
|
||||
writer.WriteLine("Bank2 {0}", RomBank2);
|
||||
writer.Write("RAM ");
|
||||
SystemRam.SaveAsHex(writer);
|
||||
writer.WriteLine("Port01 {0:X2}", Port01);
|
||||
writer.WriteLine("Port02 {0:X2}", Port02);
|
||||
writer.WriteLine("Port3F {0:X2}", Port3F);
|
||||
int SaveRamLen = Util.SaveRamBytesUsed(SaveRAM);
|
||||
if (SaveRamLen > 0)
|
||||
{
|
||||
writer.Write("SaveRAM ");
|
||||
SaveRAM.SaveAsHex(writer, SaveRamLen);
|
||||
}
|
||||
if (HasYM2413)
|
||||
{
|
||||
writer.Write("FMRegs ");
|
||||
YM2413.opll.reg.SaveAsHex(writer);
|
||||
}
|
||||
writer.WriteLine("[/SMS]");
|
||||
}
|
||||
|
||||
public void LoadStateText(TextReader reader)
|
||||
{
|
||||
while (true)
|
||||
{
|
||||
string[] args = reader.ReadLine().Split(' ');
|
||||
if (args[0].Trim() == "") continue;
|
||||
if (args[0] == "[SMS]") continue;
|
||||
if (args[0] == "[/SMS]") break;
|
||||
if (args[0] == "Bank0")
|
||||
RomBank0 = byte.Parse(args[1]);
|
||||
else if (args[0] == "Bank1")
|
||||
RomBank1 = byte.Parse(args[1]);
|
||||
else if (args[0] == "Bank2")
|
||||
RomBank2 = byte.Parse(args[1]);
|
||||
else if (args[0] == "Frame")
|
||||
Frame = int.Parse(args[1]);
|
||||
else if (args[0] == "Lag")
|
||||
_lagcount = int.Parse(args[1]);
|
||||
else if (args[0] == "RAM")
|
||||
SystemRam.ReadFromHex(args[1]);
|
||||
else if (args[0] == "SaveRAM")
|
||||
{
|
||||
for (int i = 0; i < SaveRAM.Length; i++) SaveRAM[i] = 0;
|
||||
SaveRAM.ReadFromHex(args[1]);
|
||||
}
|
||||
else if (args[0] == "FMRegs")
|
||||
{
|
||||
byte[] regs = new byte[YM2413.opll.reg.Length];
|
||||
regs.ReadFromHex(args[1]);
|
||||
for (byte i = 0; i < regs.Length; i++)
|
||||
YM2413.Write(i, regs[i]);
|
||||
}
|
||||
else if (args[0] == "Port01")
|
||||
Port01 = byte.Parse(args[1], NumberStyles.HexNumber);
|
||||
else if (args[0] == "Port02")
|
||||
Port02 = byte.Parse(args[1], NumberStyles.HexNumber);
|
||||
else if (args[0] == "Port3F")
|
||||
Port3F = byte.Parse(args[1], NumberStyles.HexNumber);
|
||||
else if (args[0] == "[Z80]")
|
||||
Cpu.LoadStateText(reader);
|
||||
else if (args[0] == "[PSG]")
|
||||
PSG.LoadStateText(reader);
|
||||
else if (args[0] == "[VDP]")
|
||||
Vdp.LoadStateText(reader);
|
||||
else
|
||||
Console.WriteLine("Skipping unrecognized identifier " + args[0]);
|
||||
}
|
||||
}
|
||||
public void LoadStateText(TextReader reader)
|
||||
{
|
||||
while (true)
|
||||
{
|
||||
string[] args = reader.ReadLine().Split(' ');
|
||||
if (args[0].Trim() == "") continue;
|
||||
if (args[0] == "[SMS]") continue;
|
||||
if (args[0] == "[/SMS]") break;
|
||||
if (args[0] == "Bank0")
|
||||
RomBank0 = byte.Parse(args[1]);
|
||||
else if (args[0] == "Bank1")
|
||||
RomBank1 = byte.Parse(args[1]);
|
||||
else if (args[0] == "Bank2")
|
||||
RomBank2 = byte.Parse(args[1]);
|
||||
else if (args[0] == "Frame")
|
||||
Frame = int.Parse(args[1]);
|
||||
else if (args[0] == "Lag")
|
||||
_lagcount = int.Parse(args[1]);
|
||||
else if (args[0] == "RAM")
|
||||
SystemRam.ReadFromHex(args[1]);
|
||||
else if (args[0] == "SaveRAM")
|
||||
{
|
||||
for (int i = 0; i < SaveRAM.Length; i++) SaveRAM[i] = 0;
|
||||
SaveRAM.ReadFromHex(args[1]);
|
||||
}
|
||||
else if (args[0] == "FMRegs")
|
||||
{
|
||||
byte[] regs = new byte[YM2413.opll.reg.Length];
|
||||
regs.ReadFromHex(args[1]);
|
||||
for (byte i = 0; i < regs.Length; i++)
|
||||
YM2413.Write(i, regs[i]);
|
||||
}
|
||||
else if (args[0] == "Port01")
|
||||
Port01 = byte.Parse(args[1], NumberStyles.HexNumber);
|
||||
else if (args[0] == "Port02")
|
||||
Port02 = byte.Parse(args[1], NumberStyles.HexNumber);
|
||||
else if (args[0] == "Port3F")
|
||||
Port3F = byte.Parse(args[1], NumberStyles.HexNumber);
|
||||
else if (args[0] == "[Z80]")
|
||||
Cpu.LoadStateText(reader);
|
||||
else if (args[0] == "[PSG]")
|
||||
PSG.LoadStateText(reader);
|
||||
else if (args[0] == "[VDP]")
|
||||
Vdp.LoadStateText(reader);
|
||||
else
|
||||
Console.WriteLine("Skipping unrecognized identifier " + args[0]);
|
||||
}
|
||||
}
|
||||
|
||||
public byte[] SaveStateBinary()
|
||||
{
|
||||
var buf = new byte[24802 + 16384 + 16384];
|
||||
var stream = new MemoryStream(buf);
|
||||
var writer = new BinaryWriter(stream);
|
||||
SaveStateBinary(writer);
|
||||
writer.Close();
|
||||
return buf;
|
||||
}
|
||||
public byte[] SaveStateBinary()
|
||||
{
|
||||
var buf = new byte[24802 + 16384 + 16384];
|
||||
var stream = new MemoryStream(buf);
|
||||
var writer = new BinaryWriter(stream);
|
||||
SaveStateBinary(writer);
|
||||
writer.Close();
|
||||
return buf;
|
||||
}
|
||||
|
||||
public void SaveStateBinary(BinaryWriter writer)
|
||||
{
|
||||
Cpu.SaveStateBinary(writer);
|
||||
PSG.SaveStateBinary(writer);
|
||||
Vdp.SaveStateBinary(writer);
|
||||
public void SaveStateBinary(BinaryWriter writer)
|
||||
{
|
||||
Cpu.SaveStateBinary(writer);
|
||||
PSG.SaveStateBinary(writer);
|
||||
Vdp.SaveStateBinary(writer);
|
||||
|
||||
writer.Write(Frame);
|
||||
writer.Write(_lagcount);
|
||||
writer.Write(RomBank0);
|
||||
writer.Write(RomBank1);
|
||||
writer.Write(RomBank2);
|
||||
writer.Write(SystemRam);
|
||||
writer.Write(SaveRAM);
|
||||
writer.Write(Port01);
|
||||
writer.Write(Port02);
|
||||
writer.Write(Port3F);
|
||||
writer.Write(YM2413.opll.reg);
|
||||
}
|
||||
writer.Write(Frame);
|
||||
writer.Write(_lagcount);
|
||||
writer.Write(RomBank0);
|
||||
writer.Write(RomBank1);
|
||||
writer.Write(RomBank2);
|
||||
writer.Write(SystemRam);
|
||||
writer.Write(SaveRAM);
|
||||
writer.Write(Port01);
|
||||
writer.Write(Port02);
|
||||
writer.Write(Port3F);
|
||||
writer.Write(YM2413.opll.reg);
|
||||
}
|
||||
|
||||
public void LoadStateBinary(BinaryReader reader)
|
||||
{
|
||||
Cpu.LoadStateBinary(reader);
|
||||
PSG.LoadStateBinary(reader);
|
||||
Vdp.LoadStateBinary(reader);
|
||||
public void LoadStateBinary(BinaryReader reader)
|
||||
{
|
||||
Cpu.LoadStateBinary(reader);
|
||||
PSG.LoadStateBinary(reader);
|
||||
Vdp.LoadStateBinary(reader);
|
||||
|
||||
Frame = reader.ReadInt32();
|
||||
_lagcount = reader.ReadInt32();
|
||||
RomBank0 = reader.ReadByte();
|
||||
RomBank1 = reader.ReadByte();
|
||||
RomBank2 = reader.ReadByte();
|
||||
SystemRam = reader.ReadBytes(SystemRam.Length);
|
||||
reader.Read(SaveRAM, 0, SaveRAM.Length);
|
||||
Port01 = reader.ReadByte();
|
||||
Port02 = reader.ReadByte();
|
||||
Port3F = reader.ReadByte();
|
||||
if (HasYM2413)
|
||||
{
|
||||
byte[] regs = new byte[YM2413.opll.reg.Length];
|
||||
reader.Read(regs, 0, regs.Length);
|
||||
for (byte i = 0; i < regs.Length; i++)
|
||||
YM2413.Write(i, regs[i]);
|
||||
}
|
||||
}
|
||||
Frame = reader.ReadInt32();
|
||||
_lagcount = reader.ReadInt32();
|
||||
RomBank0 = reader.ReadByte();
|
||||
RomBank1 = reader.ReadByte();
|
||||
RomBank2 = reader.ReadByte();
|
||||
SystemRam = reader.ReadBytes(SystemRam.Length);
|
||||
reader.Read(SaveRAM, 0, SaveRAM.Length);
|
||||
Port01 = reader.ReadByte();
|
||||
Port02 = reader.ReadByte();
|
||||
Port3F = reader.ReadByte();
|
||||
if (HasYM2413)
|
||||
{
|
||||
byte[] regs = new byte[YM2413.opll.reg.Length];
|
||||
reader.Read(regs, 0, regs.Length);
|
||||
for (byte i = 0; i < regs.Length; i++)
|
||||
YM2413.Write(i, regs[i]);
|
||||
}
|
||||
}
|
||||
|
||||
public IVideoProvider VideoProvider { get { return Vdp; } }
|
||||
public IVideoProvider VideoProvider { get { return Vdp; } }
|
||||
public CoreInputComm CoreInputComm { get; set; }
|
||||
public CoreOutputComm CoreOutputComm { get; private set; }
|
||||
|
||||
private ISoundProvider ActiveSoundProvider;
|
||||
public ISoundProvider SoundProvider { get { return ActiveSoundProvider; } }
|
||||
private ISoundProvider ActiveSoundProvider;
|
||||
public ISoundProvider SoundProvider { get { return ActiveSoundProvider; } }
|
||||
|
||||
public string SystemId { get { return "SMS"; } }
|
||||
public string SystemId { get { return "SMS"; } }
|
||||
|
||||
private string region = "Export";
|
||||
public string Region
|
||||
{
|
||||
get { return region; }
|
||||
set
|
||||
{
|
||||
if (value.NotIn(validRegions))
|
||||
throw new Exception("Passed value "+value+" is not a valid region!");
|
||||
region = value;
|
||||
}
|
||||
}
|
||||
private string region = "Export";
|
||||
public string Region
|
||||
{
|
||||
get { return region; }
|
||||
set
|
||||
{
|
||||
if (value.NotIn(validRegions))
|
||||
throw new Exception("Passed value " + value + " is not a valid region!");
|
||||
region = value;
|
||||
}
|
||||
}
|
||||
|
||||
private readonly string[] validRegions = {"Export", "Japan"};
|
||||
private readonly string[] validRegions = { "Export", "Japan" };
|
||||
|
||||
private IList<MemoryDomain> memoryDomains;
|
||||
private IList<MemoryDomain> memoryDomains;
|
||||
|
||||
private void SetupMemoryDomains()
|
||||
{
|
||||
var domains = new List<MemoryDomain>(3);
|
||||
var MainMemoryDomain = new MemoryDomain("Main RAM", SystemRam.Length, Endian.Little,
|
||||
addr => SystemRam[addr & RamSizeMask],
|
||||
(addr, value) => SystemRam[addr & RamSizeMask] = value);
|
||||
var VRamDomain = new MemoryDomain("Video RAM", Vdp.VRAM.Length, Endian.Little,
|
||||
addr => Vdp.VRAM[addr & 0x3FFF],
|
||||
(addr, value) => Vdp.VRAM[addr & 0x3FFF] = value);
|
||||
var SaveRamDomain = new MemoryDomain("Save RAM", SaveRAM.Length, Endian.Little,
|
||||
addr => SaveRAM[addr%SaveRAM.Length],
|
||||
(addr, value) => { SaveRAM[addr%SaveRAM.Length]=value; SaveRamModified=true;});
|
||||
var SystemBusDomain = new MemoryDomain("System Bus", 0x10000, Endian.Little,
|
||||
addr => Cpu.ReadMemory((ushort)addr),
|
||||
(addr, value) => Cpu.WriteMemory((ushort)addr, value));
|
||||
private void SetupMemoryDomains()
|
||||
{
|
||||
var domains = new List<MemoryDomain>(3);
|
||||
var MainMemoryDomain = new MemoryDomain("Main RAM", SystemRam.Length, Endian.Little,
|
||||
addr => SystemRam[addr & RamSizeMask],
|
||||
(addr, value) => SystemRam[addr & RamSizeMask] = value);
|
||||
var VRamDomain = new MemoryDomain("Video RAM", Vdp.VRAM.Length, Endian.Little,
|
||||
addr => Vdp.VRAM[addr & 0x3FFF],
|
||||
(addr, value) => Vdp.VRAM[addr & 0x3FFF] = value);
|
||||
var SaveRamDomain = new MemoryDomain("Save RAM", SaveRAM.Length, Endian.Little,
|
||||
addr => SaveRAM[addr % SaveRAM.Length],
|
||||
(addr, value) => { SaveRAM[addr % SaveRAM.Length] = value; SaveRamModified = true; });
|
||||
var SystemBusDomain = new MemoryDomain("System Bus", 0x10000, Endian.Little,
|
||||
addr => Cpu.ReadMemory((ushort)addr),
|
||||
(addr, value) => Cpu.WriteMemory((ushort)addr, value));
|
||||
|
||||
domains.Add(MainMemoryDomain);
|
||||
domains.Add(VRamDomain);
|
||||
domains.Add(SaveRamDomain);
|
||||
domains.Add(SystemBusDomain);
|
||||
memoryDomains = domains.AsReadOnly();
|
||||
}
|
||||
domains.Add(MainMemoryDomain);
|
||||
domains.Add(VRamDomain);
|
||||
domains.Add(SaveRamDomain);
|
||||
domains.Add(SystemBusDomain);
|
||||
memoryDomains = domains.AsReadOnly();
|
||||
}
|
||||
|
||||
public IList<MemoryDomain> MemoryDomains { get { return memoryDomains; } }
|
||||
public MemoryDomain MainMemory { get { return memoryDomains[0]; } }
|
||||
public IList<MemoryDomain> MemoryDomains { get { return memoryDomains; } }
|
||||
public MemoryDomain MainMemory { get { return memoryDomains[0]; } }
|
||||
|
||||
public void Dispose() {}
|
||||
}
|
||||
public void Dispose() { }
|
||||
}
|
||||
}
|
|
@ -15,6 +15,7 @@
|
|||
NESController[1] = new NESControllerTemplate(false);
|
||||
NESController[2] = new NESControllerTemplate(false);
|
||||
NESController[3] = new NESControllerTemplate(false);
|
||||
GameBoyController = new NESControllerTemplate(true);
|
||||
TI83Controller[0] = new TI83ControllerTemplate(true);
|
||||
}
|
||||
|
||||
|
@ -390,6 +391,9 @@
|
|||
|
||||
//TI 83 settings
|
||||
public TI83ControllerTemplate[] TI83Controller = new TI83ControllerTemplate[1];
|
||||
|
||||
//GB settings
|
||||
public GBControllerTemplate GBController = new GBControllerTemplate();
|
||||
}
|
||||
|
||||
public class SMSControllerTemplate
|
||||
|
@ -509,6 +513,47 @@
|
|||
}
|
||||
}
|
||||
|
||||
public class GBControllerTemplate
|
||||
{
|
||||
public string Up;
|
||||
public string Down;
|
||||
public string Left;
|
||||
public string Right;
|
||||
public string A;
|
||||
public string B;
|
||||
public string Start;
|
||||
public string Select;
|
||||
public bool Enabled;
|
||||
public GBControllerTemplate() { }
|
||||
public GBControllerTemplate(bool defaults)
|
||||
{
|
||||
if (defaults)
|
||||
{
|
||||
Enabled = true;
|
||||
Up = "J1 Up, UpArrow";
|
||||
Down = "J1 Down, DownArrow";
|
||||
Left = "J1 Left, LeftArrow";
|
||||
Right = "J1 Right, RightArrow";
|
||||
A = "J1 B2, X";
|
||||
B = "J1 B1, Z";
|
||||
Start = "J1 B8, Return";
|
||||
Select = "J1 B7, Space";
|
||||
}
|
||||
else
|
||||
{
|
||||
Enabled = false;
|
||||
Up = "";
|
||||
Down = "";
|
||||
Right = "";
|
||||
Left = "";
|
||||
A = "";
|
||||
B = "";
|
||||
Start = "";
|
||||
Select = "";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public class TI83ControllerTemplate
|
||||
{
|
||||
public string _0;
|
||||
|
|
|
@ -20,6 +20,7 @@ namespace BizHawk.MultiClient
|
|||
public static Controller GenControls;
|
||||
public static Controller TI83Controls;
|
||||
public static Controller NESControls;
|
||||
public static Controller GBControls;
|
||||
public static Controller ActiveController;
|
||||
public static Controller NullControls;
|
||||
}
|
||||
|
|
|
@ -200,6 +200,19 @@ namespace BizHawk.MultiClient
|
|||
return input.ToString();
|
||||
}
|
||||
|
||||
if (type.Name == "Gameboy Controller")
|
||||
{
|
||||
input.Append("|");
|
||||
input.Append(IsPressed("Right") ? "R" : ".");
|
||||
input.Append(IsPressed("Left") ? "L" : ".");
|
||||
input.Append(IsPressed("Down") ? "D" : ".");
|
||||
input.Append(IsPressed("Up") ? "U" : ".");
|
||||
input.Append(IsPressed("Start") ? "S" : ".");
|
||||
input.Append(IsPressed("Select") ? "s" : ".");
|
||||
input.Append(IsPressed("B") ? "B" : ".");
|
||||
input.Append(IsPressed("A") ? "A" : ".");
|
||||
}
|
||||
|
||||
if (type.Name == "NES Controls")
|
||||
{
|
||||
input.Append(IsPressed("Reset") ? "r" : ".");
|
||||
|
@ -376,6 +389,20 @@ namespace BizHawk.MultiClient
|
|||
if (mnemonic[19] != '.') programmaticallyPressedButtons.Add("P2 A");
|
||||
}
|
||||
|
||||
if (type.Name == "Gameboy Controller")
|
||||
{
|
||||
if (mnemonic.Length < 10) return;
|
||||
//if (mnemonic[1] != '.' && mnemonic[1] != '0') programmaticallyPressedButtons.Add("Reset");
|
||||
if (mnemonic[3] != '.') programmaticallyPressedButtons.Add("P1 Right");
|
||||
if (mnemonic[4] != '.') programmaticallyPressedButtons.Add("P1 Left");
|
||||
if (mnemonic[5] != '.') programmaticallyPressedButtons.Add("P1 Down");
|
||||
if (mnemonic[6] != '.') programmaticallyPressedButtons.Add("P1 Up");
|
||||
if (mnemonic[7] != '.') programmaticallyPressedButtons.Add("P1 Start");
|
||||
if (mnemonic[8] != '.') programmaticallyPressedButtons.Add("P1 Select");
|
||||
if (mnemonic[9] != '.') programmaticallyPressedButtons.Add("P1 B");
|
||||
if (mnemonic[10] != '.') programmaticallyPressedButtons.Add("P1 A");
|
||||
}
|
||||
|
||||
if (type.Name == "TI83 Controls")
|
||||
{
|
||||
if (mnemonic.Length < 50) return;
|
||||
|
|
|
@ -509,6 +509,18 @@ namespace BizHawk.MultiClient
|
|||
}
|
||||
Global.NESControls = nesControls;
|
||||
|
||||
var gbControls = new Controller(Gameboy.GbController);
|
||||
gbControls.BindMulti("Up", Global.Config.GBController.Up);
|
||||
gbControls.BindMulti("Down", Global.Config.GBController.Down);
|
||||
gbControls.BindMulti("Left", Global.Config.GBController.Left);
|
||||
gbControls.BindMulti("Right", Global.Config.GBController.Right);
|
||||
gbControls.BindMulti("A", Global.Config.GBController.A);
|
||||
gbControls.BindMulti("B", Global.Config.GBController.B);
|
||||
gbControls.BindMulti("Select", Global.Config.GBController.Select);
|
||||
gbControls.BindMulti("Start", Global.Config.GBController.Start);
|
||||
Global.GBControls = gbControls;
|
||||
|
||||
|
||||
var genControls = new Controller(Genesis.GenesisController);
|
||||
genControls.BindMulti("P1 Up", Global.Config.GenP1Up);
|
||||
genControls.BindMulti("P1 Left", Global.Config.GenP1Left);
|
||||
|
|
Loading…
Reference in New Issue