a new style Mnemonics lookup table, and a bunch of various refactorings.

This commit is contained in:
adelikat 2013-12-07 16:31:04 +00:00
parent 94de0b0376
commit 0737f884bd
10 changed files with 725 additions and 518 deletions

View File

@ -126,6 +126,7 @@
<Compile Include="movie\IMovieHeader.cs" />
<Compile Include="movie\IMovieRecord.cs" />
<Compile Include="movie\InputAdapters.cs" />
<Compile Include="movie\MnemonicsGenerator.cs" />
<Compile Include="movie\Movie.cs" />
<Compile Include="movie\MovieHeader.cs" />
<Compile Include="movie\MovieImport.cs" />
@ -134,6 +135,7 @@
<Compile Include="movie\MovieRecord.cs" />
<Compile Include="movie\MovieSession.cs" />
<Compile Include="movie\MultitrackRecording.cs" />
<Compile Include="movie\MnemonicsLookupTable.cs" />
<Compile Include="movie\PlatformFrameRates.cs" />
<Compile Include="movie\Subtitle.cs" />
<Compile Include="movie\SubtitleList.cs" />

View File

@ -1,6 +1,8 @@
using System;
using System.IO;
using BizHawk.Emulation.Common;
namespace BizHawk.Client.Common
{
// TODO: message callback / event handler
@ -104,19 +106,19 @@ namespace BizHawk.Client.Common
/// Adds the given input to the movie
/// Note: this edits the input log without the normal movie recording logic applied
/// </summary>
void AppendFrame(MnemonicsGenerator mg);
void AppendFrame(IController source);
/// <summary>
/// Replaces the input at the given frame with the given input
/// Note: this edits the input log without the normal movie recording logic applied
/// </summary>
void PokeFrame(int frame, MnemonicsGenerator mg);
void PokeFrame(int frame, IController source);
/// <summary>
/// Records the given input into the given frame,
/// This is subject to normal movie recording logic
/// </summary>
void RecordFrame(int frame, MnemonicsGenerator mg);
void RecordFrame(int frame, IController source);
void Truncate(int frame);
string GetInput(int frame);

View File

@ -0,0 +1,482 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using BizHawk.Emulation.Common;
namespace BizHawk.Client.Common
{
// Scheduled for deletion
public class MnemonicsGenerator
{
public IController Source; // Making this public is a temporary hack
public bool this[int player, string mnemonic]
{
get
{
return IsBasePressed("P" + player + " " + mnemonic); //TODO: not every controller uses "P"
}
}
public void SetSource(IController source)
{
Source = source;
ControlType = source.Type.Name;
}
public bool IsEmpty
{
get
{
return EmptyMnemonic == GetControllersAsMnemonic();
}
}
public string EmptyMnemonic
{
get
{
switch (Global.Emulator.SystemId)
{
default:
case "NULL":
return "|.|";
case "A26":
return "|..|.....|.....|";
case "A78":
return "|....|......|......|";
case "TI83":
return "|..................................................|.|";
case "NES":
return "|.|........|........|........|........|";
case "SNES":
return "|.|............|............|............|............|";
case "SMS":
case "GG":
case "SG":
return "|......|......|..|";
case "GEN":
return "|.|........|........|";
case "GB":
return "|.|........|";
case "DGB":
return "|.|........|.|........|";
case "PCE":
case "PCECD":
case "SGX":
return "|.|........|........|........|........|........|";
case "Coleco":
return "|..................|..................|";
case "C64":
return "|.....|.....|..................................................................|";
case "GBA":
return "|.|..........|";
case "N64":
return "|.|............|............|............|............|";
case "SAT":
return "|.|.............|.............|";
}
}
}
#region Privates
private bool IsBasePressed(string name)
{
bool ret = Source.IsPressed(name);
return ret;
}
private float GetBaseFloat(string name)
{
return Source.GetFloat(name);
}
private string ControlType;
private string GetGBAControllersAsMnemonic()
{
StringBuilder input = new StringBuilder("|");
if (IsBasePressed("Power"))
{
input.Append(MnemonicConstants.COMMANDS[ControlType]["Power"]);
}
else
{
input.Append(".");
}
input.Append("|");
foreach (string button in MnemonicConstants.BUTTONS[ControlType].Keys)
{
input.Append(IsBasePressed(button) ? MnemonicConstants.BUTTONS[ControlType][button] : ".");
}
input.Append("|");
return input.ToString();
}
private string GetSNESControllersAsMnemonic()
{
StringBuilder input = new StringBuilder("|");
if (IsBasePressed("Power"))
{
input.Append(MnemonicConstants.COMMANDS[ControlType]["Power"]);
}
else if (IsBasePressed("Reset"))
{
input.Append(MnemonicConstants.COMMANDS[ControlType]["Reset"]);
}
else
{
input.Append('.');
}
input.Append("|");
for (int player = 1; player <= MnemonicConstants.PLAYERS[ControlType]; player++)
{
foreach (string button in MnemonicConstants.BUTTONS[ControlType].Keys)
{
input.Append(IsBasePressed("P" + player + " " + button) ? MnemonicConstants.BUTTONS[ControlType][button] : ".");
}
input.Append("|");
}
return input.ToString();
}
private string GetC64ControllersAsMnemonic()
{
StringBuilder input = new StringBuilder("|");
for (int player = 1; player <= MnemonicConstants.PLAYERS[ControlType]; player++)
{
foreach (string button in MnemonicConstants.BUTTONS[ControlType].Keys)
{
input.Append(IsBasePressed("P" + player + " " + button) ? MnemonicConstants.BUTTONS[ControlType][button] : ".");
}
input.Append('|');
}
foreach (string button in MnemonicConstants.BUTTONS["Commodore 64 Keyboard"].Keys)
{
input.Append(IsBasePressed(button) ? MnemonicConstants.BUTTONS["Commodore 64 Keyboard"][button] : ".");
}
input.Append('|');
input.Append('|');
return input.ToString();
}
private string GetDualGameBoyControllerAsMnemonic()
{
// |.|........|.|........|
StringBuilder input = new StringBuilder();
foreach (var t in MnemonicConstants.DGBMnemonic)
{
if (t.Item1 != null)
input.Append(IsBasePressed(t.Item1) ? t.Item2 : '.');
else
input.Append(t.Item2); // seperator
}
return input.ToString();
}
private string GetA78ControllersAsMnemonic()
{
StringBuilder input = new StringBuilder("|");
input.Append(IsBasePressed("Power") ? 'P' : '.');
input.Append(IsBasePressed("Reset") ? 'r' : '.');
input.Append(IsBasePressed("Select") ? 's' : '.');
input.Append(IsBasePressed("Pause") ? 'p' : '.');
input.Append('|');
for (int player = 1; player <= MnemonicConstants.PLAYERS[ControlType]; player++)
{
foreach (string button in MnemonicConstants.BUTTONS[ControlType].Keys)
{
input.Append(IsBasePressed("P" + player + " " + button) ? MnemonicConstants.BUTTONS[ControlType][button] : ".");
}
input.Append('|');
}
return input.ToString();
}
private string GetN64ControllersAsMnemonic()
{
StringBuilder input = new StringBuilder("|");
if (IsBasePressed("Power"))
{
input.Append('P');
}
else if (IsBasePressed("Reset"))
{
input.Append('r');
}
else
{
input.Append('.');
}
input.Append('|');
for (int player = 1; player <= MnemonicConstants.PLAYERS[ControlType]; player++)
{
foreach (string button in MnemonicConstants.BUTTONS[ControlType].Keys)
{
input.Append(IsBasePressed("P" + player + " " + button) ? MnemonicConstants.BUTTONS[ControlType][button] : ".");
}
if (MnemonicConstants.ANALOGS[ControlType].Keys.Count > 0)
{
foreach (string name in MnemonicConstants.ANALOGS[ControlType].Keys)
{
int val;
//Nasty hackery
if (name == "Y Axis")
{
if (IsBasePressed("P" + player + " A Up"))
{
val = 127;
}
else if (IsBasePressed("P" + player + " A Down"))
{
val = -127;
}
else
{
val = (int)GetBaseFloat("P" + player + " " + name);
}
}
else if (name == "X Axis")
{
if (IsBasePressed("P" + player + " A Left"))
{
val = -127;
}
else if (IsBasePressed("P" + player + " A Right"))
{
val = 127;
}
else
{
val = (int)GetBaseFloat("P" + player + " " + name);
}
}
else
{
val = (int)GetBaseFloat("P" + player + " " + name);
}
if (val >= 0)
{
input.Append(' ');
}
input.Append(String.Format("{0:000}", val)).Append(',');
}
input.Remove(input.Length - 1, 1);
}
input.Append('|');
}
return input.ToString();
}
private string GetSaturnControllersAsMnemonic()
{
StringBuilder input = new StringBuilder("|");
if (IsBasePressed("Power"))
{
input.Append('P');
}
else if (IsBasePressed("Reset"))
{
input.Append('r');
}
else
{
input.Append('.');
}
input.Append('|');
for (int player = 1; player <= MnemonicConstants.PLAYERS[ControlType]; player++)
{
foreach (string button in MnemonicConstants.BUTTONS[ControlType].Keys)
{
input.Append(IsBasePressed("P" + player + " " + button) ? MnemonicConstants.BUTTONS[ControlType][button] : ".");
}
input.Append('|');
}
return input.ToString();
}
public string GetControllersAsMnemonic()
{
if (ControlType == "Null Controller")
{
return "|.|";
}
else if (ControlType == "Atari 7800 ProLine Joystick Controller")
{
return GetA78ControllersAsMnemonic();
}
else if (ControlType == "SNES Controller")
{
return GetSNESControllersAsMnemonic();
}
else if (ControlType == "Commodore 64 Controller")
{
return GetC64ControllersAsMnemonic();
}
else if (ControlType == "GBA Controller")
{
return GetGBAControllersAsMnemonic();
}
else if (ControlType == "Dual Gameboy Controller")
{
return GetDualGameBoyControllerAsMnemonic();
}
else if (ControlType == "Nintento 64 Controller")
{
return GetN64ControllersAsMnemonic();
}
else if (ControlType == "Saturn Controller")
{
return GetSaturnControllersAsMnemonic();
}
else if (ControlType == "PSP Controller")
{
return "|.|"; // TODO
}
StringBuilder input = new StringBuilder("|");
if (ControlType == "PC Engine Controller")
{
input.Append(".");
}
else if (ControlType == "Atari 2600 Basic Controller")
{
input.Append(IsBasePressed("Reset") ? "r" : ".");
input.Append(IsBasePressed("Select") ? "s" : ".");
}
else if (ControlType == "NES Controller")
{
if (IsBasePressed("Power"))
{
input.Append(MnemonicConstants.COMMANDS[ControlType]["Power"]);
}
else if (IsBasePressed("Reset"))
{
input.Append(MnemonicConstants.COMMANDS[ControlType]["Reset"]);
}
else if (IsBasePressed("FDS Eject"))
{
input.Append(MnemonicConstants.COMMANDS[ControlType]["FDS Eject"]);
}
else if (IsBasePressed("FDS Insert 0"))
{
input.Append("0");
}
else if (IsBasePressed("FDS Insert 1"))
{
input.Append("1");
}
else if (IsBasePressed("FDS Insert 2"))
{
input.Append("2");
}
else if (IsBasePressed("FDS Insert 3"))
{
input.Append("3");
}
else if (IsBasePressed("VS Coin 1"))
{
input.Append(MnemonicConstants.COMMANDS[ControlType]["VS Coin 1"]);
}
else if (IsBasePressed("VS Coin 2"))
{
input.Append(MnemonicConstants.COMMANDS[ControlType]["VS Coin 2"]);
}
else
{
input.Append('.');
}
}
else if (ControlType == "Genesis 3-Button Controller")
{
if (IsBasePressed("Power"))
{
input.Append(MnemonicConstants.COMMANDS[ControlType]["Power"]);
}
else if (IsBasePressed("Reset"))
{
input.Append(MnemonicConstants.COMMANDS[ControlType]["Reset"]);
}
else
{
input.Append('.');
}
}
else if (ControlType == "Gameboy Controller")
{
input.Append(IsBasePressed("Power") ? MnemonicConstants.COMMANDS[ControlType]["Power"] : ".");
}
if (ControlType != "SMS Controller" && ControlType != "TI83 Controller" && ControlType != "ColecoVision Basic Controller")
{
input.Append("|");
}
for (int player = 1; player <= MnemonicConstants.PLAYERS[ControlType]; player++)
{
string prefix = "";
if (ControlType != "Gameboy Controller" && ControlType != "TI83 Controller")
{
prefix = "P" + player.ToString() + " ";
}
foreach (string button in MnemonicConstants.BUTTONS[ControlType].Keys)
{
input.Append(IsBasePressed(prefix + button) ? MnemonicConstants.BUTTONS[ControlType][button] : ".");
}
input.Append("|");
}
if (ControlType == "SMS Controller")
{
foreach (string command in MnemonicConstants.COMMANDS[ControlType].Keys)
{
input.Append(IsBasePressed(command) ? MnemonicConstants.COMMANDS[ControlType][command] : ".");
}
input.Append("|");
}
if (ControlType == "TI83 Controller")
{
input.Append(".|"); //TODO: perhaps ON should go here?
}
return input.ToString();
}
#endregion
}
public class NewMnemonicsGenerator
{
public bool IsEmpty
{
get { return false; } // TODO
}
public string EmptyMnemonic
{
get
{
return String.Empty; // TODO
}
}
}
}

View File

@ -0,0 +1,196 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace BizHawk.Client.Common
{
public class MnemonicCollection : Dictionary<string, char>
{
private readonly string _name = String.Empty;
public MnemonicCollection(string name)
{
_name = name;
}
public string Name { get { return _name; } }
}
public class CoreMnemonicCollection : List<MnemonicCollection>
{
private readonly List<string> _systemIds;
public CoreMnemonicCollection(string systemId)
{
_systemIds = new List<string>
{
systemId
};
}
public CoreMnemonicCollection(string[] systemIds)
{
_systemIds = systemIds.ToList();
}
public MnemonicCollection this[string name]
{
get
{
return this.FirstOrDefault(x => x.Name == name);
}
}
public IEnumerable<string> SystemIds
{
get { return _systemIds; }
}
}
public class MnemonicLookupTable
{
private List<CoreMnemonicCollection> _list;
public CoreMnemonicCollection this[string systemId]
{
get
{
return _list.FirstOrDefault(core => core.SystemIds.Contains(systemId));
}
}
public MnemonicLookupTable()
{
_list = new List<CoreMnemonicCollection>
{
new CoreMnemonicCollection(new []{ "NES", "FDS" })
{
new MnemonicCollection("Console")
{
{ "Reset", 'r' },
{ "Power", 'P' },
{ "FDS Eject", 'E' },
{ "FDS Insert 0", '0' },
{ "FDS Insert 1", '1' },
{ "VS Coin 1", 'c' },
{ "VS Coin 2", 'C' }
},
new MnemonicCollection("Player 1")
{
{ "P1 Up", 'U' },
{ "P1 Down", 'D' },
{ "P1 Left", 'L' },
{ "P1 Right", 'R' },
{ "P1 Select", 's' },
{ "P1 Start", 'S' },
{ "P1 B", 'B' },
{ "P1 A", 'A' }
},
new MnemonicCollection("Player 2")
{
{ "P2 Up", 'U' },
{ "P2 Down", 'D' },
{ "P2 Left", 'L' },
{ "P2 Right", 'R' },
{ "P2 Select", 's' },
{ "P2 Start", 'S' },
{ "P2 B", 'B' },
{ "P2 A", 'A' }
},
new MnemonicCollection("Player 3")
{
{ "P3 Up", 'U' },
{ "P3 Down", 'D' },
{ "P3 Left", 'L' },
{ "P3 Right", 'R' },
{ "P3 Select", 's' },
{ "P3 Start", 'S' },
{ "P3 B", 'B' },
{ "P3 A", 'A' }
},
new MnemonicCollection("Player 4")
{
{ "P4 Up", 'U' },
{ "P4 Down", 'D' },
{ "P4 Left", 'L' },
{ "P4 Right", 'R' },
{ "P4 Select", 's' },
{ "P4 Start", 'S' },
{ "P4 B", 'B' },
{ "P4 A", 'A' }
}
},
new CoreMnemonicCollection(new []{ "SNES", "SGB" })
{
new MnemonicCollection("Console")
{
{ "Reset", 'r' },
{ "Power", 'P' },
},
new MnemonicCollection("Player 1")
{
{ "P1 Up", 'U' },
{ "P1 Down", 'D' },
{ "P1 Left", 'L' },
{ "P1 Right", 'R' },
{ "P1 Select", 's' },
{ "P1 Start", 'S' },
{ "P1 B", 'B' },
{ "P1 A", 'A' },
{ "P1 X", 'X' },
{ "P1 Y", 'Y'},
{ "P1 L", 'L'},
{ "P1 R", 'R'}
},
new MnemonicCollection("Player 2")
{
{ "P2 Up", 'U' },
{ "P2 Down", 'D' },
{ "P2 Left", 'L' },
{ "P2 Right", 'R' },
{ "P2 Select", 's' },
{ "P2 Start", 'S' },
{ "P2 B", 'B' },
{ "P2 A", 'A' },
{ "P2 X", 'X' },
{ "P2 Y", 'Y'},
{ "P2 L", 'L'},
{ "P2 R", 'R'}
},
new MnemonicCollection("Player 3")
{
{ "P3 Up", 'U' },
{ "P3 Down", 'D' },
{ "P3 Left", 'L' },
{ "P3 Right", 'R' },
{ "P3 Select", 's' },
{ "P3 Start", 'S' },
{ "P3 B", 'B' },
{ "P3 A", 'A' },
{ "P3 X", 'X' },
{ "P3 Y", 'Y'},
{ "P3 L", 'L'},
{ "P3 R", 'R'}
},
new MnemonicCollection("Player 4")
{
{ "P4 Up", 'U' },
{ "P4 Down", 'D' },
{ "P4 Left", 'L' },
{ "P4 Right", 'R' },
{ "P4 Select", 's' },
{ "P4 Start", 'S' },
{ "P4 B", 'B' },
{ "P4 A", 'A' },
{ "P4 X", 'X' },
{ "P4 Y", 'Y'},
{ "P4 L", 'L'},
{ "P4 R", 'R'}
}
}
};
}
}
}

View File

@ -4,6 +4,8 @@ using System.IO;
using System.Text;
using BizHawk.Common;
using BizHawk.Emulation.Common;
namespace BizHawk.Client.Common
{
public class Movie : IMovie
@ -327,12 +329,14 @@ namespace BizHawk.Client.Common
public void ClearFrame(int frame)
{
_log.SetFrameAt(frame, MnemonicsGenerator.GetEmptyMnemonic);
_log.SetFrameAt(frame, new MnemonicsGenerator().EmptyMnemonic);
_changes = true;
}
public void AppendFrame(MnemonicsGenerator mg)
public void AppendFrame(IController source)
{
MnemonicsGenerator mg = new MnemonicsGenerator();
mg.SetSource(source);
_log.AppendFrame(mg.GetControllersAsMnemonic());
_changes = true;
}
@ -348,13 +352,16 @@ namespace BizHawk.Client.Common
#region Public Misc Methods
public void PokeFrame(int frame, MnemonicsGenerator mg)
public void PokeFrame(int frame, IController source)
{
MnemonicsGenerator mg = new MnemonicsGenerator();
mg.SetSource(source);
_changes = true;
_log.SetFrameAt(frame, mg.GetControllersAsMnemonic());
}
public void RecordFrame(int frame, MnemonicsGenerator mg)
public void RecordFrame(int frame, IController source)
{
// Note: Truncation here instead of loadstate will make VBA style loadstates
// (Where an entire movie is loaded then truncated on the next frame
@ -367,6 +374,9 @@ namespace BizHawk.Client.Common
}
}
MnemonicsGenerator mg = new MnemonicsGenerator();
mg.SetSource(source);
_changes = true;
_log.SetFrameAt(frame, mg.GetControllersAsMnemonic());
}

