public File(uint vstart, uint vend, uint pstart, uint pend, string name, string autoName, FileType?type, Rom rom) { VirtualStart = vstart; VirtualEnd = vend; PhysicalStart = pstart; PhysicalEnd = pend; _rawContents = rom.GetSegment((int)PhysicalStart, (int)PhysicalSize); Type = type ?? (name != null ? DetectFromName(name) : DetectByContent()); Name = name ?? autoName; }
public Z64Rom(Rom rom) { _rom = rom; var identity = (UInt64)_rom.Header.Crc[0] << 32 | _rom.Header.Crc[1]; var useOffsets = true; if (!_tableOffsets.ContainsKey(identity)) { useOffsets = false; } TableOffsets offsets; if (useOffsets) { offsets = _tableOffsets[identity]; } else { offsets = new TableOffsets { FileTable = FindFileTable(rom.Data) }; if (offsets.FileTable == 0) { throw new ArgumentException("File table not found. Is this a valid Zelda 64 ROM?"); } } var fileTablePointers = _rom.GetSegment(offsets.FileTable) .ToWordGroups(4) .TakeWhile(g => !g.All(w => w == 0)) .ToList(); var nameTable = useOffsets ? _rom.GetSegment(offsets.NameTable) .ExtractStrings(fileTablePointers.Count) .ToList() : new List <string>(); Files = fileTablePointers .Where(f => f[3] != 0xFFFFFFFF && f[2] != 0xFFFFFFFF) .Select((f, i) => new File( f[0], f[1], f[2], f[3], nameTable.Count > i ? nameTable[i] : null, string.Format("{0:0000}-{1:X8}", i + 1, f[0]), null, _rom )) .ToList(); CodeFile = Files.Cast <File>().FirstOrDefault(f => f.ContainsString("Yoshitaka Yasumoto")); IEnumerable <uint[]> overlaySource; if (useOffsets) { overlaySource = offsets.OverlayTables .SelectMany(o => _rom.GetSegment(o.StartAddress, o.RecordCount * o.RecordSize) .ToWordGroups(o.RecordSize / sizeof(UInt32)) ); } else { var ovls = Files.Where(f => f.Type == FileType.Overlay) .Select(o => (UInt64)o.VirtualStart << 32 | o.VirtualEnd) .ToList(); overlaySource = CodeFile.FindTuples(ovls) .SelectMany(t => Utilities.ReadU32(CodeFile.Contents, t.Value + 12) >= 0x80800000 ? CodeFile.Contents.GetSegment(t.Value, 32) .ToWordGroups(7) : // Some overlays in Majora's Mask have the vma start and end addreses // before the virtual file address pair. Here, we compensate for this // by checking if the vma end is < 0x80800000 (overlay address space). // If it is, we prepend the preceding 8 bytes with the rest of the record. CodeFile.Contents.GetSegment(t.Value - 8, 8) .Concat(CodeFile.Contents.GetSegment(t.Value, 24)) .ToWordGroups(7)); } Overlays = overlaySource //_rom.GetSegment(offsets.EffectOverlayTable, (int)offsets.EffectOverlayCount * (int)OverlayEntry.EffectRecordSize) .Select(r => OverlayEntry.FromWords(r, Files.FirstOrDefault(f => f.VirtualStart == r[0]))) .Where(r => r.VmaStart >= 0x80800000 && r.VmaEnd != 0) .OrderBy(o => o.VmaStart) .ToList(); }