some snes controller rough in

This commit is contained in:
nattthebear 2017-04-15 15:40:34 -04:00
parent 5ff7905752
commit 5b41b7260b
5 changed files with 287 additions and 97 deletions

View File

@ -108,6 +108,7 @@
<Compile Include="BizInvoke\BizInvoker.cs" />
<Compile Include="BizInvoke\DynamicLibraryImportResolver.cs" />
<Compile Include="Base Implementations\CodeDataLog.cs" />
<Compile Include="ControllerDefinitionMerger.cs" />
<Compile Include="CoreAttributes.cs" />
<Compile Include="CoreComms.cs" />
<Compile Include="Database\CRC32.cs" />

View File

@ -0,0 +1,98 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace BizHawk.Emulation.Common
{
// the idea here is that various connected peripherals have their controls all merged
// into one definition, including logic to unmerge the data back so each one can work
// with it without knowing what else is connected
public static class ControllerDefinitionMerger
{
private static string Allocate(string input, ref int plr, ref int plrnext)
{
int offset = int.Parse(input.Substring(0, 1));
int currplr = plr + offset;
if (currplr >= plrnext)
plrnext = currplr + 1;
return string.Format("P{0} {1}", currplr, input.Substring(1));
}
/// <summary>
/// merge some controller definitions for different ports, and such. i promise to fully document this tomorrow
/// </summary>
/// <param name="Controllers"></param>
/// <returns></returns>
public static ControllerDefinition GetMerged(IEnumerable<ControllerDefinition> Controllers, out List<ControlDefUnMerger> Unmergers)
{
ControllerDefinition ret = new ControllerDefinition();
Unmergers = new List<ControlDefUnMerger>();
int plr = 1;
int plrnext = 1;
foreach (var def in Controllers)
{
Dictionary<string, string> remaps = new Dictionary<string, string>();
foreach (string s in def.BoolButtons)
{
string r = Allocate(s, ref plr, ref plrnext);
ret.BoolButtons.Add(r);
remaps[s] = r;
}
foreach (string s in def.FloatControls)
{
string r = Allocate(s, ref plr, ref plrnext);
ret.FloatControls.Add(r);
remaps[s] = r;
}
ret.FloatRanges.AddRange(def.FloatRanges);
plr = plrnext;
Unmergers.Add(new ControlDefUnMerger(remaps));
}
return ret;
}
}
public class ControlDefUnMerger
{
Dictionary<string, string> Remaps;
public ControlDefUnMerger(Dictionary<string, string> Remaps)
{
this.Remaps = Remaps;
}
private class DummyController : IController
{
IController src;
Dictionary<string, string> remaps;
public DummyController(IController src, Dictionary<string, string> remaps)
{
this.src = src;
this.remaps = remaps;
}
public ControllerDefinition Definition { get { throw new NotImplementedException(); } }
public bool this[string button] { get { return IsPressed(button); } }
public bool IsPressed(string button)
{
return src.IsPressed(remaps[button]);
}
public float GetFloat(string name)
{
return src.GetFloat(remaps[name]);
}
}
public IController UnMerge(IController c)
{
return new DummyController(c, Remaps);
}
}
}

View File

@ -906,6 +906,7 @@
<Compile Include="Consoles\Nintendo\SNES\LibsnesApi_Enums.cs" />
<Compile Include="Consoles\Nintendo\SNES\LibsnesApi_QUERY.cs" />
<Compile Include="Consoles\Nintendo\SNES\LibsnesApi_SIG.cs" />
<Compile Include="Consoles\Nintendo\SNES\LibsnesControllerDeck.cs" />
<Compile Include="Consoles\Nintendo\SNES\LibsnesCore.cs" />
<Compile Include="Consoles\Nintendo\SNES\SnesColors.cs" />
<Compile Include="Consoles\Nintendo\SNES\SNESGraphicsDecoder.cs" />

View File

