-Controller type for GBA.

-Cleanup (adelikat inspired me to always use braces).
This commit is contained in:
brandman211 2012-12-06 05:19:08 +00:00
parent e449ab34fd
commit a346389c2f
2 changed files with 218 additions and 33 deletions

View File

@ -62,7 +62,7 @@ namespace BizHawk.MultiClient
"GBA Controller", new Dictionary<string, string>() "GBA Controller", new Dictionary<string, string>()
{ {
{"Up", "U"}, {"Down", "D"}, {"Left", "L"}, {"Right", "R"}, {"Select", "s"}, {"Start", "S"}, {"B", "B"}, {"Up", "U"}, {"Down", "D"}, {"Left", "L"}, {"Right", "R"}, {"Select", "s"}, {"Start", "S"}, {"B", "B"},
{"A", "A"}, {"L", "L"}, {"R", "R"}, {"A", "A"}, {"L", "L"}, {"R", "R"}
} }
}, },
{ {
@ -83,7 +83,7 @@ namespace BizHawk.MultiClient
"SNES Controller", new Dictionary<string, string>() "SNES Controller", new Dictionary<string, string>()
{ {
{"Up", "U"}, {"Down", "D"}, {"Left", "L"}, {"Right", "R"}, {"Select", "s"}, {"Start", "S"}, {"B", "B"}, {"Up", "U"}, {"Down", "D"}, {"Left", "L"}, {"Right", "R"}, {"Select", "s"}, {"Start", "S"}, {"B", "B"},
{"A", "A"}, {"X", "X"}, {"Y", "Y"}, {"L", "L"}, {"R", "R"}, {"A", "A"}, {"X", "X"}, {"Y", "Y"}, {"L", "L"}, {"R", "R"}
} }
}, },
{ {
@ -160,9 +160,8 @@ namespace BizHawk.MultiClient
public static readonly Dictionary<string, int> PLAYERS = new Dictionary<string, int>() public static readonly Dictionary<string, int> PLAYERS = new Dictionary<string, int>()
{ {
{"Gameboy Controller", 1}, {"Genesis 3-Button Controller", 2}, {"NES Controller", 4}, {"Gameboy Controller", 1}, {"GBA Controller", 1}, {"Genesis 3-Button Controller", 2}, {"NES Controller", 4},
{"SNES Controller", 4}, {"SNES Controller", 4}, {"PC Engine Controller", 5}, {"SMS Controller", 2}, {"TI83 Controller", 1}, {"Atari 2600 Basic Controller", 2},
{"PC Engine Controller", 5}, {"SMS Controller", 2}, {"TI83 Controller", 1}, {"Atari 2600 Basic Controller", 2},
{"ColecoVision Basic Controller", 2}, {"Commodore 64 Controller", 2} {"ColecoVision Basic Controller", 2}, {"Commodore 64 Controller", 2}
}; };

View File

@ -100,8 +100,12 @@ namespace BizHawk.MultiClient
"FCM", "FM2", "FMV", "GMV", "MCM", "MC2", "MMV", "NMV", "LSMV", "SMV", "VBM", "VMV", "ZMV" "FCM", "FM2", "FMV", "GMV", "MCM", "MC2", "MMV", "NMV", "LSMV", "SMV", "VBM", "VMV", "ZMV"
}; };
foreach (string ext in extensions) foreach (string ext in extensions)
{
if (extension.ToUpper() == "." + ext) if (extension.ToUpper() == "." + ext)
{
return true; return true;
}
}
return false; return false;
} }
@ -170,7 +174,9 @@ namespace BizHawk.MultiClient
break; break;
case '2': case '2':
if (m.Frames != 0) if (m.Frames != 0)
{
warningMsg = "hard reset"; warningMsg = "hard reset";
}
break; break;
case '4': case '4':
warningMsg = "FDS Insert"; warningMsg = "FDS Insert";
@ -183,7 +189,9 @@ namespace BizHawk.MultiClient
break; break;
} }
if (warningMsg != "") if (warningMsg != "")
{
warningMsg = "Unable to import " + warningMsg + " command on line " + lineNum + "."; warningMsg = "Unable to import " + warningMsg + " command on line " + lineNum + ".";
}
} }
} }
if (Path.GetExtension(path).ToUpper() == ".LSMV" && sections.Length != 0) if (Path.GetExtension(path).ToUpper() == ".LSMV" && sections.Length != 0)
@ -201,7 +209,9 @@ namespace BizHawk.MultiClient
if (reset && ((flags.Length >= 2 && flags[1] != '0') || (flags.Length >= 4 && flags[3] != '0'))) if (reset && ((flags.Length >= 2 && flags[1] != '0') || (flags.Length >= 4 && flags[3] != '0')))
{ {
if (warningMsg == "") if (warningMsg == "")
{
warningMsg = "Unable to import delayed reset."; warningMsg = "Unable to import delayed reset.";
}
return m; return m;
} }
controllers["Reset"] = reset; controllers["Reset"] = reset;
@ -227,15 +237,21 @@ namespace BizHawk.MultiClient
string prefix = "P" + (player).ToString() + " "; string prefix = "P" + (player).ToString() + " ";
// Gameboy doesn't currently have a prefix saying which player the input is for. // Gameboy doesn't currently have a prefix saying which player the input is for.
if (controllers.Type.Name == "Gameboy Controller") if (controllers.Type.Name == "Gameboy Controller")
{
prefix = ""; prefix = "";
}
// Only count lines with that have the right number of buttons and are for valid players. // Only count lines with that have the right number of buttons and are for valid players.
if ( if (
sections[section].Length == buttons.Length && sections[section].Length == buttons.Length &&
player <= Global.PLAYERS[controllers.Type.Name] player <= Global.PLAYERS[controllers.Type.Name]
) )
{
for (int button = 0; button < buttons.Length; button++) for (int button = 0; button < buttons.Length; button++)
{
// Consider the button pressed so long as its spot is not occupied by a ".". // Consider the button pressed so long as its spot is not occupied by a ".".
controllers[prefix + buttons[button]] = (sections[section][button] != '.'); controllers[prefix + buttons[button]] = (sections[section][button] != '.');
}
}
} }
// Convert the data for the controllers to a mnemonic and add it as a frame. // Convert the data for the controllers to a mnemonic and add it as a frame.
mg.SetSource(controllers); mg.SetSource(controllers);
@ -300,7 +316,9 @@ namespace BizHawk.MultiClient
{ {
lineNum++; lineNum++;
if (line == "") if (line == "")
{
continue; continue;
}
else if (line[0] == '|') else if (line[0] == '|')
{ {
m = ImportTextFrame(line, lineNum, m, path, platform, ref warningMsg, ref errorMsg); m = ImportTextFrame(line, lineNum, m, path, platform, ref warningMsg, ref errorMsg);
@ -311,11 +329,15 @@ namespace BizHawk.MultiClient
} }
} }
else if (line.ToLower().StartsWith("sub")) else if (line.ToLower().StartsWith("sub"))
{
m = ImportTextSubtitle(line, m, path); m = ImportTextSubtitle(line, m, path);
}
else if (line.ToLower().StartsWith("emuversion")) else if (line.ToLower().StartsWith("emuversion"))
{
m.Header.Comments.Add( m.Header.Comments.Add(
EMULATIONORIGIN + " " + emulator + " version " + ParseHeader(line, "emuVersion") EMULATIONORIGIN + " " + emulator + " version " + ParseHeader(line, "emuVersion")
); );
}
else if (line.ToLower().StartsWith("version")) else if (line.ToLower().StartsWith("version"))
{ {
string version = ParseHeader(line, "version"); string version = ParseHeader(line, "version");
@ -330,18 +352,26 @@ namespace BizHawk.MultiClient
} }
} }
else if (line.ToLower().StartsWith("romfilename")) else if (line.ToLower().StartsWith("romfilename"))
{
m.Header.SetHeaderLine(MovieHeader.GAMENAME, ParseHeader(line, "romFilename")); m.Header.SetHeaderLine(MovieHeader.GAMENAME, ParseHeader(line, "romFilename"));
}
else if (line.ToLower().StartsWith("romchecksum")) else if (line.ToLower().StartsWith("romchecksum"))
{ {
string blob = ParseHeader(line, "romChecksum"); string blob = ParseHeader(line, "romChecksum");
byte[] md5 = DecodeBlob(blob); byte[] md5 = DecodeBlob(blob);
if (md5 != null && md5.Length == 16) if (md5 != null && md5.Length == 16)
{
m.Header.SetHeaderLine(MD5, BizHawk.Util.BytesToHexString(md5).ToLower()); m.Header.SetHeaderLine(MD5, BizHawk.Util.BytesToHexString(md5).ToLower());
}
else else
{
warningMsg = "Bad ROM checksum."; warningMsg = "Bad ROM checksum.";
}
} }
else if (line.ToLower().StartsWith("comment author")) else if (line.ToLower().StartsWith("comment author"))
{
m.Header.SetHeaderLine(MovieHeader.AUTHOR, ParseHeader(line, "comment author")); m.Header.SetHeaderLine(MovieHeader.AUTHOR, ParseHeader(line, "comment author"));
}
else if (line.ToLower().StartsWith("rerecordcount")) else if (line.ToLower().StartsWith("rerecordcount"))
{ {
int rerecordCount; int rerecordCount;
@ -357,7 +387,9 @@ namespace BizHawk.MultiClient
m.Rerecords = rerecordCount; m.Rerecords = rerecordCount;
} }
else if (line.ToLower().StartsWith("guid")) else if (line.ToLower().StartsWith("guid"))
{
m.Header.SetHeaderLine(MovieHeader.GUID, ParseHeader(line, "guid")); m.Header.SetHeaderLine(MovieHeader.GUID, ParseHeader(line, "guid"));
}
else if (line.ToLower().StartsWith("startsfromsavestate")) else if (line.ToLower().StartsWith("startsfromsavestate"))
{ {
// If this movie starts from a savestate, we can't support it. // If this movie starts from a savestate, we can't support it.
@ -371,7 +403,7 @@ namespace BizHawk.MultiClient
else if (line.ToLower().StartsWith("palflag")) else if (line.ToLower().StartsWith("palflag"))
{ {
bool pal = (ParseHeader(line, "palFlag") == "1"); bool pal = (ParseHeader(line, "palFlag") == "1");
m.Header.SetHeaderLine(MovieHeader.PAL, pal.ToString()); m.Header.SetHeaderLine(MovieHeader.PAL, pal.ToString());
} }
else if (line.ToLower().StartsWith("fourscore")) else if (line.ToLower().StartsWith("fourscore"))
{ {
@ -402,14 +434,21 @@ namespace BizHawk.MultiClient
private static byte[] DecodeBlob(string blob) private static byte[] DecodeBlob(string blob)
{ {
if (blob.Length < 2) if (blob.Length < 2)
{
return null; return null;
}
if (blob[0] == '0' && (blob[1] == 'x' || blob[1] == 'X')) if (blob[0] == '0' && (blob[1] == 'x' || blob[1] == 'X'))
{
// hex // hex
return BizHawk.Util.HexStringToBytes(blob.Substring(2)); return BizHawk.Util.HexStringToBytes(blob.Substring(2));
else { }
else
{
// base64 // base64
if(!blob.ToLower().StartsWith("base64:")) if (!blob.ToLower().StartsWith("base64:"))
{
return null; return null;
}
try try
{ {
return Convert.FromBase64String(blob.Substring(7)); return Convert.FromBase64String(blob.Substring(7));
@ -426,7 +465,9 @@ namespace BizHawk.MultiClient
{ {
int pos = str.IndexOf('\0'); int pos = str.IndexOf('\0');
if (pos != -1) if (pos != -1)
{
str = str.Substring(0, pos); str = str.Substring(0, pos);
}
return str; return str;
} }
@ -481,7 +522,7 @@ namespace BizHawk.MultiClient
preference. This means that this site cannot calculate movie lengths reliably. preference. This means that this site cannot calculate movie lengths reliably.
*/ */
bool pal = (((flags >> 2) & 0x1) != 0); bool pal = (((flags >> 2) & 0x1) != 0);
m.Header.SetHeaderLine(MovieHeader.PAL, pal.ToString()); m.Header.SetHeaderLine(MovieHeader.PAL, pal.ToString());
// other: reserved, set to 0 // other: reserved, set to 0
bool syncHack = (((flags >> 4) & 0x1) != 0); bool syncHack = (((flags >> 4) & 0x1) != 0);
m.Header.Comments.Add(SYNCHACK + " " + syncHack.ToString()); m.Header.Comments.Add(SYNCHACK + " " + syncHack.ToString());
@ -561,7 +602,9 @@ namespace BizHawk.MultiClient
65536-(2^24-1) 3 65536-(2^24-1) 3
*/ */
for (int b = 0; b < delta; b++) for (int b = 0; b < delta; b++)
{
frames += r.ReadByte() * (int)Math.Pow(2, b * 8); frames += r.ReadByte() * (int)Math.Pow(2, b * 8);
}
frame += frames; frame += frames;
while (frames > 0) while (frames > 0)
{ {
@ -595,7 +638,9 @@ namespace BizHawk.MultiClient
case 2: case 2:
reset = true; reset = true;
if (frame != 1) if (frame != 1)
{
warningMsg = "hard reset"; warningMsg = "hard reset";
}
break; break;
// VS System Insert Coin // VS System Insert Coin
case 7: case 7:
@ -625,7 +670,9 @@ namespace BizHawk.MultiClient
break; break;
} }
if (warningMsg != "") if (warningMsg != "")
{
warningMsg = "Unable to import " + warningMsg + " command at frame " + frame + "."; warningMsg = "Unable to import " + warningMsg + " command at frame " + frame + ".";
}
} }
/* /*
1 Even if the header says "movie begins from reset", the file still contains a quicksave, and the 1 Even if the header says "movie begins from reset", the file still contains a quicksave, and the
@ -649,7 +696,9 @@ namespace BizHawk.MultiClient
*/ */
int player = ((update >> 3) & 0x3) + 1; int player = ((update >> 3) & 0x3) + 1;
if (player > 2) if (player > 2)
{
fourscore = true; fourscore = true;
}
/* /*
ccc: ccc:
* 0 A * 0 A
@ -762,7 +811,7 @@ namespace BizHawk.MultiClient
The file format has no means of identifying NTSC/"PAL". It is always assumed that the game is NTSC - that is, The file format has no means of identifying NTSC/"PAL". It is always assumed that the game is NTSC - that is,
60 fps. 60 fps.
*/ */
m.Header.SetHeaderLine(MovieHeader.PAL, "False"); m.Header.SetHeaderLine(MovieHeader.PAL, "False");
// 090 frame data begins here // 090 frame data begins here
SimpleController controllers = new SimpleController(); SimpleController controllers = new SimpleController();
controllers.Type = new ControllerDefinition(); controllers.Type = new ControllerDefinition();
@ -786,8 +835,12 @@ namespace BizHawk.MultiClient
*/ */
int bytesPerFrame = 0; int bytesPerFrame = 0;
for (int player = 1; player <= masks.Length; player++) for (int player = 1; player <= masks.Length; player++)
{
if (masks[player - 1]) if (masks[player - 1])
{
bytesPerFrame++; bytesPerFrame++;
}
}
long frameCount = (fs.Length - 144) / bytesPerFrame; long frameCount = (fs.Length - 144) / bytesPerFrame;
for (long frame = 1; frame <= frameCount; frame++) for (long frame = 1; frame <= frameCount; frame++)
{ {
@ -799,13 +852,21 @@ namespace BizHawk.MultiClient
for (int player = 1; player <= masks.Length; player++) for (int player = 1; player <= masks.Length; player++)
{ {
if (!masks[player - 1]) if (!masks[player - 1])
{
continue; continue;
}
byte controllerState = r.ReadByte(); byte controllerState = r.ReadByte();
if (player != 3) if (player != 3)
{
for (int button = 0; button < buttons.Length; button++) for (int button = 0; button < buttons.Length; button++)
{
controllers["P" + player + " " + buttons[button]] = (((controllerState >> button) & 0x1) != 0); controllers["P" + player + " " + buttons[button]] = (((controllerState >> button) & 0x1) != 0);
}
}
else else
{
warningMsg = "FDS commands are not properly supported."; warningMsg = "FDS commands are not properly supported.";
}
} }
mg.SetSource(controllers); mg.SetSource(controllers);
m.AppendFrame(mg.GetControllersAsMnemonic()); m.AppendFrame(mg.GetControllersAsMnemonic());
@ -845,7 +906,9 @@ namespace BizHawk.MultiClient
// 015 ASCII-encoded controller config for player 2. '3' or '6'. // 015 ASCII-encoded controller config for player 2. '3' or '6'.
string player2Config = r.ReadStringFixedAscii(1); string player2Config = r.ReadStringFixedAscii(1);
if (player1Config == "6" || player2Config == "6") if (player1Config == "6" || player2Config == "6")
{
warningMsg = "6 button controllers are not properly supported."; warningMsg = "6 button controllers are not properly supported.";
}
// 016 special flags (Version A and up only) // 016 special flags (Version A and up only)
byte flags = r.ReadByte(); byte flags = r.ReadByte();
/* /*
@ -854,7 +917,7 @@ namespace BizHawk.MultiClient
header. header.
*/ */
bool pal = (((flags >> 7) & 0x1) != 0); bool pal = (((flags >> 7) & 0x1) != 0);
m.Header.SetHeaderLine(MovieHeader.PAL, pal.ToString()); m.Header.SetHeaderLine(MovieHeader.PAL, pal.ToString());
// bit 6: if "1", movie requires a savestate. // bit 6: if "1", movie requires a savestate.
if (((flags >> 6) & 0x1) != 0) if (((flags >> 6) & 0x1) != 0)
{ {
@ -911,16 +974,26 @@ namespace BizHawk.MultiClient
byte controllerState = r.ReadByte(); byte controllerState = r.ReadByte();
// * is controller 3 if a 3-player movie, or XYZ-mode if a 2-player movie. // * is controller 3 if a 3-player movie, or XYZ-mode if a 2-player movie.
if (player != 3 || threePlayers) if (player != 3 || threePlayers)
{
for (int button = 0; button < buttons.Length; button++) for (int button = 0; button < buttons.Length; button++)
{
controllers["P" + player + " " + buttons[button]] = (((controllerState >> button) & 0x1) == 0); controllers["P" + player + " " + buttons[button]] = (((controllerState >> button) & 0x1) == 0);
}
}
else else
{
for (int button = 0; button < other.Length; button++) for (int button = 0; button < other.Length; button++)
{ {
if (player1Config == "6") if (player1Config == "6")
{
controllers["P1 " + other[button]] = (((controllerState >> button) & 0x1) == 0); controllers["P1 " + other[button]] = (((controllerState >> button) & 0x1) == 0);
}
if (player2Config == "6") if (player2Config == "6")
{
controllers["P2 " + other[button]] = (((controllerState >> (button + 4)) & 0x1) == 0); controllers["P2 " + other[button]] = (((controllerState >> (button + 4)) & 0x1) == 0);
}
} }
}
} }
mg.SetSource(controllers); mg.SetSource(controllers);
m.AppendFrame(mg.GetControllersAsMnemonic()); m.AppendFrame(mg.GetControllersAsMnemonic());
@ -961,15 +1034,21 @@ namespace BizHawk.MultiClient
if (author != "") if (author != "")
{ {
if (author_last != "") if (author_last != "")
{
author_list += author_last + ", "; author_list += author_last + ", ";
}
author_last = author; author_last = author;
} }
} }
} }
if (author_list != "") if (author_list != "")
{
author_list += "and "; author_list += "and ";
}
if (author_last != "") if (author_last != "")
{
author_list += author_last; author_list += author_last;
}
m.Header.SetHeaderLine(MovieHeader.AUTHOR, author_list); m.Header.SetHeaderLine(MovieHeader.AUTHOR, author_list);
hf.Unbind(); hf.Unbind();
} }
@ -1011,7 +1090,7 @@ namespace BizHawk.MultiClient
break; break;
} }
bool pal = (gametype == "snes_pal" || gametype == "sgb_pal"); bool pal = (gametype == "snes_pal" || gametype == "sgb_pal");
m.Header.SetHeaderLine(MovieHeader.PAL, pal.ToString()); m.Header.SetHeaderLine(MovieHeader.PAL, pal.ToString());
hf.Unbind(); hf.Unbind();
} }
else if (item.name == "input") else if (item.name == "input")
@ -1027,7 +1106,9 @@ namespace BizHawk.MultiClient
while ((line = reader.ReadLine()) != null) while ((line = reader.ReadLine()) != null)
{ {
if (line == "") if (line == "")
{
continue; continue;
}
m = ImportTextFrame(line, lineNum, m, path, platform, ref warningMsg, ref errorMsg); m = ImportTextFrame(line, lineNum, m, path, platform, ref warningMsg, ref errorMsg);
if (errorMsg != "") if (errorMsg != "")
{ {
@ -1161,7 +1242,7 @@ namespace BizHawk.MultiClient
Movie m = new Movie(path + "." + Global.Config.MovieExtension); Movie m = new Movie(path + "." + Global.Config.MovieExtension);
FileStream fs = new FileStream(path, FileMode.Open, FileAccess.Read); FileStream fs = new FileStream(path, FileMode.Open, FileAccess.Read);
BinaryReader r = new BinaryReader(fs); BinaryReader r = new BinaryReader(fs);
// 000 8-byte "MDFNMOVI" signature // 000 8-byte "MDFNMOVI" signature
string signature = r.ReadStringFixedAscii(8); string signature = r.ReadStringFixedAscii(8);
if (signature != "MDFNMOVI") if (signature != "MDFNMOVI")
{ {
@ -1170,24 +1251,24 @@ namespace BizHawk.MultiClient
fs.Close(); fs.Close();
return null; return null;
} }
// 008 uint32 Mednafen Version (Current is 0A 08) // 008 uint32 Mednafen Version (Current is 0A 08)
uint emuVersion = r.ReadUInt32(); uint emuVersion = r.ReadUInt32();
m.Header.Comments.Add(EMULATIONORIGIN + " Mednafen " + emuVersion.ToString()); m.Header.Comments.Add(EMULATIONORIGIN + " Mednafen " + emuVersion.ToString());
// 00C uint32 Movie Format Version (Current is 01) // 00C uint32 Movie Format Version (Current is 01)
uint version = r.ReadUInt32(); uint version = r.ReadUInt32();
m.Header.Comments.Add(MOVIEORIGIN + " .MCM version " + version); m.Header.Comments.Add(MOVIEORIGIN + " .MCM version " + version);
// 010 32-byte MD5 of the ROM used // 010 32-byte MD5 of the ROM used
byte[] md5 = r.ReadBytes(16); byte[] md5 = r.ReadBytes(16);
// Discard the second 16 bytes. // Discard the second 16 bytes.
r.ReadBytes(16); r.ReadBytes(16);
m.Header.SetHeaderLine(MD5, BizHawk.Util.BytesToHexString(md5).ToLower()); m.Header.SetHeaderLine(MD5, BizHawk.Util.BytesToHexString(md5).ToLower());
// 030 64-byte Filename of the ROM used (with extension) // 030 64-byte Filename of the ROM used (with extension)
string gameName = NullTerminated(r.ReadStringFixedAscii(64)); string gameName = NullTerminated(r.ReadStringFixedAscii(64));
m.Header.SetHeaderLine(MovieHeader.GAMENAME, gameName); m.Header.SetHeaderLine(MovieHeader.GAMENAME, gameName);
// 070 uint32 Re-record Count // 070 uint32 Re-record Count
uint rerecordCount = r.ReadUInt32(); uint rerecordCount = r.ReadUInt32();
m.Rerecords = (int)rerecordCount; m.Rerecords = (int)rerecordCount;
// 074 5-byte Console indicator (pce, ngp, pcfx, wswan) // 074 5-byte Console indicator (pce, ngp, pcfx, wswan)
string platform = NullTerminated(r.ReadStringFixedAscii(5)); string platform = NullTerminated(r.ReadStringFixedAscii(5));
Dictionary<string, Dictionary<string, object>> platforms = new Dictionary<string, Dictionary<string, object>>() Dictionary<string, Dictionary<string, object>> platforms = new Dictionary<string, Dictionary<string, object>>()
{ {
@ -1220,7 +1301,7 @@ namespace BizHawk.MultiClient
} }
string name = (string)platforms[platform]["name"]; string name = (string)platforms[platform]["name"];
m.Header.SetHeaderLine(MovieHeader.PLATFORM, name); m.Header.SetHeaderLine(MovieHeader.PLATFORM, name);
// 079 32-byte Author name // 079 32-byte Author name
string author = NullTerminated(r.ReadStringFixedAscii(32)); string author = NullTerminated(r.ReadStringFixedAscii(32));
m.Header.SetHeaderLine(MovieHeader.AUTHOR, author); m.Header.SetHeaderLine(MovieHeader.AUTHOR, author);
// 099 103-byte Padding 0s // 099 103-byte Padding 0s
@ -1250,15 +1331,21 @@ namespace BizHawk.MultiClient
for (int player = 1; player <= ports; player++) for (int player = 1; player <= ports; player++)
{ {
if (bytesPerPort == 2) if (bytesPerPort == 2)
{
// Discard the first byte. // Discard the first byte.
r.ReadByte(); r.ReadByte();
}
ushort controllerState = r.ReadByte(); ushort controllerState = r.ReadByte();
for (int button = 0; button < buttons.Length; button++) for (int button = 0; button < buttons.Length; button++)
{
controllers["P" + player + " " + buttons[button]] = (((controllerState >> button) & 0x1) != 0); controllers["P" + player + " " + buttons[button]] = (((controllerState >> button) & 0x1) != 0);
}
} }
r.ReadByte(); r.ReadByte();
if (platform == "nes" && warningMsg == "") if (platform == "nes" && warningMsg == "")
{
warningMsg = "Control commands are not properly supported."; warningMsg = "Control commands are not properly supported.";
}
mg.SetSource(controllers); mg.SetSource(controllers);
m.AppendFrame(mg.GetControllersAsMnemonic()); m.AppendFrame(mg.GetControllersAsMnemonic());
} }
@ -1325,7 +1412,7 @@ namespace BizHawk.MultiClient
// bit 0: unused // bit 0: unused
// bit 1: "PAL" // bit 1: "PAL"
bool pal = (((flags >> 1) & 0x1) != 0); bool pal = (((flags >> 1) & 0x1) != 0);
m.Header.SetHeaderLine(MovieHeader.PAL, pal.ToString()); m.Header.SetHeaderLine(MovieHeader.PAL, pal.ToString());
// bit 2: Japan // bit 2: Japan
bool japan = (((flags >> 2) & 0x1) != 0); bool japan = (((flags >> 2) & 0x1) != 0);
m.Header.SetHeaderLine(JAPAN, japan.ToString()); m.Header.SetHeaderLine(JAPAN, japan.ToString());
@ -1376,12 +1463,16 @@ namespace BizHawk.MultiClient
{ {
byte controllerState = r.ReadByte(); byte controllerState = r.ReadByte();
for (int button = 0; button < buttons.Length; button++) for (int button = 0; button < buttons.Length; button++)
{
controllers["P" + player + " " + buttons[button]] = (((controllerState >> button) & 0x1) != 0); controllers["P" + player + " " + buttons[button]] = (((controllerState >> button) & 0x1) != 0);
}
if (player == 1) if (player == 1)
{
controllers["Pause"] = ( controllers["Pause"] = (
(((controllerState >> 6) & 0x1) != 0 && (!gamegear)) || (((controllerState >> 6) & 0x1) != 0 && (!gamegear)) ||
(((controllerState >> 7) & 0x1) != 0 && gamegear) (((controllerState >> 7) & 0x1) != 0 && gamegear)
); );
}
} }
mg.SetSource(controllers); mg.SetSource(controllers);
m.AppendFrame(mg.GetControllersAsMnemonic()); m.AppendFrame(mg.GetControllersAsMnemonic());
@ -1469,7 +1560,9 @@ namespace BizHawk.MultiClient
per frame. Nintendulator's Four-Score recording is seemingly broken. per frame. Nintendulator's Four-Score recording is seemingly broken.
*/ */
for (int controller = 1; controller < masks.Length; controller++) for (int controller = 1; controller < masks.Length; controller++)
{
masks[controller - 1] = (((controller2 >> (controller - 1)) & 0x1) != 0); masks[controller - 1] = (((controller2 >> (controller - 1)) & 0x1) != 0);
}
warningMsg = "Nintendulator's Four Score recording is seemingly broken."; warningMsg = "Nintendulator's Four Score recording is seemingly broken.";
} }
else else
@ -1505,7 +1598,9 @@ namespace BizHawk.MultiClient
break; break;
} }
if (warningMsg != "") if (warningMsg != "")
{
warningMsg = warningMsg + " is not properly supported."; warningMsg = warningMsg + " is not properly supported.";
}
} }
} }
} }
@ -1527,14 +1622,20 @@ namespace BizHawk.MultiClient
"Alternate keyboard layout", "Family Trainer", "Oeka Kids writing tablet" "Alternate keyboard layout", "Family Trainer", "Oeka Kids writing tablet"
}; };
if (expansion != 0 && warningMsg == "") if (expansion != 0 && warningMsg == "")
{
warningMsg = "Expansion port is not properly supported. This movie uses " + expansions[expansion] + "."; warningMsg = "Expansion port is not properly supported. This movie uses " + expansions[expansion] + ".";
}
// 003 1-byte number of bytes per frame, plus flags // 003 1-byte number of bytes per frame, plus flags
byte data = r.ReadByte(); byte data = r.ReadByte();
int bytesPerFrame = data & 0xF; int bytesPerFrame = data & 0xF;
int bytes = 0; int bytes = 0;
for (int controller = 1; controller < masks.Length; controller++) for (int controller = 1; controller < masks.Length; controller++)
{
if (masks[controller - 1]) if (masks[controller - 1])
{
bytes++; bytes++;
}
}
/* /*
Depending on the mapper used by the game in question, an additional byte of data may be stored during each Depending on the mapper used by the game in question, an additional byte of data may be stored during each
frame. This is most frequently used for FDS games (storing either the disk number or 0xFF to eject) or VS frame. This is most frequently used for FDS games (storing either the disk number or 0xFF to eject) or VS
@ -1542,7 +1643,9 @@ namespace BizHawk.MultiClient
not match up with the amount of bytes the controllers take up. not match up with the amount of bytes the controllers take up.
*/ */
if (bytes != bytesPerFrame) if (bytes != bytesPerFrame)
{
masks[4] = true; masks[4] = true;
}
// bit 6: Game Genie active // bit 6: Game Genie active
/* /*
bit 7: Framerate bit 7: Framerate
@ -1550,7 +1653,7 @@ namespace BizHawk.MultiClient
* if "1", "PAL" timing * if "1", "PAL" timing
*/ */
bool pal = (((data >> 7) & 0x1) != 0); bool pal = (((data >> 7) & 0x1) != 0);
m.Header.SetHeaderLine(MovieHeader.PAL, pal.ToString()); m.Header.SetHeaderLine(MovieHeader.PAL, pal.ToString());
// 004 4-byte little-endian unsigned int: rerecord count // 004 4-byte little-endian unsigned int: rerecord count
uint rerecordCount = r.ReadUInt32(); uint rerecordCount = r.ReadUInt32();
m.Rerecords = (int)rerecordCount; m.Rerecords = (int)rerecordCount;
@ -1588,13 +1691,21 @@ namespace BizHawk.MultiClient
for (int player = 1; player <= masks.Length; player++) for (int player = 1; player <= masks.Length; player++)
{ {
if (!masks[player - 1]) if (!masks[player - 1])
{
continue; continue;
}
byte controllerState = r.ReadByte(); byte controllerState = r.ReadByte();
if (player != 5) if (player != 5)
{
for (int button = 0; button < buttons.Length; button++) for (int button = 0; button < buttons.Length; button++)
{
controllers["P" + player + " " + buttons[button]] = (((controllerState >> button) & 0x1) != 0); controllers["P" + player + " " + buttons[button]] = (((controllerState >> button) & 0x1) != 0);
}
}
else if (warningMsg == "") else if (warningMsg == "")
{
warningMsg = "Extra input is not properly supported."; warningMsg = "Extra input is not properly supported.";
}
} }
mg.SetSource(controllers); mg.SetSource(controllers);
m.AppendFrame(mg.GetControllersAsMnemonic()); m.AppendFrame(mg.GetControllersAsMnemonic());
@ -1669,7 +1780,9 @@ namespace BizHawk.MultiClient
MnemonicsGenerator mg = new MnemonicsGenerator(); MnemonicsGenerator mg = new MnemonicsGenerator();
bool[] controllersUsed = new bool[5]; bool[] controllersUsed = new bool[5];
for (int controller = 1; controller <= controllersUsed.Length; controller++) for (int controller = 1; controller <= controllersUsed.Length; controller++)
{
controllersUsed[controller - 1] = (((controllerFlags >> (controller - 1)) & 0x1) != 0); controllersUsed[controller - 1] = (((controllerFlags >> (controller - 1)) & 0x1) != 0);
}
// 015 1-byte flags "movie options" // 015 1-byte flags "movie options"
byte movieFlags = r.ReadByte(); byte movieFlags = r.ReadByte();
/* /*
@ -1686,7 +1799,7 @@ namespace BizHawk.MultiClient
} }
// bit 1: if "0", movie is NTSC (60 fps); if "1", movie is PAL (50 fps) // bit 1: if "0", movie is NTSC (60 fps); if "1", movie is PAL (50 fps)
bool pal = (((movieFlags >> 1) & 0x1) != 0); bool pal = (((movieFlags >> 1) & 0x1) != 0);
m.Header.SetHeaderLine(MovieHeader.PAL, pal.ToString()); m.Header.SetHeaderLine(MovieHeader.PAL, pal.ToString());
// other: reserved, set to 0 // other: reserved, set to 0
/* /*
016 1-byte flags "sync options": 016 1-byte flags "sync options":
@ -1745,7 +1858,9 @@ namespace BizHawk.MultiClient
byte[] metadata = r.ReadBytes((int)(savestateOffset - extraRomInfo - ((version != "1.43") ? 0x40 : 0x20))); byte[] metadata = r.ReadBytes((int)(savestateOffset - extraRomInfo - ((version != "1.43") ? 0x40 : 0x20)));
string author = NullTerminated(Encoding.Unicode.GetString(metadata).Trim()); string author = NullTerminated(Encoding.Unicode.GetString(metadata).Trim());
if (author != "") if (author != "")
{
m.Header.SetHeaderLine(MovieHeader.AUTHOR, author); m.Header.SetHeaderLine(MovieHeader.AUTHOR, author);
}
if (extraRomInfo == 30) if (extraRomInfo == 30)
{ {
// 000 3 bytes of zero padding: 00 00 00 003 4-byte integer: CRC32 of the ROM 007 23-byte ascii string // 000 3 bytes of zero padding: 00 00 00 003 4-byte integer: CRC32 of the ROM 007 23-byte ascii string
@ -1784,7 +1899,9 @@ namespace BizHawk.MultiClient
for (int player = 1; player <= controllersUsed.Length; player++) for (int player = 1; player <= controllersUsed.Length; player++)
{ {
if (!controllersUsed[player - 1]) if (!controllersUsed[player - 1])
{
continue; continue;
}
/* /*
Each frame consists of 2 bytes per controller. So if there are 3 controllers, a frame is 6 bytes and Each frame consists of 2 bytes per controller. So if there are 3 controllers, a frame is 6 bytes and
if there is only 1 controller, a frame is 2 bytes. if there is only 1 controller, a frame is 2 bytes.
@ -1796,7 +1913,9 @@ namespace BizHawk.MultiClient
reset. The reset is done through the S9xSoftReset routine. reset. The reset is done through the S9xSoftReset routine.
*/ */
if (controllerState1 != 0xFF || controllerState2 != 0xFF) if (controllerState1 != 0xFF || controllerState2 != 0xFF)
{
controllers["Reset"] = false; controllers["Reset"] = false;
}
/* /*
While the meaning of controller data (for 1.51 and up) for a single standard SNES controller pad While the meaning of controller data (for 1.51 and up) for a single standard SNES controller pad
remains the same, each frame of controller data can contain additional bytes if input for peripherals remains the same, each frame of controller data can contain additional bytes if input for peripherals
@ -1837,22 +1956,30 @@ namespace BizHawk.MultiClient
break; break;
} }
if (peripheral != "" && warningMsg == "") if (peripheral != "" && warningMsg == "")
{
warningMsg = "Unable to import " + peripheral + "."; warningMsg = "Unable to import " + peripheral + ".";
}
} }
ushort controllerState = (ushort)(((controllerState1 << 4) & 0x0F00) | controllerState2); ushort controllerState = (ushort)(((controllerState1 << 4) & 0x0F00) | controllerState2);
if (player <= Global.PLAYERS[controllers.Type.Name]) if (player <= Global.PLAYERS[controllers.Type.Name])
{
for (int button = 0; button < buttons.Length; button++) for (int button = 0; button < buttons.Length; button++)
{ {
controllers["P" + player + " " + buttons[button]] = ( controllers["P" + player + " " + buttons[button]] = (
((controllerState >> button) & 0x1) != 0 ((controllerState >> button) & 0x1) != 0
); );
} }
}
else if (warningMsg == "") else if (warningMsg == "")
{
warningMsg = "Controller " + player + " not supported."; warningMsg = "Controller " + player + " not supported.";
}
} }
// The controller data contains <number_of_frames + 1> frames. // The controller data contains <number_of_frames + 1> frames.
if (frame == 0) if (frame == 0)
{
continue; continue;
}
mg.SetSource(controllers); mg.SetSource(controllers);
m.AppendFrame(mg.GetControllersAsMnemonic()); m.AppendFrame(mg.GetControllersAsMnemonic());
} }
@ -1937,7 +2064,9 @@ namespace BizHawk.MultiClient
*/ */
bool[] controllersUsed = new bool[4]; bool[] controllersUsed = new bool[4];
for (int controller = 1; controller <= controllersUsed.Length; controller++) for (int controller = 1; controller <= controllersUsed.Length; controller++)
{
controllersUsed[controller - 1] = (((controllerFlags >> (controller - 1)) & 0x1) != 0); controllersUsed[controller - 1] = (((controllerFlags >> (controller - 1)) & 0x1) != 0);
}
if (!controllersUsed[0]) if (!controllersUsed[0])
{ {
errorMsg = "Controller 1 must be in use."; errorMsg = "Controller 1 must be in use.";
@ -1966,11 +2095,17 @@ namespace BizHawk.MultiClient
// (If all 3 of these bits are "0", it is for regular GB.) // (If all 3 of these bits are "0", it is for regular GB.)
string platform = "GB"; string platform = "GB";
if (is_gba) if (is_gba)
{
platform = "GBA"; platform = "GBA";
}
if (is_gbc) if (is_gbc)
{
platform = "GBC"; platform = "GBC";
}
if (is_sgb) if (is_sgb)
{
m.Header.Comments.Add(SUPERGAMEBOYMODE + " True"); m.Header.Comments.Add(SUPERGAMEBOYMODE + " True");
}
m.Header.SetHeaderLine(MovieHeader.PLATFORM, platform); m.Header.SetHeaderLine(MovieHeader.PLATFORM, platform);
// 017 1-byte flags: (values of some boolean emulator options) // 017 1-byte flags: (values of some boolean emulator options)
flags = r.ReadByte(); flags = r.ReadByte();
@ -2048,7 +2183,14 @@ namespace BizHawk.MultiClient
r.BaseStream.Position = firstFrameOffset; r.BaseStream.Position = firstFrameOffset;
SimpleController controllers = new SimpleController(); SimpleController controllers = new SimpleController();
controllers.Type = new ControllerDefinition(); controllers.Type = new ControllerDefinition();
controllers.Type.Name = "Gameboy Controller"; if (platform == "GBA")
{
controllers.Type.Name = "Gameboy Controller";
}
else
{
controllers.Type.Name = "GBA Controller";
}
MnemonicsGenerator mg = new MnemonicsGenerator(); MnemonicsGenerator mg = new MnemonicsGenerator();
/* /*
* 01 00 A * 01 00 A
@ -2083,23 +2225,33 @@ namespace BizHawk.MultiClient
*/ */
ushort controllerState = r.ReadUInt16(); ushort controllerState = r.ReadUInt16();
for (int button = 0; button < buttons.Length; button++) for (int button = 0; button < buttons.Length; button++)
{
controllers[buttons[button]] = (((controllerState >> button) & 0x1) != 0); controllers[buttons[button]] = (((controllerState >> button) & 0x1) != 0);
}
// TODO: Handle the other buttons. // TODO: Handle the other buttons.
if (warningMsg == "") if (warningMsg == "")
{ {
for (int button = 0; button < other.Length; button++) for (int button = 0; button < other.Length; button++)
{
if (((controllerState >> (button + 8)) & 0x1) != 0) if (((controllerState >> (button + 8)) & 0x1) != 0)
{ {
warningMsg = other[button]; warningMsg = other[button];
break; break;
} }
}
if (warningMsg != "") if (warningMsg != "")
{
warningMsg = "Unable to import " + warningMsg + " at frame " + frame + "."; warningMsg = "Unable to import " + warningMsg + " at frame " + frame + ".";
}
} }
// TODO: Handle the additional controllers. // TODO: Handle the additional controllers.
for (int player = 2; player <= controllersUsed.Length; player++) for (int player = 2; player <= controllersUsed.Length; player++)
{
if (controllersUsed[player - 1]) if (controllersUsed[player - 1])
{
r.ReadBytes(2); r.ReadBytes(2);
}
}
mg.SetSource(controllers); mg.SetSource(controllers);
m.AppendFrame(mg.GetControllersAsMnemonic()); m.AppendFrame(mg.GetControllersAsMnemonic());
} }
@ -2143,7 +2295,9 @@ namespace BizHawk.MultiClient
*/ */
bool[] controllersUsed = new bool[4]; bool[] controllersUsed = new bool[4];
for (int controller = 1; controller <= controllersUsed.Length; controller++) for (int controller = 1; controller <= controllersUsed.Length; controller++)
{
controllersUsed[controller - 1] = (((flags >> (controller - 1)) & 0x1) != 0); controllersUsed[controller - 1] = (((flags >> (controller - 1)) & 0x1) != 0);
}
bool fourscore = (controllersUsed[2] || controllersUsed[3]); bool fourscore = (controllersUsed[2] || controllersUsed[3]);
m.Header.SetHeaderLine(MovieHeader.FOURSCORE, fourscore.ToString()); m.Header.SetHeaderLine(MovieHeader.FOURSCORE, fourscore.ToString());
/* /*
@ -2164,29 +2318,29 @@ namespace BizHawk.MultiClient
becomes the controller data. TODO: Figure out what this means. becomes the controller data. TODO: Figure out what this means.
Other bits: reserved, set to 0 Other bits: reserved, set to 0
*/ */
// 014 DWORD Ext0; // ROM:program CRC FDS:program ID // 014 DWORD Ext0; // ROM:program CRC FDS:program ID
r.ReadBytes(4); r.ReadBytes(4);
// 018 WORD Ext1; // ROM:unused,0 FDS:maker ID // 018 WORD Ext1; // ROM:unused,0 FDS:maker ID
r.ReadBytes(2); r.ReadBytes(2);
// 01A WORD Ext2; // ROM:unused,0 FDS:disk no. // 01A WORD Ext2; // ROM:unused,0 FDS:disk no.
r.ReadBytes(2); r.ReadBytes(2);
// 01C 4-byte little-endian integer: rerecord count // 01C 4-byte little-endian integer: rerecord count
uint rerecordCount = r.ReadUInt32(); uint rerecordCount = r.ReadUInt32();
m.Rerecords = (int)rerecordCount; m.Rerecords = (int)rerecordCount;
/* /*
020 BYTE RenderMethod 020 BYTE RenderMethod
0=POST_ALL,1=PRE_ALL 0=POST_ALL,1=PRE_ALL
2=POST_RENDER,3=PRE_RENDER 2=POST_RENDER,3=PRE_RENDER
4=TILE_RENDER 4=TILE_RENDER
*/ */
r.ReadByte(); r.ReadByte();
// 021 BYTE IRQtype // IRQ type // 021 BYTE IRQtype // IRQ type
r.ReadByte(); r.ReadByte();
// 022 BYTE FrameIRQ // FrameIRQ not allowed // 022 BYTE FrameIRQ // FrameIRQ not allowed
r.ReadByte(); r.ReadByte();
// 023 1-byte flag: 0=NTSC (60 Hz), 1="PAL" (50 Hz) // 023 1-byte flag: 0=NTSC (60 Hz), 1="PAL" (50 Hz)
bool pal = (r.ReadByte() == 1); bool pal = (r.ReadByte() == 1);
m.Header.SetHeaderLine(MovieHeader.PAL, pal.ToString()); m.Header.SetHeaderLine(MovieHeader.PAL, pal.ToString());
// 024 8-bytes: reserved, set to 0 // 024 8-bytes: reserved, set to 0
r.ReadBytes(8); r.ReadBytes(8);
// 02C 4-byte little-endian integer: save state start offset // 02C 4-byte little-endian integer: save state start offset
@ -2234,7 +2388,9 @@ namespace BizHawk.MultiClient
for (int player = 1; player <= controllersUsed.Length; player++) for (int player = 1; player <= controllersUsed.Length; player++)
{ {
if (!controllersUsed[player - 1]) if (!controllersUsed[player - 1])
{
continue; continue;
}
byte controllerState = r.ReadByte(); byte controllerState = r.ReadByte();
if (controllerState >= 0xF0) if (controllerState >= 0xF0)
{ {
@ -2243,6 +2399,7 @@ namespace BizHawk.MultiClient
ushort command = r.ReadUInt16(); ushort command = r.ReadUInt16();
string commandName = ""; string commandName = "";
if ((command & 0xFF00) == 0) if ((command & 0xFF00) == 0)
{
switch (command & 0x00FF) switch (command & 0x00FF)
{ {
// NESCMD_NONE // NESCMD_NONE
@ -2292,22 +2449,31 @@ namespace BizHawk.MultiClient
commandName = "invalid command"; commandName = "invalid command";
break; break;
} }
}
else else
{
commandName = "NESCMD_EXCONTROLLER, " + (command & 0xFF00); commandName = "NESCMD_EXCONTROLLER, " + (command & 0xFF00);
}
if (commandName != "" && warningMsg == "") if (commandName != "" && warningMsg == "")
{
warningMsg = "Unable to run command \"" + commandName + "\"."; warningMsg = "Unable to run command \"" + commandName + "\".";
}
} }
else if (controllerState == 0xF3) else if (controllerState == 0xF3)
{ {
uint dwdata = r.ReadUInt32(); uint dwdata = r.ReadUInt32();
// TODO: Make a clearer warning message. // TODO: Make a clearer warning message.
if (warningMsg == "") if (warningMsg == "")
{
warningMsg = "Unable to run SetSyncExData(" + dwdata + ")."; warningMsg = "Unable to run SetSyncExData(" + dwdata + ").";
}
} }
controllerState = r.ReadByte(); controllerState = r.ReadByte();
} }
for (int button = 0; button < buttons.Length; button++) for (int button = 0; button < buttons.Length; button++)
{
controllers["P" + player + " " + buttons[button]] = (((controllerState >> button) & 0x1) != 0); controllers["P" + player + " " + buttons[button]] = (((controllerState >> button) & 0x1) != 0);
}
} }
mg.SetSource(controllers); mg.SetSource(controllers);
m.AppendFrame(mg.GetControllersAsMnemonic()); m.AppendFrame(mg.GetControllersAsMnemonic());
@ -2338,7 +2504,7 @@ namespace BizHawk.MultiClient
// 003 2-byte little-endian unsigned int: zsnes version number // 003 2-byte little-endian unsigned int: zsnes version number
short version = r.ReadInt16(); short version = r.ReadInt16();
m.Header.Comments.Add(EMULATIONORIGIN + " ZSNES version " + version); m.Header.Comments.Add(EMULATIONORIGIN + " ZSNES version " + version);
m.Header.Comments.Add(MOVIEORIGIN + " .ZMV"); m.Header.Comments.Add(MOVIEORIGIN + " .ZMV");
// 005 4-byte little-endian integer: CRC32 of the ROM // 005 4-byte little-endian integer: CRC32 of the ROM
int crc32 = r.ReadInt32(); int crc32 = r.ReadInt32();
m.Header.SetHeaderLine(CRC32, crc32.ToString()); m.Header.SetHeaderLine(CRC32, crc32.ToString());
@ -2378,18 +2544,26 @@ namespace BizHawk.MultiClient
string peripheral = ""; string peripheral = "";
bool superScope = ((controllerFlags & 0x1) != 0); bool superScope = ((controllerFlags & 0x1) != 0);
if (superScope) if (superScope)
{
peripheral = "Super Scope"; peripheral = "Super Scope";
}
controllerFlags >>= 1; controllerFlags >>= 1;
bool secondMouse = ((controllerFlags & 0x1) != 0); bool secondMouse = ((controllerFlags & 0x1) != 0);
if (secondMouse && peripheral == "") if (secondMouse && peripheral == "")
{
peripheral = "Second Mouse"; peripheral = "Second Mouse";
}
controllerFlags >>= 1; controllerFlags >>= 1;
bool firstMouse = ((controllerFlags & 0x1) != 0); bool firstMouse = ((controllerFlags & 0x1) != 0);
if (firstMouse && peripheral == "") if (firstMouse && peripheral == "")
{
peripheral = "First Mouse"; peripheral = "First Mouse";
}
controllerFlags >>= 1; controllerFlags >>= 1;
if (peripheral != "") if (peripheral != "")
{
warningMsg = "Unable to import " + peripheral + "."; warningMsg = "Unable to import " + peripheral + ".";
}
// 027 1-byte flags: // 027 1-byte flags:
byte movieFlags = r.ReadByte(); byte movieFlags = r.ReadByte();
byte begins = (byte)(movieFlags & 0xC0); byte begins = (byte)(movieFlags & 0xC0);
@ -2416,7 +2590,7 @@ namespace BizHawk.MultiClient
// if "11", movie begins from power-on with SRAM clear // if "11", movie begins from power-on with SRAM clear
// bit 5: if "0", movie is NTSC (60 fps); if "1", movie is PAL (50 fps) // bit 5: if "0", movie is NTSC (60 fps); if "1", movie is PAL (50 fps)
bool pal = (((movieFlags >> 5) & 0x1) != 0); bool pal = (((movieFlags >> 5) & 0x1) != 0);
m.Header.SetHeaderLine(MovieHeader.PAL, pal.ToString()); m.Header.SetHeaderLine(MovieHeader.PAL, pal.ToString());
// other: reserved, set to 0 // other: reserved, set to 0
/* /*
028 3-byte little-endian unsigned int: initial save state size, highest bit specifies compression, next 23 028 3-byte little-endian unsigned int: initial save state size, highest bit specifies compression, next 23
@ -2483,10 +2657,14 @@ namespace BizHawk.MultiClient
// If the event is RLE data, next follows 4 bytes which is the frame to repeat current input till. // If the event is RLE data, next follows 4 bytes which is the frame to repeat current input till.
uint frame = r.ReadUInt32(); uint frame = r.ReadUInt32();
if (frame > frameCount) if (frame > frameCount)
{
throw new ArgumentException("RLE data repeats for frames beyond the total frame count."); throw new ArgumentException("RLE data repeats for frames beyond the total frame count.");
}
mg.SetSource(controllers); mg.SetSource(controllers);
for (; frames <= frame; frames++) for (; frames <= frame; frames++)
{
m.AppendFrame(mg.GetControllersAsMnemonic()); m.AppendFrame(mg.GetControllersAsMnemonic());
}
} }
else if (((flag >> 2) & 0x1) != 0) else if (((flag >> 2) & 0x1) != 0)
{ {
@ -2516,6 +2694,7 @@ namespace BizHawk.MultiClient
bool leftOver = false; bool leftOver = false;
byte leftOverValue = 0x0; byte leftOverValue = 0x0;
for (int player = 1; player <= 5; player++) for (int player = 1; player <= 5; player++)
{
// If the controller has changed: // If the controller has changed:
if (((flag >> (5 - player)) & 0x1) != 0) if (((flag >> (5 - player)) & 0x1) != 0)
{ {
@ -2581,14 +2760,21 @@ namespace BizHawk.MultiClient
if (player <= Global.PLAYERS[controllers.Type.Name]) if (player <= Global.PLAYERS[controllers.Type.Name])
{ {
if (player != 2 || !superScope) if (player != 2 || !superScope)
{
for (int button = 0; button < buttons.Length; button++) for (int button = 0; button < buttons.Length; button++)
{
controllers["P" + player + " " + buttons[button]] = ( controllers["P" + player + " " + buttons[button]] = (
((controllerState >> button) & 0x1) != 0 ((controllerState >> button) & 0x1) != 0
); );
}
}
} }
else if (warningMsg == "") else if (warningMsg == "")
{
warningMsg = "Controller " + player + " not supported."; warningMsg = "Controller " + player + " not supported.";
}
} }
}
mg.SetSource(controllers); mg.SetSource(controllers);
m.AppendFrame(mg.GetControllersAsMnemonic()); m.AppendFrame(mg.GetControllersAsMnemonic());
frames++; frames++;