CSmania.RU CSmania.RU

Крупнейшее русскоязычное Steam сообщество The largest Russian-speaking community Steam
Place for rent


Часовой пояс: UTC + 3 часа [ Летнее время ] All times are: UTC + 3:00 [DST]


Сервисы вновь работают! Services are running again! Используйте img.csx.pw для изображений & get.csx.pw для обмена ключами / гифтами и прочим. Use img.csx.pw for images & get.csx.pw to exchange keys / Gift and others.


Post new topic Reply to topic [ Сообщений: 18 ] [Posts: 18] На страницу 1 , 2 След. On page 1, 2 Next.
Просмотры: 4782 | Закладки: 0 | Подписки: 0 Views: 4782 | Favorites: 0 | Subscriptions: 0
Автор Author Сообщение Message
Заголовок сообщения: Формат файлов GCF/NCF Post subject: File Format GCF / NCF
Добавлено: 20 июн 2010, 16:36 Added: June 20, 2010, 16:36
Разработчик Developer
Developer
User avatar
Offline
Зарегистрирован: 14 авг 2006, 11:33 Joined: Aug 14, 2006 11:33
Сообщения: 848 Posts: 848
Темы: 30 Threads: 30
Откуда: Светлогорск, Беларусь Location: Svetlogorsk, Belarus
Формат файлов GCF (Game Cache File) File Format GCF (Game Cache File)

В данном документе описана только 6-ая версия формата. This document describes only the second version of the format.

В качестве исходного документа была использована статья с форума http://cs.rin.ru/forum As the original document was used article from the forum http://cs.rin.ru/forum



Структура файлов: The file structure:
  1. Заголовок файла; The file header;
  2. Таблица размещения блоков: Table accommodation units:
    1. Заголовок; Title;
    2. Записи; Recording;
  3. Таблица размещения файлов: File Allocation Table:
    1. Заголовок; Title;
    2. Записи; Recording;
  4. Манифест: Manifesto:
    1. Заголовок; Title;
    2. Записи (Узлы); Entries (nodes);
    3. Таблица имен; Table names;
    4. Хэш-таблица; Hash table;
    5. Минимально-необходимые файлы; Minimally necessary files;
    6. Файлы пользовательской конфигурации; User configuration files;
  5. Карта манифеста: Map of the manifesto:
    1. Заголовок; Title;
    2. Записи; Recording;
  6. Контрольные суммы: Checksums:
    1. Заголовок; Title;
    2. Заголовок таблицы; Table header;
    3. Таблица записей; Table entries;
    4. Записи контрольных сумм; Entries checksums;
    5. Сигнатура; Signature;
    6. Последняя версия приложения; The latest version of the application;
  7. Секция данных; The data section;
  8. Формат NCF-файлов. NCF-format files.


    1. Заголовок файла 1. The title of the file

    [spoiler="Структура"] [Spoiler = "structure"]
    Код: Code:
    struct FileHeader struct FileHeader
    { {
    uint32_t HeaderVersion; uint32_t HeaderVersion;
    uint32_t CacheType; uint32_t CacheType;
    uint32_t FormatVersion; uint32_t FormatVersion;
    uint32_t CacheID; uint32_t CacheID;
    uint32_t CacheVersion; uint32_t CacheVersion;
    uint32_t IsMounted; uint32_t IsMounted;
    uint32_t Dummy0; uint32_t Dummy0;
    uint32_t FileSize; uint32_t FileSize;
    uint32_t ClusterSize; uint32_t ClusterSize;
    uint32_t ClusterCount; uint32_t ClusterCount;
    uint32_t Checksum; uint32_t Checksum;
    } }

    Код: Code:
    TGCFHeader = record TGCFHeader = record
    HeaderVersion, HeaderVersion,
    CacheType, CacheType,
    FormatVersion, FormatVersion,
    CacheID, CacheID,
    CacheVersion, CacheVersion,
    IsMounted, IsMounted,
    Dummy0, Dummy0,
    FileSize FileSize
    ClusterSize ClusterSize
    ClusterCount, ClusterCount,
    Checksum: ulong; Checksum: ulong;
    end; end;
    [/spoiler] [/ Spoiler]
    Поля: Fields:
    • HeaderVersion – всегда 0x00000001. HeaderVersion - always 0x00000001. Вероятно, это номер версии для этой структуры; Probably, the version number for that structure;
    • CacheType – всегда 0x00000001 (для NCF равен 0x00000002); CacheType - always 0x00000001 (for the NCF is 0x00000002);
    • FormatVersion – версия формата файла. FormatVersion - version of the file format. Последняя версия – 6; The latest version - 6;
    • CacheID – идентификатор файла. CacheID - file identifier. Список всех идентификаторов содержится в файле ClientRegistry.blob внутри записи «Content Description Record»; List of all identifiers contained in a file within the record ClientRegistry.blob «Content Description Record»;
    • CacheVersion – номер версии файла; CacheVersion - the version number of the file;
    • IsMounted – имеет значение 0x00000001, если файл в настоящее время смонтирован, иначе будет иметь значение 0x00000000 (непроверенно); IsMounted - is set to 0x00000001, if the file is currently installed, otherwise it will have a value of 0x00000000 (untested);
    • Dummy0 – всегда 0x00000000; Dummy0 - always 0x00000000;
    • FileSize – полный размер файла; FileSize - the full file size;
    • ClusterSize – размер одного кластера в байтах; ClusterSize - one cluster size in bytes;
    • ClusterCount – общее количество кластеров в файле. ClusterCount - total number of clusters in the file. (Не количество файлов!); (Not the number of files!);
    • Checksum – используется для проверки заголовка. Checksum - used to check the title. Рассчитывается путем сложения всех байт заголовка (за исключением самой контрольной суммы). Is calculated by adding up all the header byte (except for the checksum).
[spoiler="Код для расчета контрольной суммы"] [Spoiler = "code to calculate the checksum"]
Код: Code:
// This is not a safe implementation, it is merely a basic example of // This is not a safe implementation, it is merely a basic example of
// how the algorithm works. // How the algorithm works.
uint32_t FileHeaderChecksum(const uint8_t *headerData) uint32_t FileHeaderChecksum (const uint8_t * headerData)
{ {
uint32_t checksum = 0; uint32_t checksum = 0;
for (size_t i = 0; i < (sizeof(FileHeader) - sizeof(uint32_t)); i++) for (size_t i = 0; i <(sizeof (FileHeader) - sizeof (uint32_t)); i ++)
checksum += headerData[i]; checksum + = headerData [i];
return checksum; return checksum;
} }

Код: Code:
function HeaderChecksum(HeaderData: pByte; Length: integer): ulong; function HeaderChecksum (HeaderData: pByte; Length: integer): ulong;
var var
checksum: ulong; checksum: ulong;
i: integer; i: integer;
begin begin
checksum:=0; checksum: = 0;
for i:=0 to Length-1 do for i: = 0 to Length-1 do
begin begin
inc(checksum, headerData^); inc (checksum, headerData ^);
inc(Headerdata); inc (Headerdata);
end; end;
result:=checksum; result: = checksum;
end; end;
[/spoiler] [/ Spoiler]


2. Таблица размещения блоков 2. Allocation Table blocks

В данной таблице можно пометить файлы, которые еще не были распакованы или расшифрованы. In this table, you can mark files that have not yet been unpacked or decrypted. Одному файлу может принадлежать несколько блоков, особенно если он не был до конца распакован или расшифрован. One file can belong to several blocks, especially if it was not until the end of the decompressed or decrypted.
2.a Заголовок 2.a Title

