void IZiPatchCommand.Handle(BinaryReader reader, long commandSize, ZiPatchExecute execute) { reader.BaseStream.Position += 2; PatchVersion = reader.ReadByte(); reader.BaseStream.Position++; PatchType = Encoding.ASCII.GetString(reader.ReadBytes(4)); reader.BaseStream.Position += 0xEC; }
private static void InstallPatch(string path, string gamePath, string repository) { var execute = new ZiPatchExecute(gamePath, repository); try { execute.Execute(path); } catch (Exception e) { Log.Error(e, "Failed to execute ZiPatch."); throw; } }
private (ulong OutputOffset, ulong OutputLength, string path) ReadFileCommandInfo(BinaryReader reader) { var outputOffset = reader.ReadUInt64BE(); var outputLength = reader.ReadUInt64BE(); var fileNameLength = reader.ReadUInt32BE(); var expansionId = reader.ReadUInt16BE(); reader.BaseStream.Position += 2; var path = $"{ZiPatchExecute.ResolveExId((byte) expansionId)}\\{Encoding.ASCII.GetString(reader.ReadBytes((int) fileNameLength))}"; // Cut null byte from end of path path = path.Substring(0, path.Length - 1); //Log.Verbose(" -> SQPK FILECMDINFO: outputOffset:{0} outputLen:{1} {2}", outputOffset, outputLength, path); return(outputOffset, outputLength, path); }
public void Handle(BinaryReader reader, long commandSize, ZiPatchExecute execute) { if (commandSize > MAX_HEADER_SIZE) { Log.Debug($"Detected file header with size > {MAX_HEADER_SIZE}"); throw new ArgumentException("Patch file is invalid or not ZiPatch."); } reader.ReadBytes(2); PatchVersion = reader.ReadByte(); reader.ReadByte(); PatchType = Encoding.ASCII.GetString(reader.ReadBytes(4)); //reader.BaseStream.Position += 0xEC; reader.ReadBytes(0xEC); }
void IZiPatchCommand.Handle(BinaryReader reader, long commandSize, ZiPatchExecute execute) { var sqpkCommandSize = reader.ReadUInt32BE(); var sqpkCommandType = (char)reader.ReadByte(); switch (sqpkCommandType) { case 'A': { CommandType = SqPackCommandType.Add; reader.BaseStream.Position += 3; var file = execute.ResolveSqPackFile(reader); var blockInfo = ReadBlockInfo(reader); var data = reader.ReadBytes((int)(blockInfo.BlockCount * SQPK_FILE_BLOCK_SIZE)); //data.Dump(); if (!ZiPatchExecute.IsDryRun) { file.Write(data, (int)blockInfo.BlockOffset, data.Length); } file.Close(); Log.Verbose(" -> SQPK ADD command executed for offset {0} with data of {1}", blockInfo.BlockOffset.ToString("X"), data.Length.ToString("X")); break; } case 'D': { CommandType = SqPackCommandType.Delete; reader.BaseStream.Position += 3; var file = execute.ResolveSqPackFile(reader); var blockInfo = ReadBlockInfo(reader); file.Close(); break; } case 'E': { CommandType = SqPackCommandType.Expand; var operation = reader.ReadByte(); reader.BaseStream.Position += 2; // Skipped var file = execute.ResolveSqPackFile(reader); var blockInfo = ReadBlockInfo(reader); reader.BaseStream.Position++; // Skipped file.Close(); break; } // HEADER command - Overwrite the header of the specified SqPack DAT file with the 1024 byte payload case 'H': { CommandType = SqPackCommandType.Header; var targetType = (char)reader.ReadByte(); var headerType = (char)reader.ReadByte(); reader.BaseStream.Position++; // Skipped var file = execute.ResolveSqPackFile(reader); var headerData = reader.ReadBytes(1024); headerData.Dump(); if (targetType == 'D') { var offset = 0; if (sqpkCommandSize != 0x410) { throw new Exception("HEADER command has invalid size: " + sqpkCommandSize); } if (headerType != 'V') { if (headerType != 'D') { throw new Exception("Unknown HEADER headerType: " + headerType); } offset = 0x400; } if (!ZiPatchExecute.IsDryRun) { file.Write(headerData, offset, headerData.Length); } file.Close(); Log.Verbose(" -> SQPK HEADER command executed for offset {0}", offset.ToString("X")); } else { throw new NotImplementedException("Unimplemented HEADER target type: " + targetType); } break; } // FILE command - Extract file data at specified offset case 'F': CommandType = SqPackCommandType.File; reader.BaseStream.Position += 3; var fileCommandInfo = ReadFileCommandInfo(reader); HandleFileWrite(reader, null, fileCommandInfo.OutputOffset, fileCommandInfo.OutputLength); break; // PATCHINFO? - Unknown case 'T': CommandType = SqPackCommandType.PatchInfo; reader.BaseStream.Position += commandSize - 5; break; // INDEX - case 'I': CommandType = SqPackCommandType.Index; reader.BaseStream.Position += commandSize - 5; break; // Not quite sure? case 'X': CommandType = SqPackCommandType.Unknown; reader.BaseStream.Position += commandSize - 5; break; default: throw new NotImplementedException("Unimplemented ZiPatch SQPK subcommand type: " + sqpkCommandType); } Log.Verbose(" -> SQPK: type:{0}", CommandType); }
public ZiPatchCommandPack(BinaryReader reader, ZiPatchExecute execute) { _execute = execute; Read(reader); }