2011-06-27 05:31:46 +00:00
|
|
|
|
using System;
|
|
|
|
|
using System.Text;
|
|
|
|
|
using System.Collections.Generic;
|
|
|
|
|
|
|
|
|
|
namespace BizHawk.MultiClient
|
|
|
|
|
{
|
2011-07-24 20:23:27 +00:00
|
|
|
|
/// <summary>
|
|
|
|
|
/// will hold buttons for 1 frame and then release them. (Calling Click() from your button click is what you want to do)
|
|
|
|
|
/// TODO - should the duration be controllable?
|
|
|
|
|
/// </summary>
|
|
|
|
|
public class ClickyVirtualPadController : IController
|
|
|
|
|
{
|
|
|
|
|
public ControllerDefinition Type { get; set; }
|
|
|
|
|
public bool this[string button] { get { return IsPressed(button); } }
|
|
|
|
|
public float GetFloat(string name) { return 0.0f; } //TODO
|
|
|
|
|
public void UpdateControls(int frame) { }
|
|
|
|
|
public bool IsPressed(string button)
|
|
|
|
|
{
|
|
|
|
|
return Pressed.Contains(button);
|
|
|
|
|
}
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// call this once per frame to do the timekeeping for the hold and release
|
|
|
|
|
/// </summary>
|
|
|
|
|
public void FrameTick()
|
|
|
|
|
{
|
|
|
|
|
Pressed.Clear();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// call this to hold the button down for one frame
|
|
|
|
|
/// </summary>
|
|
|
|
|
public void Click(string button)
|
|
|
|
|
{
|
|
|
|
|
Pressed.Add(button);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
HashSet<string> Pressed = new HashSet<string>();
|
|
|
|
|
}
|
|
|
|
|
|
2011-07-10 06:24:04 +00:00
|
|
|
|
//filters input for things called Up and Down while considering the client's AllowUD_LR option.
|
|
|
|
|
//this is a bit gross but it is unclear how to do it more nicely
|
|
|
|
|
public class UD_LR_ControllerAdapter : IController
|
|
|
|
|
{
|
|
|
|
|
public ControllerDefinition Type { get { return Source.Type; } }
|
|
|
|
|
public IController Source;
|
|
|
|
|
|
|
|
|
|
public bool this[string button] { get { return IsPressed(button); } }
|
|
|
|
|
public float GetFloat(string name) { return 0.0f; } //TODO
|
|
|
|
|
public void UpdateControls(int frame) { }
|
2011-08-09 00:57:56 +00:00
|
|
|
|
|
2011-07-10 06:24:04 +00:00
|
|
|
|
public bool IsPressed(string button)
|
|
|
|
|
{
|
|
|
|
|
if (Global.Config.AllowUD_LR == true)
|
|
|
|
|
return Source.IsPressed(button);
|
|
|
|
|
|
|
|
|
|
string prefix;
|
|
|
|
|
|
|
|
|
|
if (button.Contains("Down"))
|
|
|
|
|
{
|
|
|
|
|
prefix = button.GetPrecedingString("Down");
|
|
|
|
|
if (Source.IsPressed(prefix + "Up"))
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
if (button.Contains("Right"))
|
|
|
|
|
{
|
|
|
|
|
prefix = button.GetPrecedingString("Right");
|
|
|
|
|
if (Source.IsPressed(prefix + "Left"))
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return Source.IsPressed(button);
|
|
|
|
|
}
|
|
|
|
|
}
|
2011-07-10 02:14:58 +00:00
|
|
|
|
|
|
|
|
|
public class SimpleController : IController
|
|
|
|
|
{
|
|
|
|
|
public ControllerDefinition Type { get; set; }
|
|
|
|
|
|
|
|
|
|
protected WorkingDictionary<string, bool> Buttons = new WorkingDictionary<string, bool>();
|
2011-07-24 19:52:13 +00:00
|
|
|
|
public virtual bool this[string button] { get { return Buttons[button]; } set { Buttons[button] = value; } }
|
|
|
|
|
public virtual bool IsPressed(string button) { return this[button]; }
|
|
|
|
|
public float GetFloat(string name) { return 0.0f; } //TODO
|
|
|
|
|
public void UpdateControls(int frame) { }
|
2011-08-09 00:57:56 +00:00
|
|
|
|
|
2012-03-24 18:39:55 +00:00
|
|
|
|
public IEnumerable<KeyValuePair<string, bool>> BoolButtons()
|
|
|
|
|
{
|
|
|
|
|
foreach (var kvp in Buttons) yield return kvp;
|
|
|
|
|
}
|
|
|
|
|
|
2011-07-24 19:52:13 +00:00
|
|
|
|
public virtual void LatchFrom(IController source)
|
|
|
|
|
{
|
|
|
|
|
foreach (string button in source.Type.BoolButtons)
|
|
|
|
|
{
|
|
|
|
|
Buttons[button] = source[button];
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2011-08-09 00:51:46 +00:00
|
|
|
|
public class ORAdapter : IController
|
|
|
|
|
{
|
|
|
|
|
public bool IsPressed(string button) { return this[button]; }
|
|
|
|
|
public float GetFloat(string name) { return 0.0f; } //TODO
|
|
|
|
|
public void UpdateControls(int frame) { }
|
|
|
|
|
|
|
|
|
|
public IController Source;
|
|
|
|
|
public IController SourceOr;
|
|
|
|
|
public ControllerDefinition Type { get { return Source.Type; } set { throw new InvalidOperationException(); } }
|
2012-02-18 15:49:44 +00:00
|
|
|
|
|
2011-08-09 00:51:46 +00:00
|
|
|
|
public bool this[string button]
|
|
|
|
|
{
|
|
|
|
|
get
|
|
|
|
|
{
|
|
|
|
|
bool source = Source[button] | SourceOr[button];
|
|
|
|
|
return source;
|
|
|
|
|
}
|
|
|
|
|
set { throw new InvalidOperationException(); }
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
2011-07-24 19:52:13 +00:00
|
|
|
|
public class StickyXORAdapter : IController
|
|
|
|
|
{
|
|
|
|
|
private HashSet<string> stickySet = new HashSet<string>();
|
|
|
|
|
public IController Source;
|
|
|
|
|
|
|
|
|
|
public ControllerDefinition Type { get { return Source.Type; } set { throw new InvalidOperationException(); } }
|
|
|
|
|
|
2011-07-10 02:14:58 +00:00
|
|
|
|
public bool IsPressed(string button) { return this[button]; }
|
|
|
|
|
public float GetFloat(string name) { return 0.0f; } //TODO
|
|
|
|
|
public void UpdateControls(int frame) { }
|
2011-08-09 00:57:56 +00:00
|
|
|
|
|
2011-07-24 19:52:13 +00:00
|
|
|
|
public bool this[string button] {
|
|
|
|
|
get
|
|
|
|
|
{
|
|
|
|
|
bool source = Source[button];
|
|
|
|
|
if (source)
|
|
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
source ^= stickySet.Contains(button);
|
|
|
|
|
return source;
|
|
|
|
|
}
|
|
|
|
|
set { throw new InvalidOperationException(); }
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public void SetSticky(string button, bool isSticky)
|
|
|
|
|
{
|
|
|
|
|
if(isSticky)
|
|
|
|
|
stickySet.Add(button);
|
|
|
|
|
else stickySet.Remove(button);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public bool IsSticky(string button)
|
|
|
|
|
{
|
|
|
|
|
return stickySet.Contains(button);
|
|
|
|
|
}
|
2011-07-10 02:14:58 +00:00
|
|
|
|
}
|
|
|
|
|
|
2011-06-27 05:31:46 +00:00
|
|
|
|
public class MnemonicsGenerator
|
|
|
|
|
{
|
|
|
|
|
IController Source;
|
|
|
|
|
public void SetSource(IController source)
|
|
|
|
|
{
|
|
|
|
|
Source = source;
|
|
|
|
|
ControlType = source.Type.Name;
|
|
|
|
|
}
|
|
|
|
|
string ControlType;
|
|
|
|
|
|
2011-07-13 00:18:47 +00:00
|
|
|
|
bool IsBasePressed(string name)
|
|
|
|
|
{
|
2011-06-27 05:31:46 +00:00
|
|
|
|
bool ret = Source.IsPressed(name);
|
2012-02-19 07:08:55 +00:00
|
|
|
|
if (ret)
|
|
|
|
|
{
|
|
|
|
|
//int zzz=9;
|
|
|
|
|
}
|
2011-06-27 05:31:46 +00:00
|
|
|
|
return ret;
|
|
|
|
|
}
|
|
|
|
|
|
2012-08-17 02:18:25 +00:00
|
|
|
|
public string GetEmptyMnemonic()
|
|
|
|
|
{
|
|
|
|
|
switch (Global.Emulator.SystemId)
|
|
|
|
|
{
|
|
|
|
|
default:
|
|
|
|
|
case "NULL":
|
|
|
|
|
return "|.|";
|
|
|
|
|
case "A26":
|
|
|
|
|
return "|..|.....|.....|";
|
|
|
|
|
case "TI83":
|
|
|
|
|
return "|..................................................|.|";
|
|
|
|
|
case "NES":
|
|
|
|
|
return "|.|........|........|........|........|";
|
|
|
|
|
case "SMS":
|
|
|
|
|
case "GG":
|
|
|
|
|
case "SG":
|
|
|
|
|
return "|......|......|..|";
|
|
|
|
|
case "GEN":
|
|
|
|
|
return "|.|........|........|";
|
|
|
|
|
case "GB":
|
|
|
|
|
return "|.|........|";
|
|
|
|
|
case "PCE":
|
|
|
|
|
case "PCECD":
|
|
|
|
|
case "SGX":
|
|
|
|
|
return "|.|........|........|........|........|........|";
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2011-06-27 05:31:46 +00:00
|
|
|
|
public string GetControllersAsMnemonic()
|
|
|
|
|
{
|
2012-06-10 04:32:25 +00:00
|
|
|
|
if (Global.Emulator.SystemId == "NULL" || ControlType == "Null Controller")
|
2012-03-03 18:24:34 +00:00
|
|
|
|
return "|.|";
|
|
|
|
|
|
2011-06-27 05:31:46 +00:00
|
|
|
|
StringBuilder input = new StringBuilder("|");
|
|
|
|
|
|
2012-03-09 15:30:09 +00:00
|
|
|
|
if (
|
|
|
|
|
ControlType == "Genesis 3-Button Controller" || ControlType == "Gameboy Controller" ||
|
|
|
|
|
ControlType == "PC Engine Controller"
|
|
|
|
|
)
|
2011-12-24 15:35:52 +00:00
|
|
|
|
{
|
2012-03-09 15:30:09 +00:00
|
|
|
|
input.Append(".");
|
2012-02-21 00:40:44 +00:00
|
|
|
|
}
|
2012-03-30 03:43:25 +00:00
|
|
|
|
if (ControlType == "Atari 2600 Basic Controller")
|
|
|
|
|
{
|
|
|
|
|
input.Append(IsBasePressed("Reset") ? "r" : ".");
|
2012-03-30 23:42:09 +00:00
|
|
|
|
input.Append(IsBasePressed("Select") ? "s" : ".");
|
2012-03-30 03:43:25 +00:00
|
|
|
|
}
|
|
|
|
|
if (ControlType == "NES Controller")
|
2012-02-21 00:40:44 +00:00
|
|
|
|
{
|
2012-09-03 21:38:11 +00:00
|
|
|
|
input.Append(IsBasePressed("Reset") ? Global.COMMANDS[ControlType]["Reset"] : ".");
|
2012-02-21 00:40:44 +00:00
|
|
|
|
}
|
|
|
|
|
if (ControlType != "SMS Controller" && ControlType != "TI83 Controller")
|
|
|
|
|
{
|
|
|
|
|
input.Append("|");
|
|
|
|
|
}
|
|
|
|
|
for (int player = 1; player <= Global.PLAYERS[ControlType]; player++)
|
|
|
|
|
{
|
|
|
|
|
string prefix = "";
|
2012-02-24 04:44:40 +00:00
|
|
|
|
if (ControlType != "Gameboy Controller" && ControlType != "TI83 Controller")
|
2011-06-27 05:31:46 +00:00
|
|
|
|
{
|
2012-02-21 00:40:44 +00:00
|
|
|
|
prefix = "P" + player.ToString() + " ";
|
2011-06-27 05:31:46 +00:00
|
|
|
|
}
|
2012-02-21 00:40:44 +00:00
|
|
|
|
foreach (string button in Global.BUTTONS[ControlType].Keys)
|
2011-06-27 05:31:46 +00:00
|
|
|
|
{
|
2012-02-21 00:40:44 +00:00
|
|
|
|
input.Append(IsBasePressed(prefix + button) ? Global.BUTTONS[ControlType][button] : ".");
|
-Finished my simplification of InputAdapters for everything but TI-83 (I don't remember how to test it). Saved 183 lines from the last revision, and this number is probably going to grow tremendously after TI-83 is handled.
-Inadvertently fixed the seemingly broken Genesis 3-Button Controller mnemonics...the controllers weren't responding at all before. I guess refactoring and working with simplified code IS worth it. <_<
--That said, this is still really broken:
---Mnemonics don't show up while recording.
---Input goes past the frame length, and it's never labeled finished.
---Doesn't seem to sync at all.
---This exception:
---------------------------
Oh, no, a terrible thing happened!
System.Exception: unhandled opcode at pc=013648
at BizHawk.Emulation.CPUs.M68000.MC68000.ExecuteCycles(Int32 cycles) in C:\Users\Administrator\Repo\bizhawk\BizHawk.Emulation\CPUs\68000\MC68000.cs:line 147
at BizHawk.Emulation.Consoles.Sega.Genesis.FrameAdvance(Boolean render) in C:\Users\Administrator\Repo\bizhawk\BizHawk.Emulation\Consoles\Sega\Genesis\Genesis.cs:line 106
at BizHawk.MultiClient.MainForm.StepRunLoop_Core() in C:\Users\Administrator\Repo\bizhawk\BizHawk.MultiClient\MainForm.cs:line 1676
at BizHawk.MultiClient.MainForm.ProgramRunLoop() in C:\Users\Administrator\Repo\bizhawk\BizHawk.MultiClient\MainForm.cs:line 346
at BizHawk.MultiClient.Program.Main(String[] args) in C:\Users\Administrator\Repo\bizhawk\BizHawk.MultiClient\Program.cs:line 47
---------------------------
System.Exception: unhandled opcode at pc=013648
at BizHawk.Emulation.CPUs.M68000.MC68000.ExecuteCycles(Int32 cycles) in C:\Users\Administrator\Repo\bizhawk\BizHawk.Emulation\CPUs\68000\MC68000.cs:line 147
at BizHawk.Emulation.Consoles.Sega.Genesis.FrameAdvance(Boolean render) in C:\Users\Administrator\Repo\bizhawk\BizHawk.Emulation\Consoles\Sega\Genesis\Genesis.cs:line 106
at BizHawk.MultiClient.MainForm.StepRunLoop_Core() in C:\Users\Administrator\Repo\bizhawk\BizHawk.MultiClient\MainForm.cs:line 1676
at BizHawk.MultiClient.MainForm.ProgramRunLoop() in C:\Users\Administrator\Repo\bizhawk\BizHawk.MultiClient\MainForm.cs:line 346
at BizHawk.MultiClient.Program.Main(String[] args) in C:\Users\Administrator\Repo\bizhawk\BizHawk.MultiClient\Program.cs:line 47
---------------------------
OK
---------------------------
--I don't think I broke anything...if anything, I fixed it slightly so that input is at least recognized in some way.
--Question: Is Genesis going to be properly supported by release time? If so, I might hold off a Genesis TAS until this is done. I hate Gens.
-Moved BUTTONS, COMMANDS, and new variable PLAYERS, which indicates how many players are for a given system, to Global.cs.
--If there's a better place for this, please let me know.
--That said, if there are places in the code that refer to the mnemonics of button names of a given system, we should definitely apply these variables for easier modification. Please let me know where these places might be.
-Fixed ImportText(). It now only reads as many controllers as the given system supports.
TODO:
-Merge the TI-83 stuff.
-Mnemonic header.
-Comment!
-Fix the TI-83 mnemonics with the IRCs blessings.
-Port the new mnemonics to the wiki.
-Fix the importers.
--I don't think ImportMMV handles the Pause and Reset commands (Or buttons, I don't even know) covert.
2012-02-20 23:25:26 +00:00
|
|
|
|
}
|
2012-02-21 00:40:44 +00:00
|
|
|
|
input.Append("|");
|
|
|
|
|
}
|
|
|
|
|
if (ControlType == "SMS Controller")
|
|
|
|
|
{
|
|
|
|
|
foreach (string command in Global.COMMANDS[ControlType].Keys)
|
-Finished my simplification of InputAdapters for everything but TI-83 (I don't remember how to test it). Saved 183 lines from the last revision, and this number is probably going to grow tremendously after TI-83 is handled.
-Inadvertently fixed the seemingly broken Genesis 3-Button Controller mnemonics...the controllers weren't responding at all before. I guess refactoring and working with simplified code IS worth it. <_<
--That said, this is still really broken:
---Mnemonics don't show up while recording.
---Input goes past the frame length, and it's never labeled finished.
---Doesn't seem to sync at all.
---This exception:
---------------------------
Oh, no, a terrible thing happened!
System.Exception: unhandled opcode at pc=013648
at BizHawk.Emulation.CPUs.M68000.MC68000.ExecuteCycles(Int32 cycles) in C:\Users\Administrator\Repo\bizhawk\BizHawk.Emulation\CPUs\68000\MC68000.cs:line 147
at BizHawk.Emulation.Consoles.Sega.Genesis.FrameAdvance(Boolean render) in C:\Users\Administrator\Repo\bizhawk\BizHawk.Emulation\Consoles\Sega\Genesis\Genesis.cs:line 106
at BizHawk.MultiClient.MainForm.StepRunLoop_Core() in C:\Users\Administrator\Repo\bizhawk\BizHawk.MultiClient\MainForm.cs:line 1676
at BizHawk.MultiClient.MainForm.ProgramRunLoop() in C:\Users\Administrator\Repo\bizhawk\BizHawk.MultiClient\MainForm.cs:line 346
at BizHawk.MultiClient.Program.Main(String[] args) in C:\Users\Administrator\Repo\bizhawk\BizHawk.MultiClient\Program.cs:line 47
---------------------------
System.Exception: unhandled opcode at pc=013648
at BizHawk.Emulation.CPUs.M68000.MC68000.ExecuteCycles(Int32 cycles) in C:\Users\Administrator\Repo\bizhawk\BizHawk.Emulation\CPUs\68000\MC68000.cs:line 147
at BizHawk.Emulation.Consoles.Sega.Genesis.FrameAdvance(Boolean render) in C:\Users\Administrator\Repo\bizhawk\BizHawk.Emulation\Consoles\Sega\Genesis\Genesis.cs:line 106
at BizHawk.MultiClient.MainForm.StepRunLoop_Core() in C:\Users\Administrator\Repo\bizhawk\BizHawk.MultiClient\MainForm.cs:line 1676
at BizHawk.MultiClient.MainForm.ProgramRunLoop() in C:\Users\Administrator\Repo\bizhawk\BizHawk.MultiClient\MainForm.cs:line 346
at BizHawk.MultiClient.Program.Main(String[] args) in C:\Users\Administrator\Repo\bizhawk\BizHawk.MultiClient\Program.cs:line 47
---------------------------
OK
---------------------------
--I don't think I broke anything...if anything, I fixed it slightly so that input is at least recognized in some way.
--Question: Is Genesis going to be properly supported by release time? If so, I might hold off a Genesis TAS until this is done. I hate Gens.
-Moved BUTTONS, COMMANDS, and new variable PLAYERS, which indicates how many players are for a given system, to Global.cs.
--If there's a better place for this, please let me know.
--That said, if there are places in the code that refer to the mnemonics of button names of a given system, we should definitely apply these variables for easier modification. Please let me know where these places might be.
-Fixed ImportText(). It now only reads as many controllers as the given system supports.
TODO:
-Merge the TI-83 stuff.
-Mnemonic header.
-Comment!
-Fix the TI-83 mnemonics with the IRCs blessings.
-Port the new mnemonics to the wiki.
-Fix the importers.
--I don't think ImportMMV handles the Pause and Reset commands (Or buttons, I don't even know) covert.
2012-02-20 23:25:26 +00:00
|
|
|
|
{
|
2012-02-21 00:40:44 +00:00
|
|
|
|
input.Append(IsBasePressed(command) ? Global.COMMANDS[ControlType][command] : ".");
|
2011-06-27 05:31:46 +00:00
|
|
|
|
}
|
2012-02-21 00:40:44 +00:00
|
|
|
|
input.Append("|");
|
2011-06-27 05:31:46 +00:00
|
|
|
|
}
|
2012-02-21 00:40:44 +00:00
|
|
|
|
if (ControlType == "TI83 Controller")
|
2011-06-27 05:31:46 +00:00
|
|
|
|
{
|
2012-02-21 00:40:44 +00:00
|
|
|
|
input.Append(".|"); //TODO: perhaps ON should go here?
|
2011-06-27 05:31:46 +00:00
|
|
|
|
}
|
2012-02-21 00:40:44 +00:00
|
|
|
|
return input.ToString();
|
2011-06-27 05:31:46 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// just copies source to sink, or returns whatever a NullController would if it is disconnected. useful for immovable hardpoints.
|
|
|
|
|
/// </summary>
|
|
|
|
|
public class CopyControllerAdapter : IController
|
|
|
|
|
{
|
|
|
|
|
public IController Source;
|
|
|
|
|
NullController _null = new NullController();
|
|
|
|
|
|
2011-07-13 00:18:47 +00:00
|
|
|
|
IController Curr
|
|
|
|
|
{
|
|
|
|
|
get
|
|
|
|
|
{
|
|
|
|
|
if (Source == null) return _null;
|
|
|
|
|
else return Source;
|
|
|
|
|
}
|
2011-06-27 05:31:46 +00:00
|
|
|
|
}
|
2011-08-09 00:57:56 +00:00
|
|
|
|
|
2011-07-13 00:18:47 +00:00
|
|
|
|
public ControllerDefinition Type { get { return Curr.Type; } }
|
|
|
|
|
public bool this[string button] { get { return Curr[button]; } }
|
|
|
|
|
public bool IsPressed(string button) { return Curr.IsPressed(button); }
|
|
|
|
|
public float GetFloat(string name) { return Curr.GetFloat(name); }
|
|
|
|
|
public void UpdateControls(int frame) { Curr.UpdateControls(frame); }
|
2011-06-27 05:31:46 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
class ButtonNameParser
|
|
|
|
|
{
|
|
|
|
|
ButtonNameParser()
|
|
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public static ButtonNameParser Parse(string button)
|
|
|
|
|
{
|
|
|
|
|
//see if we're being asked for a button that we know how to rewire
|
|
|
|
|
string[] parts = button.Split(' ');
|
|
|
|
|
if (parts.Length < 2) return null;
|
|
|
|
|
if (parts[0][0] != 'P') return null;
|
|
|
|
|
int player = 0;
|
|
|
|
|
if (!int.TryParse(parts[0].Substring(1), out player))
|
|
|
|
|
return null;
|
|
|
|
|
var bnp = new ButtonNameParser();
|
|
|
|
|
bnp.PlayerNum = player;
|
|
|
|
|
bnp.ButtonPart = button.Substring(parts[0].Length + 1);
|
|
|
|
|
return bnp;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public int PlayerNum;
|
|
|
|
|
public string ButtonPart;
|
|
|
|
|
|
|
|
|
|
public override string ToString()
|
|
|
|
|
{
|
|
|
|
|
return string.Format("P{0} {1}", PlayerNum, ButtonPart);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// rewires player1 controls to playerN
|
|
|
|
|
/// </summary>
|
|
|
|
|
public class MultitrackRewiringControllerAdapter : IController
|
|
|
|
|
{
|
|
|
|
|
public IController Source;
|
|
|
|
|
public int PlayerSource = 1;
|
|
|
|
|
public int PlayerTargetMask = 0;
|
|
|
|
|
|
2011-07-13 00:18:47 +00:00
|
|
|
|
public ControllerDefinition Type { get { return Source.Type; } }
|
|
|
|
|
public bool this[string button] { get { return this.IsPressed(button); } }
|
|
|
|
|
public float GetFloat(string name) { return Source.GetFloat(name); }
|
|
|
|
|
public void UpdateControls(int frame) { Source.UpdateControls(frame); }
|
2011-08-09 00:57:56 +00:00
|
|
|
|
|
2011-06-27 05:31:46 +00:00
|
|
|
|
public bool IsPressed(string button)
|
|
|
|
|
{
|
|
|
|
|
//do we even have a source?
|
2011-07-13 00:18:47 +00:00
|
|
|
|
if (PlayerSource == -1) return Source.IsPressed(button);
|
2011-06-27 05:31:46 +00:00
|
|
|
|
|
|
|
|
|
//see if we're being asked for a button that we know how to rewire
|
|
|
|
|
ButtonNameParser bnp = ButtonNameParser.Parse(button);
|
2011-07-13 00:18:47 +00:00
|
|
|
|
if (bnp == null) return Source.IsPressed(button);
|
2011-06-27 05:31:46 +00:00
|
|
|
|
|
|
|
|
|
//ok, this looks like a normal `P1 Button` type thing. we can handle it
|
|
|
|
|
//were we supposed to replace this one?
|
|
|
|
|
int foundPlayerMask = (1 << bnp.PlayerNum);
|
2011-07-13 00:18:47 +00:00
|
|
|
|
if ((PlayerTargetMask & foundPlayerMask) == 0) return Source.IsPressed(button);
|
2011-06-27 05:31:46 +00:00
|
|
|
|
//ok, we were. swap out the source player and then grab his button
|
|
|
|
|
bnp.PlayerNum = PlayerSource;
|
|
|
|
|
return Source.IsPressed(bnp.ToString());
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public class MovieControllerAdapter : IController
|
|
|
|
|
{
|
|
|
|
|
public MovieControllerAdapter()
|
|
|
|
|
{
|
|
|
|
|
//OutputController = new ForceControllerAdapter();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//IController implementation:
|
2011-07-24 23:14:16 +00:00
|
|
|
|
public ControllerDefinition Type { get; set; }
|
2011-06-27 05:31:46 +00:00
|
|
|
|
public bool this[string button] { get { return MyBoolButtons[button]; } }
|
|
|
|
|
public bool IsPressed(string button) { return MyBoolButtons[button]; }
|
2011-07-24 23:14:16 +00:00
|
|
|
|
public float GetFloat(string name) { return 0; }
|
|
|
|
|
public void UpdateControls(int frame) { }
|
2011-06-27 05:31:46 +00:00
|
|
|
|
//--------
|
|
|
|
|
|
2011-07-24 23:14:16 +00:00
|
|
|
|
WorkingDictionary<string, bool> MyBoolButtons = new WorkingDictionary<string, bool>();
|
2011-06-27 05:31:46 +00:00
|
|
|
|
|
2012-02-18 15:49:44 +00:00
|
|
|
|
void Force(string button, bool state)
|
2011-06-27 05:31:46 +00:00
|
|
|
|
{
|
|
|
|
|
MyBoolButtons[button] = state;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
string ControlType { get { return Type.Name; } }
|
|
|
|
|
|
|
|
|
|
class MnemonicChecker
|
|
|
|
|
{
|
|
|
|
|
public MnemonicChecker(string _m)
|
|
|
|
|
{
|
|
|
|
|
m = _m;
|
|
|
|
|
}
|
|
|
|
|
string m;
|
|
|
|
|
public bool this[int c]
|
|
|
|
|
{
|
|
|
|
|
get { return m[c] != '.'; }
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// latches one player from the source
|
|
|
|
|
/// </summary>
|
2011-07-24 23:14:16 +00:00
|
|
|
|
public void LatchPlayerFromSource(IController playerSource, int playerNum)
|
2011-06-27 05:31:46 +00:00
|
|
|
|
{
|
2011-07-24 23:14:16 +00:00
|
|
|
|
foreach (string button in playerSource.Type.BoolButtons)
|
2011-06-27 05:31:46 +00:00
|
|
|
|
{
|
|
|
|
|
ButtonNameParser bnp = ButtonNameParser.Parse(button);
|
|
|
|
|
if (bnp == null) continue;
|
|
|
|
|
if (bnp.PlayerNum != playerNum) continue;
|
2011-07-24 23:14:16 +00:00
|
|
|
|
bool val = playerSource[button];
|
2011-06-27 05:31:46 +00:00
|
|
|
|
MyBoolButtons[button] = val;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
2011-07-24 23:14:16 +00:00
|
|
|
|
/// latches all buttons from the provided source
|
2011-06-27 05:31:46 +00:00
|
|
|
|
/// </summary>
|
2011-07-24 23:14:16 +00:00
|
|
|
|
public void LatchFromSource(IController source)
|
2011-06-27 05:31:46 +00:00
|
|
|
|
{
|
|
|
|
|
foreach (string button in Type.BoolButtons)
|
|
|
|
|
{
|
2011-07-24 23:14:16 +00:00
|
|
|
|
MyBoolButtons[button] = source[button];
|
2011-06-27 05:31:46 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// latches all buttons from the supplied mnemonic string
|
|
|
|
|
/// </summary>
|
|
|
|
|
public void SetControllersAsMnemonic(string mnemonic)
|
|
|
|
|
{
|
2012-06-10 04:32:25 +00:00
|
|
|
|
if (Global.Emulator.SystemId == "NULL" || ControlType == "Null Controller")
|
2012-03-03 18:24:34 +00:00
|
|
|
|
return;
|
2011-06-27 05:31:46 +00:00
|
|
|
|
MnemonicChecker c = new MnemonicChecker(mnemonic);
|
2011-07-13 00:18:47 +00:00
|
|
|
|
|
2011-06-27 05:31:46 +00:00
|
|
|
|
MyBoolButtons.Clear();
|
|
|
|
|
|
2012-02-21 00:40:44 +00:00
|
|
|
|
int start = 3;
|
|
|
|
|
if (ControlType == "NES Controller")
|
2011-06-27 05:31:46 +00:00
|
|
|
|
{
|
2012-02-21 00:40:44 +00:00
|
|
|
|
if (mnemonic.Length < 2) return;
|
2012-06-01 05:49:26 +00:00
|
|
|
|
Force("Reset", mnemonic[1] != '.' && mnemonic[1] != '0' && mnemonic[1] != 'l');
|
2012-02-21 00:40:44 +00:00
|
|
|
|
}
|
|
|
|
|
if (ControlType == "SMS Controller" || ControlType == "TI83 Controller")
|
|
|
|
|
{
|
|
|
|
|
start = 1;
|
|
|
|
|
}
|
2012-03-30 03:43:25 +00:00
|
|
|
|
if (ControlType == "Atari 2600 Basic Controller")
|
|
|
|
|
{
|
2012-06-30 00:42:42 +00:00
|
|
|
|
if (mnemonic.Length < 2) return;
|
2012-03-30 03:43:25 +00:00
|
|
|
|
Force("Reset", mnemonic[1] != '.' && mnemonic[1] != '0');
|
2012-03-30 23:42:09 +00:00
|
|
|
|
Force("Select", mnemonic[2] != '.' && mnemonic[2] != '0');
|
|
|
|
|
start = 4;
|
2012-03-30 03:43:25 +00:00
|
|
|
|
}
|
2012-02-21 00:40:44 +00:00
|
|
|
|
for (int player = 1; player <= Global.PLAYERS[ControlType]; player++)
|
|
|
|
|
{
|
|
|
|
|
int srcindex = (player - 1) * (Global.BUTTONS[ControlType].Count + 1);
|
|
|
|
|
int ctr = start;
|
|
|
|
|
if (mnemonic.Length < srcindex + ctr + Global.BUTTONS[ControlType].Count - 1)
|
-Finished my simplification of InputAdapters for everything but TI-83 (I don't remember how to test it). Saved 183 lines from the last revision, and this number is probably going to grow tremendously after TI-83 is handled.
-Inadvertently fixed the seemingly broken Genesis 3-Button Controller mnemonics...the controllers weren't responding at all before. I guess refactoring and working with simplified code IS worth it. <_<
--That said, this is still really broken:
---Mnemonics don't show up while recording.
---Input goes past the frame length, and it's never labeled finished.
---Doesn't seem to sync at all.
---This exception:
---------------------------
Oh, no, a terrible thing happened!
System.Exception: unhandled opcode at pc=013648
at BizHawk.Emulation.CPUs.M68000.MC68000.ExecuteCycles(Int32 cycles) in C:\Users\Administrator\Repo\bizhawk\BizHawk.Emulation\CPUs\68000\MC68000.cs:line 147
at BizHawk.Emulation.Consoles.Sega.Genesis.FrameAdvance(Boolean render) in C:\Users\Administrator\Repo\bizhawk\BizHawk.Emulation\Consoles\Sega\Genesis\Genesis.cs:line 106
at BizHawk.MultiClient.MainForm.StepRunLoop_Core() in C:\Users\Administrator\Repo\bizhawk\BizHawk.MultiClient\MainForm.cs:line 1676
at BizHawk.MultiClient.MainForm.ProgramRunLoop() in C:\Users\Administrator\Repo\bizhawk\BizHawk.MultiClient\MainForm.cs:line 346
at BizHawk.MultiClient.Program.Main(String[] args) in C:\Users\Administrator\Repo\bizhawk\BizHawk.MultiClient\Program.cs:line 47
---------------------------
System.Exception: unhandled opcode at pc=013648
at BizHawk.Emulation.CPUs.M68000.MC68000.ExecuteCycles(Int32 cycles) in C:\Users\Administrator\Repo\bizhawk\BizHawk.Emulation\CPUs\68000\MC68000.cs:line 147
at BizHawk.Emulation.Consoles.Sega.Genesis.FrameAdvance(Boolean render) in C:\Users\Administrator\Repo\bizhawk\BizHawk.Emulation\Consoles\Sega\Genesis\Genesis.cs:line 106
at BizHawk.MultiClient.MainForm.StepRunLoop_Core() in C:\Users\Administrator\Repo\bizhawk\BizHawk.MultiClient\MainForm.cs:line 1676
at BizHawk.MultiClient.MainForm.ProgramRunLoop() in C:\Users\Administrator\Repo\bizhawk\BizHawk.MultiClient\MainForm.cs:line 346
at BizHawk.MultiClient.Program.Main(String[] args) in C:\Users\Administrator\Repo\bizhawk\BizHawk.MultiClient\Program.cs:line 47
---------------------------
OK
---------------------------
--I don't think I broke anything...if anything, I fixed it slightly so that input is at least recognized in some way.
--Question: Is Genesis going to be properly supported by release time? If so, I might hold off a Genesis TAS until this is done. I hate Gens.
-Moved BUTTONS, COMMANDS, and new variable PLAYERS, which indicates how many players are for a given system, to Global.cs.
--If there's a better place for this, please let me know.
--That said, if there are places in the code that refer to the mnemonics of button names of a given system, we should definitely apply these variables for easier modification. Please let me know where these places might be.
-Fixed ImportText(). It now only reads as many controllers as the given system supports.
TODO:
-Merge the TI-83 stuff.
-Mnemonic header.
-Comment!
-Fix the TI-83 mnemonics with the IRCs blessings.
-Port the new mnemonics to the wiki.
-Fix the importers.
--I don't think ImportMMV handles the Pause and Reset commands (Or buttons, I don't even know) covert.
2012-02-20 23:25:26 +00:00
|
|
|
|
{
|
2012-02-21 00:40:44 +00:00
|
|
|
|
return;
|
-Finished my simplification of InputAdapters for everything but TI-83 (I don't remember how to test it). Saved 183 lines from the last revision, and this number is probably going to grow tremendously after TI-83 is handled.
-Inadvertently fixed the seemingly broken Genesis 3-Button Controller mnemonics...the controllers weren't responding at all before. I guess refactoring and working with simplified code IS worth it. <_<
--That said, this is still really broken:
---Mnemonics don't show up while recording.
---Input goes past the frame length, and it's never labeled finished.
---Doesn't seem to sync at all.
---This exception:
---------------------------
Oh, no, a terrible thing happened!
System.Exception: unhandled opcode at pc=013648
at BizHawk.Emulation.CPUs.M68000.MC68000.ExecuteCycles(Int32 cycles) in C:\Users\Administrator\Repo\bizhawk\BizHawk.Emulation\CPUs\68000\MC68000.cs:line 147
at BizHawk.Emulation.Consoles.Sega.Genesis.FrameAdvance(Boolean render) in C:\Users\Administrator\Repo\bizhawk\BizHawk.Emulation\Consoles\Sega\Genesis\Genesis.cs:line 106
at BizHawk.MultiClient.MainForm.StepRunLoop_Core() in C:\Users\Administrator\Repo\bizhawk\BizHawk.MultiClient\MainForm.cs:line 1676
at BizHawk.MultiClient.MainForm.ProgramRunLoop() in C:\Users\Administrator\Repo\bizhawk\BizHawk.MultiClient\MainForm.cs:line 346
at BizHawk.MultiClient.Program.Main(String[] args) in C:\Users\Administrator\Repo\bizhawk\BizHawk.MultiClient\Program.cs:line 47
---------------------------
System.Exception: unhandled opcode at pc=013648
at BizHawk.Emulation.CPUs.M68000.MC68000.ExecuteCycles(Int32 cycles) in C:\Users\Administrator\Repo\bizhawk\BizHawk.Emulation\CPUs\68000\MC68000.cs:line 147
at BizHawk.Emulation.Consoles.Sega.Genesis.FrameAdvance(Boolean render) in C:\Users\Administrator\Repo\bizhawk\BizHawk.Emulation\Consoles\Sega\Genesis\Genesis.cs:line 106
at BizHawk.MultiClient.MainForm.StepRunLoop_Core() in C:\Users\Administrator\Repo\bizhawk\BizHawk.MultiClient\MainForm.cs:line 1676
at BizHawk.MultiClient.MainForm.ProgramRunLoop() in C:\Users\Administrator\Repo\bizhawk\BizHawk.MultiClient\MainForm.cs:line 346
at BizHawk.MultiClient.Program.Main(String[] args) in C:\Users\Administrator\Repo\bizhawk\BizHawk.MultiClient\Program.cs:line 47
---------------------------
OK
---------------------------
--I don't think I broke anything...if anything, I fixed it slightly so that input is at least recognized in some way.
--Question: Is Genesis going to be properly supported by release time? If so, I might hold off a Genesis TAS until this is done. I hate Gens.
-Moved BUTTONS, COMMANDS, and new variable PLAYERS, which indicates how many players are for a given system, to Global.cs.
--If there's a better place for this, please let me know.
--That said, if there are places in the code that refer to the mnemonics of button names of a given system, we should definitely apply these variables for easier modification. Please let me know where these places might be.
-Fixed ImportText(). It now only reads as many controllers as the given system supports.
TODO:
-Merge the TI-83 stuff.
-Mnemonic header.
-Comment!
-Fix the TI-83 mnemonics with the IRCs blessings.
-Port the new mnemonics to the wiki.
-Fix the importers.
--I don't think ImportMMV handles the Pause and Reset commands (Or buttons, I don't even know) covert.
2012-02-20 23:25:26 +00:00
|
|
|
|
}
|
2012-02-21 00:40:44 +00:00
|
|
|
|
string prefix = "";
|
2012-02-24 04:44:40 +00:00
|
|
|
|
if (ControlType != "Gameboy Controller" && ControlType != "TI83 Controller")
|
2011-06-27 05:31:46 +00:00
|
|
|
|
{
|
2012-02-21 00:40:44 +00:00
|
|
|
|
prefix = "P" + player + " ";
|
2011-06-27 05:31:46 +00:00
|
|
|
|
}
|
2012-02-21 00:40:44 +00:00
|
|
|
|
foreach (string button in Global.BUTTONS[ControlType].Keys)
|
2012-02-14 04:28:47 +00:00
|
|
|
|
{
|
2012-02-21 00:40:44 +00:00
|
|
|
|
Force(prefix + button, c[srcindex + ctr++]);
|
2012-02-14 04:28:47 +00:00
|
|
|
|
}
|
2011-06-27 05:31:46 +00:00
|
|
|
|
}
|
2012-02-21 00:40:44 +00:00
|
|
|
|
if (ControlType == "SMS Controller")
|
2011-06-27 05:31:46 +00:00
|
|
|
|
{
|
2012-02-21 00:40:44 +00:00
|
|
|
|
int srcindex = Global.PLAYERS[ControlType] * (Global.BUTTONS[ControlType].Count + 1);
|
|
|
|
|
int ctr = start;
|
|
|
|
|
foreach (string command in Global.COMMANDS[ControlType].Keys)
|
|
|
|
|
{
|
|
|
|
|
Force(command, c[srcindex + ctr++]);
|
|
|
|
|
}
|
2011-06-27 05:31:46 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//not being used..
|
|
|
|
|
|
|
|
|
|
///// <summary>
|
|
|
|
|
///// adapts an IController to force some buttons to a different state.
|
|
|
|
|
///// unforced button states will flow through to the adaptee
|
|
|
|
|
///// </summary>
|
|
|
|
|
//public class ForceControllerAdapter : IController
|
|
|
|
|
//{
|
|
|
|
|
// public IController Controller;
|
|
|
|
|
|
|
|
|
|
// public Dictionary<string, bool> Forces = new Dictionary<string, bool>();
|
|
|
|
|
// public void Clear()
|
|
|
|
|
// {
|
|
|
|
|
// Forces.Clear();
|
|
|
|
|
// }
|
|
|
|
|
|
|
|
|
|
// public ControllerDefinition Type { get { return Controller.Type; } }
|
|
|
|
|
|
|
|
|
|
// public bool this[string button] { get { return IsPressed(button); } }
|
|
|
|
|
|
|
|
|
|
// public bool IsPressed(string button)
|
|
|
|
|
// {
|
|
|
|
|
// if (Forces.ContainsKey(button))
|
|
|
|
|
// return Forces[button];
|
|
|
|
|
// else return Controller.IsPressed(button);
|
|
|
|
|
// }
|
|
|
|
|
|
|
|
|
|
// public float GetFloat(string name)
|
|
|
|
|
// {
|
|
|
|
|
// return Controller.GetFloat(name); //TODO!
|
|
|
|
|
// }
|
|
|
|
|
|
|
|
|
|
// public void UpdateControls(int frame)
|
|
|
|
|
// {
|
|
|
|
|
// Controller.UpdateControls(frame);
|
|
|
|
|
// }
|
|
|
|
|
//}
|
|
|
|
|
}
|