[spoiler="Структура"] [Spoiler = "structure"]
Код: Code:
struct BlockAllocationTableHeader struct BlockAllocationTableHeader
{ {
uint32_t BlockCount; uint32_t BlockCount;
uint32_t BlocksUsed; uint32_t BlocksUsed;
uint32_t LastUsedBlock; uint32_t LastUsedBlock;
uint32_t Dummy0; uint32_t Dummy0;
uint32_t Dummy1; uint32_t Dummy1;
uint32_t Dummy2; uint32_t Dummy2;
uint32_t Dummy3; uint32_t Dummy3;
uint32_t Checksum; uint32_t Checksum;
} }

Код: Code:
TGCFBlockAllocationTableHeader = record TGCFBlockAllocationTableHeader = record
BlockCount, BlockCount,
BlocksUsed, BlocksUsed,
LastUsedBlock, LastUsedBlock,
Dummy0, Dummy0,
Dummy1, Dummy1,
Dummy2, Dummy2,
Dummy3, Dummy3,
Checksum: uint; Checksum: uint;
end; end;
[/spoiler] [/ Spoiler]
Поля: Fields:
  • BlockCount – число блоков в файле. BlockCount - the number of blocks in the file. Может быть равно FileHeader.ClusterCount; May be equal FileHeader.ClusterCount;
  • BlocksUsed – число используемых блоков; BlocksUsed - the number of used blocks;
  • LastUsedBlock – индекс последнего используемого блока; LastUsedBlock - the index of the last used block;
  • Checksum – проверка заголовка. Checksum - check header. Равняется сумме всех остальных полей. Equal to the sum of all the other fields.
2.b Записи 2.b Records

Данный массив имеет размер, указанный в BlockAllocationTableHeader.BlockCount. This array has the size specified in BlockAllocationTableHeader.BlockCount.
[spoiler="Структура"] [Spoiler = "structure"]
Код: Code:
struct BlockAllocationTableEntry struct BlockAllocationTableEntry
{ {
uint16_t Flags; uint16_t Flags;
uint16_t Dummy0; uint16_t Dummy0;
uint32_t FileDataOffset; uint32_t FileDataOffset;
uint32_t FileDataSize; uint32_t FileDataSize;
uint32_t FirstClusterIndex; uint32_t FirstClusterIndex;
uint32_t NextBlockIndex; uint32_t NextBlockIndex;
uint32_t PreviousBlockIndex; uint32_t PreviousBlockIndex;
uint32_t ManifestIndex; uint32_t ManifestIndex;
} }

Код: Code:
TGCFBlockEntry = record TGCFBlockEntry = record
Flags: Word; Flags: Word;
Dummy0: word; Dummy0: word;
FileDataOffset, FileDataOffset,
FileDataSize, FileDataSize,
FirstClusterIndex, FirstClusterIndex,
NextBlockEntryIndex, NextBlockEntryIndex,
PreviousBlockEntryIndex, PreviousBlockEntryIndex,
ManifestIndex: uint; ManifestIndex: uint;
end; end;
[/spoiler] [/ Spoiler]
Поля: Fields:
  • Flags – тип блока. Flags - block type. Возможные значения (в виде флагов): Possible values ​​(in the form of flags):
    • 0x8000 – используется; 0x8000 - used;
    • 0x4000 – локальная копия имеет приоритет над сохраненной копией (непроверенно); 0x4000 - local copy takes precedence over their copies (unverified);
    • 0x0004 – зашифровано (непроверенно); 0x0004 - encrypted (untested);
    • 0x0002 – зашифровано и сжато (непроверенно); 0x0002 - encrypted and compressed (untested);
    • 0x0001 – RAW. 0x0001 - RAW.
  • Dummy0 – неизвестно; Dummy0 - unknown;
  • FileDataOffset – смещение в извлекаемом файле, по которому располагаются данные блока; FileDataOffset - offset in the recovered files, which are located data block;
  • FileDataSize – длина данных для данного блока; FileDataSize - length of data for the block;
  • FirstClusterIndex – индекс первого кластера, содержащего данные блока; FirstClusterIndex - index of the first cluster containing the data block;
  • NextBlockIndex – индекс следующего блока. NextBlockIndex - the index of the next block. Если значение равно If the value is
  • BlockAllocationTableHeader.BlockCount, тогда следующего блока нет; BlockAllocationTableHeader.BlockCount, then the next block is not;
  • PreviousBlockIndex – индекс предыдущего блока. PreviousBlockIndex - the index of the previous block. Если значение равно BlockAllocationTableHeader.BlockCount, тогда следующего блока нет; If the value is BlockAllocationTableHeader.BlockCount, then no next block;
  • ManifestIndex – индекс файла, которому принадлежит этот блок. ManifestIndex - index file that owns the block. Равен 0xFFFFFFFF, если не принадлежит. Equal to 0xFFFFFFFF, if you do not belong.


3. Таблица размещения файлов 3. File Allocation Table

Представляет собой простой способ расположения частей файлов, даже если они не могут быть сохранены вместе в кэше. Is a simple way to position portions of files, even if they can not be stored together in the cache.
3.a Заголовок 3.a Title

[spoiler="Структура"] [Spoiler = "structure"]
Код: Code:
struct FileAllocationTableHeader struct FileAllocationTableHeader
{ {
uint32_t ClusterCount; uint32_t ClusterCount;
uint32_t FirstUnusedEntry; uint32_t FirstUnusedEntry;
uint32_t IsLongTerminator; uint32_t IsLongTerminator;
uint32_t Checksum; uint32_t Checksum;
} }

Код: Code:
TGCFFileAllocationTableHeader = record TGCFFileAllocationTableHeader = record
ClusterCount, ClusterCount,
FirstUnusedEntry, FirstUnusedEntry,
IsLongTerminator, IsLongTerminator,
Checksum: ulong; Checksum: ulong;
end; end;
[/spoiler] [/ Spoiler]
Поля: Fields:
  • ClusterCount – количество кластеров в файле. ClusterCount - number of clusters in a file. Должно совпадать с Must be the same
  • FileHeader.ClusterCount; FileHeader.ClusterCount;
  • FirstUnusedEntry – индекс первой неиспользованной записи; FirstUnusedEntry - index of the first unused entries;
  • IsLongTerminator – определяет границу блока. IsLongTerminator - defines the boundary of the block. Если равен 0, то это 0x0000FFFF, если 1 - 0xFFFFFFFF; If equal to 0, it 0x0000FFFF, if 1 - 0xFFFFFFFF;
  • Checksum - проверка заголовка. Checksum - check header. Равняется сумме всех остальных полей. Equal to the sum of all the other fields.
3.b Записи 3.b Entries

Представляет собой массив длиной FileAllocationTableHeader.ClusterCount элементов. Is an array of length FileAllocationTableHeader.ClusterCount elements. В массиве хранятся индексы следующего кластера для файла (типа uint32_t). In the array indexes are stored for the next cluster of the file (such as uint32_t). Если значение равно граничному (см. FileAllocationTableHeader.IsLongTerminator), значит в файле больше нет секторов. If the value is the boundary (see. FileAllocationTableHeader.IsLongTerminator), then the file is no longer sectors.


4. Манифест 4. Manifesto

Здесь находятся все мета-данные для работы с файлами. Here are all the meta-data for the files. Ранее использовалось название «каталог», однако сейчас используется «манифест». Previously used the name "directory", but is now used "manifesto".
4.a Заголовок 4.a Title

