GGHawkLink: Initial Commit
- Make necessary access changes in SMS - Implmement multi-disk bundler support - Initial Video and sound support
This commit is contained in:
parent
4a73565ab2
commit
4f17934d6c
|
@ -17,6 +17,7 @@ using BizHawk.Emulation.Cores.Nintendo.GBHawk;
|
|||
using BizHawk.Emulation.Cores.Nintendo.GBHawkLink;
|
||||
using BizHawk.Emulation.Cores.Nintendo.SNES;
|
||||
using BizHawk.Emulation.Cores.PCEngine;
|
||||
using BizHawk.Emulation.Cores.Sega.GGHawkLink;
|
||||
using BizHawk.Emulation.Cores.Sega.Saturn;
|
||||
using BizHawk.Emulation.Cores.Sony.PSP;
|
||||
using BizHawk.Emulation.Cores.Sony.PSX;
|
||||
|
@ -805,6 +806,22 @@ namespace BizHawk.Client.Common
|
|||
}
|
||||
nextEmulator = new GPGX(nextComm, null, genDiscs, GetCoreSettings<GPGX>(), GetCoreSyncSettings<GPGX>());
|
||||
break;
|
||||
case "Game Gear":
|
||||
var leftBytesGG = xmlGame.Assets.First().Value;
|
||||
var rightBytesGG = xmlGame.Assets.Skip(1).First().Value;
|
||||
|
||||
var leftGG = Database.GetGameInfo(leftBytesGG, "left.gg");
|
||||
var rightGG = Database.GetGameInfo(rightBytesGG, "right.gg");
|
||||
|
||||
nextEmulator = new GGHawkLink(
|
||||
nextComm,
|
||||
leftGG,
|
||||
leftBytesGG,
|
||||
rightGG,
|
||||
rightBytesGG,
|
||||
GetCoreSettings<GGHawkLink>(),
|
||||
GetCoreSyncSettings<GGHawkLink>());
|
||||
break;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -145,7 +145,8 @@
|
|||
"PSX",
|
||||
"SAT",
|
||||
"ZXSpectrum",
|
||||
"AmstradCPC"});
|
||||
"AmstradCPC",
|
||||
"Game Gear"});
|
||||
this.SystemDropDown.Location = new System.Drawing.Point(425, 75);
|
||||
this.SystemDropDown.Name = "SystemDropDown";
|
||||
this.SystemDropDown.Size = new System.Drawing.Size(69, 21);
|
||||
|
|
|
@ -1336,6 +1336,31 @@
|
|||
</Compile>
|
||||
<Compile Include="Consoles\PC Engine\PCEngine.TurboCD.cs" />
|
||||
<Compile Include="Consoles\PC Engine\ScsiCDBus.cs" />
|
||||
<Compile Include="Consoles\Sega\GGHawkLink\GGHawkLink.cs" />
|
||||
<Compile Include="Consoles\Sega\GGHawkLink\GGHawkLink.ICodeDataLog.cs" />
|
||||
<Compile Include="Consoles\Sega\GGHawkLink\GGHawkLink.IDebuggable.cs">
|
||||
<DependentUpon>GGHawkLink.cs</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="Consoles\Sega\GGHawkLink\GGHawkLink.IEmulator.cs">
|
||||
<DependentUpon>GGHawkLink.cs</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="Consoles\Sega\GGHawkLink\GGHawkLink.IInputPollable.cs">
|
||||
<DependentUpon>GGHawkLink.cs</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="Consoles\Sega\GGHawkLink\GGHawkLink.IMemoryDomains.cs">
|
||||
<DependentUpon>GGHawkLink.cs</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="Consoles\Sega\GGHawkLink\GGHawkLink.ISaveRam.cs">
|
||||
<DependentUpon>GGHawkLink.cs</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="Consoles\Sega\GGHawkLink\GGHawkLink.ISettable.cs">
|
||||
<DependentUpon>GGHawkLink.cs</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="Consoles\Sega\GGHawkLink\GGHawkLink.IStatable.cs">
|
||||
<DependentUpon>GGHawkLink.cs</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="Consoles\Sega\GGHawkLink\GGHawkLinkControllerDeck.cs" />
|
||||
<Compile Include="Consoles\Sega\GGHawkLink\GGHawkLinkControllers.cs" />
|
||||
<Compile Include="Consoles\Sega\gpgx64\GPGX.ISoundProvider.cs">
|
||||
<DependentUpon>GPGX.cs</DependentUpon>
|
||||
</Compile>
|
||||
|
|
|
@ -39,7 +39,7 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBHawkLink
|
|||
|
||||
linkSettings = (GBLinkSettings)settings ?? new GBLinkSettings();
|
||||
linkSyncSettings = (GBLinkSyncSettings)syncSettings ?? new GBLinkSyncSettings();
|
||||
_controllerDeck = new GBHawkLinkControllerDeck(GBHawkControllerDeck.DefaultControllerName, GBHawkControllerDeck.DefaultControllerName);
|
||||
_controllerDeck = new GBHawkLinkControllerDeck(GBHawkLinkControllerDeck.DefaultControllerName, GBHawkLinkControllerDeck.DefaultControllerName);
|
||||
|
||||
CoreComm = comm;
|
||||
|
||||
|
|
|
@ -0,0 +1,115 @@
|
|||
using System;
|
||||
using System.IO;
|
||||
using System.Collections.Generic;
|
||||
|
||||
using BizHawk.Emulation.Common;
|
||||
using BizHawk.Emulation.Cores.Components.Z80A;
|
||||
|
||||
namespace BizHawk.Emulation.Cores.Sega.GGHawkLink
|
||||
{
|
||||
public sealed partial class GGHawkLink : ICodeDataLogger
|
||||
{
|
||||
public void SetCDL(ICodeDataLog cdl)
|
||||
{
|
||||
CDL = cdl;
|
||||
if (cdl == null)
|
||||
{
|
||||
L.Cpu.ReadMemory = L.ReadMemory;
|
||||
L.Cpu.WriteMemory = L.WriteMemory;
|
||||
L.Cpu.FetchMemory = L.FetchMemory;
|
||||
}
|
||||
else
|
||||
{
|
||||
L.Cpu.ReadMemory = ReadMemory_CDL;
|
||||
L.Cpu.WriteMemory = L.WriteMemory;
|
||||
L.Cpu.FetchMemory = FetchMemory_CDL;
|
||||
}
|
||||
}
|
||||
|
||||
public void NewCDL(ICodeDataLog cdl)
|
||||
{
|
||||
cdl["ROM"] = new byte[MemoryDomains["ROM"].Size];
|
||||
cdl["Main RAM"] = new byte[MemoryDomains["Main RAM"].Size];
|
||||
|
||||
if (MemoryDomains.Has("Save RAM"))
|
||||
{
|
||||
cdl["Save RAM"] = new byte[MemoryDomains["Save RAM"].Size];
|
||||
}
|
||||
|
||||
if (MemoryDomains.Has("Cart (Volatile) RAM"))
|
||||
{
|
||||
cdl["Cart (Volatile) RAM"] = new byte[MemoryDomains["Cart (Volatile) RAM"].Size];
|
||||
}
|
||||
|
||||
cdl.SubType = "SMS";
|
||||
cdl.SubVer = 0;
|
||||
}
|
||||
|
||||
[FeatureNotImplemented]
|
||||
public void DisassembleCDL(Stream s, ICodeDataLog cdl)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
private enum CDLog_AddrType
|
||||
{
|
||||
None,
|
||||
ROM,
|
||||
MainRAM,
|
||||
SaveRAM,
|
||||
CartRAM, //"Cart (Volatile) RAM" aka ExtRam
|
||||
}
|
||||
|
||||
[Flags]
|
||||
private enum CDLog_Flags
|
||||
{
|
||||
ExecFirst = 0x01,
|
||||
ExecOperand = 0x02,
|
||||
Data = 0x04
|
||||
};
|
||||
|
||||
private struct CDLog_MapResults
|
||||
{
|
||||
public CDLog_AddrType Type;
|
||||
public int Address;
|
||||
}
|
||||
|
||||
private delegate CDLog_MapResults MapMemoryDelegate(ushort addr, bool write);
|
||||
private MapMemoryDelegate MapMemory;
|
||||
private ICodeDataLog CDL;
|
||||
|
||||
private void RunCDL(ushort address, CDLog_Flags flags)
|
||||
{
|
||||
if (MapMemory != null)
|
||||
{
|
||||
CDLog_MapResults results = MapMemory(address, false);
|
||||
switch (results.Type)
|
||||
{
|
||||
case CDLog_AddrType.None: break;
|
||||
case CDLog_AddrType.ROM: CDL["ROM"][results.Address] |= (byte)flags; break;
|
||||
case CDLog_AddrType.MainRAM: CDL["Main RAM"][results.Address] |= (byte)flags; break;
|
||||
case CDLog_AddrType.SaveRAM: CDL["Save RAM"][results.Address] |= (byte)flags; break;
|
||||
case CDLog_AddrType.CartRAM: CDL["Cart (Volatile) RAM"][results.Address] |= (byte)flags; break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// A wrapper for FetchMemory which inserts CDL logic
|
||||
/// </summary>
|
||||
private byte FetchMemory_CDL(ushort address)
|
||||
{
|
||||
RunCDL(address, CDLog_Flags.ExecFirst);
|
||||
return L.ReadMemory(address);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// A wrapper for ReadMemory which inserts CDL logic
|
||||
/// </summary>
|
||||
private byte ReadMemory_CDL(ushort address)
|
||||
{
|
||||
RunCDL(address, CDLog_Flags.Data);
|
||||
return L.ReadMemory(address);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,152 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
using BizHawk.Emulation.Common;
|
||||
|
||||
namespace BizHawk.Emulation.Cores.Sega.GGHawkLink
|
||||
{
|
||||
public partial class GGHawkLink : IDebuggable
|
||||
{
|
||||
public IDictionary<string, RegisterValue> GetCpuFlagsAndRegisters()
|
||||
{
|
||||
return new Dictionary<string, RegisterValue>
|
||||
{
|
||||
["A"] = L.Cpu.Regs[L.Cpu.A],
|
||||
["AF"] = L.Cpu.Regs[L.Cpu.F] + (L.Cpu.Regs[L.Cpu.A] << 8),
|
||||
["B"] = L.Cpu.Regs[L.Cpu.B],
|
||||
["BC"] = L.Cpu.Regs[L.Cpu.C] + (L.Cpu.Regs[L.Cpu.B] << 8),
|
||||
["C"] = L.Cpu.Regs[L.Cpu.C],
|
||||
["D"] = L.Cpu.Regs[L.Cpu.D],
|
||||
["DE"] = L.Cpu.Regs[L.Cpu.E] + (L.Cpu.Regs[L.Cpu.D] << 8),
|
||||
["E"] = L.Cpu.Regs[L.Cpu.E],
|
||||
["F"] = L.Cpu.Regs[L.Cpu.F],
|
||||
["H"] = L.Cpu.Regs[L.Cpu.H],
|
||||
["HL"] = L.Cpu.Regs[L.Cpu.L] + (L.Cpu.Regs[L.Cpu.H] << 8),
|
||||
["I"] = L.Cpu.Regs[L.Cpu.I],
|
||||
["IX"] = L.Cpu.Regs[L.Cpu.Ixl] + (L.Cpu.Regs[L.Cpu.Ixh] << 8),
|
||||
["IY"] = L.Cpu.Regs[L.Cpu.Iyl] + (L.Cpu.Regs[L.Cpu.Iyh] << 8),
|
||||
["L"] = L.Cpu.Regs[L.Cpu.L],
|
||||
["PC"] = L.Cpu.Regs[L.Cpu.PCl] + (L.Cpu.Regs[L.Cpu.PCh] << 8),
|
||||
["R"] = L.Cpu.Regs[L.Cpu.R],
|
||||
["Shadow AF"] = L.Cpu.Regs[L.Cpu.F_s] + (L.Cpu.Regs[L.Cpu.A_s] << 8),
|
||||
["Shadow BC"] = L.Cpu.Regs[L.Cpu.C_s] + (L.Cpu.Regs[L.Cpu.B_s] << 8),
|
||||
["Shadow DE"] = L.Cpu.Regs[L.Cpu.E_s] + (L.Cpu.Regs[L.Cpu.D_s] << 8),
|
||||
["Shadow HL"] = L.Cpu.Regs[L.Cpu.L_s] + (L.Cpu.Regs[L.Cpu.H_s] << 8),
|
||||
["SP"] = L.Cpu.Regs[L.Cpu.SPl] + (L.Cpu.Regs[L.Cpu.SPh] << 8),
|
||||
["Flag C"] = L.Cpu.FlagC,
|
||||
["Flag N"] = L.Cpu.FlagN,
|
||||
["Flag P/V"] = L.Cpu.FlagP,
|
||||
["Flag 3rd"] = L.Cpu.Flag3,
|
||||
["Flag H"] = L.Cpu.FlagH,
|
||||
["Flag 5th"] = L.Cpu.Flag5,
|
||||
["Flag Z"] = L.Cpu.FlagZ,
|
||||
["Flag S"] = L.Cpu.FlagS
|
||||
};
|
||||
}
|
||||
|
||||
public void SetCpuRegister(string register, int value)
|
||||
{
|
||||
switch (register)
|
||||
{
|
||||
default:
|
||||
throw new InvalidOperationException();
|
||||
case "A":
|
||||
L.Cpu.Regs[L.Cpu.A] = (ushort)value;
|
||||
break;
|
||||
case "AF":
|
||||
L.Cpu.Regs[L.Cpu.F] = (ushort)(value & 0xFF);
|
||||
L.Cpu.Regs[L.Cpu.A] = (ushort)(value & 0xFF00);
|
||||
break;
|
||||
case "B":
|
||||
L.Cpu.Regs[L.Cpu.B] = (ushort)value;
|
||||
break;
|
||||
case "BC":
|
||||
L.Cpu.Regs[L.Cpu.C] = (ushort)(value & 0xFF);
|
||||
L.Cpu.Regs[L.Cpu.B] = (ushort)(value & 0xFF00);
|
||||
break;
|
||||
case "C":
|
||||
L.Cpu.Regs[L.Cpu.C] = (ushort)value;
|
||||
break;
|
||||
case "D":
|
||||
L.Cpu.Regs[L.Cpu.D] = (ushort)value;
|
||||
break;
|
||||
case "DE":
|
||||
L.Cpu.Regs[L.Cpu.E] = (ushort)(value & 0xFF);
|
||||
L.Cpu.Regs[L.Cpu.D] = (ushort)(value & 0xFF00);
|
||||
break;
|
||||
case "E":
|
||||
L.Cpu.Regs[L.Cpu.E] = (ushort)value;
|
||||
break;
|
||||
case "F":
|
||||
L.Cpu.Regs[L.Cpu.F] = (ushort)value;
|
||||
break;
|
||||
case "H":
|
||||
L.Cpu.Regs[L.Cpu.H] = (ushort)value;
|
||||
break;
|
||||
case "HL":
|
||||
L.Cpu.Regs[L.Cpu.L] = (ushort)(value & 0xFF);
|
||||
L.Cpu.Regs[L.Cpu.H] = (ushort)(value & 0xFF00);
|
||||
break;
|
||||
case "I":
|
||||
L.Cpu.Regs[L.Cpu.I] = (ushort)value;
|
||||
break;
|
||||
case "IX":
|
||||
L.Cpu.Regs[L.Cpu.Ixl] = (ushort)(value & 0xFF);
|
||||
L.Cpu.Regs[L.Cpu.Ixh] = (ushort)(value & 0xFF00);
|
||||
break;
|
||||
case "IY":
|
||||
L.Cpu.Regs[L.Cpu.Iyl] = (ushort)(value & 0xFF);
|
||||
L.Cpu.Regs[L.Cpu.Iyh] = (ushort)(value & 0xFF00);
|
||||
break;
|
||||
case "L":
|
||||
L.Cpu.Regs[L.Cpu.L] = (ushort)value;
|
||||
break;
|
||||
case "PC":
|
||||
L.Cpu.Regs[L.Cpu.PCl] = (ushort)(value & 0xFF);
|
||||
L.Cpu.Regs[L.Cpu.PCh] = (ushort)(value & 0xFF00);
|
||||
break;
|
||||
case "R":
|
||||
L.Cpu.Regs[L.Cpu.R] = (ushort)value;
|
||||
break;
|
||||
case "Shadow AF":
|
||||
L.Cpu.Regs[L.Cpu.F_s] = (ushort)(value & 0xFF);
|
||||
L.Cpu.Regs[L.Cpu.A_s] = (ushort)(value & 0xFF00);
|
||||
break;
|
||||
case "Shadow BC":
|
||||
L.Cpu.Regs[L.Cpu.C_s] = (ushort)(value & 0xFF);
|
||||
L.Cpu.Regs[L.Cpu.B_s] = (ushort)(value & 0xFF00);
|
||||
break;
|
||||
case "Shadow DE":
|
||||
L.Cpu.Regs[L.Cpu.E_s] = (ushort)(value & 0xFF);
|
||||
L.Cpu.Regs[L.Cpu.D_s] = (ushort)(value & 0xFF00);
|
||||
break;
|
||||
case "Shadow HL":
|
||||
L.Cpu.Regs[L.Cpu.L_s] = (ushort)(value & 0xFF);
|
||||
L.Cpu.Regs[L.Cpu.H_s] = (ushort)(value & 0xFF00);
|
||||
break;
|
||||
case "SP":
|
||||
L.Cpu.Regs[L.Cpu.SPl] = (ushort)(value & 0xFF);
|
||||
L.Cpu.Regs[L.Cpu.SPh] = (ushort)(value & 0xFF00);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
public IMemoryCallbackSystem MemoryCallbacks { get; } = new MemoryCallbackSystem(new[] { "System Bus" });
|
||||
|
||||
public bool CanStep(StepType type)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
[FeatureNotImplemented]
|
||||
public void Step(StepType type)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public long TotalExecutedCycles
|
||||
{
|
||||
get { return (long)L.Cpu.TotalExecutedCycles; }
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,275 @@
|
|||
using BizHawk.Common.NumberExtensions;
|
||||
using BizHawk.Emulation.Common;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
using BizHawk.Emulation.Cores.Sega.MasterSystem;
|
||||
|
||||
namespace BizHawk.Emulation.Cores.Sega.GGHawkLink
|
||||
{
|
||||
public partial class GGHawkLink : IEmulator, IVideoProvider, ISoundProvider
|
||||
{
|
||||
public IEmulatorServiceProvider ServiceProvider { get; }
|
||||
|
||||
public ControllerDefinition ControllerDefinition => _controllerDeck.Definition;
|
||||
|
||||
public bool FrameAdvance(IController controller, bool render, bool rendersound)
|
||||
{
|
||||
//Console.WriteLine("-----------------------FRAME-----------------------");
|
||||
if (_tracer.Enabled)
|
||||
{
|
||||
L.Cpu.TraceCallback = s => _tracer.Put(s);
|
||||
}
|
||||
else
|
||||
{
|
||||
L.Cpu.TraceCallback = null;
|
||||
}
|
||||
|
||||
_frame++;
|
||||
|
||||
if (controller.IsPressed("Power"))
|
||||
{
|
||||
HardReset();
|
||||
}
|
||||
|
||||
bool cablediscosignalNew = controller.IsPressed("Toggle Cable");
|
||||
if (cablediscosignalNew && !_cablediscosignal)
|
||||
{
|
||||
_cableconnected ^= true;
|
||||
Console.WriteLine("Cable connect status to {0}", _cableconnected);
|
||||
LinkConnected = _cableconnected;
|
||||
}
|
||||
|
||||
_cablediscosignal = cablediscosignalNew;
|
||||
|
||||
_islag = true;
|
||||
|
||||
GetControllerState(controller);
|
||||
|
||||
do_frame(controller, render, rendersound);
|
||||
|
||||
_islag = L._isLag;
|
||||
|
||||
if (_islag)
|
||||
{
|
||||
_lagcount++;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public void do_frame(IController controller, bool render, bool rendersound)
|
||||
{
|
||||
/*
|
||||
L.do_controller_check();
|
||||
R.do_controller_check();
|
||||
|
||||
// advance one full frame
|
||||
for (int i = 0; i < 70224; i++)
|
||||
{
|
||||
L.do_single_step();
|
||||
R.do_single_step();
|
||||
|
||||
// the signal to shift out a bit is when serial_clock = 1
|
||||
if (((L.serialport.serial_clock == 1) || (L.serialport.serial_clock == 2)) && !do_r_next)
|
||||
{
|
||||
if (LinkConnected)
|
||||
{
|
||||
L.serialport.send_external_bit((byte)(L.serialport.serial_data & 0x80));
|
||||
|
||||
if ((R.serialport.clk_rate == -1) && R.serialport.serial_start)
|
||||
{
|
||||
R.serialport.serial_clock = L.serialport.serial_clock;
|
||||
R.serialport.send_external_bit((byte)(R.serialport.serial_data & 0x80));
|
||||
R.serialport.coming_in = L.serialport.going_out;
|
||||
}
|
||||
|
||||
L.serialport.coming_in = R.serialport.going_out;
|
||||
}
|
||||
}
|
||||
else if ((R.serialport.serial_clock == 1) || (R.serialport.serial_clock == 2))
|
||||
{
|
||||
do_r_next = false;
|
||||
|
||||
if (LinkConnected)
|
||||
{
|
||||
R.serialport.send_external_bit((byte)(R.serialport.serial_data & 0x80));
|
||||
|
||||
if ((L.serialport.clk_rate == -1) && L.serialport.serial_start)
|
||||
{
|
||||
L.serialport.serial_clock = R.serialport.serial_clock;
|
||||
L.serialport.send_external_bit((byte)(L.serialport.serial_data & 0x80));
|
||||
L.serialport.coming_in = R.serialport.going_out;
|
||||
}
|
||||
|
||||
R.serialport.coming_in = L.serialport.going_out;
|
||||
}
|
||||
|
||||
if (R.serialport.serial_clock == 2) { do_r_next = true; }
|
||||
}
|
||||
else
|
||||
{
|
||||
do_r_next = false;
|
||||
}
|
||||
|
||||
// if we hit a frame boundary, update video
|
||||
if (L.vblank_rise)
|
||||
{
|
||||
buff_L = L.GetVideoBuffer();
|
||||
L.vblank_rise = false;
|
||||
FillVideoBuffer();
|
||||
}
|
||||
if (R.vblank_rise)
|
||||
{
|
||||
buff_R = R.GetVideoBuffer();
|
||||
R.vblank_rise = false;
|
||||
FillVideoBuffer();
|
||||
}
|
||||
}
|
||||
*/
|
||||
L.FrameAdvance(controller, render, rendersound);
|
||||
R.FrameAdvance(controller, render, rendersound);
|
||||
|
||||
buff_L = L.Vdp.GetVideoBuffer();
|
||||
buff_R = R.Vdp.GetVideoBuffer();
|
||||
|
||||
FillVideoBuffer();
|
||||
|
||||
}
|
||||
|
||||
public void GetControllerState(IController controller)
|
||||
{
|
||||
InputCallbacks.Call();
|
||||
//L.controller_state = _controllerDeck.ReadPort1(controller);
|
||||
//R.controller_state = _controllerDeck.ReadPort2(controller);
|
||||
}
|
||||
|
||||
public int Frame => _frame;
|
||||
|
||||
public string SystemId => "DGB";
|
||||
|
||||
public bool DeterministicEmulation { get; set; }
|
||||
|
||||
public void ResetCounters()
|
||||
{
|
||||
_frame = 0;
|
||||
_lagcount = 0;
|
||||
_islag = false;
|
||||
}
|
||||
|
||||
public CoreComm CoreComm { get; }
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
L.Dispose();
|
||||
R.Dispose();
|
||||
}
|
||||
|
||||
#region Video provider
|
||||
|
||||
public int _frameHz = 60;
|
||||
|
||||
public int[] _vidbuffer = new int[160 * 2 * 144];
|
||||
public int[] buff_L = new int[160 * 144];
|
||||
public int[] buff_R = new int[160 * 144];
|
||||
|
||||
public int[] GetVideoBuffer()
|
||||
{
|
||||
return _vidbuffer;
|
||||
}
|
||||
|
||||
public void FillVideoBuffer()
|
||||
{
|
||||
// combine the 2 video buffers from the instances
|
||||
for (int i = 0; i < 144; i++)
|
||||
{
|
||||
for (int j = 0; j < 160; j++)
|
||||
{
|
||||
_vidbuffer[i * 320 + j] = buff_L[i * 160 + j];
|
||||
_vidbuffer[i * 320 + j + 160] = buff_R[i * 160 + j];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public int VirtualWidth => 160 * 2;
|
||||
public int VirtualHeight => 144;
|
||||
public int BufferWidth => 160 * 2;
|
||||
public int BufferHeight => 144;
|
||||
public int BackgroundColor => unchecked((int)0xFF000000);
|
||||
public int VsyncNumerator => _frameHz;
|
||||
public int VsyncDenominator => 1;
|
||||
|
||||
public static readonly uint[] color_palette_BW = { 0xFFFFFFFF , 0xFFAAAAAA, 0xFF555555, 0xFF000000 };
|
||||
public static readonly uint[] color_palette_Gr = { 0xFFA4C505, 0xFF88A905, 0xFF1D551D, 0xFF052505 };
|
||||
|
||||
public uint[] color_palette = new uint[4];
|
||||
|
||||
#endregion
|
||||
|
||||
#region audio
|
||||
|
||||
public bool CanProvideAsync => false;
|
||||
|
||||
public void SetSyncMode(SyncSoundMode mode)
|
||||
{
|
||||
if (mode != SyncSoundMode.Sync)
|
||||
{
|
||||
throw new InvalidOperationException("Only Sync mode is supported_");
|
||||
}
|
||||
}
|
||||
|
||||
public SyncSoundMode SyncMode => SyncSoundMode.Sync;
|
||||
|
||||
public void GetSamplesSync(out short[] samples, out int nsamp)
|
||||
{
|
||||
short[] temp_samp_L = new short[735 * 2];
|
||||
short[] temp_samp_R = new short[735 * 2];
|
||||
|
||||
int nsamp_L = 735;
|
||||
int nsamp_R = 735;
|
||||
|
||||
L.PSG.GetSamples(temp_samp_L);
|
||||
R.PSG.GetSamples(temp_samp_R);
|
||||
|
||||
if (linkSettings.AudioSet == GGLinkSettings.AudioSrc.Left)
|
||||
{
|
||||
samples = temp_samp_L;
|
||||
nsamp = nsamp_L;
|
||||
}
|
||||
else if (linkSettings.AudioSet == GGLinkSettings.AudioSrc.Right)
|
||||
{
|
||||
samples = temp_samp_R;
|
||||
nsamp = nsamp_R;
|
||||
}
|
||||
else
|
||||
{
|
||||
samples = new short[0];
|
||||
nsamp = 0;
|
||||
}
|
||||
}
|
||||
|
||||
public void GetSamplesAsync(short[] samples)
|
||||
{
|
||||
throw new NotSupportedException("Async is not available");
|
||||
}
|
||||
|
||||
public void DiscardSamples()
|
||||
{
|
||||
L.PSG.DiscardSamples();
|
||||
R.PSG.DiscardSamples();
|
||||
}
|
||||
|
||||
private void GetSamples(short[] samples)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public void DisposeSound()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
|
@ -0,0 +1,24 @@
|
|||
using BizHawk.Emulation.Common;
|
||||
|
||||
namespace BizHawk.Emulation.Cores.Sega.GGHawkLink
|
||||
{
|
||||
public partial class GGHawkLink : IInputPollable
|
||||
{
|
||||
public int LagCount
|
||||
{
|
||||
get { return _lagcount; }
|
||||
set { _lagcount = value; }
|
||||
}
|
||||
|
||||
public bool IsLagFrame
|
||||
{
|
||||
get { return _islag; }
|
||||
set { _islag = value; }
|
||||
}
|
||||
|
||||
public IInputCallbackSystem InputCallbacks { get; } = new InputCallbackSystem();
|
||||
|
||||
public bool _islag = true;
|
||||
private int _lagcount;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,115 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
using BizHawk.Emulation.Common;
|
||||
|
||||
namespace BizHawk.Emulation.Cores.Sega.GGHawkLink
|
||||
{
|
||||
public partial class GGHawkLink
|
||||
{
|
||||
private IMemoryDomains MemoryDomains;
|
||||
|
||||
public void SetupMemoryDomains()
|
||||
{
|
||||
var domains = new List<MemoryDomain>
|
||||
{
|
||||
new MemoryDomainDelegate(
|
||||
"Main RAM L",
|
||||
L.SystemRam.Length,
|
||||
MemoryDomain.Endian.Little,
|
||||
addr => L.SystemRam[addr],
|
||||
(addr, value) => L.SystemRam[addr] = value,
|
||||
1),
|
||||
new MemoryDomainDelegate(
|
||||
"Main RAM R",
|
||||
R.SystemRam.Length,
|
||||
MemoryDomain.Endian.Little,
|
||||
addr => R.SystemRam[addr],
|
||||
(addr, value) => R.SystemRam[addr] = value,
|
||||
1),
|
||||
new MemoryDomainDelegate(
|
||||
"System Bus L",
|
||||
0X10000,
|
||||
MemoryDomain.Endian.Little,
|
||||
addr => PeekSystemBusL(addr),
|
||||
(addr, value) => PokeSystemBusL(addr, value),
|
||||
1),
|
||||
new MemoryDomainDelegate(
|
||||
"System Bus R",
|
||||
0X10000,
|
||||
MemoryDomain.Endian.Little,
|
||||
addr => PeekSystemBusR(addr),
|
||||
(addr, value) => PokeSystemBusR(addr, value),
|
||||
1),
|
||||
new MemoryDomainDelegate(
|
||||
"ROM L",
|
||||
L.RomData.Length,
|
||||
MemoryDomain.Endian.Little,
|
||||
addr => L.RomData[addr],
|
||||
(addr, value) => L.RomData[addr] = value,
|
||||
1),
|
||||
new MemoryDomainDelegate(
|
||||
"ROM R",
|
||||
R.RomData.Length,
|
||||
MemoryDomain.Endian.Little,
|
||||
addr => R.RomData[addr],
|
||||
(addr, value) => R.RomData[addr] = value,
|
||||
1),
|
||||
new MemoryDomainDelegate(
|
||||
"VRAM L",
|
||||
L.Vdp.VRAM.Length,
|
||||
MemoryDomain.Endian.Little,
|
||||
addr => L.Vdp.VRAM[addr],
|
||||
(addr, value) => L.Vdp.VRAM[addr] = value,
|
||||
1),
|
||||
new MemoryDomainDelegate(
|
||||
"VRAM R",
|
||||
R.Vdp.VRAM.Length,
|
||||
MemoryDomain.Endian.Little,
|
||||
addr => R.Vdp.VRAM[addr],
|
||||
(addr, value) => R.Vdp.VRAM[addr] = value,
|
||||
1)
|
||||
};
|
||||
|
||||
if (L.SaveRAM != null)
|
||||
{
|
||||
var CartRamL = new MemoryDomainByteArray("Cart RAM L", MemoryDomain.Endian.Little, L.SaveRAM, true, 1);
|
||||
domains.Add(CartRamL);
|
||||
}
|
||||
|
||||
if (R.SaveRAM != null)
|
||||
{
|
||||
var CartRamR = new MemoryDomainByteArray("Cart RAM R", MemoryDomain.Endian.Little, R.SaveRAM, true, 1);
|
||||
domains.Add(CartRamR);
|
||||
}
|
||||
|
||||
MemoryDomains = new MemoryDomainList(domains);
|
||||
(ServiceProvider as BasicServiceProvider).Register<IMemoryDomains>(MemoryDomains);
|
||||
}
|
||||
|
||||
private byte PeekSystemBusL(long addr)
|
||||
{
|
||||
ushort addr2 = (ushort)(addr & 0xFFFF);
|
||||
return L.ReadMemory(addr2);
|
||||
}
|
||||
|
||||
private byte PeekSystemBusR(long addr)
|
||||
{
|
||||
ushort addr2 = (ushort)(addr & 0xFFFF);
|
||||
return R.ReadMemory(addr2);
|
||||
}
|
||||
|
||||
private void PokeSystemBusL(long addr, byte value)
|
||||
{
|
||||
ushort addr2 = (ushort)(addr & 0xFFFF);
|
||||
L.WriteMemory(addr2, value);
|
||||
}
|
||||
|
||||
private void PokeSystemBusR(long addr, byte value)
|
||||
{
|
||||
ushort addr2 = (ushort)(addr & 0xFFFF);
|
||||
R.WriteMemory(addr2, value);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,81 @@
|
|||
using System;
|
||||
using BizHawk.Emulation.Common;
|
||||
|
||||
namespace BizHawk.Emulation.Cores.Sega.GGHawkLink
|
||||
{
|
||||
public partial class GGHawkLink : ISaveRam
|
||||
{
|
||||
public byte[] CloneSaveRam()
|
||||
{
|
||||
if ((L.SaveRAM != null) || (R.SaveRAM != null))
|
||||
{
|
||||
int Len1 = 0;
|
||||
int Len2 = 0;
|
||||
int index = 0;
|
||||
|
||||
if (L.SaveRAM != null)
|
||||
{
|
||||
Len1 = L.SaveRAM.Length;
|
||||
}
|
||||
|
||||
if (R.SaveRAM != null)
|
||||
{
|
||||
Len2 = R.SaveRAM.Length;
|
||||
}
|
||||
|
||||
byte[] temp = new byte[Len1 + Len2];
|
||||
|
||||
if (L.SaveRAM != null)
|
||||
{
|
||||
for (int i = 0; i < L.SaveRAM.Length; i++)
|
||||
{
|
||||
temp[index] = L.SaveRAM[i];
|
||||
index++;
|
||||
}
|
||||
}
|
||||
|
||||
if (R.SaveRAM != null)
|
||||
{
|
||||
for (int i = 0; i < L.SaveRAM.Length; i++)
|
||||
{
|
||||
temp[index] = R.SaveRAM[i];
|
||||
index++;
|
||||
}
|
||||
}
|
||||
|
||||
return temp;
|
||||
}
|
||||
else
|
||||
{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public void StoreSaveRam(byte[] data)
|
||||
{
|
||||
if ((L.SaveRAM != null) && (R.SaveRAM == null))
|
||||
{
|
||||
Buffer.BlockCopy(data, 0, L.SaveRAM, 0, L.SaveRAM.Length);
|
||||
}
|
||||
else if ((R.SaveRAM != null) && (L.SaveRAM == null))
|
||||
{
|
||||
Buffer.BlockCopy(data, 0, R.SaveRAM, 0, R.SaveRAM.Length);
|
||||
}
|
||||
else if ((R.SaveRAM != null) && (L.SaveRAM != null))
|
||||
{
|
||||
Buffer.BlockCopy(data, 0, L.SaveRAM, 0, L.SaveRAM.Length);
|
||||
Buffer.BlockCopy(data, L.SaveRAM.Length, R.SaveRAM, 0, R.SaveRAM.Length);
|
||||
}
|
||||
|
||||
Console.WriteLine("loading SRAM here");
|
||||
}
|
||||
|
||||
public bool SaveRamModified
|
||||
{
|
||||
get
|
||||
{
|
||||
return linkSyncSettings.Use_SRAM;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,78 @@
|
|||
using System;
|
||||
using System.ComponentModel;
|
||||
|
||||
using Newtonsoft.Json;
|
||||
|
||||
using BizHawk.Common;
|
||||
using BizHawk.Emulation.Common;
|
||||
|
||||
namespace BizHawk.Emulation.Cores.Sega.GGHawkLink
|
||||
{
|
||||
public partial class GGHawkLink : IEmulator, IStatable, ISettable<GGHawkLink.GGLinkSettings, GGHawkLink.GGLinkSyncSettings>
|
||||
{
|
||||
public GGLinkSettings GetSettings()
|
||||
{
|
||||
return linkSettings.Clone();
|
||||
}
|
||||
|
||||
public GGLinkSyncSettings GetSyncSettings()
|
||||
{
|
||||
return linkSyncSettings.Clone();
|
||||
}
|
||||
|
||||
public bool PutSettings(GGLinkSettings o)
|
||||
{
|
||||
linkSettings = o;
|
||||
return false;
|
||||
}
|
||||
|
||||
public bool PutSyncSettings(GGLinkSyncSettings o)
|
||||
{
|
||||
bool ret = GGLinkSyncSettings.NeedsReboot(linkSyncSettings, o);
|
||||
linkSyncSettings = o;
|
||||
return ret;
|
||||
}
|
||||
|
||||
private GGLinkSettings linkSettings = new GGLinkSettings();
|
||||
public GGLinkSyncSettings linkSyncSettings = new GGLinkSyncSettings();
|
||||
|
||||
public class GGLinkSettings
|
||||
{
|
||||
public enum AudioSrc
|
||||
{
|
||||
Left,
|
||||
Right,
|
||||
Both
|
||||
}
|
||||
|
||||
[DisplayName("Audio Selection")]
|
||||
[Description("Choose Audio Source. Both will produce Stereo sound.")]
|
||||
[DefaultValue(AudioSrc.Left)]
|
||||
public AudioSrc AudioSet { get; set; }
|
||||
|
||||
public GGLinkSettings Clone()
|
||||
{
|
||||
return (GGLinkSettings)MemberwiseClone();
|
||||
}
|
||||
}
|
||||
|
||||
public class GGLinkSyncSettings
|
||||
{
|
||||
|
||||
[DisplayName("Use Existing SaveRAM")]
|
||||
[Description("When true, existing SaveRAM will be loaded at boot up")]
|
||||
[DefaultValue(false)]
|
||||
public bool Use_SRAM { get; set; }
|
||||
|
||||
public GGLinkSyncSettings Clone()
|
||||
{
|
||||
return (GGLinkSyncSettings)MemberwiseClone();
|
||||
}
|
||||
|
||||
public static bool NeedsReboot(GGLinkSyncSettings x, GGLinkSyncSettings y)
|
||||
{
|
||||
return !DeepEquality.DeepEquals(x, y);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,68 @@
|
|||
using System.IO;
|
||||
using Newtonsoft.Json;
|
||||
|
||||
using BizHawk.Common;
|
||||
using BizHawk.Emulation.Common;
|
||||
using BizHawk.Emulation.Cores.Sega.MasterSystem;
|
||||
|
||||
namespace BizHawk.Emulation.Cores.Sega.GGHawkLink
|
||||
{
|
||||
public partial class GGHawkLink : IStatable
|
||||
{
|
||||
public bool BinarySaveStatesPreferred => true;
|
||||
|
||||
public void SaveStateText(TextWriter writer)
|
||||
{
|
||||
L.SaveStateText(writer);
|
||||
R.SaveStateText(writer);
|
||||
SyncState(new Serializer(writer));
|
||||
}
|
||||
|
||||
public void LoadStateText(TextReader reader)
|
||||
{
|
||||
L.LoadStateText(reader);
|
||||
R.LoadStateText(reader);
|
||||
SyncState(new Serializer(reader));
|
||||
}
|
||||
|
||||
public void SaveStateBinary(BinaryWriter bw)
|
||||
{
|
||||
L.SaveStateBinary(bw);
|
||||
R.SaveStateBinary(bw);
|
||||
// other variables
|
||||
SyncState(new Serializer(bw));
|
||||
}
|
||||
|
||||
public void LoadStateBinary(BinaryReader br)
|
||||
{
|
||||
L.LoadStateBinary(br);
|
||||
R.LoadStateBinary(br);
|
||||
// other variables
|
||||
SyncState(new Serializer(br));
|
||||
}
|
||||
|
||||
public byte[] SaveStateBinary()
|
||||
{
|
||||
MemoryStream ms = new MemoryStream();
|
||||
BinaryWriter bw = new BinaryWriter(ms);
|
||||
SaveStateBinary(bw);
|
||||
bw.Flush();
|
||||
return ms.ToArray();
|
||||
}
|
||||
|
||||
//private JsonSerializer ser = new JsonSerializer { Formatting = Formatting.Indented };
|
||||
|
||||
private void SyncState(Serializer ser)
|
||||
{
|
||||
ser.Sync("Lag", ref _lagcount);
|
||||
ser.Sync("Frame", ref _frame);
|
||||
ser.Sync("IsLag", ref _islag);
|
||||
ser.Sync("_cableconnected", ref _cableconnected);
|
||||
ser.Sync("_cablediscosignal", ref _cablediscosignal);
|
||||
ser.Sync("do_r_next", ref do_r_next);
|
||||
_controllerDeck.SyncState(ser);
|
||||
|
||||
LinkConnected = _cableconnected;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,91 @@
|
|||
using System;
|
||||
|
||||
using BizHawk.Common.BufferExtensions;
|
||||
using BizHawk.Emulation.Common;
|
||||
using BizHawk.Emulation.Cores.Components.Z80A;
|
||||
|
||||
using BizHawk.Emulation.Cores.Sega.MasterSystem;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace BizHawk.Emulation.Cores.Sega.GGHawkLink
|
||||
{
|
||||
[Core(
|
||||
"GGHawkLink",
|
||||
"",
|
||||
isPorted: false,
|
||||
isReleased: false)]
|
||||
[ServiceNotApplicable(typeof(IDriveLight))]
|
||||
public partial class GGHawkLink : IEmulator, ISaveRam, IDebuggable, IStatable, IInputPollable, IRegionable, ILinkable,
|
||||
ISettable<GGHawkLink.GGLinkSettings, GGHawkLink.GGLinkSyncSettings>
|
||||
{
|
||||
// we want to create two GG instances that we will run concurrently
|
||||
public SMS L;
|
||||
public SMS R;
|
||||
|
||||
// if true, the link cable is currently connected
|
||||
private bool _cableconnected = true;
|
||||
|
||||
// if true, the link cable toggle signal is currently asserted
|
||||
private bool _cablediscosignal = false;
|
||||
|
||||
private bool do_r_next = false;
|
||||
|
||||
public GGHawkLink(CoreComm comm, GameInfo game_L, byte[] rom_L, GameInfo game_R, byte[] rom_R, /*string gameDbFn,*/ object settings, object syncSettings)
|
||||
{
|
||||
var ser = new BasicServiceProvider(this);
|
||||
|
||||
linkSettings = (GGLinkSettings)settings ?? new GGLinkSettings();
|
||||
linkSyncSettings = (GGLinkSyncSettings)syncSettings ?? new GGLinkSyncSettings();
|
||||
_controllerDeck = new GGHawkLinkControllerDeck(GGHawkLinkControllerDeck.DefaultControllerName, GGHawkLinkControllerDeck.DefaultControllerName);
|
||||
|
||||
CoreComm = comm;
|
||||
|
||||
var temp_set_L = new SMS.SMSSettings();
|
||||
var temp_set_R = new SMS.SMSSettings();
|
||||
|
||||
var temp_sync_L = new SMS.SMSSyncSettings();
|
||||
var temp_sync_R = new SMS.SMSSyncSettings();
|
||||
|
||||
L = new SMS(new CoreComm(comm.ShowMessage, comm.Notify) { CoreFileProvider = comm.CoreFileProvider },
|
||||
game_L, rom_L, temp_set_L, temp_sync_L);
|
||||
|
||||
R = new SMS(new CoreComm(comm.ShowMessage, comm.Notify) { CoreFileProvider = comm.CoreFileProvider },
|
||||
game_R, rom_R, temp_set_R, temp_sync_R);
|
||||
|
||||
ser.Register<IVideoProvider>(this);
|
||||
ser.Register<ISoundProvider>(this);
|
||||
|
||||
_tracer = new TraceBuffer { Header = L.Cpu.TraceHeader };
|
||||
ser.Register<ITraceable>(_tracer);
|
||||
|
||||
ServiceProvider = ser;
|
||||
|
||||
SetupMemoryDomains();
|
||||
|
||||
HardReset();
|
||||
|
||||
LinkConnected = _cableconnected;
|
||||
}
|
||||
|
||||
public void HardReset()
|
||||
{
|
||||
L.HardReset();
|
||||
R.HardReset();
|
||||
}
|
||||
|
||||
public DisplayType Region => DisplayType.NTSC;
|
||||
|
||||
public int _frame = 0;
|
||||
|
||||
private readonly GGHawkLinkControllerDeck _controllerDeck;
|
||||
|
||||
private readonly ITraceable _tracer;
|
||||
|
||||
public bool LinkConnected { get; private set; }
|
||||
|
||||
private void ExecFetch(ushort addr)
|
||||
{
|
||||
MemoryCallbacks.CallExecutes(addr, "System Bus");
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,85 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
using BizHawk.Common;
|
||||
using BizHawk.Common.ReflectionExtensions;
|
||||
using BizHawk.Emulation.Common;
|
||||
|
||||
namespace BizHawk.Emulation.Cores.Sega.GGHawkLink
|
||||
{
|
||||
public class GGHawkLinkControllerDeck
|
||||
{
|
||||
public GGHawkLinkControllerDeck(string controller1Name, string controller2Name)
|
||||
{
|
||||
if (!ValidControllerTypes.ContainsKey(controller1Name))
|
||||
{
|
||||
throw new InvalidOperationException("Invalid controller type: " + controller1Name);
|
||||
}
|
||||
|
||||
if (!ValidControllerTypes.ContainsKey(controller2Name))
|
||||
{
|
||||
throw new InvalidOperationException("Invalid controller type: " + controller2Name);
|
||||
}
|
||||
|
||||
Port1 = (IPort)Activator.CreateInstance(ValidControllerTypes[controller1Name], 1);
|
||||
Port2 = (IPort)Activator.CreateInstance(ValidControllerTypes[controller2Name], 2);
|
||||
|
||||
Definition = new ControllerDefinition
|
||||
{
|
||||
Name = Port1.Definition.Name,
|
||||
BoolButtons = Port1.Definition.BoolButtons
|
||||
.Concat(Port2.Definition.BoolButtons)
|
||||
.Concat(new[] { "Toggle Cable" } )
|
||||
.ToList()
|
||||
};
|
||||
}
|
||||
|
||||
public byte ReadPort1(IController c)
|
||||
{
|
||||
return Port1.Read(c);
|
||||
}
|
||||
|
||||
public byte ReadPort2(IController c)
|
||||
{
|
||||
return Port2.Read(c);
|
||||
}
|
||||
|
||||
public ControllerDefinition Definition { get; }
|
||||
|
||||
public void SyncState(Serializer ser)
|
||||
{
|
||||
ser.BeginSection("Port1");
|
||||
Port1.SyncState(ser);
|
||||
ser.EndSection();
|
||||
|
||||
ser.BeginSection("Port2");
|
||||
Port2.SyncState(ser);
|
||||
ser.EndSection();
|
||||
}
|
||||
|
||||
private readonly IPort Port1;
|
||||
private readonly IPort Port2;
|
||||
|
||||
private static Dictionary<string, Type> _controllerTypes;
|
||||
|
||||
public static Dictionary<string, Type> ValidControllerTypes
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_controllerTypes == null)
|
||||
{
|
||||
_controllerTypes = typeof(GGHawkLinkControllerDeck).Assembly
|
||||
.GetTypes()
|
||||
.Where(t => typeof(IPort).IsAssignableFrom(t))
|
||||
.Where(t => !t.IsAbstract && !t.IsInterface)
|
||||
.ToDictionary(tkey => tkey.DisplayName());
|
||||
}
|
||||
|
||||
return _controllerTypes;
|
||||
}
|
||||
}
|
||||
|
||||
public static string DefaultControllerName => typeof(StandardControls).DisplayName();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,94 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel;
|
||||
using System.Linq;
|
||||
|
||||
using BizHawk.Common;
|
||||
using BizHawk.Emulation.Common;
|
||||
|
||||
namespace BizHawk.Emulation.Cores.Sega.GGHawkLink
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents a GG add on
|
||||
/// </summary>
|
||||
public interface IPort
|
||||
{
|
||||
byte Read(IController c);
|
||||
|
||||
ControllerDefinition Definition { get; }
|
||||
|
||||
void SyncState(Serializer ser);
|
||||
|
||||
int PortNum { get; }
|
||||
}
|
||||
|
||||
[DisplayName("Game Gear Controller")]
|
||||
public class StandardControls : IPort
|
||||
{
|
||||
public StandardControls(int portNum)
|
||||
{
|
||||
PortNum = portNum;
|
||||
Definition = new ControllerDefinition
|
||||
{
|
||||
Name = "GG Controller",
|
||||
BoolButtons = BaseDefinition
|
||||
.Select(b => "P" + PortNum + " " + b)
|
||||
.ToList()
|
||||
};
|
||||
}
|
||||
|
||||
public int PortNum { get; }
|
||||
|
||||
public ControllerDefinition Definition { get; }
|
||||
|
||||
public byte Read(IController c)
|
||||
{
|
||||
byte result = 0xFF;
|
||||
|
||||
if (c.IsPressed(Definition.BoolButtons[0]))
|
||||
{
|
||||
result -= 4;
|
||||
}
|
||||
if (c.IsPressed(Definition.BoolButtons[1]))
|
||||
{
|
||||
result -= 8;
|
||||
}
|
||||
if (c.IsPressed(Definition.BoolButtons[2]))
|
||||
{
|
||||
result -= 2;
|
||||
}
|
||||
if (c.IsPressed(Definition.BoolButtons[3]))
|
||||
{
|
||||
result -= 1;
|
||||
}
|
||||
if (c.IsPressed(Definition.BoolButtons[4]))
|
||||
{
|
||||
result -= 128;
|
||||
}
|
||||
if (c.IsPressed(Definition.BoolButtons[5]))
|
||||
{
|
||||
result -= 64;
|
||||
}
|
||||
if (c.IsPressed(Definition.BoolButtons[6]))
|
||||
{
|
||||
result -= 32;
|
||||
}
|
||||
if (c.IsPressed(Definition.BoolButtons[7]))
|
||||
{
|
||||
result -= 16;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
private static readonly string[] BaseDefinition =
|
||||
{
|
||||
"Up", "Down", "Left", "Right", "B1", "B2", "Start"
|
||||
};
|
||||
|
||||
public void SyncState(Serializer ser)
|
||||
{
|
||||
//nothing
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1 @@
|
|||
TODO:
|
|
@ -18,8 +18,8 @@ namespace BizHawk.Emulation.Cores.Sega.MasterSystem
|
|||
|
||||
public IInputCallbackSystem InputCallbacks { get; private set; }
|
||||
|
||||
private int _lagCount = 0;
|
||||
private bool _lagged = true;
|
||||
private bool _isLag = false;
|
||||
public int _lagCount = 0;
|
||||
public bool _lagged = true;
|
||||
public bool _isLag = false;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -28,7 +28,7 @@ namespace BizHawk.Emulation.Cores.Sega.MasterSystem
|
|||
|
||||
public bool SaveRamModified { get; private set; }
|
||||
|
||||
private byte[] SaveRAM;
|
||||
public byte[] SaveRAM;
|
||||
private byte SaveRamBank;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -213,21 +213,26 @@ namespace BizHawk.Emulation.Cores.Sega.MasterSystem
|
|||
Cpu.Regs[Cpu.SPh] = 0xDF;
|
||||
}
|
||||
|
||||
public void HardReset()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
// Constants
|
||||
private const int BankSize = 16384;
|
||||
|
||||
// ROM
|
||||
private byte[] RomData;
|
||||
public byte[] RomData;
|
||||
private byte RomBank0, RomBank1, RomBank2, RomBank3;
|
||||
private byte Bios_bank;
|
||||
private byte RomBanks;
|
||||
private byte[] BiosRom;
|
||||
|
||||
// Machine resources
|
||||
private Z80A Cpu;
|
||||
private byte[] SystemRam;
|
||||
public Z80A Cpu;
|
||||
public byte[] SystemRam;
|
||||
public VDP Vdp;
|
||||
private SN76489 PSG;
|
||||
public SN76489 PSG;
|
||||
private YM2413 YM2413;
|
||||
public bool IsGameGear { get; set; }
|
||||
public bool IsGameGear_C { get; set; }
|
||||
|
@ -281,21 +286,21 @@ namespace BizHawk.Emulation.Cores.Sega.MasterSystem
|
|||
return DisplayType.NTSC;
|
||||
}
|
||||
|
||||
private byte ReadMemory(ushort addr)
|
||||
public byte ReadMemory(ushort addr)
|
||||
{
|
||||
MemoryCallbacks.CallReads(addr, "System Bus");
|
||||
|
||||
return ReadMemoryMapper(addr);
|
||||
}
|
||||
|
||||
private void WriteMemory(ushort addr, byte value)
|
||||
public void WriteMemory(ushort addr, byte value)
|
||||
{
|
||||
WriteMemoryMapper(addr, value);
|
||||
|
||||
MemoryCallbacks.CallWrites(addr, "System Bus");
|
||||
}
|
||||
|
||||
private byte FetchMemory(ushort addr)
|
||||
public byte FetchMemory(ushort addr)
|
||||
{
|
||||
return ReadMemoryMapper(addr);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue