/// <summary> /// Load the contents of an external file to the copy buffer /// Returns the column count /// </summary> public static void Load(string filename, ref TASMovieInputCollection buffer) { StreamReader reader = File.OpenText(filename); string header = reader.ReadLine(); int controllers = 0; // TODO::This is a weak validation routine if (header.Length != 3) { MessageBox.Show(frmMain.frm, "Buffer file appears to be invalid", "Oops", MessageBoxButtons.OK, MessageBoxIcon.None, MessageBoxDefaultButton.Button1); return; } string lineItem = null; while ((lineItem = reader.ReadLine()) != null) { TASMovieInput[] frame = new TASMovieInput[1]; string[] split = lineItem.Split('|'); for (int i = 0; i < split.Length; i++) { frame[0].Controller[i] = split[i]; } TASMovieInput.Insert(ref buffer.Input, ref frame, buffer.Input.Length); controllers = split.Length; } reader.Close(); reader.Dispose(); buffer.Format = (TASForm.MovieType)Enum.Parse(typeof(TASForm.MovieType), header); buffer.Controllers = controllers; }
/// <summary> /// Insert the buffered frame input at/after the selected position. /// </summary> private void pasteFrames(bool after) { bool notEmpty = (lvInput.Items.Count > 0); if (notEmpty) { // check for a valid paste position if (lvInput.SelectedIndices.Count == 0) { return; } } int framePos = notEmpty ? (after ? lvInput.SelectedIndices[lvInput.SelectedIndices.Count - 1] + 1: lvInput.SelectedIndices[0]) : 0; // confirm whether to paste frames if (mnuEditingPrompt.Checked) { DialogResult confirmPaste = MessageBox.Show(this, "Paste " + FrameBuffer.Input.Length + " frame(s) " + (notEmpty && after ? "after frame " + (framePos - 1) : "at frame " + framePos) + " ?", "Confirm Paste", MessageBoxButtons.OKCancel, MessageBoxIcon.Question, MessageBoxDefaultButton.Button1); if (confirmPaste != DialogResult.OK) { return; } } UndoBuffer.Add(ref UndoHistory, ref FrameData.Input); TASMovieInput.Insert(ref FrameData.Input, ref FrameBuffer.Input, framePos); updateControlsAfterEdit(); lvInput.SelectedIndices.Clear(); for (int i = 0; i < FrameBuffer.Input.Length; i++) { lvInput.Items[framePos + i].Selected = true; } int focusPos = lvInput.SelectedIndices[lvInput.SelectedIndices.Count - 1]; lvInput.Items[focusPos].Focused = true; lvInput.Focus(); lvInput.EnsureVisible(focusPos); lvInput.Refresh(); Msg.AddMsg("Pasted " + FrameBuffer.Input.Length + " frame(s)"); }
/// <summary> /// Check if two TASMovieInput instances are equal /// </summary> private bool areFramesEqual(TASMovieInput left, TASMovieInput right, int controllers) { for (int i = 0; i < controllers; i++) { if (left.Controller[i] == null && right.Controller[i] == null) { return(true); } else if (left.Controller[i] == right.Controller[i]) { return(true); } } return(false); }
/// <summary> /// Remove the row from the listview at the selectedIndex point and /// update the inputArray, or if multiple rows have been selected, prompt for deletion /// </summary> private void removeFrames() { // make sure something is selected if (lvInput.SelectedIndices.Count == 0) { return; } int[] selectedIndices = new int[lvInput.SelectedIndices.Count]; lvInput.SelectedIndices.CopyTo(selectedIndices, 0); //int framePosition = Convert.ToInt32(lvInput.Items[frameIndex].Text); // prompt for multiple frame insertion if (lvInput.SelectedIndices.Count > 1 && mnuEditingPrompt.Checked) { DialogResult confirmDelete = MessageBox.Show(this, "Are you sure you want to remove the selected " + lvInput.SelectedIndices.Count + " frames", "Confirm Multiple Frame Removal", MessageBoxButtons.OKCancel, MessageBoxIcon.Question, MessageBoxDefaultButton.Button1); if (confirmDelete != DialogResult.OK) { return; } } UndoBuffer.Add(ref UndoHistory, ref FrameData.Input); TASMovieInput.Remove(ref FrameData.Input, selectedIndices); //* // HACK::ensures that the virtual list doesn't try to access an element that // no longer exists after a block of frames is deleted int focusPos = selectedIndices[selectedIndices.Length - 1] - selectedIndices.Length; if (FrameData.Input.Length > 0) { // if we haven't removed all frames... lvInput.Items[focusPos].Focused = true; lvInput.Focus(); lvInput.EnsureVisible(focusPos); } lvInput.SelectedIndices.Clear(); //*/ updateControlsAfterEdit(); Msg.AddMsg("Removed " + lvInput.SelectedIndices.Count + " frame(s)"); }
/// <summary> /// Perform the splice /// </summary> private void btnSplice_Click(object sender, EventArgs e) { // exit if not enough movies are opened if (Movies.Length < 2) { MessageBox.Show(frmMain.frm, "At least two (2) movies must be loaded for splicing to be performed", "Movie Count Too Low", MessageBoxButtons.OK, MessageBoxIcon.None, MessageBoxDefaultButton.Button1); return; } // ensure all loaded movies are of the same type for (int i = 0; i < Movies.Length - 1; i++) { if (Movies[i].MovieType != Movies[i + 1].MovieType) { MessageBox.Show(frmMain.frm, "Movies aren't all of the same type", "Type Mismatch", MessageBoxButtons.OK, MessageBoxIcon.None, MessageBoxDefaultButton.Button1); return; } } TASMovieInput[] spliced = new TASMovieInput[0]; for (int i = 0; i < Movies.Length; i++) { // handle zeroes if (Movies[i].End == 0) { Movies[i].End = Movies[i].Movie.Header.FrameCount; } // NOTE::increase VBM by 1 frame since we enumerate from zero if (Movies[i].MovieType == MovieType.VBM) { Movies[i].End++; } spliced = TASMovieInput.Splice(ref spliced, ref Movies[i].Movie.Input.FrameData, 0, spliced.Length, Movies[i].Start, Movies[i].End); } TASMovieInputCollection temp = new TASMovieInputCollection(); temp.Format = Movies[0].MovieType; temp.Input = spliced; frmSaveAs frm = new frmSaveAs(ref Movies[0].Movie, ref temp, "spliced-"); frm.ShowDialog(); frm.Dispose(); }
/// <summary> /// Convert frame input from binary values to their string representation /// </summary> private TASMovieInput parseControllerData(int[] joop) { TASMovieInput frameData = new TASMovieInput(); for (int i = 0; i < 4; i++) { for (int j = 0; j < 8; j++) { if ((1 & (joop[i] >> j)) == 1) { frameData.Controller[i] += InputValues[j]; } } } return(frameData); }
/// <summary> /// Copy the selected frames to the buffer arraylist /// </summary> private void copyFrames() { // make sure something is selected if (lvInput.SelectedIndices.Count == 0) { return; } int[] selectedIndices = new int[lvInput.SelectedIndices.Count]; lvInput.SelectedIndices.CopyTo(selectedIndices, 0); FrameBuffer.Controllers = FrameData.Controllers; FrameBuffer.Format = FrameData.Format; FrameBuffer.Input = TASMovieInput.Copy(ref FrameData.Input, selectedIndices); enablePasteControls(); }
/// <summary> /// Locate the selected substring in the current TASMovieInput[] object /// </summary> private void btnFindInput_Click(object sender, EventArgs e) { if (FrameData == null) { return; } int start = (lvInput.SelectedIndices.Count > 0) ? lvInput.SelectedIndices[0] + 1 : 0; int end = lvInput.Items.Count; int position = TASMovieInput.Search(ref FrameData, txtJumpToFrame.Text, start, end); if (position < 0) { if (start > 0) { DialogResult answer = MessageBox.Show(MovieSplicer.UI.frmMain.frm, "Input pattern not found between selected position and end of movie.\nContinue searching from the beginning?", "Continue", MessageBoxButtons.OKCancel, MessageBoxIcon.Question, MessageBoxDefaultButton.Button1); if (answer == DialogResult.OK) { position = TASMovieInput.Search(ref FrameData, txtJumpToFrame.Text, 0, start); } } } if (position >= 0 && position < FrameData.Length) { // clear the selection collection // NOTE::This is since we will be creating a new selected items collection // with only 1 item (the resulting frame), but we don't want to clear if no results are // found (since it'll just jump back to the top and repeat if we do) lvInput.SelectedIndices.Clear(); lvInput.Items[position].Selected = true; lvInput.Items[position].Focused = true; lvInput.Focus(); lvInput.EnsureVisible(position); } else { MessageBox.Show(MovieSplicer.UI.frmMain.frm, "Input pattern not found", "Sorry", MessageBoxButtons.OK, MessageBoxIcon.None, MessageBoxDefaultButton.Button1); } }
/// <summary> /// Convert an input's controller values to a string /// </summary> private string frameEncode(TASMovieInput input, int controllers) { string temp = ""; for (int i = 0; i < controllers; i++) { temp += "Controller #" + (i + 1) + ": "; for (int j = 0; j < inputIn.Length; j++) { if (input.Controller[i] != null) { if (input.Controller[i].Contains(inputIn[j])) { temp += inputOut[j] + " "; } } } temp += "\n"; } return(temp); }
/// <summary> /// Append a blank row into the listview after the selectedIndex point and /// update the inputArray, or prompt for insertion of multiple frames based /// on how many frames were selected. /// </summary> private void appendFrames() { int framePosition = FrameData.Input.Length; int totalFrames = 1; // make sure something is selected if (lvInput.SelectedIndices.Count > 0) { framePosition = lvInput.SelectedIndices[lvInput.SelectedIndices.Count - 1] + 1; totalFrames = lvInput.SelectedIndices.Count; } if (FrameData.Input.Length == 0) { framePosition = 0; } // prompt for multiple frame insertion if (lvInput.SelectedIndices.Count > 1 && mnuEditingPrompt.Checked) { DialogResult confirmAdd = MessageBox.Show(this, "Are you sure you want to append " + totalFrames + " frames after frame " + framePosition, "Confirm Multiple Frame Insertion", MessageBoxButtons.OKCancel, MessageBoxIcon.Question, MessageBoxDefaultButton.Button1); if (confirmAdd != DialogResult.OK) { return; } } UndoBuffer.Add(ref UndoHistory, ref FrameData.Input); TASMovieInput.Insert(ref FrameData.Input, new TASMovieInput(), framePosition, totalFrames); updateControlsAfterEdit(); Msg.AddMsg("Appended " + totalFrames + " frame(s) after position " + framePosition); }
public bool findNext(string find, bool downward) { if (Movie == null) { return(false); } int start = 0; int end = lvInput.Items.Count; if (downward) { start = lvInput.SelectedIndices.Count > 0 ? lvInput.SelectedIndices[0] + 1 : 0; } else { start = (lvInput.SelectedIndices.Count > 0 ? lvInput.SelectedIndices[lvInput.SelectedIndices.Count - 1] : end) - 1; end = -1; } int position = TASMovieInput.Search(ref FrameData.Input, find, start, end); if (position < 0) { if (lvInput.SelectedIndices.Count > 0) { DialogResult answer = MessageBox.Show(MovieSplicer.UI.frmMain.frm, "Input pattern not found between selected position and end of movie.\nContinue searching from the " + (downward ? "beginning" : "end") + " of the movie?", "Continue", MessageBoxButtons.OKCancel, MessageBoxIcon.Question, MessageBoxDefaultButton.Button1); if (answer == DialogResult.OK) { end = downward ? 0 : lvInput.Items.Count - 1; position = TASMovieInput.Search(ref FrameData.Input, find, end, start); } } } if (position >= 0 && position < FrameData.Input.Length) { // clear the selection collection // NOTE::This is since we will be creating a new selected items collection // with only 1 item (the resulting frame), but we don't want to clear if no results are // found (since it'll just jump back to the top and repeat if we do) lvInput.SelectedIndices.Clear(); lvInput.Items[position].Selected = true; lvInput.Items[position].Focused = true; lvInput.Focus(); lvInput.EnsureVisible(position); return(true); } else { MessageBox.Show(this, "Input pattern not found", "Sorry", MessageBoxButtons.OK, MessageBoxIcon.None, MessageBoxDefaultButton.Button1); return(false); } }
/// <summary> /// Save changes to the currently buffered FCM file /// </summary> public override void Save(string filename, ref TASMovieInput[] input) { int[] controllerIndices = Input.ActiveControllerIndices; int buffer = 0; int[] joop = { 0, 0, 0, 0 }; List<byte> outputbuffer = new List<byte>(); // start from either power-on or reset //if (Options.MovieStartFlag[2]) //outputFile[position++] = (0x82 & 0x9F) | (0 << 5); //else // if (Options.MovieStartFlag[1]) //outputFile[position++] = (0x81 & 0x9F) | (0 << 5); // FIXME int[] coop = parseControlData(input[0].Controller[4]); if (coop == null) coop = new int[1]; Options.MovieStartFlag[2] = ((coop[0] & (1 << 1)) > 0); Options.MovieStartFlag[1] = ((coop[0] & (1 << 0)) > 0); for (int frame = 0; frame < input.Length; frame++) { // control data come first coop = parseControlData(input[frame].Controller[4]); foreach (byte c in coop) doEncode(c, ref buffer, ref outputbuffer); // cycle through the controllers for (int i = 0; i < controllerIndices.Length - 1; i++) { int j = controllerIndices[i]; int current = parseControllerData(input[frame].Controller[j]); if (current != joop[j]) { // cycle through each bit to see if it's changed for (int k = 0; k < 8; k++) { // if there is a difference, write it out as a command if (((current ^ joop[j]) & (1 << k)) > 0) doEncode(j, k, ref buffer, ref outputbuffer); } } joop[j] = current; } buffer++; } doEncode(0, 0x80, ref buffer, ref outputbuffer); byte[] head = ReadBytes(ref FileContents, 0, ControllerDataOffset); updateMetaData(ref head); int cdataLength = outputbuffer.Count; byte[] outputFile = new byte[head.Length + cdataLength]; head.CopyTo(outputFile, 0); outputbuffer.CopyTo(outputFile, head.Length); // write the new controllerDataLength Write32(ref outputFile, Offsets[8], cdataLength); WriteByteArrayToFile(ref outputFile, filename, input.Length, Offsets[6]); }
/// <summary> /// Convert frame input from binary values to their string representation /// </summary> private TASMovieInput parseControllerData(int[] joop) { TASMovieInput frameData = new TASMovieInput(); for (int i = 0; i < 4; i++) for (int j = 0; j < 8; j++) if ((1 & (joop[i] >> j)) == 1) frameData.Controller[i] += InputValues[j]; return frameData; }
/// <summary> /// Save changes to the currently buffered FCM file /// </summary> public override void Save(string filename, ref TASMovieInput[] input) { byte[] head = ReadBytes(ref FileContents, 0, ControllerDataOffset); int cdataLength = getRLELength(ref input); int controllers = Input.ControllerCount; int buffer = 0; int[] joop = { 0, 0, 0, 0 }; int position = ControllerDataOffset; byte[] outputFile = new byte[head.Length + cdataLength]; head.CopyTo(outputFile, 0); // start from either power-on or reset if (Options.MovieStartFlag[2]) outputFile[position++] = (0x82 & 0x9F) | (0 << 5); else // if (Options.MovieStartFlag[1]) outputFile[position++] = (0x81 & 0x9F) | (0 << 5); // FIXME int frame = 0; while (frame < input.Length) { //// cycle through the controllers for (int j = 0; j < controllers; j++) { int current = parseControllerData(input[frame].Controller[j]); if (current != joop[j]) { // cycle through each bit to see if it's changed for (int k = 0; k < 8; k++) { // if there is a difference, write it out as a command if (((current ^ joop[j]) & (1 << k)) > 0) doEncode(j, k, ref buffer, ref outputFile, ref position); } } joop[j] = current; } buffer++; frame++; } doEncode(0, 0x80, ref buffer, ref outputFile, ref position); //outputFile[position++] = ((0x80) & 0x9F) | (0 << 5); // null command // write the new controllerDataLength Write32(ref outputFile, Offsets[8], cdataLength); updateMetaData(ref outputFile); WriteByteArrayToFile(ref outputFile, filename, input.Length, Offsets[6]); }
/// <summary> /// Get the RLE length of the input so we can size the output array accordingly /// /// HACK::this whole routine is a bad idea, but i need to know the final length of the array, /// and dynamic allocation just doesn't seem to want to work :P /// </summary> public int getRLELength(ref TASMovieInput[] input) { int buffer = 0; int[] joop = { 0, 0, 0, 0 }; int length = 1; for (int i = 0; i < input.Length; i++) { // cycle through the controllers for (int j = 0; j < 4; j++) { int current = parseControllerData(input[i].Controller[j]); if (current != joop[j]) { // cycle through each bit to see if it's changed for (int k = 0; k < 8; k++) { // if there is a difference, write it out as a command if (((current ^ joop[j]) & (1 << k)) > 0) { length++; while (buffer > 0) { length++; buffer >>= 8; } } } } joop[j] = current; } buffer++; } // handle additional buffered values that may have escaped the initial loop // TODO::Functional, but inefficent length++; while (buffer > 0) { length++; buffer >>= 8; } return length; }
/// <summary> /// Save an PXM file back out to disk /// </summary> public override void Save(string filename, ref TASMovieInput[] input) { int Controller1Size = PXMSpecific.ControllerSize[0]; int Controller2Size = PXMSpecific.ControllerSize[1]; int Controller1Type = PXMSpecific.ControllerType[0]; int Controller2Type = PXMSpecific.ControllerType[1]; int ControlSize = BYTES_PER_FRAME[0]; int oldAuthorNameLength = Read32(ref FileContents, Offsets[15]); // PSXjin workaround for (int i = 9; i < 15; ++i) { int minLength = Read32(ref FileContents, Offsets[i]) - Offsets[16]; if (minLength > 0 && minLength < oldAuthorNameLength) { oldAuthorNameLength = minLength; } } byte[] author = WriteChars(Extra.Author); int deltaAuthorNameLength = author.Length - oldAuthorNameLength; // head excludes the author info but includes its length byte[] head = ReadBytes(ref FileContents, 0, Offsets[16]); // assuming that controller data are always at the end byte[] extra = ReadBytes(ref FileContents, Offsets[16] + oldAuthorNameLength, ControllerDataOffset - Offsets[16] - oldAuthorNameLength); // get the size of the file byte[] (minus the header & extra data) int size = input.Length * (Controller1Size + Controller2Size + ControlSize); // create the output array and copy in the contents byte[] outputFile = new byte[head.Length + author.Length + extra.Length + size]; head.CopyTo(outputFile, 0); int newSaveStateOffset = SaveStateOffset + deltaAuthorNameLength; int newMemoryCard1Offset = PXMSpecific.MemoryCard1Offset + deltaAuthorNameLength; int newMemoryCard2Offset = PXMSpecific.MemoryCard2Offset + deltaAuthorNameLength; int newCheatListOffset = PXMSpecific.CheatListOffset + deltaAuthorNameLength; int newCDRomIDOffset = PXMSpecific.CDRomIDOffset + deltaAuthorNameLength; int newControllerDataOffset = ControllerDataOffset + deltaAuthorNameLength; Write32(ref outputFile, Offsets[7], input.Length); Write32(ref outputFile, Offsets[9], newSaveStateOffset); Write32(ref outputFile, Offsets[10], newMemoryCard1Offset); Write32(ref outputFile, Offsets[11], newMemoryCard2Offset); Write32(ref outputFile, Offsets[12], newCheatListOffset); Write32(ref outputFile, Offsets[13], newCDRomIDOffset); Write32(ref outputFile, Offsets[14], newControllerDataOffset); Write32(ref outputFile, Offsets[15], author.Length); for (int j = 0; j < author.Length; ++j) outputFile[Offsets[16] + j] = Convert.ToByte(author[j]); extra.CopyTo(outputFile, head.Length + author.Length); // add the controller data int position = newControllerDataOffset; for (int i = 0; i < input.Length; i++) { parseControllerData(input[i].Controller[0], Controller1Type).CopyTo(outputFile, position); position += Controller1Size; parseControllerData(input[i].Controller[1], Controller2Type).CopyTo(outputFile, position); position += Controller2Size; parseControlData(input[i].Controller[2]).CopyTo(outputFile, position); position += ControlSize; } //// DEBUGGING // //MovieSplicer.UI.frmDebug frm = new MovieSplicer.UI.frmDebug(); //for (int i = 0; i < FileContents.Length; i++) //{ // System.Windows.Forms.ListViewItem lvi = new System.Windows.Forms.ListViewItem(); // lvi.Text = i.ToString(); // lvi.SubItems.Add(FileContents[i].ToString()); // string item = (i < outputFile.Length) ? outputFile[i].ToString() : "out of range"; // lvi.SubItems.Add(item); // frm.Add(lvi); //} //frm.Show(); ///////////////// WriteByteArrayToFile(ref outputFile, filename, input.Length, Offsets[7]); }
/// <summary> /// Process the input values in the file to a TASMovieInput collection /// </summary> private void getFrameInput(ref byte[] byteArray) { Input.FrameData = new TASMovieInput[Header.FrameCount]; int position = ControllerDataOffset; int frameCount = 0; int[] joop = { 0, 0, 0, 0 }; while (ControllerDataLength > 0) { int updateType = byteArray[position] >> 7; int NDelta = (byteArray[position] >> 5) & 3; int delta = 0; int data = byteArray[position] & 0x1F; ++position; --ControllerDataLength; switch (NDelta) { case 0: break; case 1: delta |= byteArray[position++]; break; case 2: delta |= byteArray[position++]; delta |= byteArray[position++] << 8; break; case 3: delta |= byteArray[position++]; delta |= byteArray[position++] << 8; delta |= byteArray[position++] << 16; break; } // populate parsed data once (since it doesn't change until delta == 0, // there's no need to process each time the loop iterates) TASMovieInput parsedControllerData = parseControllerData(joop); while (delta > 0) { // Save the controlled data Input.FrameData[frameCount] = new TASMovieInput(); Input.FrameData[frameCount] = parsedControllerData; ++frameCount; --delta; } if (ControllerDataLength > NDelta) { ControllerDataLength -= NDelta; } else { ControllerDataLength = 0; } if (updateType == 0) // Controller data { int ctrlno = (data >> 3); joop[ctrlno] ^= (1 << (data & 7)); if (ctrlno == 0) { Input.Controllers[0] = true; } if (ctrlno == 1) { Input.Controllers[1] = true; } if (ctrlno == 2) { Input.Controllers[2] = true; } if (ctrlno == 3) { Input.Controllers[3] = true; } } // Exerpt from Nesmock 1.6.0 source. //else // Control data // switch (data) // { // case 0: break; // nothing // case 1: Save = false; break; // reset // case 2: Save = false; break; // power cycle // case 7: break; // VS coin // case 8: break; // VS dip0 // case 24: FDS = true; Cdata[frame].FDS |= 1; break; /* FDS insert, FIXME */ // case 25: FDS = true; Cdata[frame].FDS |= 2; break; /* FDS eject, FIXME */ // case 26: FDS = true; Cdata[frame].FDS |= 4; break; /* FDS swap, FIXME */ // } } }
/// <summary> /// Save an MMV file back out to disk /// </summary> public override void Save(string filename, ref TASMovieInput[] input) { byte[] head = ReadBytes(ref FileContents, 0, ControllerDataOffset); int controllers = Input.ControllerCount; int packSize = MMVSpecific.PackSize; // get the size of the file byte[] (minus the header) int size = input.Length * packSize; // create the output array and copy in the contents byte[] outputFile = new byte[head.Length + size]; head.CopyTo(outputFile, 0); // add the controller data int position = 0; for (int i = 0; i < input.Length; i++) { outputFile[head.Length + position++] = parseControllerData(input[i].Controller[0]); outputFile[head.Length + position++] = parseControllerData(input[i].Controller[1]); } updateMetadata(ref outputFile); WriteByteArrayToFile(ref outputFile, filename, input.Length, Offsets[2]); }
/// <summary> /// Save the contenst of the frame data back out to a VBM file /// /// TODO::This isn't the most elegant solution, but there's a major performance hit /// if I try to repeatedly resize the array from within the loop. /// </summary> public override void Save(string filename, ref TASMovieInput[] input) { byte[] head = ReadBytes(ref FileContents, 0, ControllerDataOffset); int size = 0; int controllers = Input.ControllerCount; // get the size of the file byte[] (minus the header) for (int i = 0; i < input.Length; i++) for (int j = 0; j < controllers; j++) size += 2; // create the output array and copy in the contents byte[] outputFile = new byte[head.Length + size]; head.CopyTo(outputFile, 0); // add the controller data int position = 0; for (int i = 0; i < input.Length; i++) { for (int j = 0; j < controllers; j++) { // check if the controller we're about to process is used if (Input.Controllers[j]) { byte[] parsed = parseControllerData(input[i].Controller[j]); outputFile[head.Length + position++] = parsed[0]; outputFile[head.Length + position++] = parsed[1]; } } } // update the movie description and author for (int i = 0; i < 64; i++) if (i < Extra.Author.Length) outputFile[HEADER_SIZE + i] = Convert.ToByte(Extra.Author[i]); else outputFile[HEADER_SIZE + i] = 0; for (int j = 0; j < 128; j++) if (j < Extra.Description.Length) outputFile[HEADER_SIZE + 64 + j] = Convert.ToByte(Extra.Description[j]); else outputFile[HEADER_SIZE + 64 + j] = 0; //// DEBUGGING // //MovieSplicer.UI.frmDebug frm = new MovieSplicer.UI.frmDebug(); //for (int i = 0; i < FileContents.Length; i++) //{ // System.Windows.Forms.ListViewItem lvi = new System.Windows.Forms.ListViewItem(); // lvi.Text = i.ToString(); // lvi.SubItems.Add(FileContents[i].ToString()); // string item = (i < outputFile.Length) ? outputFile[i].ToString() : "out of range"; // lvi.SubItems.Add(item); // frm.Add(lvi); //} //frm.Show(); ///////////////// WriteByteArrayToFile(ref outputFile, filename, input.Length - 1, Offsets[3]); }
/// <summary> /// Save an SMV file back out to disk /// </summary> public override void Save(string filename, ref TASMovieInput[] input) { byte[] head = ReadBytes(ref FileContents, 0, ControllerDataOffset); SMVSpecific.SampleSize = Input.ControllerCount * BYTES_PER_FRAME[1] + SMVSpecific.NonJoypadSampleSize; SMVSpecific.NumControllers = Input.ControllerCount; // create the output array and copy in the contents byte[] outputFile = new byte[head.Length + input.Length * SMVSpecific.SampleSize]; head.CopyTo(outputFile, 0); // add the controller data int position = 0; for (int i = 0; i < input.Length; i++) { for (int j = 0; j < Input.Controllers.Length; j++) { // check if the controller we're about to process is used if (Input.Controllers[j]) { byte[] parsed = parseControllerData(input[i].Controller[j]); outputFile[head.Length + position++] = parsed[0]; outputFile[head.Length + position++] = parsed[1]; } } if (i >= unsupportedInputBuffer.Length) { for (int k = 0; k < SMVSpecific.NonJoypadSampleSize; k++) outputFile[head.Length + position++] = 0; } else { for (int k = 0; k < SMVSpecific.NonJoypadSampleSize; k++) outputFile[head.Length + position++] = unsupportedInputBuffer[i][SMVSpecific.NonJoypadSampleSize + k]; } } updateMetadata(ref outputFile); //// DEBUGGING // //MovieSplicer.UI.frmDebug frm = new MovieSplicer.UI.frmDebug(); //for (int i = 0; i < FileContents.Length; i++) //{ // System.Windows.Forms.ListViewItem lvi = new System.Windows.Forms.ListViewItem(); // lvi.Text = i.ToString(); // lvi.SubItems.Add(FileContents[i].ToString()); // string item = (i < outputFile.Length) ? outputFile[i].ToString() : "out of range"; // lvi.SubItems.Add(item); // frm.Add(lvi); //} //frm.Show(); ///////////////// WriteByteArrayToFile(ref outputFile, filename, input.Length - 1, Offsets[4]); }
/// <summary> /// Save the content of the frame data back out to an M64 file /// </summary> public override void Save(string filename, ref TASMovieInput[] input) { byte[] head = ReadBytes(ref FileContents, 0, ControllerDataOffset); int size = 0; int controllers = Input.ControllerCount; // get the size of the file byte[] (minus the header) for (int i = 0; i < input.Length; i++) for (int j = 0; j < controllers; j++) size += BYTES_PER_FRAME; // create the output array and copy in the contents byte[] outputFile = new byte[head.Length + size + (BYTES_PER_FRAME * controllers)]; head.CopyTo(outputFile, 0); // add the controller data int position = 0; for (int i = 0; i < input.Length; i++) for (int j = 0; j < controllers; j++) // check if the controller we're about to process is used if (Input.Controllers[j]) { byte[] parsed = parseControllerData(input[i].Controller[j]); outputFile[head.Length + position++] = parsed[0]; outputFile[head.Length + position++] = parsed[1]; outputFile[head.Length + position++] = parsed[2]; outputFile[head.Length + position++] = parsed[3]; } updateMetadata(ref outputFile); WriteByteArrayToFile(ref outputFile, filename, input.Length, Offsets[8]); //return true; }
/// <summary> /// Update the input array with the changed frame data /// </summary> private void btnUpdate_Click(object sender, EventArgs e) { if (lvInput.SelectedIndices.Count == 0) { return; } bool[] updateFlag = { false, false, false, false, false }; TASMovieInput updated = new TASMovieInput(); if (sender == button1) { updated.Controller[0] = txtFrameDataC1.Text; updateFlag[0] = true; } else if (sender == button2) { updated.Controller[1] = txtFrameDataC2.Text; updateFlag[1] = true; } else if (sender == button3) { updated.Controller[2] = txtFrameDataC3.Text; updateFlag[2] = true; } else if (sender == button4) { updated.Controller[3] = txtFrameDataC4.Text; updateFlag[3] = true; } else if (sender == button5) { updated.Controller[4] = txtFrameDataC5.Text; updateFlag[4] = true; } else { if (chkFrameDataC1.Checked) { updated.Controller[0] = txtFrameData.Text; updateFlag[0] = true; } if (chkFrameDataC2.Checked) { updated.Controller[1] = txtFrameData.Text; updateFlag[1] = true; } if (chkFrameDataC3.Checked) { updated.Controller[2] = txtFrameData.Text; updateFlag[2] = true; } if (chkFrameDataC4.Checked) { updated.Controller[3] = txtFrameData.Text; updateFlag[3] = true; } if (chkFrameDataC5.Checked) { updated.Controller[4] = txtFrameData.Text; updateFlag[4] = true; } } // if no controllers were set, return if (!updateFlag[0] && !updateFlag[1] && !updateFlag[2] && !updateFlag[3] && !updateFlag[4]) { return; } // prompt for multiple frame insertion if (lvInput.SelectedIndices.Count > 1 && EditingPrompts) { DialogResult confirmUpdate = MessageBox.Show(MovieSplicer.UI.frmMain.frm, "Are you sure you want to update the " + lvInput.SelectedIndices.Count + " frames with the same input?", "Confirm Multiple Frame Update", MessageBoxButtons.OKCancel, MessageBoxIcon.Question, MessageBoxDefaultButton.Button1); if (confirmUpdate != DialogResult.OK) { return; } } UndoBuffer.Add(ref UndoHistory, ref FrameData); int[] selectedIndices = new int[lvInput.SelectedIndices.Count]; lvInput.SelectedIndices.CopyTo(selectedIndices, 0); // append or overwrite check if (chkAppendInput.Checked) { TASMovieInput.UpdatePlus(ref FrameData, updated, updateFlag, AutoFire, selectedIndices); } else { TASMovieInput.Update(ref FrameData, updated, updateFlag, AutoFire, selectedIndices); } lvInput.ClearVirtualCache(); lvInput.Refresh(); Msg.AddMsg("Updated " + lvInput.SelectedIndices.Count + " frame(s)"); }
/// <summary> /// Insert the buffered frame input at/after each selected position. /// </summary> private void pasteFramesMultiple(bool after) { // check for a valid paste position if (lvInput.SelectedIndices.Count <= 1) { return; } int[] selectedIndices = new int[lvInput.SelectedIndices.Count]; if (after) { for (int i = 0; i < selectedIndices.Length; i++) { selectedIndices[i] = lvInput.SelectedIndices[i] + 1; } } else { lvInput.SelectedIndices.CopyTo(selectedIndices, 0); } bool multiplePaste = false; // ask whether to paste multiple times if (mnuEditingPrompt.Checked) { DialogResult confirmPaste = MessageBox.Show(this, "Paste " + selectedIndices.Length + " chunks of " + FrameBuffer.Input.Length + " frame(s) " + (after ? "after" : "before") + " each selected frame?\nWarning: this might be extremely slow!", "Confirm Paste", MessageBoxButtons.YesNoCancel, MessageBoxIcon.Question, MessageBoxDefaultButton.Button1); if (confirmPaste == DialogResult.Yes) { multiplePaste = true; } else if (confirmPaste == DialogResult.No) { multiplePaste = false; } else { return; } } UndoBuffer.Add(ref UndoHistory, ref FrameData.Input); if (multiplePaste) { TASMovieInput.InsertMultiple(ref FrameData.Input, ref FrameBuffer.Input, selectedIndices); } else { TASMovieInput.Insert(ref FrameData.Input, ref FrameBuffer.Input, (after ? selectedIndices[selectedIndices.Length - 1] : selectedIndices[0])); } lvInput.ClearVirtualCache(); lvInput.VirtualListSource = FrameData.Input; lvInput.VirtualListSize = FrameData.Input.Length; lvInput.SelectedIndices.Clear(); lvInput.Refresh(); if (multiplePaste) { for (int i = 0; i < selectedIndices.Length; i++) { for (int j = 0; j < FrameBuffer.Input.Length; j++) { lvInput.Items[selectedIndices[i] + i * FrameBuffer.Input.Length + j].Selected = true; } } } else { int startPos = (after ? selectedIndices[selectedIndices.Length - 1] : selectedIndices[0]); for (int i = 0; i < FrameBuffer.Input.Length; i++) { lvInput.Items[startPos + i].Selected = true; } } int focusPos = lvInput.SelectedIndices[lvInput.SelectedIndices.Count - 1]; lvInput.Items[focusPos].Focused = true; lvInput.Focus(); lvInput.EnsureVisible(focusPos); updateControlsAfterEdit(); if (multiplePaste) { Msg.AddMsg("Pasted " + lvInput.SelectedIndices.Count + " chunks of " + FrameBuffer.Input.Length + " frame(s)"); } else { Msg.AddMsg("Pasted " + FrameBuffer.Input.Length + " frame(s)"); } }
/// <summary> /// Save a new GMV file (if a string null is passed, prompt for overwrite of the source file) /// </summary> public override void Save(string filename, ref TASMovieInput[] input) { byte[] head = ReadBytes(ref FileContents, 0, HEADER_SIZE); // create the output array and copy in the contents byte[] outputFile = new byte[head.Length + input.Length * 3]; head.CopyTo(outputFile, 0); // add the controller data int position = 0; int controllers = Input.ControllerCount; for (int i = 0; i < input.Length; i++) { outputFile[head.Length + position++] = parseControllerData(input[i].Controller[0]); outputFile[head.Length + position++] = parseControllerData(input[i].Controller[1]); if (controllers == 3) outputFile[head.Length + position++] = parseControllerData(input[i].Controller[2]); else if (GMVSpecific.Player1Config == "6" || GMVSpecific.Player2Config == "6") outputFile[head.Length + position++] = parseExtraControllerData(input[i].Controller[0], input[i].Controller[1]); else outputFile[head.Length + position++] = 0xFF; } // update the movie description for (int i = 0; i < 40; i++) if (i < Extra.Description.Length) outputFile[Offsets[6] + i] = Convert.ToByte(Extra.Description[i]); else outputFile[Offsets[6] + i] = 0; // NOTE::GMV files calculate frameCount based on filesize WriteByteArrayToFile(ref outputFile, filename, -1, -1); }
/// <summary> /// Save input changes back out to file /// /// TODO::Save might fail if this is an FDS movie (since FDS is factored into the BytesPerFrame) /// </summary> public override void Save(string filename, ref TASMovieInput[] input) { byte[] head = ReadBytes(ref FileContents, 0, Offsets[8]); // create the output array and copy in the contents byte[] outputFile = new byte[head.Length + input.Length * BytesPerFrame]; head.CopyTo(outputFile, 0); int position = 0; int controllers = Input.ControllerCount; for (int i = 0; i < input.Length; i++) for (int j = 0; j < controllers; j++) outputFile[head.Length + position++] = parseControllerData(input[i].Controller[j]); // update the movie description for (int i = 0; i < 64; i++) if (i < Extra.Description.Length) outputFile[Offsets[7] + i] = Convert.ToByte(Extra.Description[i]); else outputFile[Offsets[7] + i] = 0; // NOTE::FMV files calculate frameCount based on filesize WriteByteArrayToFile(ref outputFile, filename, -1, -1); }
/// <summary> /// Process the input values in the file to a TASMovieInput collection /// </summary> private void getFrameInput(ref byte[] byteArray) { Input.FrameData = new TASMovieInput[Header.FrameCount]; int position = ControllerDataOffset; int frameCount = 0; int[] joop = { 0, 0, 0, 0 }; List <int> coop = new List <int>(); while (ControllerDataLength > 0) { int updateType = byteArray[position] >> 7; int NDelta = (byteArray[position] >> 5) & 3; int delta = 0; int data = byteArray[position] & 0x1F; ++position; --ControllerDataLength; switch (NDelta) { case 0: break; case 1: delta |= byteArray[position++]; break; case 2: delta |= byteArray[position++]; delta |= byteArray[position++] << 8; break; case 3: delta |= byteArray[position++]; delta |= byteArray[position++] << 8; delta |= byteArray[position++] << 16; break; } // Save the controlled data if (delta > 0) { if (coop.Count > 0) { // set the control data Input.FrameData[frameCount] = parseControllerData(joop); Input.FrameData[frameCount].Controller[4] = parseControlData(ref coop); ++frameCount; --delta; coop.Clear(); } // populate parsed data once (since it doesn't change until delta == 0, // there's no need to process each time the loop iterates) TASMovieInput parsedControllerData = parseControllerData(joop); while (delta > 0) { Input.FrameData[frameCount] = parsedControllerData; ++frameCount; --delta; } } if (ControllerDataLength > NDelta) { ControllerDataLength -= NDelta; } else { ControllerDataLength = 0; } if (updateType == 0) // Controller data { int ctrlno = (data >> 3); joop[ctrlno] ^= (1 << (data & 7)); if (ctrlno == 0) { Input.Controllers[0] = true; } if (ctrlno == 1) { Input.Controllers[1] = true; } if (ctrlno == 2) { Input.Controllers[2] = true; } if (ctrlno == 3) { Input.Controllers[3] = true; } } else // Control data { switch (data) { case 0: coop.Add(0); break; // EOF case 1: coop.Add(1); break; // Reset case 2: coop.Add(2); break; // Power Cycle case 7: coop.Add(3); break; // VS Coin case 8: coop.Add(4); break; // VS Dip 0 case 24: coop.Add(5); break; // TODO: FDS Insert/Eject??? case 25: coop.Add(6); break; // TODO: FDS Eject??? case 26: coop.Add(7); break; // FDS Select Side default: break; } } } }