public static byte[] Chunk(List <byte[]> input, string name) { var ms = new MemoryStream(); byte[] scratch = new byte[4]; ms.Write(scratch, 0, 2); ms.Write(BitConverter.GetBytes(input.Count - 1), 0, 4); int offset = 0x2A; int count = 0; // Writes the section headers foreach (var s in input) { EndianMethods.WriteInt(ms, offset); offset += 4; offset += s.Length; count++; } count = 0; // Writes the section contents foreach (var s in input) { EndianMethods.WriteInt(ms, s.Length); ms.Write(s, 0, s.Length); count++; } // Re-encodes the data as LZSS format ms.Position = 0; var compress = new MemoryStream(); Lzs.Encode(ms, compress); // Container for our compressed data, will pass this back to be appended to flevel byte[] data = new byte[compress.Length + 28]; // Adds field name 20bytes as a header byte[] nameBytes = Encoding.ASCII.GetBytes(name); Array.Resize(ref nameBytes, 24); int z = 0; while (z < 24) { data[z] = nameBytes[z]; z++; } // Writes in encoded data - Offset to avoid losing the field title header compress.Position = 0; compress.Read(data, 28, (int)compress.Length); // Updates the field header for file length; jumps from byte after header to start of next field's name EndianMethods.WriteInt(data, 20, (int)compress.Length + 4); EndianMethods.WriteInt(data, 24, (int)compress.Length + 0); return(data); }
// Method that chunks an flevel then re-assembles it void bw_Compress(object sender, DoWorkEventArgs e) { ExtractArgs ea = (ExtractArgs)e.Argument; using (var fs = new FileStream(ea.Input, FileMode.Open)) { var df = FF7Files.LoadLGP(fs, ea.Input); int file = 0; List <byte[]> chunks = new List <byte[]>(); //string flev = Path.Combine(ea.Output, Path.GetFileName("flevel.lgp")); string flev = Directory.GetCurrentDirectory() + "\\PC\\Output File\\flevel.lgp"; // Apply ToC and CRC to the new flevel byte[] addStart = new byte[23301]; fs.Position = 0; fs.Read(addStart, 0, addStart.Length); using (var appendStart = new FileStream(flev, FileMode.Append)) { appendStart.Write(addStart, 0, addStart.Length); appendStart.Close(); } int tocPointer = 36; // Holds pointer location for where to write new offset for ToC ulong fieldOffset = 0x5B05; // Holds offset value to write into tocPointer int fieldCount = 0; // Counts fields foreach (var item in df.Items) { (sender as BackgroundWorker).ReportProgress(100 * file++ / df.Items.Count); // This route is for field files if (Path.GetExtension(item.Name).Length == 0 && item.Name != "maplist" // These files 'shrink' when included; seem functional but excluded for now && item.Name != "blackbgb" && item.Name != "frcyo" && item.Name != "fship_4" && item.Name != "las0_8" && item.Name != "las2_1" && item.Name != "uutai1" ) { byte[] ff = new byte[item.Length - 24]; fs.Position = item.Start + 24; fs.Read(ff, 0, ff.Length); chunks = FieldFile.Unchunk(ff); // >>>> // Can adjust the uncompressed chunks here if need be before they go to recompression // Randomisation tasks should be called here, triggered based on section # // >>>> // If using consistent allocation of models, then that logic should be done somewhere here so // that all fields passing through have access to the newly assigned HRC strings and can pass // them through to the rando logic. // Sends Field Script chunk of field to be randomised if (chkItems.Checked) { chunks[0] = FieldScript.ChangeItemsMateria(chunks[0], item.Name); } // Sends Model Loader chunk of field to be randomised if (chkModels.Checked) { chunks[2] = ModelLoader.SwapFieldModels(chunks[2]); } // Recompresses the chunks into a field var field = FieldFile.Chunk(chunks, item.Name); // Skip the first ToC offset as this won't change if (fieldCount != 0) { // Adds field length to pointer so we know where next section starts tocPointer += 27; byte[] byteOffset = EndianMethods.GetLittleEndianConvert(fieldOffset); using (Stream stream = File.Open(flev, FileMode.Open)) { stream.Position = tocPointer; stream.Write(byteOffset, 0, 4); } } // Takes the size of the chunked field; used to determine next offset for ToC fieldOffset += (ulong)field.Length; fieldCount++; // Writes it into the new flevel using (var stream = new FileStream(flev, FileMode.Append)) { stream.Write(field, 0, field.Length); } } // This route is for non-field files else { byte[] field = new byte[item.Length]; fs.Position = item.Start; fs.Read(field, 0, field.Length); // Adds field length to pointer so we know where next section starts tocPointer += 27; byte[] byteOffset = EndianMethods.GetLittleEndianConvert(fieldOffset); using (Stream stream = File.Open(flev, FileMode.Open)) { stream.Position = tocPointer; stream.Write(byteOffset, 0, 4); } // Takes the size of the misc file fieldOffset += (ulong)field.Length; fieldCount++; // Writes it into the new flevel using (var stream = new FileStream(flev, FileMode.Append)) { stream.Write(field, 0, field.Length); } } } // Adds the final terminating string to the flevel byte[] terminate = new byte[] { 0x46, 0x49, 0x4E, 0x41, 0x4C, 0x20, 0x46, 0x41, 0x4E, 0x54, 0x41, 0x53, 0x59, 0x37 }; using (var finalStream = new FileStream(flev, FileMode.Append)) { finalStream.Write(terminate, 0, terminate.Length); } } }