public Bitmap MakeTilesetBitmap(TOCEntry entry, bool collisions) // entry can be COL or PIC { string picName, palName, colName; TOCEntry picEntry, palEntry, colEntry; // level number from BLOCK?.PIC or WORLD?.COL file if (!int.TryParse(entry.Name.Substring(5, 1), out int levelNumber)) { return(null); } if (entry.Type == TOCEntryType.CollisionInfo) // get matching block?.pic { colEntry = entry; picName = $"BLOCK{levelNumber}.PIC"; if (!assets.Entries.ContainsKey(picName)) { return(null); } picEntry = assets.Entries[picName]; } else // get matching world?.col { if (levelNumber == 6) { levelNumber = 5; } picEntry = entry; // collision entry colName = $"WORLD{levelNumber}.COL"; if (!assets.Entries.ContainsKey(colName)) { return(null); } colEntry = assets.Entries[colName]; } if (levelNumber == 6) { levelNumber = 5; } // palette entry palName = $"WORLD{levelNumber}.PAL"; if (!assets.Entries.ContainsKey(palName)) { return(null); } palEntry = assets.Entries[palName]; // read col data COLFile colFile = collisions ? new COLFile(colEntry.Data) : null; try { return(FromBitmaps(PICConverter.PICToBitmaps(picEntry.Data, palEntry.Data), colFile)); } catch { return(null); } }
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 bool Make(TOCEntry entry) { mapEntry = entry; Error = ""; // level number string mapName = mapEntry.Name; if (!int.TryParse(mapName.Substring(1, 1), out int levelNumber)) { Error = $"unable to derive level number from map name {mapName}"; return(false); } // tileset string tilesetName = $"BLOCK{levelNumber}.PIC"; if (!assets.Entries.ContainsKey(tilesetName)) { Error = $"tileset {tilesetName} not found"; return(false); } tilesetEntry = assets.Entries[tilesetName]; // entities if (levelNumber < 6) { string eibName = $"WORLD{mapName.Substring(1, 3)}.EIB"; if (!assets.Entries.ContainsKey(eibName)) { Error = $"entities {eibName} not found"; return(false); } entitiesEntry = assets.Entries[eibName]; } else { entitiesEntry = null; } if (levelNumber == 6) { levelNumber = 5; // level 6 is using palette of level 5 } // collisions string collisionsName = $"WORLD{levelNumber}.COL"; if (!assets.Entries.ContainsKey(collisionsName)) { Error = $"collisions {collisionsName} not found"; return(false); } collisionsEntry = assets.Entries[collisionsName]; // palette string palName = $"WORLD{levelNumber}.PAL"; if (!assets.Entries.ContainsKey(palName)) { Error = $"palette {palName} not found"; return(false); } paletteEntry = assets.Entries[palName]; worker.RunWorkerAsync(); // calls make() return(true); }