Beispiel #1
0
        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));
                }
            };
        }
Beispiel #2
0
        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);
        }
Beispiel #3
0
        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);
        }
Beispiel #4
0
 public TilemapMaker(TOC assets)
 {
     this.assets = assets;
 }