hello guys I have extracted files form olympic games tokyo 2020. and found all files(textures, models and everything) have .pac extention. Also all of them have same header " PACx402L" I can't open them for use.Please help me to open them.Here is some samples: https://drive.google.com/file/d/1PILLGV ... OE8R6/view
// Tokyo Olympics 2020 pac format specification 2.0 // By: Radfordhound // Heavily based off of Skyth's Forces pac specification callfunction HeaderV4 1//Header;
open "." TEMPORARY_FILE
callfunction EmbeddedPAC 1//EmbeddedPACs[]; // These are LZ4 compressed and need to be decompressed first
startfunction HeaderV4 char[8] Signature // = "PACx402L"; uint PacID; // Random number? Might actually be date created/modified. uint FileSize; uint RootOffset; uint RootCompressedSize; uint RootUncompressedSize; ushort Type //= 1; // Always 1? Oh gosh can these giant pacs have splits please no ushort Constant //= 0x208; // No idea what this is for uint ChunkCount; log TEMPORARY_FILE 0 0 append for i = 0 < ChunkCount callfunction Chunk 1 clog TEMPORARY_FILE RootOffset CompressedSize UncompressedSize math RootOffset + CompressedSize next i append // Pad to a 0x16 offset endfunction
startfunction Chunk // When decompressing the root pac allocate a buffer of // size Header.RootUncompressedSize, then loop through these // chunks and decompress each one, one-by-one, into that buffer.
// If you try to decompress all at once instead the data can be corrupted. uint CompressedSize; uint UncompressedSize; endfunction
// Once you've decompressed the root PAC it'll look like this:
startfunction EmbeddedPAC callfunction HeaderV3 1//PACHeader; callfunction NodeTree 1//TypesTree; // Type nodes point to file node trees callfunction SplitsInfo 1//SplitInfo; // If there are no splits this isn't present print "XXXXXXXXXXX1" for callfunction DataEntry 1//DataEntries[]; // If there are no data entries this isn't present next endfunction
startfunction HeaderV3 char[8] Signature //= "PACx402L"; // Yes, it's the same as HeaderV4 even though it's a different format. uint PacID //= Header.PacID; // Always same as Header.PacID? uint FileSize; // Size of the pac. uint NodesSize; // Size of the section containing all of the NodeTrees and their Nodes. uint SplitsInfoSize; // Size of the section containing all of the split information. uint DataEntriesSize; // Size of the section containing all of the DataEntries. uint StringTableSize; // Size of the string table. uint DataSize; // Size of the section containing all of the file's data. uint OffsetTableSize; // Size of the offset table. ushort Type; ushort Constant //= 0x108; uint SplitCount; endfunction
startfunction NodeTree uint NodeCount; uint DataNodeCount; ulong NodesOffset; ulong DataNodeIndicesOffset; for i = 0 < NodeCount callfunction Node next i endfunction
startfunction Node // Either the type name or the file name, depending on what type of node this is. See below. ulong NameOffset;
// If this node is part of the first NodeTree in the pac, this points to // another NodeTree which contains files of the type described by this node's name. // Otherwise, this points to a DataEntry containing information on the file. ulong DataOffset;
ulong ChildIndexTableOffset; int ParentIndex; int GlobalIndex; int DataIndex; ushort ChildCount; bool HasData; byte FullPathSize; // Not counting this node's name. endfunction
startfunction SplitsInfo ulong SplitCount; // Could also be a uint with padding but this makes more sense to me ulong SplitEntriesOffset; // Yes, literally points to next 8 bytes. for i = 0 < SplitCount callfunction SplitEntry //SplitEntries[SplitCount]; next i print "XXXXXXXXXXX2" for callfunction Chunk 1//SplitChunks[]; next endfunction
startfunction SplitEntry ulong SplitName; // E.G. ath10n_trr_cmn.pac.000 uint SplitCompressedSize; uint SplitUncompressedSize; uint SplitOffset; // Where this split is within the big pac that contains this pac uint SplitChunkCount; ulong SplitChunksOffset; endfunction
startfunction DataEntry // Random number? Not the same as Header.PacID or PACHeader.PacID, like it was in Forces. // Might actually be date created/modified. uint PacID; ulong DataSize; char Padding1[4]; // Always 0? ulong DataPosition; char Padding2[8]; // Always 0? ulong ExtensionPosition; ulong DataType; endfunction