[spoiler="Структура"] [Spoiler = "structure"]
Код: Code:
struct ManifestHeader struct ManifestHeader
{ {
uint32_t HeaderVersion; uint32_t HeaderVersion;
uint32_t CacheID; uint32_t CacheID;
uint32_t CacheVersion; uint32_t CacheVersion;
uint32_t NodeCount; uint32_t NodeCount;
uint32_t FileCount; uint32_t FileCount;
uint32_t CompressionBlockSize; uint32_t CompressionBlockSize;
uint32_t BinarySize; uint32_t BinarySize;
uint32_t NameSize; uint32_t NameSize;
uint32_t HashTableKeyCount; uint32_t HashTableKeyCount;
uint32_t NumOfMinimumFootprintFiles; uint32_t NumOfMinimumFootprintFiles;
uint32_t NumOfUserConfigFiles; uint32_t NumOfUserConfigFiles;
uint32_t Bitmask; uint32_t Bitmask;
uint32_t Fingerprint; uint32_t Fingerprint;
uint32_t Checksum; uint32_t Checksum;
} }

Код: Code:
TGCFManifestHeader = record TGCFManifestHeader = record
HeaderVersion, HeaderVersion,
CacheID, CacheID,
CacheVersion, CacheVersion,
NodeCount, NodeCount,
FileCount, FileCount,
CompressionBlockSize, CompressionBlockSize,
BinarySize, BinarySize,
NameSize, NameSize,
HashTableKeyCount, HashTableKeyCount,
NumOfMinimumFootprintFiles, NumOfMinimumFootprintFiles,
NumOfUserConfigFiles, NumOfUserConfigFiles,
Bitmask, Bitmask,
Fingerprint, Fingerprint,
Checksum: ulong; Checksum: ulong;
end; end;
[/spoiler] [/ Spoiler]
Поля: Fields:
  • HeaderVersion – всегда 0x00000004. HeaderVersion - always 0x00000004. Это текущая версия манифеста; This is the current version of the manifesto;
  • CacheID – идентификатор кэша (должен совпадать с FileHeader.ApplicationID); CacheID - cache identifier (must match FileHeader.ApplicationID);
  • CacheVersion – версия файла (должна совпадать с FileHeader.ApplicationVersion); CacheVersion - version of the file (must be the same FileHeader.ApplicationVersion);
  • NodeCount – количество элементов манифеста; NodeCount - the number of elements of the manifesto;
  • FileCount – количество файлов в кэше; FileCount - the number of files in the cache;
  • CompressionBlockSize – определяет, сколько байт используется в контрольной сумме / сжатом файле; CompressionBlockSize - determines how many bytes are used in the checksum / compressed file;
  • BinarySize – размер манифеста в байтах (включая данную структуру); BinarySize - manifest size in bytes (including this structure);
  • NameSize – размер таблицы имен в байтах; NameSize - size of the table names in bytes;
  • HashTableKeyCount – количество ключей в хэш-таблице; HashTableKeyCount - the number of keys in the hash table;
  • NumOfMinimumFootprintFiles – количество минимально-необходимых файлов; NumOfMinimumFootprintFiles - the amount minimally necessary files;
  • NumOfUserConfigFiles – количество файлов пользовательской конфигурации; NumOfUserConfigFiles - the number of files the user configuration;
  • Bitmask – битовая маска флагов. Bitmask - bitmask flags. Известные маски: Known mask:
    • 0x00000001 - Build Mode (назначение неизвестно); 0x00000001 - Build Mode (purpose unknown);
    • 0x00000002 – чистая цепочка (назначение неизвестно); 0x00000002 - clean chain (destination unknown);
    • 0x00000004 – длинная цепочка (назначение неизвестно; может быть, это связано с языковыми файлами); 0x00000004 - a long chain (purpose unknown; perhaps it is due to the language files);
  • Fingerprint – скорее всего генерируется каждый раз при обновлении. Fingerprint - most likely generated each time you upgrade. Может использоваться для быстрого определения необходимости обновить файл; Can be used to quickly determine whether to update the file;
  • Checksum – контрольная сумма, вычисленная по алгоритму adler32 для всех полей записи за исключением двух (Fingerprint и Checksum) – они обнуляются при пересчете. Checksum - checksum computed by the algorithm adler32 for all fields except for two entries (Fingerprint and Checksum) - they are cleared from the translation.
[spoiler="Пример вычисления контрольной суммы"] [Spoiler = "Example of calculating the checksum"]
Код: Code:
#define OFFSET_OF(TYPE, MEMBER) ((size_t)&((TYPE*)0)->MEMBER) #define OFFSET_OF (TYPE, MEMBER) ((size_t) & ((TYPE *) 0) -> MEMBER)
uint32_t ManifestChecksum(const uint8_t *manifestData, uint32_t manifestSize) uint32_t ManifestChecksum (const uint8_t * manifestData, uint32_t manifestSize)
{ {
ManifestHeader *manifest = (ManifestHeader*)manifestData; ManifestHeader * manifest = (ManifestHeader *) manifestData;
ASSERT(manifest->BinarySize <= manifestSize); ASSERT (manifest-> BinarySize <= manifestSize);

// Temporary "replacement" bytes for non-calculated fields. // Temporary "replacement" bytes for non-calculated fields.
static const uint32_t nullFields[2] = { static const uint32_t nullFields [2] = {
0, // Fingerprint 0, // Fingerprint
0 // Checksum 0 // Checksum
}; };

// Calculate checksum in a 3-part process. // Calculate checksum in a 3-part process.
uint32_t checksum = 0; uint32_t checksum = 0;
checksum = adler32(checksum, manifest, OFFSET_OF(ManifestHeader, Fingerprint)); checksum = adler32 (checksum, manifest, OFFSET_OF (ManifestHeader, Fingerprint));
checksum = adler32(checksum, nullFields, sizeof(nullFields)); checksum = adler32 (checksum, nullFields, sizeof (nullFields));
checksum = adler32(checksum, manifest + sizeof(CacheManifestHeader), checksum = adler32 (checksum, manifest + sizeof (CacheManifestHeader),
manifest->BinarySize - sizeof(CacheManifestHeader)); manifest-> BinarySize - sizeof (CacheManifestHeader));

// Return the checksum. // Return the checksum.
return checksum; return checksum;
} }
[/spoiler] [/ Spoiler]
4.b Записи (узлы) 4.b Entries (nodes)

Представляет собой массив длиной ManifestHeader.NodeCount элементов. Is an array of length ManifestHeader.NodeCount elements.
[spoiler="Структура"] [Spoiler = "structure"]
Код: Code:
struct ManifestNode struct ManifestNode
{ {
uint32_t NameOffset; uint32_t NameOffset;
uint32_t CountOrSize; uint32_t CountOrSize;
uint32_t FileId; uint32_t FileId;
uint32_t Attributes; uint32_t Attributes;
uint32_t ParentIndex; uint32_t ParentIndex;
uint32_t NextIndex; uint32_t NextIndex;
uint32_t ChildIndex; uint32_t ChildIndex;
} }