@ -142,7 +142,7 @@ namespace BizHawk.Emulation.Cores.Nintendo.NES
this.Left = Left;
this.Right = Right;
List<ControlDefUnMerger> cdum;
Definition = ControllerDefMerger.GetMerged(new[] { Left.GetDefinition(), Right.GetDefinition() }, out cdum);
Definition = ControllerDefinitionMerger.GetMerged(new[] { Left.GetDefinition(), Right.GetDefinition() }, out cdum);
LeftU = cdum[0];
RightU = cdum[1];
@ -688,7 +688,7 @@ namespace BizHawk.Emulation.Cores.Nintendo.NES
{
Player3 = ExpSlot;
List<ControlDefUnMerger> cdum;
Definition = ControllerDefMerger.GetMerged(
Definition = ControllerDefinitionMerger.GetMerged(
new[] { Player1.GetDefinition(), Player2.GetDefinition(), Player3.GetDefinition() }, out cdum);
Definition.BoolButtons.Add("P2 Microphone");
Player1U = cdum[0];
@ -1131,101 +1131,6 @@ namespace BizHawk.Emulation.Cores.Nintendo.NES
}
}
#region control definition adapters
// the idea here is that various connected peripherals have their controls all merged
// into one definition, including logic to unmerge the data back so each one can work
// with it without knowing what else is connected
public class ControlDefUnMerger
{
Dictionary<string, string> Remaps;
public ControlDefUnMerger(Dictionary<string, string> Remaps)
{
this.Remaps = Remaps;
}
private class DummyController : IController
{
IController src;
Dictionary<string, string> remaps;
public DummyController(IController src, Dictionary<string, string> remaps)
{
this.src = src;
this.remaps = remaps;
}
public ControllerDefinition Definition { get { throw new NotImplementedException(); } }
public bool this[string button] { get { return IsPressed(button); } }
public bool IsPressed(string button)
{
return src.IsPressed(remaps[button]);
}
public float GetFloat(string name)
{
return src.GetFloat(remaps[name]);
}
}
public IController UnMerge(IController c)
{
return new DummyController(c, Remaps);
}
}
public static class ControllerDefMerger
{
private static string Allocate(string input, ref int plr, ref int plrnext)
{
int offset = int.Parse(input.Substring(0, 1));
int currplr = plr + offset;
if (currplr >= plrnext)
plrnext = currplr + 1;
return string.Format("P{0} {1}", currplr, input.Substring(1));
}
/// <summary>
/// handles all player number merging
/// </summary>
/// <param name="Controllers"></param>
/// <returns></returns>
public static ControllerDefinition GetMerged(IEnumerable<ControllerDefinition> Controllers, out List<ControlDefUnMerger> Unmergers)
{
ControllerDefinition ret = new ControllerDefinition();
Unmergers = new List<ControlDefUnMerger>();
int plr = 1;
int plrnext = 1;
foreach (var def in Controllers)
{
Dictionary<string, string> remaps = new Dictionary<string, string>();
foreach (string s in def.BoolButtons)
{
string r = Allocate(s, ref plr, ref plrnext);
ret.BoolButtons.Add(r);
remaps[s] = r;
}
foreach (string s in def.FloatControls)
{
string r = Allocate(s, ref plr, ref plrnext);
ret.FloatControls.Add(r);
remaps[s] = r;
}
ret.FloatRanges.AddRange(def.FloatRanges);
plr = plrnext;
Unmergers.Add(new ControlDefUnMerger(remaps));
}
return ret;
}
}
#endregion
#region settings
public class NESControlSettings

View File

