public RelocationPointerList GetListForPart(byte module, byte block) { for (int i = 0; i < pointerBlocks.Length; i++) { RelocationPointerList e = pointerBlocks[i]; if (e.module == module && e.id == block) { return(e); } } return(null); }
private void ReadPointerBlock(Reader reader, RelocationPointerList pointerBlock) { for (int j = 0; j < pointerBlock.count; j++) { // One pointer info struct contains the address where the pointer is located and the module & block of the part it points to. // The address that it points to is to be read at address offsetInMemory. // The part's baseInMemory should be subtracted from it to get the offset relative to the part. pointerBlock.pointers[j] = new RelocationPointerInfo(); pointerBlock.pointers[j].offsetInMemory = reader.ReadUInt32(); pointerBlock.pointers[j].module = reader.ReadByte(); pointerBlock.pointers[j].id = reader.ReadByte(); if (Settings.s.engineVersion > Settings.EngineVersion.TT && Settings.s.game != Settings.Game.PlaymobilLaura) { pointerBlock.pointers[j].byte6 = reader.ReadByte(); pointerBlock.pointers[j].byte7 = reader.ReadByte(); } } }
// Used for Tonic Trouble's Fixlvl.rtb, which contains a list of fix->lvl pointers that should be loaded along with the fix.rtb file public void Add(RelocationTable rt) { if (rt == null) { return; } for (int i = 0; i < rt.pointerBlocks.Length; i++) { RelocationPointerList ptrList = GetListForPart(rt.pointerBlocks[i].module, rt.pointerBlocks[i].id); if (ptrList == null) { Array.Resize(ref pointerBlocks, pointerBlocks.Length + 1); pointerBlocks[pointerBlocks.Length - 1] = rt.pointerBlocks[i]; } else { ptrList.count += rt.pointerBlocks[i].count; Array.Resize(ref ptrList.pointers, (int)ptrList.count); Array.Copy(rt.pointerBlocks[i].pointers, 0, ptrList.pointers, ptrList.count - rt.pointerBlocks[i].count, rt.pointerBlocks[i].count); } } }
void Read(EndianBinaryReader reader) { MapLoader l = MapLoader.Loader; byte count = reader.ReadByte(); reader.ReadUInt32(); pointerBlocks = new RelocationPointerList[count]; for (int i = 0; i < count; i++) { // A pointer list contains pointers located in SNA part with matching module & block pointerBlocks[i] = new RelocationPointerList(); pointerBlocks[i].module = reader.ReadByte(); pointerBlocks[i].id = reader.ReadByte(); l.print("Parsing pointer block for (" + pointerBlocks[i].module + "," + pointerBlocks[i].id + ")"); //l.print("Module: " + parts[i].module + " - Block: " + parts[i].block); pointerBlocks[i].count = reader.ReadUInt32(); pointerBlocks[i].pointers = new RelocationPointerInfo[pointerBlocks[i].count]; for (int j = 0; j < pointerBlocks[i].count; j++) { // One pointer info struct contains the address where the pointer is located and the module & block of the part it points to. // The address that it points to is to be read at address offsetInMemory. // The part's baseInMemory should be subtracted from it to get the offset relative to the part. pointerBlocks[i].pointers[j] = new RelocationPointerInfo(); pointerBlocks[i].pointers[j].offsetInMemory = reader.ReadUInt32(); if (pointerBlocks[i].pointers[j].offsetInMemory == 1824756 || pointerBlocks[i].pointers[j].offsetInMemory == 1824748) { l.print("Found! It's (" + pointerBlocks[i].module + "," + pointerBlocks[i].id + ")"); } pointerBlocks[i].pointers[j].module = reader.ReadByte(); pointerBlocks[i].pointers[j].id = reader.ReadByte(); pointerBlocks[i].pointers[j].byte6 = reader.ReadByte(); pointerBlocks[i].pointers[j].byte7 = reader.ReadByte(); } } }
async Task Read(Reader reader) { MapLoader l = MapLoader.Loader; PartialHttpStream httpStream = reader.BaseStream as PartialHttpStream; if (httpStream != null) { await httpStream.FillCacheForRead(5); } byte count = reader.ReadByte(); if (Settings.s.game != Settings.Game.R2Demo && Settings.s.engineVersion > Settings.EngineVersion.Montreal) { reader.ReadUInt32(); } pointerBlocks = new RelocationPointerList[count]; for (int i = 0; i < count; i++) { if (reader.BaseStream.Position >= reader.BaseStream.Length) { Array.Resize(ref pointerBlocks, i); break; } if (httpStream != null) { await httpStream.FillCacheForRead(6); } // A pointer list contains pointers located in SNA part with matching module & block pointerBlocks[i] = new RelocationPointerList(); pointerBlocks[i].module = reader.ReadByte(); pointerBlocks[i].id = reader.ReadByte(); l.print("Parsing pointer block for (" + pointerBlocks[i].module + "," + pointerBlocks[i].id + ")"); //l.print("Module: " + parts[i].module + " - Block: " + parts[i].block); pointerBlocks[i].count = reader.ReadUInt32(); pointerBlocks[i].pointers = new RelocationPointerInfo[pointerBlocks[i].count]; if (pointerBlocks[i].count > 0) { if (Settings.s.snaCompression) { if (httpStream != null) { await httpStream.FillCacheForRead(5 *4); } uint isCompressed = reader.ReadUInt32(); uint compressedSize = reader.ReadUInt32(); uint compressedChecksum = reader.ReadUInt32(); uint decompressedSize = reader.ReadUInt32(); uint decompressedChecksum = reader.ReadUInt32(); if (httpStream != null) { await httpStream.FillCacheForRead((int)compressedSize); } byte[] compressedData = reader.ReadBytes((int)compressedSize); if (isCompressed != 0) { using (var compressedStream = new MemoryStream(compressedData)) using (var lzo = new LzoStream(compressedStream, CompressionMode.Decompress)) using (Reader lzoReader = new Reader(lzo, Settings.s.IsLittleEndian)) { ReadPointerBlock(lzoReader, pointerBlocks[i]); } } else { using (var uncompressedStream = new MemoryStream(compressedData)) using (Reader unCompressedReader = new Reader(uncompressedStream, Settings.s.IsLittleEndian)) { ReadPointerBlock(unCompressedReader, pointerBlocks[i]); } } } else { if (httpStream != null) { await httpStream.FillCacheForRead((int)pointerBlocks[i].count * 8); } ReadPointerBlock(reader, pointerBlocks[i]); } } } }
ushort GetRelocationKey(RelocationPointerList list) // The list of pointers for a certain SNA block { return(GetRelocationKey(list.module, list.id)); }