Код: Code:
TGCFManifestNode = record TGCFManifestNode = record
NameOffset, NameOffset,
CountOrSize, CountOrSize,
FileId, FileId,
Attributes, Attributes,
ParentIndex, ParentIndex,
NextIndex, NextIndex,
ChildIndex: ulong; ChildIndex: ulong;
end; end;
[/spoiler] [/ Spoiler]
Поля: Fields:
  • NameOffset – смещение в таблице имен, начиная с которого находится имя узла. NameOffset - the offset in the table names from which there is a host name. Имя представляет собой строку C (null-терминантная строка, оканчивается символом '\0'); Name is a string C (null-terminantnaya string ends with a '\ 0');
  • CountOrSize – размер узла. CountOrSize - size of the site. Для файла равен размеру файла в байтах, для каталога – количеству дочерних узлов; For the file is the size of the file in bytes, for the catalog - the number of child nodes;
  • FileId – ID файла. FileId - ID file. Если узел является папкой, то имеет значение 0xFFFFFFFF; If the node is a folder, it is set to 0xFFFFFFFF;
    Attributes – различные флаги узла. Attributes - various flags node. Известные значения: Known values:
    • 0x00004000 – узел является файлом; 0x00004000 - the node is a file;
    • 0x00000800 – узел является исполняемым файлом (непроверенно); 0x00000800 - node is an executable file (untested);
    • 0x00000400 – узел является скрытым файлом (непроверенно); 0x00000400 - the node is a hidden file (untested);
    • 0x00000200 – узел является файлом только для чтения (непроверенно); 0x00000200 - the node is read-only files (untested);
    • 0x00000100 – файл зашифрован; 0x00000100 - the file is encrypted;
    • 0x00000080 - The node is a purge file (непроверенно); 0x00000080 - The node is a purge file (untested);
    • 0x00000040 – файл необходимо скопировать перед перезаписью (непроверенно); 0x00000040 - file must be copied before overwriting (untested);
    • 0x00000020 – узел является no-cache file (непроверенно); 0x00000020 - the node is a no-cache file (untested);
    • 0x00000008 – узел является заблокированным файлом; 0x00000008 - the node is locked files;
    • 0x00000002 – узел является запускаемым файлом; 0x00000002 - the node is executable file;
    • 0x00000001 – узел является файлом пользовательской конфигурации. 0x00000001 - the node is a custom configuration file. Данный файл не переписывается при его существовании; This file is not overwritten when its existence;
  • ParentIndex – индекс родительского узла. ParentIndex - the index of the parent node. Если узел находится в корне, то имеет значение 0xFFFFFFFF. If the node is at the root, it has a value of 0xFFFFFFFF. Всегда должен являться ссылкой на каталог; Should always be linked to a directory;
  • NextIndex – индекс следующего узла на данном уровне дерева. NextIndex - the index of the next node at this level of the tree. Если далее узлы отсутствуют, то имеет значение 0x00000000. If there are no further nodes, it has a value of 0x00000000. Может ссылаться только на те узла, у которых ParentIndex одинаков с ParentIndex текущего элемента; Can refer only to the site, which is identical with ParentIndex ParentIndex current item;
  • ChildIndex – индекс первого дочернего элемента. ChildIndex - index of the first child. Если дочерних узлов нет, то имеет значение 0x00000000. If no child nodes, the matter 0x00000000.
Первым узел (с индексом 0) всегда должен быть корневой узел, не имеющий ни родителей, ни следующих/предыдущих элементов. The first node (index 0) must always be the root node, having neither parents nor the next / previous items. Его имя должно быть пустой строкой (“\0” в таблице имен). His name should be an empty string ("\ 0" in the table name).
4.c Таблица имен 4.c Table names

Простой массив символов размером ManifestHeader.NameSize байт. Simple character array size ManifestHeader.NameSize bytes.
4.d Хэш-таблица 4.d hash table

Данная хэш-таблица отличается от остальных тем, что состоит из 2-х таблиц – HashTableKeys и HashTableIndices. This hash table differs from others in that it consists of 2 tables - HashTableKeys and HashTableIndices.
HashTableKeys содержит ManifestHeader. HashTableKeys contains ManifestHeader. HashTableKeyCount записей. HashTableKeyCount records. В ней находятся значения хэш-функции для имен элементов (только имен, без пути; имя должно быть только в нижнем регистре). It contains the hash value for the element names (names only, without the path and the name must be in lower case only).
HashTableIndices содержит ManifestHeader. HashTableIndices contains ManifestHeader. NodeCount записей. NodeCount records. В ней находятся индексы элементов, на которые ссылается предыдущая таблица. It contains the indices of the items that are referenced by the previous table.
Данная таблица служит для быстрого получения необходимых элементов по их имени. This table is used to quickly obtain the necessary elements on their behalf. Для этого необходимо сделать следующее: To do this, you must do the following:
  • Привести искомое имя к нижнему регистру и вычислить значение хэш-функции по алгоритму jenkinsLookupHash2; Result in the desired name to lower case and compute the hash value for the algorithm jenkinsLookupHash2;
  • Взять значение из таблицы HashTableKeys из ячейки с номером, равным остатку от целочисленного деления полученного ранее значения хэш-функции на значение ManifestHeader. Mark HashTableKeys value from the table with the number of cells equal to the remainder of the integer division of the previous hash value to a value ManifestHeader. HashTableKeysCount и уменьшаем его на ManifestHeader. HashTableKeysCount and reduce it to ManifestHeader. HashTableKeysCount. HashTableKeysCount. Полученное число будет ссылаться на ячейку в таблице HashTableIndices; The resulting number will refer to a cell in the table HashTableIndices;
  • Берем значение из таблицы HashTableIndices и объединяем с маской 0x7FFFFFFF. Take the value from the table HashTableIndices and combine with a mask 0x7FFFFFFF. Результатом будет индекс узла, в котором вероятно и находится искомый элемент; The result will be the index of the node, which is likely and the desired element;
  • Если требуемый узел не найден, то переходим к следующей ячейке таблицы HashTableIndices. If the requested node is not found, then go to the next table cell HashTableIndices. Если значение текущей ячейки этой таблицы совпадает с маской 0x80000000, то мы достигли конца участка для данного значения хэш-функции. If the value of the current cell of the table coincides with the mask 0x80000000, we have reached the end of the section for a given hash value.