@ -0,0 +1,185 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using BizHawk.Emulation.Common;
namespace BizHawk.Emulation.Cores.Nintendo.SNES
{
public class LibsnesControllerDeck
{
public enum ControllerType
{
Unplugged,
Gamepad,
Multitap,
Payload
}
private static ILibsnesController Factory(ControllerType t)
{
switch (t)
{
case ControllerType.Unplugged: return new SnesUnpluggedController();
case ControllerType.Gamepad: return new SnesController();
case ControllerType.Multitap: return new SnesMultitapController();
case ControllerType.Payload: return new SnesPayloadController();
default: throw new InvalidOperationException();
}
}
private readonly ILibsnesController[] _ports;
private readonly ControlDefUnMerger[] _mergers;
public ControllerDefinition Definition { get; private set; }
public LibsnesControllerDeck(ControllerType left, ControllerType right)
{
_ports = new[] { Factory(left), Factory(right) };
List<ControlDefUnMerger> tmp;
Definition = ControllerDefinitionMerger.GetMerged(_ports.Select(p => p.Definition), out tmp);
_mergers = tmp.ToArray();
}
public void NativeInit(LibsnesApi api)
{
for (int i = 0; i < 2; i++)
{
api.SetInputPortBeforeInit(i, _ports[i].PortType);
}
}
public ushort CoreInputState(IController controller, int port, int device, int index, int id)
{
return _ports[port].GetState(_mergers[port].UnMerge(controller), index, id);
}
}
public interface ILibsnesController
{
/// <summary>
/// the type to pass back to the native init
/// </summary>
LibsnesApi.SNES_INPUT_PORT PortType { get; }
/// <summary>
/// respond to a native core poll
/// </summary>
/// <param name="controller">controller input from user, remapped</param>
/// <param name="index">libsnes specific value, sometimes multitap number</param>
/// <param name="id">libsnes specific value, sometimes button number</param>
/// <returns></returns>
ushort GetState(IController controller, int index, int id);
ControllerDefinition Definition { get; }
// due to the way things are implemented, right now, all of the ILibsnesControllers are stateless
// but if one needed state, that would be doable
// void SyncState(Serializer ser);
}
public class SnesController : ILibsnesController
{
public LibsnesApi.SNES_INPUT_PORT PortType { get; } = LibsnesApi.SNES_INPUT_PORT.Joypad;
private static readonly string[] Buttons =
{
"0B",
"0Y",
"0Select",
"0Start",
"0Up",
"0Down",
"0Left",
"0Right",
"0A",
"0X",
"0L",
"0R"
};
private static readonly ControllerDefinition _definition = new ControllerDefinition
{
BoolButtons = Buttons.ToList()
};
public ControllerDefinition Definition { get; } = _definition;
public ushort GetState(IController controller, int index, int id)
{
if (id >= 12)
{
return 0;
}
return (ushort)(controller.IsPressed(Buttons[id]) ? 1 : 0);
}
}
public class SnesMultitapController: ILibsnesController
{
public LibsnesApi.SNES_INPUT_PORT PortType { get; } = LibsnesApi.SNES_INPUT_PORT.Multitap;
private static readonly string[] Buttons =
{
"B",
"Y",
"Select",
"Start",
"Up",
"Down",
"Left",
"Right",
"A",
"X",
"L",
"R"
};
private static readonly ControllerDefinition _definition = new ControllerDefinition
{
BoolButtons = Enumerable.Range(0, 4).SelectMany(i => Buttons.Select(b => i + b)).ToList()
};
public ControllerDefinition Definition { get; } = _definition;
public ushort GetState(IController controller, int index, int id)
{
if (id >= 12)
{
return 0;
}
return (ushort)(controller.IsPressed(index + Buttons[id]) ? 1 : 0);
}
}
public class SnesPayloadController : ILibsnesController
{
public LibsnesApi.SNES_INPUT_PORT PortType { get; } = LibsnesApi.SNES_INPUT_PORT.Multitap;
private static readonly ControllerDefinition _definition = new ControllerDefinition
{
BoolButtons = Enumerable.Range(0, 32).Select(i => "0B" + i).ToList()
};
public ControllerDefinition Definition { get; } = _definition;
public ushort GetState(IController controller, int index, int id)
{
return (ushort)(controller.IsPressed("0B" + (index << 4 & 16 | id)) ? 1 : 0);
}
}
public class SnesUnpluggedController : ILibsnesController
{
public LibsnesApi.SNES_INPUT_PORT PortType { get; } = LibsnesApi.SNES_INPUT_PORT.None;
private static readonly ControllerDefinition _definition = new ControllerDefinition();
public ControllerDefinition Definition { get; } = _definition;
public ushort GetState(IController controller, int index, int id)
{
return 0;
}
}
}