Cache Index

An index is one category of cache content - models, sprites, maps, and so on - and is stored as a main_file_cache.idxN file that says where each of its archives lives inside the single main_file_cache.dat2 data file.

ECacheIndex names the ones worth knowing about. TCacheIndex opens one and reads its reference table; TCacheIndex.Cache unpacks its archives.


CacheIndex.Create

function TCacheIndex.Create(id: Integer; constref reader: TCacheReader): TCacheIndex; static;
function TCacheIndex.Create(id: ECacheIndex; constref reader: TCacheReader): TCacheIndex; static; overload;

Opens index id of reader’s cache by reading its .idxN file, and raises if that file is missing.

This only opens the index. Its reference table is read by TCacheIndex.Load, which TCacheReader.Load calls straight afterwards.


CacheIndex.ReadArchiveSector

function TCacheIndex.ReadArchiveSector(id, owner: Integer; constref data: TByteArray): TArchiveSector;

Reassembles archive id out of the data file and returns it still compressed - call TArchiveSector.Decompress on the result to get at its contents.

data is the index table to look the archive up in, and owner is the index number the sectors must be tagged with. An archive is not stored in one piece: the index gives its total size and the position of its first sector, and every sector’s header points at the next one. Each header also repeats the archive id, the sector’s position in the chain and the owning index, all of which are checked as the chain is walked - anything that does not line up means the cache is corrupt or the archive does not exist, and an empty sector is returned.


CacheIndex.Load

procedure TCacheIndex.Load();

Reads this index’s entry out of the master index, which is where its reference table lives.

The reference table is what says which archives the index holds and what is in them, so this has to run before the index can be used for anything.


CacheIndex._CacheArchive

procedure TCacheIndex._CacheArchive(idx: Integer);

Decompresses the archive sitting at position idx of this index’s archive list and splits it into its files. An archive that is already cached is left alone.


CacheIndex.Cache

procedure TCacheIndex.Cache();
procedure TCacheIndex.Cache(id: Integer); overload;
procedure TCacheIndex.Cache(archive: EConfigArchive); overload;

Decompresses this index’s archives and splits them into their files, leaving the contents in ReferenceTable.Archives.

Without arguments every archive is decompressed. Given an archive id, or for the config index an EConfigArchive name, only that one is - which is what you want when a few archives are all you are after, because decompressing a whole index is expensive: all of ECacheIndex.MAPS unpacks well over a hundred megabytes, and of the few hundred milliseconds the config index costs the item and enum archives are a small part. An id the index does not hold is ignored, since the lookup that follows raises on it anyway.

Each form is a no-op once the archives it covers are cached, so calling it before reaching for an archive’s data is safe.

Example:

CacheReader.Indices[ECacheIndex.CONFIGS].Cache(EConfigArchive.ITEM);
archive := CacheReader.Indices[ECacheIndex.CONFIGS].ReferenceTable.Archives.Value[EConfigArchive.ITEM];