[spoiler="Пример поиска файлов с использованием хэш-таблицы"] [Spoiler = "Example search files using a hash table"]
Код: Code:
uint32_t getFileIDFast(Manifest *manifest, const char *path) uint32_t getFileIDFast (Manifest * manifest, const char * path)
{ {
const char *fileName = getFileName(path); const char * fileName = getFileName (path);
char *fileNameLower = (char *)malloc(strlen(fileName) + 1); char * fileNameLower = (char *) malloc (strlen (fileName) + 1);
ASSERT(fileNameLower != NULL); ASSERT (fileNameLower! = NULL);
strcpy(fileNameLower, fileName); strcpy (fileNameLower, fileName);
strlwr(fileNameLower); strlwr (fileNameLower);
// Compute the hash of the file name. // Compute the hash of the file name.
uint32_t hash = jenkinsLookupHash2((uint8_t *)fileNameLower, strlen(fileNameLower), 1); uint32_t hash = jenkinsLookupHash2 ((uint8_t *) fileNameLower, strlen (fileNameLower), 1);
// Compute HashTableKeys index. // Compute HashTableKeys index.
// This could also be implemented (theoretically faster) using: // This could also be implemented (theoretically faster) using:
// hashIndex = hash & (manifest->HashTableKeysCount - 1); // HashIndex = hash & (manifest-> HashTableKeysCount - 1);
uint32_t hashIndex = hash % manifest->HashTableKeysCount; uint32_t hashIndex = hash% manifest-> HashTableKeysCount;

// Get the HashTableIndexes index. // Get the HashTableIndexes index.
uint32_t hashedFileIndex = manifest->HashTableKeys[hashIndex]; uint32_t hashedFileIndex = manifest-> HashTableKeys [hashIndex];
if (hashedFileIndex == -1) if (hashedFileIndex == -1)
{ {
// Clean up. // Clean up.
free(fileNameLower); free (fileNameLower);

// No files found with the given hash. // No files found with the given hash.
return 0; return 0;
} }
hashedFileIndex -= manifest->HashTableKeysCount; hashedFileIndex - = manifest-> HashTableKeysCount;
int stop; int stop;
do do
{ {
uint32_t hashedValue = manifest->HashTableIndices[hashedFileIndex]; uint32_t hashedValue = manifest-> HashTableIndices [hashedFileIndex];
uint32_t fileId = hashedValue & 0x7FFFFFFF; uint32_t fileId = hashedValue & 0x7FFFFFFF;
stop = (hashedValue & 0x80000000) != 0; stop = (hashedValue & 0x80000000)! = 0;
filePath = getManifestFilePath(manifest, fileId); filePath = getManifestFilePath (manifest, fileId);
if (filePath == NULL) if (filePath == NULL)
continue; continue;
// Compare the given file path to the one from the hash table // Compare the given file path to the one from the hash table
// results. // Results. (This should be a case insensitive and path (This should be a case insensitive and path
// separator (slash) insensitive comparison.) // Separator (slash) insensitive comparison.)
if (!pathEquals(filePath, path)) if (! pathEquals (filePath, path))
{ {
// Cleanup. // Cleanup.
free(filePath); free (filePath);

// File found. // File found.
return fileId; return fileId;
} }
// Cleanup. // Cleanup.
free(filePath); free (filePath);
} while (!stop && fileIDsCount < maxFileIDs); } While (! Stop && fileIDsCount <maxFileIDs);
// Clean up. // Clean up.
free(fileNameLower); free (fileNameLower);
// Return the number of entries found. // Return the number of entries found.
return 0xFFFFFFFF; return 0xFFFFFFFF;
} }

Код: Code:
function TGCF.GetItemByPath(Path: AnsiString): integer; function TGCF.GetItemByPath (Path: AnsiString): integer;
var var
end_block: boolean; end_block: boolean;
Hash, HashIdx, HashValue: ulong; Hash, HashIdx, HashValue: ulong;
FileID, HashFileIdx: integer; FileID, HashFileIdx: integer;
PathEx: AnsiString; PathEx: AnsiString;
begin begin
result:=-1; result: = - 1;
PathEx:=ExtractFileName(LowerCase(Path)); PathEx: = ExtractFileName (LowerCase (Path));
Hash:=jenkinsLookupHash2(pAnsiChar(PathEx), Length(PathEx), 1); Hash: = jenkinsLookupHash2 (pAnsiChar (PathEx), Length (PathEx), 1);
HashIdx:=Hash mod fHeader.pDirectoryHeader.HashTableKeyCount; HashIdx: = Hash mod fHeader.pDirectoryHeader.HashTableKeyCount;
HashFileIdx:=fHeader.lpHashTableKeys[HashIdx]; HashFileIdx: = fHeader.lpHashTableKeys [HashIdx];
if HashFileIdx=-1 then if HashFileIdx = -1 then
Exit; Exit;
dec(HashFileIdx, fHeader.pDirectoryHeader.HashTableKeyCount); dec (HashFileIdx, fHeader.pDirectoryHeader.HashTableKeyCount);
repeat repeat
HashValue:=fHeader.lpHashTableIndices[HashFileIdx]; HashValue: = fHeader.lpHashTableIndices [HashFileIdx];
FileID:=HashValue and $7FFFFFFF; FileID: = HashValue and $ 7FFFFFFF;
end_block:= (HashValue and $80000000 = $80000000); end_block: = (HashValue and $ 80 million = $ 80 million);
if StrComp_NoCase(PAnsiChar(GetItemPath(FileID)), pAnsiChar(Path))=0 then if StrComp_NoCase (PAnsiChar (GetItemPath (FileID)), pAnsiChar (Path)) = 0 then
begin begin
result:=FileID; result: = FileID;
Exit; Exit;
end; end;
inc(HashFileIdx); inc (HashFileIdx);
until end_block; until end_block;
end; end;
[/spoiler] [/ Spoiler]
4.e Минимально-необходимые файлы 4.e Minimally necessary files

Данный массив имеет размер ManifestHeader.NumOfMinimumFootprintFiles. This array has a size ManifestHeader.NumOfMinimumFootprintFiles. Все элементы, имеющиеся в данном массиве, должны быть извлечены на диск. All the elements are available in the array must be recovered to disk. Если эти записи были обновлены или изменены (или на диске или в файле кэша), то их необходимо переписать заново. If these records have been updated or changed (or on the disc or file cache), they must be re-written. В массиве хранятся индексы в таблице узлов (типа uint32_t). In the array indexes are stored in the table node (type uint32_t).
4.f Файлы пользовательской конфигурации 4.f user configuration files

Данный массив имеет размер ManifestHeader.NumOfUserConfigFiles. This array has a size ManifestHeader.NumOfUserConfigFiles. Все элементы, имеющиеся в данном массиве, должны быть извлечены на диск, если они не были извлечены ранее. All the elements are available in the array must be recovered to disk when they were not previously learned. Версия на диске должна иметь больший приоритет перед файлом в кэше, независимо от любых изменений. Version on the disc should have a higher priority over the file in the cache, regardless of any changes. В массиве хранятся индексы в таблице узлов (типа uint32_t). In the array indexes are stored in the table node (type uint32_t).


5. Карта манифеста 5. Map Manifesto

В данной таблице содержатся связанные цепочки индексов кластеров. This table contains a chain indices related clusters.
5.a Заголовок 5.a Title

[spoiler="Структура"] [Spoiler = "structure"]
Код: Code:
struct ManifestMapHeader struct ManifestMapHeader
{ {
uint32_t HeaderVersion; uint32_t HeaderVersion;
uint32_t Dummy0; uint32_t Dummy0;
} }

Код: Code:
TGCFManifestMapHeader = record TGCFManifestMapHeader = record
Dummy0, Dummy0,
Dummy1: ulong Dummy1: ulong
end; end;
[/spoiler] [/ Spoiler]
Поля: Fields:
  • HeaderVersion – всегда 0x00000001. HeaderVersion - always 0x00000001. Версия заголовка; Version of the title;
  • Dummy0 – всегда 0x00000000. Dummy0 - always 0x00000000.
5.b Записи 5.b Entries

Данный массив имеет размер ManifestHeader.NodeCount. This array has a size ManifestHeader.NodeCount. Значения массива (типа uint32_t) являются индексами первого блока (в таблице размещения блоков) для файла. The values ​​of the array (type uint32_t) are the indices of the first block (block allocation table) file. Если значение равно BlockAllocationTableHeader.BlockCount, то элемент не сохранен в кэше или является каталогом. If the value is BlockAllocationTableHeader.BlockCount, the element is not cached, or a directory.


6. Контрольные суммы 6. Checksums

Данная запись в значительной мере избыточна, так как содержит много неиспользованных и дублированных сумм. This record is largely redundant, since it contains a lot of unused and duplicate amounts. Тем не менее, они используются, но только для других версий кэша (вплоть до LatestApplicationVersion). Nevertheless, they are used, but only for the other versions of the cache (until LatestApplicationVersion).
6.a Заголовок 6.a Title

