public RomFile(string fileName, int fileID, UnknownData rawFileData) { FileName = fileName; FileID = fileID; _elements = new N64DataElementCollection(); _elements.UnknownDataAdded += _elements_UnknownDataAdded; _elements.UnknownDataRemoved += _elements_UnknownDataRemoved; _elementContainers = new List<IN64ElementContainer>(); _miscElementContainer = new MiscN64ElementContainer(); FileLength = rawFileData.RawDataSize; _elements.AddElement(rawFileData); }
public bool AddElement(N64DataElement element, bool overwriteUnknownData = true) { if (element.FileOffset < 0) return false; int startOffset = element.FileOffset; int endOffset = startOffset + element.RawDataSize - 1; //Find if it is inside a currently existing element, or if it can be added freely int indexToAdd = 0; bool insideElement = false; for (; indexToAdd < _elements.Count; indexToAdd++) { if (endOffset < _elements[indexToAdd].FileOffset) { //Found where to insert the new element break; } else if (_elements[indexToAdd].ContainsOffset(startOffset) || _elements[indexToAdd].ContainsOffset(endOffset) || element.ContainsOffset(_elements[indexToAdd].FileOffset)) { insideElement = true; break; } } //If there were conflicts if (insideElement) { //Determine if we can overwrite unknown data with known data if (_elements[indexToAdd] is UnknownData && overwriteUnknownData && !((UnknownData)_elements[indexToAdd]).Locked) { //Step one: determine how many elements this new one spans int endingIndex = indexToAdd; for (; endingIndex < _elements.Count - 1; endingIndex++) { //If it doesn't run into this next data element, then it stops before it. Break out of the loop if (!_elements[endingIndex + 1].ContainsOffset(endOffset) && !element.ContainsOffset(_elements[endingIndex + 1].FileOffset)) break; //Only unlocked unknown data may be split if (!(_elements[endingIndex + 1] is UnknownData) || ((UnknownData)_elements[indexToAdd]).Locked) return false; } //Step two: determine how to split the start/ends. bool startUnknownLeftOver = false; bool endUnknownLeftOver = false; if (_elements[indexToAdd].ContainsOffset(startOffset) && _elements[indexToAdd].FileOffset != startOffset) startUnknownLeftOver = true; if (_elements[endingIndex].ContainsOffset(endOffset) && _elements[endingIndex].FileOffset + _elements[endingIndex].RawDataSize - 1 != endOffset) endUnknownLeftOver = true; if (startUnknownLeftOver) { byte[] unknownData = new byte[startOffset - _elements[indexToAdd].FileOffset]; Array.Copy(_elements[indexToAdd].RawData, 0, unknownData, 0, unknownData.Length); UnknownData newData = new UnknownData(_elements[indexToAdd].FileOffset, unknownData); _elements.Insert(indexToAdd, newData); if (UnknownDataAdded != null) UnknownDataAdded(newData); indexToAdd++; endingIndex++; } if (endUnknownLeftOver) { byte[] unknownData = new byte[_elements[endingIndex].FileOffset + _elements[endingIndex].RawDataSize - (endOffset + 1)]; Array.Copy(_elements[endingIndex].RawData, (endOffset + 1) - _elements[endingIndex].FileOffset, unknownData, 0, unknownData.Length); UnknownData newData = new UnknownData(endOffset + 1, unknownData); _elements.Insert(endingIndex + 1, newData); if (UnknownDataAdded != null) UnknownDataAdded(newData); } //Step 3: Remove the overlapping unknowns, insert the new data for (int i = 0; i <= endingIndex - indexToAdd; i++) { if (UnknownDataRemoved != null) UnknownDataRemoved((UnknownData)_elements[indexToAdd]); _elements.RemoveAt(indexToAdd); } _elements.Insert(indexToAdd, element); return true; } else { return false; } } //Down here, there were no conflicts _elements.Insert(indexToAdd, element); return true; }
/// <summary> /// Allow split data from the N64DataElementCollection to still be sorted into containers /// </summary> /// <param name="data"></param> private void _elements_UnknownDataAdded(UnknownData data) { bool added = false; foreach (IN64ElementContainer container in _elementContainers) { if (container.AddElement(data)) added = true; } if(!added) _miscElementContainer.AddElement(data); }
public bool ExpandFileTo(int newFileSize, byte fillByte = 0x00) { if (newFileSize <= FileLength) return false; N64DataElement lastElement = GetElementAt(FileLength - 1); if (lastElement == null) return false; //Create a new UnknownData element byte[] newBytes = new byte[newFileSize - FileLength]; for(int i = 0; i < newBytes.Length; i++) newBytes[i] = fillByte; UnknownData newData = new UnknownData(FileLength, newBytes); return AddElement(newData); }
/// <summary> /// Allow split data from the N64DataElementCollection to still be sorted into containers /// </summary> /// <param name="data"></param> private void _elements_UnknownDataRemoved(UnknownData data) { foreach (IN64ElementContainer container in _elementContainers) { container.RemoveElement(data); } _miscElementContainer.RemoveElement(data); }