public MapMaker(TOC assets, Action <int> progressCallback, Action <bool> completeCallback) { this.assets = assets; this.progressCallback = progressCallback; this.completeCallback = completeCallback; worker = new BackgroundWorker(); worker.WorkerReportsProgress = true; worker.WorkerSupportsCancellation = true; worker.DoWork += make; worker.ProgressChanged += (sender, e) => { if (!worker.CancellationPending) { progressCallback(e.ProgressPercentage); } }; worker.RunWorkerCompleted += (sender, e) => { if (worker.CancellationPending) { TilesBitmap.Dispose(); } else { completeCallback(string.IsNullOrEmpty(Error)); } }; }
public static byte[] GenerateEXE(byte[] startupProgramData, TOC assets) { if (startupProgramData.Length != 12832) { throw new Exception("startup program must be 12832 bytes long"); } List <TOCEntry> entries = new List <TOCEntry>(); foreach (var asset in assets.Entries) { if (!asset.Value.Name.EndsWith(".gap")) { entries.Add(asset.Value); } } entries.Sort((a, b) => a.Index.CompareTo(b.Index)); var f = new BinaryWriter(new MemoryStream()); f.Write(startupProgramData); foreach (var entry in entries) { entry.PackedStart = (int)f.BaseStream.Position; var bat = PackFile2(f, entry.Data, 1024); entry.PackedEnd = (int)f.BaseStream.Position; foreach (var batEntry in bat) { f.Write(batEntry); } } PackFile(f, GenerateToc(entries.ToArray()), int.MaxValue); var buffer = ((MemoryStream)f.BaseStream).GetBuffer(); Array.Resize(ref buffer, (int)f.BaseStream.Position); return(buffer); }
public static TOC Load(byte[] exeData, bool gapsAsEntries = false) { List <TOCEntry> entries = new List <TOCEntry>(); // locate the packed TOC in the binary if (BitConverter.ToInt32(exeData, exeData.Length - 4) != 0x53464945) // "EIFS" { throw new Exception("error loading toc"); } int packedTocLength = BitConverter.ToUInt16(exeData, exeData.Length - 6); int packedTocPos = exeData.Length - 6 - packedTocLength; // unpack the TOC and parse it var tocBuffer = new byte[10000]; int length = UnpackBlock(tocBuffer, exeData.SubArray(packedTocPos, packedTocLength)); if (length < 1) { throw new Exception("error unpacking toc"); } ParseToc(entries, tocBuffer); //var fff = new StreamWriter("debug.txt"); //int numGood = 0; // unpack all files var buffer = new byte[1024]; foreach (var entry in entries) { entry.Data = new byte[entry.Size]; List <BlockInfo> blockInfos = new List <BlockInfo>(); // keep reading packed blocks until we reach the end pointer // a block produces 1024 bytes of unpacked data at max! int readPos = entry.PackedStart; int writePos = 0; int numStreamRead = 0; for (; readPos < entry.PackedEnd;) { int blockLength = exeData[readPos] + exeData[readPos + 1] * 256; blockInfos.Add(new BlockInfo { Position = readPos, Length = blockLength }); var numBytes = UnpackBlock(buffer, exeData.SubArray(readPos, blockLength + 6)); Array.Copy(buffer, 0, entry.Data, writePos, numBytes); numStreamRead += blockLength; writePos += numBytes; readPos += blockLength + 2; } blockInfos.Add(new BlockInfo { Position = readPos, Length = 0 }); if (writePos != entry.Size) { throw new Exception("unpacking error"); } // verify the block-address table: for (int i = 0; i < blockInfos.Count; ++i) { int address = BitConverter.ToInt32(exeData, readPos); if (address != blockInfos[i].Position) { throw new Exception("bad BAT entry"); } readPos += 4; } entry._BATEnd = readPos; // int length2 = BitConverter.ToUInt16(exeData, readPos); readPos += 2; //if(BitConverter.ToUInt32(exeData, readPos) != 0x53464945) // "EIFS" // throw new Exception("bad magic id"); } //fff.WriteLine(numGood + " good out of " + entries.Count); //fff.Flush(); if (gapsAsEntries) { List <TOCEntry> tmp = new List <TOCEntry>(entries); tmp.Sort((a, b) => a.PackedStart.CompareTo(b.PackedStart)); for (int i = 0; i + 1 < tmp.Count; ++i) { var gap = new TOCEntry(); gap.Name = tmp[i].Name + ".gap"; gap.Index = tmp[i].Index; gap.PackedStart = tmp[i]._BATEnd; gap.PackedEnd = tmp[i + 1].PackedStart; gap.Data = exeData.SubArray(tmp[i]._BATEnd, tmp[i + 1].PackedStart - tmp[i]._BATEnd); gap.Size = gap.Data.Length; entries.Add(gap); } } var toc = new TOC(); toc.Entries = new Dictionary <string, TOCEntry>(); foreach (var entry in entries) { toc.Entries.Add(entry.Name, entry); } return(toc); }
public TilemapMaker(TOC assets) { this.assets = assets; }