[spoiler="Структура"] [Spoiler = "structure"]
Код: Code:
struct ChecksumDataContainer struct ChecksumDataContainer
{ {
uint32_t HeaderVersion; uint32_t HeaderVersion;
uint32_t ChecksumSize; uint32_t ChecksumSize;
} }

Код: Code:
TGCFChecksumDataContainer = record TGCFChecksumDataContainer = record
HeaderVersion, HeaderVersion,
ChecksumSize: ulong; ChecksumSize: ulong;
end; end;
[/spoiler] [/ Spoiler]
Поля: Fields:
  • HeaderVersion – всегда 0x00000001. HeaderVersion - always 0x00000001. Версия заголовка; Version of the title;
  • ChecksumSize – количество байт в данной структуре (от ChecksumDataContainer и до LatestApplicationVersion). ChecksumSize - the number of bytes in this structure (from ChecksumDataContainer and to LatestApplicationVersion).
6. b Заголовок таблицы 6. b Table Header

[spoiler="Структура"] [Spoiler = "structure"]
Код: Code:
struct FileIdChecksumTableHeader struct FileIdChecksumTableHeader
{ {
uint32_t FormatCode; uint32_t FormatCode;
uint32_t Dummy0; uint32_t Dummy0;
uint32_t FileIdCount; uint32_t FileIdCount;
uint32_t ChecksumCount; uint32_t ChecksumCount;
} }

Код: Code:
[code] TGCFFileIdChecksumTableHeader = record [Code] TGCFFileIdChecksumTableHeader = record
FormatCode FormatCode
Dummy0 Dummy0
FileIdCount, FileIdCount,
ChecksumCount: ChecksumCount:
end;[/code] end; [/ code]
[/spoiler] [/ Spoiler]
Поля: Fields:
  • FormatCode – всегда 0x14893721; FormatCode - always 0x14893721;
  • Dummy0 – всегда 0x00000001; Dummy0 - always 0x00000001;
  • FileIdCount – количество записей; FileIdCount - the number of records;
  • ChecksumCount – общее количество контрольных сумм. ChecksumCount - the total number of checksums.
6.c Таблица записей Table 6.c records

Данный массив имеет размер FileIdChecksumTableHeader.FileIdCount. This array has a size FileIdChecksumTableHeader.FileIdCount. Он содержит идентификаторы файлов для всех версий данного кэш-файла. It contains a file identifiers for all versions of the cache file. Таким образом для получения контрольной суммы для файла необходимо взять значение из массива, используя идентификатор файла как индекс. Thus to obtain the checksum for the file you must take the value from the array using the file ID as an index.
[spoiler="Структура"] [Spoiler = "structure"]
Код: Code:
struct FileIdChecksumTableEntry struct FileIdChecksumTableEntry
{ {
uint32_t ChecksumCount; uint32_t ChecksumCount;
uint32_t FirstChecksumIndex; uint32_t FirstChecksumIndex;
} }

Код: Code:
TGCFFileIdChecksumTableEntry = record TGCFFileIdChecksumTableEntry = record
ChecksumCount, ChecksumCount,
FirstChecksumIndex: ulong; FirstChecksumIndex: ulong;
end; end;
[/spoiler] [/ Spoiler]
Поля: Fields:
  • ChecksumCount – определяет, сколько контрольных сумм принадлежит данной секции; ChecksumCount - determines how many checksums belongs to this section;
  • FirstChecksumIndex – индекс первого значения ChecksumEntry для данной секции. FirstChecksumIndex - the index of the first value ChecksumEntry for this section.
6.d Записи контрольных сумм 6.d Entries checksums

Данный массив имеет размер FileIdChecksumTableHeader.ChecksumCount и содержит контрольные суммы для всех сегментов. This array has a size FileIdChecksumTableHeader.ChecksumCount and contains checksums for all segments. В каждом блоке может быть несколько записей, следующих друг за другом. Each block may have several entries that follow each other.
Значение контрольной суммы рассчитывается для частей файлов размером ManifestHeader.CompressionBlockSize. Checksum value calculated for parts of files larger ManifestHeader.CompressionBlockSize. Если размер сегмента файла меньше размера блока, то контрольная сумма вычисляется только для оставшегося размера файла. If the segment size of the file is less than the block size, the checksum is calculated only for the remainder of the file size.
[spoiler="Расчет контрольной суммы"] [Spoiler = "Calculate checksum"]
Код: Code:
// You need to use to use the zlib library <http://www.zlib.net/> // You need to use to use the zlib library <http://www.zlib.net/>
// or something with equivalent checksum algorithms. // Or something with equivalent checksum algorithms.
uint32_t FileChecksum(const uint8_t *data, uint32_t length) uint32_t FileChecksum (const uint8_t * data, uint32_t length)
{ {
return adler32(0, data, length) ^ crc32(0, data, length); return adler32 (0, data, length) ^ crc32 (0, data, length);
} }

Код: Code:
function Checksum(lpBuffer: pByte; uiBufferSize: uint): ulong; function Checksum (lpBuffer: pByte; uiBufferSize: uint): ulong;
begin begin
result:=Adler32(0, lpBuffer, uiBufferSize) xor CRC32(lpBuffer, uiBufferSize); result: = Adler32 (0, lpBuffer, uiBufferSize) xor CRC32 (lpBuffer, uiBufferSize);
end; end;
[/spoiler] [/ Spoiler]
6.e Сигнатура 6.e signature

Представляет собой 0x80 байт RSA-сигнатуры (используя SHA-1 и RSASSA-PKCS1-v1_5) от секции контрольных сумм. Is a 0x80 byte RSA-signature (using SHA-1 and RSASSA-PKCS1-v1_5) of section checksums. RSA в качестве публичного ключа использует объявленный в Content Description Record, соответствующий ID файла кэша. RSA as public key uses declared in the Content Description Record, the corresponding file ID cache.
6.f Последняя версия приложения 6.f latest version of the application

Данная структура не существует, если ChecksumDataContainer.HeaderVersion имеет значение 0. Представляет собой значение типа uint32_t, хранящее последнюю версию контрольных сумм файла. This structure does not exist if ChecksumDataContainer.HeaderVersion is set to 0. This is a value of type uint32_t, storing the latest version of the checksum file. Должно быть равно FileHeader. Must be equal to FileHeader. CacheID. CacheID. Если это значение меньше чем FileHeader. If this value is less than FileHeader. CacheID, то данные контрольные суммы являются устаревшими и не должны использоваться. CacheID, the data checksums are obsolete and should not be used.
7 Секция данных Section 7 data

[spoiler="Структура"] [Spoiler = "structure"]
Код: Code:
struct DataHeader struct DataHeader
{ {
uint32_t ClusterCount; uint32_t ClusterCount;
uint32_t ClusterSize; uint32_t ClusterSize;
uint32_t FirstClusterOffset; uint32_t FirstClusterOffset;
uint32_t ClustersUsed; uint32_t ClustersUsed;
uint32_t Checksum; uint32_t Checksum;
} }

