BizHawk/BizHawk.Emulation.Cores/Consoles/Sega/Saturn/SaturnusControllerDeck.cs

141 lines
3.1 KiB
C#
Raw Normal View History

using BizHawk.Emulation.Common;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace BizHawk.Emulation.Cores.Consoles.Sega.Saturn
{
public class SaturnusControllerDeck
{
private const int DataSize = 32;
private static readonly Type[] Implementors =
{
typeof(None),
typeof(Gamepad),
typeof(None),
typeof(None),
typeof(None),
typeof(None),
typeof(None),
typeof(None)
};
private readonly IDevice[] _devices;
private readonly ControlDefUnMerger[] _unmerger;
private readonly byte[] _data;
public ControllerDefinition Definition { get; }
public SaturnusControllerDeck(bool[] multitap, Device[] devices, LibSaturnus core)
{
int count = 2 + multitap.Count(b => b) * 5;
int[] dev = new int[12];
int[] mt = new int[2];
for (int i = 0; i < 12; i++)
dev[i] = (int)(i < count ? devices[i] : Device.None);
for (int i = 0; i < 2; i++)
mt[i] = multitap[i] ? 1 : 0;
core.SetupInput(dev, mt);
_devices = dev.Take(count)
.Select(i => Activator.CreateInstance(Implementors[i]))
.Cast<IDevice>()
.ToArray();
_data = new byte[count * DataSize];
List<ControlDefUnMerger> cdum;
Definition = ControllerDefinitionMerger.GetMerged(_devices.Select(d => d.Definition),
out cdum);
_unmerger = cdum.ToArray();
}
public byte[] Poll(IController controller)
{
for (int i = 0, offset = 0; i < _devices.Length; i++, offset += DataSize)
_devices[i].Update(_unmerger[i].UnMerge(controller), _data, offset);
return _data;
}
public enum Device
{
None,
Gamepad,
ThreeDeePad,
Mouse,
Wheel,
Mission,
DualMission,
Keyboard
}
private interface IDevice
{
void Update(IController controller, byte[] dest, int offset);
ControllerDefinition Definition { get; }
}
private class None : IDevice
{
private static readonly ControllerDefinition NoneDefition = new ControllerDefinition();
public ControllerDefinition Definition => NoneDefition;
public void Update(IController controller, byte[] dest, int offset)
{
}
}
private abstract class ButtonedDevice : IDevice
{
protected ButtonedDevice()
{
Definition = new ControllerDefinition
{
BoolButtons = ButtonNames.Where(s => s != null).ToList()
};
}
protected abstract string[] ButtonNames { get; }
public ControllerDefinition Definition { get; }
public virtual void Update(IController controller, byte[] dest, int offset)
{
byte data = 0;
int pos = 0;
int bit = 0;
for (int i = 0; i < ButtonNames.Length; i++)
{
if (ButtonNames[i] != null && controller.IsPressed(ButtonNames[i]))
data |= (byte)(1 << bit);
if (++bit == 8)
{
bit = 0;
dest[offset + pos++] = data;
data = 0;
}
}
if (bit != 0)
dest[offset] = data;
}
}
private class Gamepad : ButtonedDevice
{
private static readonly string[] _buttonNames =
{
"0Z", "0Y", "0X", "0R",
"0Up", "0Down", "0Left", "0Right",
"0B", "0C", "0A", "0Start",
null,null, null, "0L"
};
protected override string[] ButtonNames => _buttonNames;
}
}
}