View File

@ -152,7 +152,6 @@ namespace BizHawk.Client.Common
break;
}
SimpleController controllers = new SimpleController {Type = new ControllerDefinition {Name = controller}};
MnemonicsGenerator mg = new MnemonicsGenerator();
// Split up the sections of the frame.
string[] sections = line.Split('|');
if (ext == ".FM2" && sections.Length >= 2 && sections[1].Length != 0)
@ -249,8 +248,7 @@ namespace BizHawk.Client.Common
}
}
// Convert the data for the controllers to a mnemonic and add it as a frame.
mg.SetSource(controllers);
m.AppendFrame(mg);
m.AppendFrame(controllers);
return m;
}
@ -568,14 +566,12 @@ namespace BizHawk.Client.Common
// Advance to first byte of input data.
r.BaseStream.Position = firstFrameOffset;
SimpleController controllers = new SimpleController {Type = new ControllerDefinition {Name = "NES Controller"}};
MnemonicsGenerator mg = new MnemonicsGenerator();
string[] buttons = new[] { "A", "B", "Select", "Start", "Up", "Down", "Left", "Right" };
bool fds = false;
bool fourscore = false;
int frame = 1;
while (frame <= frameCount)
{
mg.SetSource(controllers);
byte update = r.ReadByte();
// aa: Number of delta bytes to follow
int delta = (update >> 5) & 0x3;
@ -596,7 +592,7 @@ namespace BizHawk.Client.Common
frame += frames;
while (frames > 0)
{
m.AppendFrame(mg);
m.AppendFrame(controllers);
if (controllers["Reset"])
{
controllers["Reset"] = false;
@ -801,7 +797,6 @@ namespace BizHawk.Client.Common
m.Header[HeaderKeys.PAL] = "False";
// 090 frame data begins here
SimpleController controllers = new SimpleController {Type = new ControllerDefinition {Name = "NES Controller"}};
MnemonicsGenerator mg = new MnemonicsGenerator();
/*
* 01 Right
* 02 Left
@ -853,8 +848,7 @@ namespace BizHawk.Client.Common
warningMsg = "FDS commands are not properly supported.";
}
}
mg.SetSource(controllers);
m.AppendFrame(mg);
m.AppendFrame(controllers);
}
r.Close();
fs.Close();
@ -921,7 +915,6 @@ namespace BizHawk.Client.Common
{
Type = new ControllerDefinition {Name = "Genesis 3-Button Controller"}
};
MnemonicsGenerator mg = new MnemonicsGenerator();
/*
040 frame data
For controller bytes, each value is determined by OR-ing together values for whichever of the following are
@ -980,8 +973,7 @@ namespace BizHawk.Client.Common
}
}
}
mg.SetSource(controllers);
m.AppendFrame(mg);
m.AppendFrame(controllers);
}
return m;
}
@ -1292,7 +1284,6 @@ namespace BizHawk.Client.Common
// TODO: Verify if NTSC/"PAL" mode used for the movie can be detected or not.
// 100 variable Input data
SimpleController controllers = new SimpleController {Type = new ControllerDefinition {Name = name + " Controller"}};
MnemonicsGenerator mg = new MnemonicsGenerator();
int bytes = 256;
// The input stream consists of 1 byte for power-on and reset, and then X bytes per each input port per frame.
if (platform == "nes")
@ -1327,8 +1318,7 @@ namespace BizHawk.Client.Common
{
warningMsg = "Control commands are not properly supported.";
}
mg.SetSource(controllers);
m.AppendFrame(mg);
m.AppendFrame(controllers);
}
r.Close();
fs.Close();
@ -1414,7 +1404,6 @@ namespace BizHawk.Client.Common
byte[] md5 = r.ReadBytes(16);
m.Header[MD5] = String.Format("{0:x8}", Util.BytesToHexString(md5).ToLower());
SimpleController controllers = new SimpleController {Type = new ControllerDefinition {Name = "SMS Controller"}};
MnemonicsGenerator mg = new MnemonicsGenerator();
/*
76543210
* bit 0 (0x01): up
@ -1449,8 +1438,7 @@ namespace BizHawk.Client.Common
);
}
}
mg.SetSource(controllers);
m.AppendFrame(mg);
m.AppendFrame(controllers);
}
r.Close();
fs.Close();
@ -1641,7 +1629,6 @@ namespace BizHawk.Client.Common
uint length = r.ReadUInt32();
// ... (variable) controller data
SimpleController controllers = new SimpleController {Type = new ControllerDefinition {Name = "NES Controller"}};
MnemonicsGenerator mg = new MnemonicsGenerator();
/*
Standard controllers store data in the following format:
* 01: A
@ -1679,8 +1666,7 @@ namespace BizHawk.Client.Common
warningMsg = "Extra input is not properly supported.";
}
}
mg.SetSource(controllers);
m.AppendFrame(mg);
m.AppendFrame(controllers);
}
r.Close();
fs.Close();
@ -1746,7 +1732,6 @@ namespace BizHawk.Client.Common
* other: reserved, set to 0
*/
SimpleController controllers = new SimpleController {Type = new ControllerDefinition {Name = "SNES Controller"}};
MnemonicsGenerator mg = new MnemonicsGenerator();
bool[] controllersUsed = new bool[5];
for (int controller = 1; controller <= controllersUsed.Length; controller++)
{
@ -1951,8 +1936,7 @@ namespace BizHawk.Client.Common
{
continue;
}
mg.SetSource(controllers);
m.AppendFrame(mg);
m.AppendFrame(controllers);
}
r.Close();
fs.Close();
@ -2162,7 +2146,6 @@ namespace BizHawk.Client.Common
{
controllers.Type.Name = "GBA Controller";
}
MnemonicsGenerator mg = new MnemonicsGenerator();
/*
* 01 00 A
* 02 00 B
@ -2223,8 +2206,7 @@ namespace BizHawk.Client.Common
r.ReadBytes(2);
}
}
mg.SetSource(controllers);
m.AppendFrame(mg);
m.AppendFrame(controllers);
}
r.Close();
fs.Close();
@ -2333,7 +2315,6 @@ namespace BizHawk.Client.Common
}
r.BaseStream.Position = firstFrameOffset;
SimpleController controllers = new SimpleController {Type = new ControllerDefinition {Name = "NES Controller"}};
MnemonicsGenerator mg = new MnemonicsGenerator();
/*
* 01 A
* 02 B
@ -2443,8 +2424,7 @@ namespace BizHawk.Client.Common
controllers["P" + player + " " + buttons[button]] = (((controllerState >> button) & 0x1) != 0);
}
}
mg.SetSource(controllers);
m.AppendFrame(mg);
m.AppendFrame(controllers);
}
r.Close();
fs.Close();
@ -2566,7 +2546,6 @@ namespace BizHawk.Client.Common
// Next follows a ZST format savestate.
r.ReadBytes((int)savestateSize);
SimpleController controllers = new SimpleController {Type = new ControllerDefinition {Name = "SNES Controller"}};
MnemonicsGenerator mg = new MnemonicsGenerator();
/*
* bit 11: A
* bit 10: X
@ -2611,8 +2590,7 @@ namespace BizHawk.Client.Common
if (flag == 0x0)
{
controllers["Reset"] = true;
mg.SetSource(controllers);
m.AppendFrame(mg);
m.AppendFrame(controllers);
controllers["Reset"] = false;
}
// TODO: Other commands.
@ -2625,10 +2603,9 @@ namespace BizHawk.Client.Common
{
throw new ArgumentException("RLE data repeats for frames beyond the total frame count.");
}
mg.SetSource(controllers);
for (; frames <= frame; frames++)
{
m.AppendFrame(mg);
m.AppendFrame(controllers);
}
}
else if (((flag >> 2) & 0x1) != 0)
@ -2740,8 +2717,7 @@ namespace BizHawk.Client.Common
}
}
}
mg.SetSource(controllers);
m.AppendFrame(mg);
m.AppendFrame(controllers);
frames++;
}
}

View File

@ -5,6 +5,8 @@ using System.Text;
using BizHawk.Common;
using BizHawk.Emulation.Common;
// TODO: this entire file is scheduled to be obsolete
namespace BizHawk.Client.Common
{
public static class MnemonicConstants
@ -185,468 +187,6 @@ namespace BizHawk.Client.Common
};
}
public class MnemonicsGenerator
{
public IController Source; // Making this public is a temporary hack
private string ControlType;
public bool this[int player, string mnemonic]
{
get
{
return IsBasePressed("P" + player + " " + mnemonic); //TODO: not every controller uses "P"
}
}
public void SetSource(IController source)
{
Source = source;
ControlType = source.Type.Name;
}
bool IsBasePressed(string name)
{
bool ret = Source.IsPressed(name);
return ret;
}
float GetBaseFloat(string name)
{
return Source.GetFloat(name);
}
public bool IsEmpty
{
get
{
string empty = GetEmptyMnemonic;
string input = GetControllersAsMnemonic();
if (empty == input)
{
return true;
}
else
{
return false;
}
}
}
public static string GetEmptyMnemonic
{
get
{
switch (Global.Emulator.SystemId)
{
default:
case "NULL":
return "|.|";
case "A26":
return "|..|.....|.....|";
case "A78":
return "|....|......|......|";
case "TI83":
return "|..................................................|.|";
case "NES":
return "|.|........|........|........|........|";
case "SNES":
return "|.|............|............|............|............|";
case "SMS":
case "GG":
case "SG":
return "|......|......|..|";
case "GEN":
return "|.|........|........|";
case "GB":
return "|.|........|";
case "DGB":
return "|.|........|.|........|";
case "PCE":
case "PCECD":
case "SGX":
return "|.|........|........|........|........|........|";
case "Coleco":
return "|..................|..................|";
case "C64":
return "|.....|.....|..................................................................|";
case "GBA":
return "|.|..........|";
case "N64":
return "|.|............|............|............|............|";
case "SAT":
return "|.|.............|.............|";
}
}
}
private string GetGBAControllersAsMnemonic()
{
StringBuilder input = new StringBuilder("|");
if (IsBasePressed("Power"))
{
input.Append(MnemonicConstants.COMMANDS[ControlType]["Power"]);
}
else
{
input.Append(".");
}
input.Append("|");
foreach (string button in MnemonicConstants.BUTTONS[ControlType].Keys)
{
input.Append(IsBasePressed(button) ? MnemonicConstants.BUTTONS[ControlType][button] : ".");
}
input.Append("|");
return input.ToString();
}
//adelikat: I"m going to do all controllers like this, so what if it is redundant! It is better than reducing lines of code with convoluted logic that is difficult to expand to support new platforms
private string GetSNESControllersAsMnemonic()
{
StringBuilder input = new StringBuilder("|");
if (IsBasePressed("Power"))
{
input.Append(MnemonicConstants.COMMANDS[ControlType]["Power"]);
}
else if (IsBasePressed("Reset"))
{
input.Append(MnemonicConstants.COMMANDS[ControlType]["Reset"]);
}
else
{
input.Append('.');
}
input.Append("|");
for (int player = 1; player <= MnemonicConstants.PLAYERS[ControlType]; player++)
{
foreach (string button in MnemonicConstants.BUTTONS[ControlType].Keys)
{
input.Append(IsBasePressed("P" + player + " " + button) ? MnemonicConstants.BUTTONS[ControlType][button] : ".");
}
input.Append("|");
}
return input.ToString();
}
private string GetC64ControllersAsMnemonic()
{
StringBuilder input = new StringBuilder("|");
for (int player = 1; player <= MnemonicConstants.PLAYERS[ControlType]; player++)
{
foreach (string button in MnemonicConstants.BUTTONS[ControlType].Keys)
{
input.Append(IsBasePressed("P" + player + " " + button) ? MnemonicConstants.BUTTONS[ControlType][button] : ".");
}
input.Append('|');
}
foreach (string button in MnemonicConstants.BUTTONS["Commodore 64 Keyboard"].Keys)
{
input.Append(IsBasePressed(button) ? MnemonicConstants.BUTTONS["Commodore 64 Keyboard"][button] : ".");
}
input.Append('|');
input.Append('|');
return input.ToString();
}
private string GetDualGameBoyControllerAsMnemonic()
{
// |.|........|.|........|
StringBuilder input = new StringBuilder();
foreach (var t in MnemonicConstants.DGBMnemonic)
{
if (t.Item1 != null)
input.Append(IsBasePressed(t.Item1) ? t.Item2 : '.');
else
input.Append(t.Item2); // seperator
}
return input.ToString();
}
private string GetA78ControllersAsMnemonic()
{
StringBuilder input = new StringBuilder("|");
input.Append(IsBasePressed("Power") ? 'P' : '.');
input.Append(IsBasePressed("Reset") ? 'r' : '.');
input.Append(IsBasePressed("Select") ? 's' : '.');
input.Append(IsBasePressed("Pause") ? 'p' : '.');
input.Append('|');
for (int player = 1; player <= MnemonicConstants.PLAYERS[ControlType]; player++)
{
foreach (string button in MnemonicConstants.BUTTONS[ControlType].Keys)
{
input.Append(IsBasePressed("P" + player + " " + button) ? MnemonicConstants.BUTTONS[ControlType][button] : ".");
}
input.Append('|');
}
return input.ToString();
}
private string GetN64ControllersAsMnemonic()
{
StringBuilder input = new StringBuilder("|");
if (IsBasePressed("Power"))
{
input.Append('P');
}
else if (IsBasePressed("Reset"))
{
input.Append('r');
}
else
{
input.Append('.');
}
input.Append('|');
for (int player = 1; player <= MnemonicConstants.PLAYERS[ControlType]; player++)
{
foreach (string button in MnemonicConstants.BUTTONS[ControlType].Keys)
{
input.Append(IsBasePressed("P" + player + " " + button) ? MnemonicConstants.BUTTONS[ControlType][button] : ".");
}
if (MnemonicConstants.ANALOGS[ControlType].Keys.Count > 0)
{
foreach (string name in MnemonicConstants.ANALOGS[ControlType].Keys)
{
int val;
//Nasty hackery
if (name == "Y Axis")
{
if (IsBasePressed("P" + player + " A Up"))
{
val = 127;
}
else if (IsBasePressed("P" + player + " A Down"))
{
val = -127;
}
else
{
val = (int)GetBaseFloat("P" + player + " " + name);
}
}
else if (name == "X Axis")
{
if (IsBasePressed("P" + player + " A Left"))
{
val = -127;
}
else if (IsBasePressed("P" + player + " A Right"))
{
val = 127;
}
else
{
val = (int)GetBaseFloat("P" + player + " " + name);
}
}
else
{
val = (int)GetBaseFloat("P" + player + " " + name);
}
if (val >= 0)
{
input.Append(' ');
}
input.Append(String.Format("{0:000}", val)).Append(',');
}
input.Remove(input.Length - 1, 1);
}
input.Append('|');
}
return input.ToString();
}
private string GetSaturnControllersAsMnemonic()
{
StringBuilder input = new StringBuilder("|");
if (IsBasePressed("Power"))
{
input.Append('P');
}
else if (IsBasePressed("Reset"))
{
input.Append('r');
}
else
{
input.Append('.');
}
input.Append('|');
for (int player = 1; player <= MnemonicConstants.PLAYERS[ControlType]; player++)
{
foreach (string button in MnemonicConstants.BUTTONS[ControlType].Keys)
{
input.Append(IsBasePressed("P" + player + " " + button) ? MnemonicConstants.BUTTONS[ControlType][button] : ".");
}
input.Append('|');
}
return input.ToString();
}
public string GetControllersAsMnemonic()
{
if (ControlType == "Null Controller")
{
return "|.|";
}
else if (ControlType == "Atari 7800 ProLine Joystick Controller")
{
return GetA78ControllersAsMnemonic();
}
else if (ControlType == "SNES Controller")
{
return GetSNESControllersAsMnemonic();
}
else if (ControlType == "Commodore 64 Controller")
{
return GetC64ControllersAsMnemonic();
}
else if (ControlType == "GBA Controller")
{
return GetGBAControllersAsMnemonic();
}
else if (ControlType == "Dual Gameboy Controller")
{
return GetDualGameBoyControllerAsMnemonic();
}
else if (ControlType == "Nintento 64 Controller")
{
return GetN64ControllersAsMnemonic();
}
else if (ControlType == "Saturn Controller")
{
return GetSaturnControllersAsMnemonic();
}
else if (ControlType == "PSP Controller")
{
return "|.|"; // TODO
}
StringBuilder input = new StringBuilder("|");
if (ControlType == "PC Engine Controller")
{
input.Append(".");
}
else if (ControlType == "Atari 2600 Basic Controller")
{
input.Append(IsBasePressed("Reset") ? "r" : ".");
input.Append(IsBasePressed("Select") ? "s" : ".");
}
else if (ControlType == "NES Controller")
{
if (IsBasePressed("Power"))
{
input.Append(MnemonicConstants.COMMANDS[ControlType]["Power"]);
}
else if (IsBasePressed("Reset"))
{
input.Append(MnemonicConstants.COMMANDS[ControlType]["Reset"]);
}
else if (IsBasePressed("FDS Eject"))
{
input.Append(MnemonicConstants.COMMANDS[ControlType]["FDS Eject"]);
}
else if (IsBasePressed("FDS Insert 0"))
{
input.Append("0");
}
else if (IsBasePressed("FDS Insert 1"))
{
input.Append("1");
}
else if (IsBasePressed("FDS Insert 2"))
{
input.Append("2");
}
else if (IsBasePressed("FDS Insert 3"))
{
input.Append("3");
}
else if (IsBasePressed("VS Coin 1"))
{
input.Append(MnemonicConstants.COMMANDS[ControlType]["VS Coin 1"]);
}
else if (IsBasePressed("VS Coin 2"))
{
input.Append(MnemonicConstants.COMMANDS[ControlType]["VS Coin 2"]);
}
else
{
input.Append('.');
}
}
else if (ControlType == "Genesis 3-Button Controller")
{
if (IsBasePressed("Power"))
{
input.Append(MnemonicConstants.COMMANDS[ControlType]["Power"]);
}
else if (IsBasePressed("Reset"))
{
input.Append(MnemonicConstants.COMMANDS[ControlType]["Reset"]);
}
else
{
input.Append('.');
}
}
else if (ControlType == "Gameboy Controller")
{
input.Append(IsBasePressed("Power") ? MnemonicConstants.COMMANDS[ControlType]["Power"] : ".");
}
if (ControlType != "SMS Controller" && ControlType != "TI83 Controller" && ControlType != "ColecoVision Basic Controller")
{
input.Append("|");
}
for (int player = 1; player <= MnemonicConstants.PLAYERS[ControlType]; player++)
{
string prefix = "";
if (ControlType != "Gameboy Controller" && ControlType != "TI83 Controller")
{
prefix = "P" + player.ToString() + " ";
}
foreach (string button in MnemonicConstants.BUTTONS[ControlType].Keys)
{
input.Append(IsBasePressed(prefix + button) ? MnemonicConstants.BUTTONS[ControlType][button] : ".");
}
input.Append("|");
}
if (ControlType == "SMS Controller")
{
foreach (string command in MnemonicConstants.COMMANDS[ControlType].Keys)
{
input.Append(IsBasePressed(command) ? MnemonicConstants.COMMANDS[ControlType][command] : ".");
}
input.Append("|");
}
if (ControlType == "TI83 Controller")
{
input.Append(".|"); //TODO: perhaps ON should go here?
}
return input.ToString();
}
}
public class MovieControllerAdapter : IController
{
//IController implementation:

View File

@ -151,7 +151,7 @@ namespace BizHawk.Client.Common
if (!mg.IsEmpty)
{
LatchInputFromPlayer(Global.MovieInputSourceAdapter);
Movie.PokeFrame(Global.Emulator.Frame, mg);
Movie.PokeFrame(Global.Emulator.Frame, Global.MovieOutputHardpoint);
}
else
{
@ -173,9 +173,7 @@ namespace BizHawk.Client.Common
// the movie session makes sure that the correct input has been read and merged to its MovieControllerAdapter;
// this has been wired to Global.MovieOutputHardpoint in RewireInputChain
var mg = new MnemonicsGenerator();
mg.SetSource(Global.MovieOutputHardpoint);
Movie.RecordFrame(Global.Emulator.Frame, mg);
Movie.RecordFrame(Global.Emulator.Frame, Global.MovieOutputHardpoint);
}
}

View File

@ -4,6 +4,8 @@ using System.IO;
using System.Linq;
using System.Text;
using BizHawk.Emulation.Common;
namespace BizHawk.Client.Common
{
public class TasMovie : IMovie
@ -162,13 +164,13 @@ namespace BizHawk.Client.Common
}
}
public void AppendFrame(MnemonicsGenerator mg)
public void AppendFrame(IController source)
{
Changes = true;
_records.Add(new MovieRecord(mg.Source, true));
_records.Add(new MovieRecord(source, true));
}
public void RecordFrame(int frame, MnemonicsGenerator mg)
public void RecordFrame(int frame, IController source)
{
if (_mode == Moviemode.Record)
{
@ -183,21 +185,21 @@ namespace BizHawk.Client.Common
if (frame < _records.Count)
{
PokeFrame(frame, mg);
PokeFrame(frame, source);
}
else
{
AppendFrame(mg);
AppendFrame(source);
}
}
}
public void PokeFrame(int frame, MnemonicsGenerator mg)
public void PokeFrame(int frame, IController source)
{
if (frame < _records.Count)
{
Changes = true;
_records[frame].SetInput(mg.Source);
_records[frame].SetInput(source);
}
}

View File

@ -11,7 +11,6 @@
public void SetSticky(string button, bool sticky) { }
public bool IsSticky(string button) { return false; }
private static readonly NullController nullController = new NullController();
public static NullController GetNullController() { return nullController; }
}