private byte[] getFileZBlock(GrfFile file) { /* Get new stream */ var stream = FileManager.Load(filename) as Stream; if (stream == null) { throw new Exception("GE_ERRNO"); } byte[] data; using (var br = new System.IO.BinaryReader(stream)) { br.BaseStream.Seek(file.pos, SeekOrigin.Begin); data = br.ReadBytes((int)file.compressed_len_aligned); } byte[] keyschedule = new byte[0x80]; return(GrfCrypt.GRFProcess(data, file.compressed_len_aligned, file.flags, file.compressed_len, keyschedule)); }
public byte[] GetData(GrfFile file) { //not a file if (file.IsDir()) { return(null); } //empty file if (file.real_len == 0) { return(null); } //check if data was already extracted if (file.data != null) { return(file.data); } /* Retrieve the unencrypted block */ byte[] zbuf = getFileZBlock(file); if (zbuf == null) { return(null); } using (var stream = new InflaterInputStream(new MemoryStream(zbuf))) { file.data = new byte[file.real_len]; stream.Read(file.data, 0, file.data.Length); } return(file.data); }
/*! \brief Private function to read GRF0x2xx headers * * Reads the information about files within the archive... * for archive versions 0x02xx * * \todo Find GRF versions other than just 0x200 (do any exist?) * * \param grf Pointer to the Grf struct to read to * \param error Pointer to a GrfErrorType struct/enum for error reporting * \param callback Function to call for each read file. It should return 0 if * everything is fine, 1 if everything is fine (but further * reading should stop), or -1 if there has been an error * \return 0 if everything went fine, 1 if something went wrong */ static uint GRF_readVer2_info(System.IO.BinaryReader br, Grf grf, GrfOpenCallback callback) { uint i, offset, len, len2; byte[] buf, zbuf; /* Check grf */ if (grf.version != 0x200) { throw new Exception("GE_NSUP"); } /* Read the original and compressed sizes */ buf = br.ReadBytes(8); /* Allocate memory and read the compressed file table */ len = GrfSupport.LittleEndian32(buf, 0); zbuf = br.ReadBytes((int)len); if (0 == (len2 = GrfSupport.LittleEndian32(buf, 4))) { return(0); } /* Allocate memory and uncompress the compressed file table */ Array.Resize(ref buf, (int)len2); var stream = new InflaterInputStream(new MemoryStream(zbuf)); stream.Read(buf, 0, buf.Length); stream.Close(); /* Read information about each file */ for (i = offset = 0; i < grf.nfiles; i++) { /* Grab the filename length */ len = GrfSupport.getCStringLength(buf, offset) + 1; /* Make sure its not too large */ if (len >= GrfTypes.GRF_NAMELEN) { throw new Exception("GE_CORRUPTED"); } /* Grab filename */ GrfFile file = new GrfFile(); file.name = GrfSupport.getCString(buf, offset); offset += len; /* Grab the rest of the information */ file.compressed_len = GrfSupport.LittleEndian32(buf, (int)offset); file.compressed_len_aligned = GrfSupport.LittleEndian32(buf, (int)offset + 4); file.real_len = GrfSupport.LittleEndian32(buf, (int)offset + 8); file.flags = buf[offset + 0xC]; file.pos = GrfSupport.LittleEndian32(buf, (int)(offset + 0xD)) + (uint)GRF_HEADER_FULL_LEN; file.hash = GrfSupport.GRF_NameHash(file.name); file.name = NormalizePath(file.name); grf.files.Add(file.name, file); /* Advance to the next file */ offset += 0x11; /* Run the callback, if we have one */ if (callback != null) { callback.doCallback(file); if (!callback.hasReturned()) { throw new Exception("NO_RETURN"); } if (callback.Response < 0) { /* Callback function had an error, so we * have an error */ return(1); } else if (callback.Response > 0) { /* Callback function found the file it needed, * just exit now */ return(0); } } } /* Calling functions will set success... * GRF_SETERR(error,GE_SUCCESS,GRF_readVer2_info); */ return(0); }
public void doCallback(GrfFile file) { this.file = file; callback.Invoke(this); }