Код: Code:
TGCFDataBlockHeader = record TGCFDataBlockHeader = record
ClusterCount, ClusterCount,
PhysicalSectorSize, PhysicalSectorSize,
FirstSectorOffset, FirstSectorOffset,
ClustersUsed, ClustersUsed,
Checksum : ulong; Checksum: ulong;
end; end;
[/spoiler] [/ Spoiler]
Поля: Fields:
  • ClusterCount – количество кластеров в файле. ClusterCount - number of clusters in a file. Должно совпадать с Must be the same
  • FileHeader.ClusterCount; FileHeader.ClusterCount;
  • ClusterSize – размер одного кластера в байтах. ClusterSize - the size in bytes of one cluster. Должен совпадать с Must be the same
  • FileHeader.ClusterSize; FileHeader.ClusterSize;
  • FirstClusterOffset – смещение (относительно начала файла) для первого кластера; FirstClusterOffset - offset (relative to the beginning of the file) for the first cluster;
  • ClustersUsed – количество использованных кластеров; ClustersUsed - the number of used clusters;
  • Checksum – для проверки заголовка. Checksum - to check the title. Рассчитывается путем сложения всех предыдущих полей. Is calculated by adding all previous fields.




Формат NCF (Not-Cache File) Format NCF (Not-Cache File)

  1. Структура данных файлов схожа с GCF, за исключением следующих пунктов: The structure is similar to data files GCF, except for the following points:
  2. FileHeader. FileHeader. CacheType равен 0x00000002; CacheType is 0x00000002;
  3. Отсутствуют следующие поля: Missing the following fields:
    • таблица размещения блоков; allocation table blocks;
    • таблица размещения файлов; file allocation table;
    • секция данных; section data;
  4. Файлы располагаются не в файле кэша, а на диске в папке “common\папка_игры”. The files are not located in the cache file, and on the drive in "common \ papka_igry."


О поддержке файлов >4Гб On the support files> 4GB

Для получения точного размера файла кэша существует два пути: For the exact size of the file cache, there are two ways:
    из FileHeader.FileSize. from FileHeader.FileSize. Если полученный и записанный размеры не совпадают, то сверить с 0x100000000+FileHeader.FileSize - именно так вычисляется размер для файлов кэша >4Гб); If the received and recorded the sizes do not match, then verify with 0x100000000 + FileHeader.FileSize - this is how to calculate the size of the cache files> 4GB);
  1. вычислив значение DataHeader.FirstClusterOffset + DataHeader.ClusterCount*DataHeader.ClusterSize. calculating the value DataHeader.FirstClusterOffset + DataHeader.ClusterCount * DataHeader.ClusterSize.

Добавлено спустя 2 минуты: Added after 2 minutes:
По сравнению с исходным документом есть некоторые отличия - добавлены описания заголовков/функций для языка Delphi (object Pascal), некоторые места я сократил, оставив из описания только необходимое (без ущерба информативности ). Compared with the original document, there are some differences - added description titles / functions for language Delphi (object Pascal), some places I cut, leaving only what is necessary from the description (without prejudice informativeness).

PS: Переводил целый день и еще две недели (без нескольких дней) ждал открытия форума для публикации. PS: He translated the whole day and two weeks (excluding a few days) waiting for the opening of a forum for the publication.

PSS: Абсолютно все положения (кроме сигнатуры контрольных сумм) проверенны мною на практических примерах (проверка производилась в программах CFToolBox и GCFScape). PSS: Absolutely all positions (except for the signature checksums) I have tested on practical examples (check made in the programs and CFToolBox GCFScape).

PSSS: Все, написанное в данном документе, переводилось для использования в Universal Steam Extractor (rev.3), где уже вовсю идут работы ). PSSS: Everything written in this document is translated for use in Universal Steam Extractor (rev.3), which are already hard at work).

_________________ _________________
Репозиторий с моими проектами Repository with my projects


Занимаюсь переносом всех Engaged in the transfer of all своих библиотек на С++, а так же созданием их кроссплатформенных версий. their libraries in C ++, as well as the creation of cross-platform versions.


В команду переводчиков манги "Ah! My Goddess!" The team of translators manga "Ah! My Goddess!" требуются переводчики с английского и тайперы (последних можем обучить, главное - желание). require translators from English and Tipper (last can train, the main thing - desire).


Последний раз редактировалось andreil 20 июн 2010, 22:10, всего редактировалось 1 раз. Last edited andreil June 20, 2010, 22:10, edited 1 time.

Вернуться к началу Back to top
Profile
(0) (0)
Заголовок сообщения: Re: Формат файлов GCF/NCF Post subject: Re: File Format GCF / NCF
Добавлено: 20 июн 2010, 17:17 Added: June 20, 2010, 17:17
Майор Maj.
Maj.
Offline
Зарегистрирован: 30 сен 2008, 15:07 Joined: 30 Sep 2008 15:07
Сообщения: 781 Posts: 781
Темы: 33 Threads: 33
Очень впечатляет. Very impressive. Столько работы... So much work ...
Теперь осталось создать создавалку GCF It now remains to create sozdavalku GCF :-) . .


Вернуться к началу Back to top
Profile
(0) (0)
Заголовок сообщения: Re: Формат файлов GCF/NCF Post subject: Re: File Format GCF / NCF
Добавлено: 20 июн 2010, 17:27 Added: June 20, 2010, 17:27
Разработчик Developer
Developer
User avatar
Offline
Зарегистрирован: 14 авг 2006, 11:33 Joined: Aug 14, 2006 11:33
Сообщения: 848 Posts: 848
Темы: 30 Threads: 30
Откуда: Светлогорск, Беларусь Location: Svetlogorsk, Belarus
Вообще-то работы уже идут In fact, the work already underway ;)

Добавлено спустя 45 секунд: Added after 45 seconds:
Если кто заметит ошибки/опечатки в тексте - сообщите, исправлю. If anyone notices errors / typos in the text - please, fix it.

_________________ _________________
Репозиторий с моими проектами Repository with my projects


Занимаюсь переносом всех Engaged in the transfer of all своих библиотек на С++, а так же созданием их кроссплатформенных версий. their libraries in C ++, as well as the creation of cross-platform versions.


В команду переводчиков манги "Ah! My Goddess!" The team of translators manga "Ah! My Goddess!" требуются переводчики с английского и тайперы (последних можем обучить, главное - желание). require translators from English and Tipper (last can train, the main thing - desire).


Вернуться к началу Back to top
Profile
(0) (0)
Заголовок сообщения: Re: Формат файлов GCF/NCF Post subject: Re: File Format GCF / NCF
Добавлено: 20 июн 2010, 19:56 Added: June 20, 2010, 19:56
Эксперты no-Steam Experts no-Steam
Experts no-Steam
User avatar
Offline
Зарегистрирован: 29 янв 2009, 21:37 Joined: Jan 29, 2009 21:37
Сообщения: 1297 Posts: 1297
Темы: 22 Threads: 22
Откуда: MOSCOШ Location: MOSCOSH
andreil andreil
гы, круто gee, cool
единственная ошибка, что я заметил - это вместо PSSS должно быть PPPS (постпостскриптум, а не постскриптумскриптум) the only error that I noticed - it should be instead of PSSS PPPS (postpostskriptum, not postskriptumskriptum)

_________________ _________________
pchelk.in pchelk.in


Вернуться к началу Back to top
Profile
(0) (0)
Заголовок сообщения: Re: Формат файлов GCF/NCF Post subject: Re: File Format GCF / NCF
Добавлено: 20 июн 2010, 19:59 Added: June 20, 2010, 19:59
Капитан Captain
Captain
User avatar
Offline
Зарегистрирован: 05 ноя 2008, 22:05 Joined: 05 Nov 2008 22:05
Сообщения: 661 Posts: 661
Темы: 7 Threads: 7
Откуда: Воронеж Location: Voronezh
bugme bugme , можно и так (post sub scriptum) , You could (post sub scriptum)


