-ImportSMV

--Fixed "controller in use" handling.
---Applied the same logic to ImportVBM, refactored ImportVMV to match.
--Prevented more than 2 controllers from crashing the controller types check for 1.51 and up.
-ImportZMV
--Showed warning messages for both mouses if enabled.
--Marked the controllers used just like I mentioned previously, though it seems to show that no controllers are plugged in...
--Went past the savestate data.
This commit is contained in:
brandman211 2012-09-17 04:16:27 +00:00
parent f9b392511b
commit bdd74e356c
1 changed files with 58 additions and 43 deletions

View File

@ -1568,7 +1568,6 @@ namespace BizHawk.MultiClient
uint frameCount = r.ReadUInt32(); uint frameCount = r.ReadUInt32();
// 014 1-byte flags "controller mask" // 014 1-byte flags "controller mask"
byte controllerFlags = r.ReadByte(); byte controllerFlags = r.ReadByte();
int players = 0;
/* /*
* bit 0: controller 1 in use * bit 0: controller 1 in use
* bit 1: controller 2 in use * bit 1: controller 2 in use
@ -1581,9 +1580,9 @@ namespace BizHawk.MultiClient
controllers.Type = new ControllerDefinition(); controllers.Type = new ControllerDefinition();
controllers.Type.Name = "SNES Controller"; controllers.Type.Name = "SNES Controller";
MnemonicsGenerator mg = new MnemonicsGenerator(); MnemonicsGenerator mg = new MnemonicsGenerator();
for (int controller = 1; controller <= Global.PLAYERS[controllers.Type.Name]; controller++) bool[] controllersUsed = new bool[5];
if (((controllerFlags >> (controller - 1)) & 0x1) != 0) for (int controller = 1; controller <= controllersUsed.Length; controller++)
players++; 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();
/* /*
@ -1695,8 +1694,10 @@ namespace BizHawk.MultiClient
for (int frame = 0; frame <= frameCount; frame++) for (int frame = 0; frame <= frameCount; frame++)
{ {
controllers["Reset"] = true; controllers["Reset"] = true;
for (int player = 1; player <= players; player++) for (int player = 1; player <= controllersUsed.Length; player++)
{ {
if (!controllersUsed[player - 1])
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.
@ -1714,7 +1715,7 @@ namespace BizHawk.MultiClient
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
is being recorded. is being recorded.
*/ */
if (version != "1.43") if (version != "1.43" && player <= controllerTypes.Length)
{ {
string peripheral = ""; string peripheral = "";
switch (controllerTypes[player - 1]) switch (controllerTypes[player - 1])
@ -1752,8 +1753,15 @@ namespace BizHawk.MultiClient
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])
for (int button = 0; button < buttons.Length; button++) for (int button = 0; button < buttons.Length; button++)
controllers["P" + player + " " + buttons[button]] = (((controllerState >> button) & 1) == 1); {
controllers["P" + player + " " + buttons[button]] = (
((controllerState >> button) & 1) == 1
);
}
else if (warningMsg != "")
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)
@ -1833,28 +1841,23 @@ namespace BizHawk.MultiClient
return null; return null;
} }
// 015 1-byte flags: controller flags // 015 1-byte flags: controller flags
flags = r.ReadByte(); byte controllerFlags = r.ReadByte();
// TODO: Handle the additional controllers. /*
int players = 0; * bit 0: controller 1 in use
// bit 0: controller 1 in use * bit 1: controller 2 in use (SGB games can be 2-player multiplayer)
if ((flags & 1) == 1) * bit 2: controller 3 in use (SGB games can be 3- or 4-player multiplayer with multitap)
players++; * bit 3: controller 4 in use (SGB games can be 3- or 4-player multiplayer with multitap)
else */
bool[] controllersUsed = new bool[4];
for (int controller = 1; controller <= controllersUsed.Length; controller++)
controllersUsed[controller - 1] = (((controllerFlags >> (controller - 1)) & 0x1) != 0);
if (!controllersUsed[0])
{ {
errorMsg = "Controller 1 must be in use."; errorMsg = "Controller 1 must be in use.";
r.Close(); r.Close();
fs.Close(); fs.Close();
return null; return null;
} }
// bit 1: controller 2 in use (SGB games can be 2-player multiplayer)
if (((flags >> 1) & 1) == 1)
players++;
// bit 2: controller 3 in use (SGB games can be 3- or 4-player multiplayer with multitap)
if (((flags >> 2) & 1) == 1)
players++;
// bit 3: controller 4 in use (SGB games can be 3- or 4-player multiplayer with multitap)
if (((flags >> 3) & 1) == 1)
players++;
// other: reserved // other: reserved
// 016 1-byte flags: system flags (game always runs at 60 frames/sec) // 016 1-byte flags: system flags (game always runs at 60 frames/sec)
flags = r.ReadByte(); flags = r.ReadByte();
@ -2001,7 +2004,9 @@ namespace BizHawk.MultiClient
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.
r.ReadBytes((players - 1) * 2); for (int player = 2; player <= controllersUsed.Length; player++)
if (controllersUsed[player - 1])
r.ReadBytes(2);
mg.SetSource(controllers); mg.SetSource(controllers);
m.AppendFrame(mg.GetControllersAsMnemonic()); m.AppendFrame(mg.GetControllersAsMnemonic());
} }
@ -2037,15 +2042,16 @@ namespace BizHawk.MultiClient
m.Header.Comments.Add(COMMENT + " Record version " + recordVersion); m.Header.Comments.Add(COMMENT + " Record version " + recordVersion);
// 010 4-byte flags (control byte) // 010 4-byte flags (control byte)
uint flags = r.ReadUInt32(); uint flags = r.ReadUInt32();
// bit 0: controller 1 in use /*
bool controller1 = ((flags & 1) == 1); * bit 0: controller 1 in use
// bit 1: controller 2 in use * bit 1: controller 2 in use
bool controller2 = (((flags >> 1) & 1) == 1); * bit 2: controller 3 in use
// bit 2: controller 3 in use * bit 3: controller 4 in use
bool controller3 = (((flags >> 2) & 1) == 1); */
// bit 3: controller 4 in use bool[] controllersUsed = new bool[4];
bool controller4 = (((flags >> 3) & 1) == 1); for (int controller = 1; controller <= controllersUsed.Length; controller++)
bool fourscore = (controller3 || controller4); controllersUsed[controller - 1] = (((flags >> (controller - 1)) & 0x1) != 0);
bool fourscore = (controllersUsed[2] || controllersUsed[3]);
m.Header.SetHeaderLine(MovieHeader.FOURSCORE, fourscore.ToString()); m.Header.SetHeaderLine(MovieHeader.FOURSCORE, fourscore.ToString());
/* /*
bit 6: 1=reset-based, 0=savestate-based (movie version <= 0x300 is always savestate-based) bit 6: 1=reset-based, 0=savestate-based (movie version <= 0x300 is always savestate-based)
@ -2099,7 +2105,7 @@ namespace BizHawk.MultiClient
// 03C 4-byte little-endian integer: CRC (CRC excluding this data(to prevent cheating)) // 03C 4-byte little-endian integer: CRC (CRC excluding this data(to prevent cheating))
int crc32 = r.ReadInt32(); int crc32 = r.ReadInt32();
m.Header.SetHeaderLine("CRC32", crc32.ToString()); m.Header.SetHeaderLine("CRC32", crc32.ToString());
if (!controller1 && !controller2 && !controller3 && !controller4) if (!controllersUsed[0] && !controllersUsed[1] && !controllersUsed[2] && !controllersUsed[3])
{ {
warningMsg = "No input recorded."; warningMsg = "No input recorded.";
r.Close(); r.Close();
@ -2122,7 +2128,6 @@ namespace BizHawk.MultiClient
* 80 Right * 80 Right
*/ */
string[] buttons = new string[8] { "A", "B", "Select", "Start", "Up", "Down", "Left", "Right" }; string[] buttons = new string[8] { "A", "B", "Select", "Start", "Up", "Down", "Left", "Right" };
bool[] masks = new bool[4] {controller1, controller2, controller3, controller4};
for (int frame = 1; frame <= frameCount; frame++) for (int frame = 1; frame <= frameCount; frame++)
{ {
/* /*
@ -2132,9 +2137,9 @@ namespace BizHawk.MultiClient
3 takes 1 byte, and controller 4 takes 1 byte. If all four exist, the frame is 4 bytes. For example, if 3 takes 1 byte, and controller 4 takes 1 byte. If all four exist, the frame is 4 bytes. For example, if
the movie only has controller 1 data, a frame is 1 byte. the movie only has controller 1 data, a frame is 1 byte.
*/ */
for (int player = 1; player <= masks.Length; player++) for (int player = 1; player <= controllersUsed.Length; player++)
{ {
if (!masks[player - 1]) if (!controllersUsed[player - 1])
continue; continue;
// TODO: Check for commands: Lines 207-239 of Nesmock. // TODO: Check for commands: Lines 207-239 of Nesmock.
byte controllerState = r.ReadByte(); byte controllerState = r.ReadByte();
@ -2181,16 +2186,16 @@ namespace BizHawk.MultiClient
r.ReadBytes(4); r.ReadBytes(4);
// 015 4-byte little-endian unsigned int: number of frames advanced step by step // 015 4-byte little-endian unsigned int: number of frames advanced step by step
r.ReadBytes(4); r.ReadBytes(4);
// 016 1-byte: average recording frames per second // 019 1-byte: average recording frames per second
r.ReadByte(); r.ReadBytes(1);
// 020 4-byte little-endian unsigned int: number of key combos // 01A 4-byte little-endian unsigned int: number of key combos
r.ReadBytes(4); r.ReadBytes(4);
// 01E 2-byte little-endian unsigned int: number of internal chapters // 01E 2-byte little-endian unsigned int: number of internal chapters
r.ReadBytes(2); r.ReadBytes(2);
// 020 2-byte little-endian unsigned int: length of the author name field in bytes // 020 2-byte little-endian unsigned int: length of the author name field in bytes
ushort authorSize = r.ReadUInt16(); ushort authorSize = r.ReadUInt16();
// 022 3-byte little-endian unsigned int: size of an uncompressed save state in bytes // 022 3-byte little-endian unsigned int: size of an uncompressed save state in bytes
r.ReadBytes(3); uint savestateSize = (uint)(r.ReadByte() | (r.ReadByte() << 8) | (r.ReadByte() << 16));
/* /*
025 1-byte flags: initial input configuration 025 1-byte flags: initial input configuration
bit 7: first input enabled bit 7: first input enabled
@ -2207,10 +2212,18 @@ namespace BizHawk.MultiClient
warningMsg = "Super Scope"; warningMsg = "Super Scope";
controllerFlags >>= 1; controllerFlags >>= 1;
if ((controllerFlags & 0x1) != 0 && warningMsg != "") if ((controllerFlags & 0x1) != 0 && warningMsg != "")
warningMsg = "Mouse"; warningMsg = "Second Mouse";
controllerFlags >>= 1;
if ((controllerFlags & 0x1) != 0 && warningMsg != "")
warningMsg = "First Mouse";
controllerFlags >>= 1; controllerFlags >>= 1;
if (warningMsg != "") if (warningMsg != "")
warningMsg = "Unable to import " + warningMsg + "."; warningMsg = "Unable to import " + warningMsg + ".";
bool[] controllersUsed = new bool[5];
for (int controller = 1; controller <= controllersUsed.Length; controller++)
controllersUsed[controllersUsed.Length - controller] = (
((controllerFlags >> (controller - 1)) & 0x1) != 0
);
// 026 1-byte: reserved // 026 1-byte: reserved
r.ReadByte(); r.ReadByte();
// 027 1-byte flags: // 027 1-byte flags:
@ -2246,6 +2259,8 @@ namespace BizHawk.MultiClient
specifies size specifies size
*/ */
r.ReadBytes(3); r.ReadBytes(3);
// Next follows a ZST format savestate.
r.ReadBytes((int)savestateSize);
return m; return m;
} }
} }