1 module zgrf.types; 2 3 import zgrf.constants; 4 5 /// Holds information that is present in all GRF files. 6 struct GRFHeader 7 { 8 /// "Master of Magic" 9 ubyte[15] signature; 10 /** 11 * Either [0x00, 0x01, 0x03, ..., 0x0C, 0x0D, 0x0E] => Use Mixcrypt 12 * or [0x00, 0x00, 0x00, ..., 0x00, 0x00, 0x00] => Not encrypted 13 */ 14 ubyte[15] encryption; 15 /// Offset of the filetable after the header: offset + GRFHeader.sizeof 16 uint filetableOffset; 17 /// Unknown 18 uint seed; 19 /// actual filecount = rawFilecount - seed - 7 20 uint rawFilecount; 21 /// actual filecount 22 uint filecount; 23 /// Version of the GRF. Either 0x102, 0x103 or 0x200. 24 uint grfVersion; 25 } 26 27 /// Holds information about a single GRFFile 28 struct GRFFile 29 { 30 /// Compressed filesize using either zlib or lzma 31 uint compressed_size; 32 /// Same as above with extra padding for the DES algorithm 33 uint compressed_size_padded; 34 /// Uncompressed size 35 uint size; 36 /// Offset of the file after the file header 37 uint offset; 38 /// Hash of the filename 39 uint hash; 40 /// See zgrf.constants : FileFlags 41 FileFlags flags; 42 /// Offset in filetable 43 ulong offset_ft; 44 /// Filename 45 wstring name; 46 /// Raw filename 47 ubyte[] rawName; 48 /// Data content 49 ubyte[] data; 50 /// GRF where this file is saved in 51 GRF* grf; 52 } 53 54 /// Hashmap of files 55 alias GRFFiletable = GRFFile[uint]; 56 57 /** 58 * Holds information about a GRF file. 59 * 60 * Examples: 61 * -------- 62 * import zgrf.types; 63 * 64 * GRF grf = GRF("data.grf"); 65 * -------- 66 */ 67 struct GRF 68 { 69 import std.stdio : File; 70 71 /// Filehandle that is used to read any data from 72 File filehandle; 73 /// Filename of the GRF file 74 string filename; 75 /// Filesize of the GRF file 76 size_t filesize; 77 /// GRF Header. Will be filled once [zgrf.grf.readHeader] is called. 78 GRFHeader header; 79 /// Associative array of the files. Will be filled once [zgrf.grf.readFiletable] is called. 80 GRFFiletable files; 81 82 /** 83 * Opens the filehandle and stores the filesize 84 * 85 * Params: 86 * name = Filename of the GRF 87 */ 88 this(string name) 89 { 90 filename = name; 91 filehandle = File(filename, "rb"); 92 import core.stdc.stdio : SEEK_SET, SEEK_END; 93 94 filehandle.seek(0, SEEK_END); 95 filesize = filehandle.tell(); 96 filehandle.seek(0, SEEK_SET); 97 } 98 } 99 100 /** 101 * Holds information about multiple GRF. 102 * Use this struct if you wish to open multiple GRF files 103 * but retain a single GRF. Essentially merging the two GRF 104 * files. 105 * 106 * Examples: 107 * ----------- 108 * import zgrf.types; 109 * 110 * // rdata.grf is loaded first and any files that are not in rdata.grf 111 * // are loaded from data.grf 112 * VirtualGRF grf = VirtualGRF(["rdata.grf", "data.grf"]); 113 * ---------- 114 */ 115 struct VirtualGRF 116 { 117 /// The GRFs in this VirtualGRF 118 GRF[] grfs; 119 /// The merged filetable from the GRFs 120 GRFFiletable files; 121 122 /// See [GRF] 123 this(string[] filenames) 124 { 125 foreach(filename; filenames) 126 { 127 grfs ~= GRF(filename); 128 } 129 } 130 }