Вернуться к началу Back to top
Profile
(0) (0)
Заголовок сообщения: Re: Формат файлов GCF/NCF Post subject: Re: File Format GCF / NCF
Добавлено: 20 июн 2010, 20:01 Added: June 20, 2010, 20:01
Эксперты no-Steam Experts no-Steam
Experts no-Steam
User avatar
Offline
Зарегистрирован: 29 янв 2009, 21:37 Joined: Jan 29, 2009 21:37
Сообщения: 1297 Posts: 1297
Темы: 22 Threads: 22
Откуда: MOSCOШ Location: MOSCOSH
SavicH SavicH , буду знать %) , I'll know%)

_________________ _________________
pchelk.in pchelk.in


Вернуться к началу Back to top
Profile
(0) (0)
Заголовок сообщения: Re: Формат файлов GCF/NCF Post subject: Re: File Format GCF / NCF
Добавлено: 20 июн 2010, 20:22 Added: June 20, 2010, 20:22
Модератор Moderator
Moderator
User avatar
Offline
Зарегистрирован: 09 дек 2007, 22:29 Registered: Dec 09 2007 22:29
Сообщения: 1585 Posts: 1585
Темы: 31 Threads: 31
Цитата: Quote:
прои х proi x водилась vodilas

Браво, проделана большая работа Bravo, a lot of work


Вернуться к началу Back to top
Profile
(0) (0)
Added: June 20, 2010, 20:30
Разработчик Developer
Developer
User avatar
Offline
Joined: December 6, 2007, 05:45 Posts: 2897 Threads: 36

I do not understand why in the global?
On a subject: Hey, this is all so known. Andrey translated and svёl all the information from source to read for the layman view. Well nothing revolutionary. Well, for the work of all are worth deliver a cookie.

_________________ _________________
Image
Respect team CSMania.RU - ask questions correctly !


Вернуться к началу Back to top
Profile
(0) (0)
Added: June 20, 2010, 21:37
Модератор Moderator
Moderator
User avatar
Offline
Joined: March 30, 2008, 11:19 Posts: 3099 Threads: 34

And also you can understand how difficult GCF format NCF. That is to say, everything is relative

_________________ _________________

Цитата: Quote:
Every day in Africa A Gazelle Wakes up.
It Knows it must Run faster than the FASTEST Lion or it Will be Killed.
Every Morning A Lion Wakes up. It Knows That it must OutRun the Gazelle or it Will starve to Death.
It does not matter Whether you are A or A Lion Gazelle.
When the sun comes up, you better be running.


Вернуться к началу Back to top
Profile
(0) (0)
Заголовок сообщения: Re: Формат файлов GCF/NCF Post subject: Re: File Format GCF / NCF
Added: June 20, 2010, 21:52
Лейтенант Lt.
Lt.
Offline
Joined: August 27, 2009, 21:45 Posts: 119
But GTF resistant to external influences and impervious to viruses and other byakam. Well, plus the absence of fragmentation, and only one file instead of hundreds or thousands of


Вернуться к началу Back to top
Profile
(0) (0)
Заголовок сообщения: Re: Формат файлов GCF/NCF Post subject: Re: File Format GCF / NCF
Added: June 20, 2010, 21:57
Эксперты no-Steam Experts no-Steam
Experts no-Steam
User avatar
Offline
Зарегистрирован: 29 янв 2009, 21:37 Joined: Jan 29, 2009 21:37
Сообщения: 1297 Posts: 1297
Темы: 22 Threads: 22
Откуда: MOSCOШ Location: MOSCOSH
andreil, common \ papka_igry

_________________ _________________
pchelk.in pchelk.in


Вернуться к началу Back to top
Profile
(0) (0)
Заголовок сообщения: Re: Формат файлов GCF/NCF Post subject: Re: File Format GCF / NCF
Added: June 20, 2010, 21:57
Модератор Moderator
Moderator
User avatar
Offline
Joined: March 30, 2008, 11:19 Posts: 3099 Threads: 34

But lately Valve something went too far ... So many files to make some from scratch.

_________________ _________________

Цитата: Quote:
Every day in Africa A Gazelle Wakes up.
It Knows it must Run faster than the FASTEST Lion or it Will be Killed.
Every Morning A Lion Wakes up. It Knows That it must OutRun the Gazelle or it Will starve to Death.
It does not matter Whether you are A or A Lion Gazelle.
When the sun comes up, you better be running.


Вернуться к началу Back to top
Profile
(0) (0)
Заголовок сообщения: Re: Формат файлов GCF/NCF Post subject: Re: File Format GCF / NCF
Added: June 20, 2010, 22:11
Разработчик Developer
Developer
User avatar
Offline
Зарегистрирован: 14 авг 2006, 11:33 Joined: Aug 14, 2006 11:33
Сообщения: 848 Posts: 848
Темы: 30 Threads: 30
Откуда: Светлогорск, Беларусь Location: Svetlogorsk, Belarus
Fixed like both remarks As for demand - many people have asked, "Where to find?" "but it does not have?", here and decided to publish:)

;)

_________________ _________________
Репозиторий с моими проектами Repository with my projects


Занимаюсь переносом всех Engaged in the transfer of all своих библиотек на С++, а так же созданием их кроссплатформенных версий. their libraries in C ++, as well as the creation of cross-platform versions.


В команду переводчиков манги "Ah! My Goddess!" The team of translators manga "Ah! My Goddess!" требуются переводчики с английского и тайперы (последних можем обучить, главное - желание). require translators from English and Tipper (last can train, the main thing - desire).


Вернуться к началу Back to top
Profile
(0) (0)
Заголовок сообщения: Re: Формат файлов GCF/NCF Post subject: Re: File Format GCF / NCF
Posted: July 1, 2011, 19:58
Нович0к Novich0k
Novich0k
Offline
Joined: June 20, 2011, 00:20
Сообщения: 1 Posts: 1
andreil wrote (a):
Fixed like both remarks As for demand - many people have asked, "Where to find?" "but it does not have?", here and decided to publish:)

;)

Repazitory not ROBIT.


Вернуться к началу Back to top
Profile
(0) (0)
Заголовок сообщения: Re: Формат файлов GCF/NCF Post subject: Re: File Format GCF / NCF
Posted: July 1, 2011, 21:23
Разработчик Developer
Developer
Offline
Joined: January 9, 2009, 14:09 Posts: 939 Topics: 33 Location: Moving to / dev / null


Siemens31
Rep of zitory work, you may use them improperly. Besides it all repository andreil'a recovery record.

_________________ _________________
Evaporation Project - Frozen completely Minehack Project Minecraft Launcher - released


Вернуться к началу Back to top
Profile
(0) (0)
Показать сообщения за: Display posts from previous: Поле сортировки Sort by
Post new topic Reply to topic [ Сообщений: 18 ] [Posts: 18] На страницу 1 , 2 След. On page 1, 2 Next.

Часовой пояс: UTC + 3 часа [ Летнее время ] All times are: UTC + 3:00 [DST]


Кто сейчас на конференции Who is online

Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 5 Users browsing this forum: No registered users and guests: 5


Вы не можете начинать темы You can not start a new topic
Вы не можете отвечать на сообщения You can not reply to posts
Вы не можете редактировать свои сообщения You can not edit your posts
Вы не можете удалять свои сообщения You can not delete your posts
Вы не можете добавлять вложения You may not post attachments

Найти: Search for:

Создано на основе phpBB ® Forum Software © phpBB Group Created by phpBB ® Forum Software © phpBB Group
© CSmania.RU Network , 2004–2014 © csmania.ru Network , 2004-2014

Original text