/// <summary> /// Creates an array of midway points from a byte array. /// </summary> /// <remarks>Remember that the first six bytes should be <see cref="MmpHeader"/> and the version numbers (major, minor, bugfix)</remarks> /// <param name="data">The binary data which contains the midway points.</param> /// <param name="major_">The major version (for backwards compatibility).</param> /// <param name="minor_">The minor version (for backwards compatibility).</param> /// <param name="bugfix_">The bugfix version (for backwards compatibility).</param> /// <returns>A [<see cref="maxLevels"/>, <see cref="maxMidways"/>] array of midway points.</returns> public static Midway[,] FromBinary(byte[] data, byte major_ = MajorVersion, byte minor_ = MinorVersion, byte bugfix_ = BugfixVersion) { int iData = 0; Midway[,] midways = new Midway[maxLevels, maxMidways]; byte[] header = new byte[3]; int major, minor, bugfix; // Placeholder // Header stuff Array.Copy(data, iData, header, 0, 3); if (Encoding.ASCII.GetString(header) != MmpHeader) { throw new ArgumentException("This file is not a proper .mmp file."); } major = data[3]; // minor = data[4]; // Store version number to local variables. bugfix = data[5]; // iData += 6; // Increment byte index. // Loop starts here. for (int i = 0; i < maxLevels; i++) { for (int j = 0; j < maxMidways; j++) { // For each midway point, get four bytes midways[i, j].ConvertFromBytes(data.SubArray(iData, 4)); iData += 4; } } return(midways); }
/// <summary> /// Removes any unused Midway point (<see cref="IsEmpty"/> for the definition details.). /// </summary> /// <param name="midwayTable">The table which should be compressed.</param> public static void CompressTable(ref Midway[,] midwayTable) { // Create a new, empty table Midway[,] newTable = new Midway[maxLevels, maxMidways]; // For each level... for (int j = 0; j < maxLevels; j++) { // Index for the new table int iNew = 0; for (int iOld = 0; iOld < maxMidways; iOld++) { // Only copy the old midway point value if (!midwayTable[j, iOld].IsEmpty()) { newTable[j, iNew++] = midwayTable[j, iOld]; } } } midwayTable = newTable; }
/// <summary> /// Opens multi_midway_tables.asm and generates an array of midway points. /// </summary> /// <returns>The 2D midway point table from the ASM file.</returns> public static Midway[,] ImportAsm(Stream stream) { // Generate a maxLevels * maxMidways Midway array. Midway[,] midways = new Midway[maxLevels, maxMidways]; try { using (StreamReader reader = new StreamReader(stream)) { // The difficult part is to read the arrays. // Remember there is a variable amount of lines in table. // The trick is to only read lines which have got a '$' in it // In order to verify the file, it needs to have the following conditions: // - There are 96 different rows with data for 96 levels // - Each table is a 16-bit table. // Failing any of the conditions means: It's not a valid file. // There is no checks for the length. int iLevel = 0; bool containsData; string line; while ((line = reader.ReadLine()) != null) { containsData = false; int iStart = 0; int iMidway = 0; int commentIndex = line.IndexOf(';'); // Ignore comments if (commentIndex >= 0) { line = line.Substring(0, commentIndex); } // Remove leading spaces and tabs to prevent confusions. char[] charsToTrim = { ' ', '\t' }; line = line.Trim(charsToTrim); if (line.Length < 3) { continue; // This includes lines which are less than 3 chars long. } if (line.Substring(0, 3) != "dw ") { continue; // Now check if the line starts with a "dw " (start of a table). } // Let's go! while ((iStart = line.IndexOf('$', iStart)) >= 0) { try { midways[iLevel, iMidway].CalculateMidway(line.Substring(++iStart, 4)); containsData = true; } catch (ArgumentException ex) { throw new ArgumentException(ex.Message); } // Increment the index to get the next midway point, increment the starting index. iMidway++; iStart++; } if (containsData) { if (++iLevel > 96) { throw new ArgumentOutOfRangeException("Error: Multi_midway_tables.asm isn't a valid file."); } } } // Before we return, we have to make sure there have been enough levels to read. if (iLevel != 96) { throw new ArgumentOutOfRangeException("Error: Multi_midway_tables.asm isn't a valid file."); } } } catch (IOException ex) { throw new IOException("Error: Multi_midway_tables.asm couldn't be read: " + ex.Message); } return(midways); }