LL BRAIN DUMP -- Event13 -- v0.9 (incomplete) - 01/26/2000 ----------------------------------------------------------------------------------- by: _!Lachesis_atatata! pronounced: shaka >yell< lachesis shaka atatata >yell< (you may yell or scream at your capability. what you yell is irrelevant) member of: ICGOMA (International Cooperative Governance Organization of Meaningless Acronyms) in conjunction with: UCFEDD (Uraguayan Consortium of Ferrets with Erectile Dysfunction Disorder) APDOFF (Agrarian Paramilitary Defense Organization of Feminist Farmers) MOOOOO (MOOOOO) ----------------------------------------------------------------------------------- A. Introduction B. Overall Layout B1. Header B2. Image Entries B3. Name Chunk B4. Dependent Links C. Problem Notes D. >gratzi< ----------------------------------------------------------------------------------- A. INTRODUCTION ----------------------------------------------------------------------------------- this brain dump describes the format of .LL files used in Homeworld by Relic Entertainment Inc. the LL file is they key to the shared image scheme used by the Homeworld engine. it is a database which contains information on how to resolve an image name to an actual image file. the only kind of image files referenced in this database are LiF files. i'm not using the word "texture" because not all images are textures. LiF files can also be used for things like cursors. yet again, there is enough info here to read one (mostly), but not to create one. if you go to the Relic Editing Forum and do a search for "Lachesis_atatata" as author, i may have posted other information not discussed in this document. in general, that forum is the place to go to find answers. if information from this document is used for implementations or in other documents, please credit me. it's just the nice thing to do. i'll be haunting the message boards, if you have a question, post it. if i don't reply i: 1. don't know the answer 2. am busy with something at some point on the globe 3. am dead* if there are errors on this document ... oops :) * (...at this point, this may be the most likely scenario...) ----------------------------------------------------------------------------------- B. OVERALL LAYOUT ----------------------------------------------------------------------------------- there are four main areas to the LL file format arranged sequentially one after the other: 1. header 2. image entries 3. name chunk 4. dependent links each is described in the sections below. ----------------------------------------------------------------------------------- B1. HEADER ----------------------------------------------------------------------------------- the header area comes at the beginning of the file. it has the normal elements you would expect to be there. there is only one header. ------------------------------------------------------------------------------- typedef unsigned long ulong_t; typedef unsigned char ubyte_t; const uchar_t LL_FILE_ID[] = { 0x45, 0x76, 0x65, 0x6E, 0x74, 0x31, 0x33, 0x00 }; //note: "Event13" + null const ulong_t LL_FILE_VERSION = 0x00000104; struct header { ubyte_t magic_cookie[8]; ulong_t version; ulong_t image_entry_count; ulong_t name_chunk_size; ulong_t dependent_link_count; ulong_t unknown_1; }; ------------------------------------------------------------------------------- magic_cookie identifier for the file. The only currently known value for this is contained in LL_FILE_ID. version the version of the file. currently LL_FILE_VERSION. image_entry_count the number of image entries contained in the database. (see B2. IMAGE ENTRIES) name_chunk_size the size of the name chunk. (see B3. NAME CHUNK) dependent_link_count the number of dependent links. (see B4. DEPENDENT LINKS) unknown_1 something. i'm out of energy. ----------------------------------------------------------------------------------- B2. IMAGE ENTRIES ----------------------------------------------------------------------------------- image entries are the core of the database. there are two kinds of entries: 1. an entry which refers to an image. 2. an entry which refers to another entry. there is an array of header.image_entry_count image entries. the first entry can be found immediately after the header. ------------------------------------------------------------------------------- struct image_entry { ulong_t file_name_offset; ulong_t width; ulong_t height; ulong_t crc32; ulong_t unknown_1; ulong_t reference_count; ulong_t dependent_link_idx; ulong_t shared_image_entry_idx; }; ------------------------------------------------------------------------------- file_name_offset the offset to this entry's file name. this is NOT from the start of the file, but from the start of the Name Chunk. (WARNING: this is an OFFSET) (see B3. NAME CHUNK) width width of the image (duh) height height of the image (duh) crc32 this is a CRC32. of WHAT i don't know. i tried a bunch of things. i'm not trying anything else. unknown_1 this contains some sort of flag set. not checked hard. reference_count this contains the number of OTHER images which reference this one. dependent_link_idx if reference_count is not 0, then this contains an index into the Dependent Links area. otherwise it contains 0xFFFFFFFF. (see B4. DEPENDENT LINKS) shared_image_entry_idx if this image is actually just a reference to another image (a shared image) then this contains an index to ANOTHER image_entry. otherwise it contains 0xFFFFFFFF. note: from what i've seen, you CANNOT have nested shared textures. ie. you cannot have an image which refers to another image, which refers to another image yet again. as a consequence, dependent_link_idx and shared_image_entry_idx are mutually exclusive. only one can be valid. ----------------------------------------------------------------------------------- B3. NAME CHUNK ----------------------------------------------------------------------------------- the name chunk holds all the names of all the files being referenced by the image entries. null-terminated string are just packed together one after the other. the start of the name chunk comes immediately after the last image entry. so, the forumula is: name chunk offset = sizeof(header) + (sizeof(image_entry) * header.image_entry_count) ----------------------------------------------------------------------------------- B4. DEPENDENT LINKS ----------------------------------------------------------------------------------- for a shared image_entry, these links are indexes to other image_entries which depend on it. (are using it) so, if image_entry.reference_count is 4, then there are 4 dependent links starting at image_entry.dependent_link_idx, which point to 4 other image_entry structures, which are images that are dependent upon the shared image. the start of the dependent link array comes immediately after the Name Chunk. so, the formula is: dependent links offset = name chunk offset + header.name_chunk_size; ------------------------------------------------------------------------------- struct dependent_link { ulong_t image_entry_index; }; image_entry_index an index into the image_entry array. ----------------------------------------------------------------------------------- C. Problem Notes ----------------------------------------------------------------------------------- to Relic or anyone else who cares: the names of the last few dozen entries in textures.ll are corrupt. ----------------------------------------------------------------------------------- D. >gratzi< ----------------------------------------------------------------------------------- >gratzi< to Relic for the BIG addendum, LiF and GEO specs, and the BTG editor. >gratzi< to Relic if they release some more stuff so i can get some sleep. :) >gratzi< to UberJumper who hosted some screenshots of my perpetually delayed GeoVision application. (which will possibly never get done due to the huge amount of time and effort it takes to crack these file formats, let alone actually DO something with them) -----------------------------------------------------------------------------------