Сейчас на форуме: jinoweb (+6 невидимых) |
![]() |
eXeL@B —› Программирование —› Определить алго для патч-движка |
Посл.ответ | Сообщение |
|
Создано: 26 сентября 2018 13:35 · Поправил: Kindly · Личное сообщение · #1 пытаюсь сделать свой патч-движок, наподобие xdelta, но столкнулся с основной проблемой, итак, краткое описание алгоритма: сравнить два файла побайтно между собой и записать разницу в "diff"-файл с указанием размера отличающихся байт и смещения (или размер от начала файла), чтобы при применении патча было ясно по какому смещению, какую сигнатуру записать и какого размера и т.д., формат моего diff, примерно, следующий: заголовок/размер old/размер new/offset/size/differentbytes/offset/size/differentbytes/... на выхлопе получается гораздо большой diff файл, сравнительно xdelta, т.к. на каждую различительную сигнатуру у меня уходит 8 байт (4 offset и 4 на размер). особенно это ощущается, если байты могут отличаться один через один, и тогда на каждое сравнение всего одного байта уходит +8 байт драгоценного места и в итоге diff файл может увеличиться в разы. обдумывал разные варианты, но все они сводятся примерно к этому же, но остался последний вариант, который требует решения, если таковое возможно ![]() идея такова. 1. выполнить побайтное сравнение всех байтов поочередно от 00 до FF. 2. записать сколько раз каждый отличающийся байт присутствует в файле и высчитать все размеры смещений, например: сканируем количество отличающихся байт AA и записываем сколько штук различий, к примеру: AA:1000 и мы знаем, что в файле записать этот байт надо 1000 раз, но по предварительно вычисленным размерам друг до друга, например: AA:1000:03,50,129,180,189,206,300,315,423,1070,1288,2030, и т.д. вплоть до числа 0xFFFFFFF7 если записывать это дело в строку, то уйдет опять же приличное количество места. в идеале хотелось бы знать, существует ли алгоритм, который позволяет закодировать ленту чисел в одно свое "магическое" число, а потом позволить раскодировать/разложить это "магическое" число на исходные числа в ленте по порядку, чтобы можно было крутить в цикле и записывать нужный байт в нужное место по расшифрованному значению, на подобие: for I:=1 to 1000 do begin buf := Encrypt(i,offset); end; for I:=1 to 1000 do begin offset := Decrypt(buf[i]); Write($AA,offset); end; помогите разобраться - или нет такого алго и данная задача не выполнимая? использование сжатия не предполагается на данном этапе. ну и самый последний вариант "забить" всегда есть, если это сделать априори не реально и продолжить пользоваться готовыми решениями. ![]() ----- Array[Login..Logout] of Life ![]() |
|
Создано: 26 сентября 2018 17:47 · Поправил: TryAga1n · Личное сообщение · #2 Можно использовать первый адрес для патча как "нулевой", а последующие - как смещения, относительно "нулевого". Если патчить РЕ файл, то для каждой секции находить "нулевой" адрес. Экономия мизерная конечно, но уже что-то. ******************** Можно маленький пример diff, буквально на одну строчку, с описанием, что откуда? Чтобы нагляднее было думать) ![]() |
|
Создано: 26 сентября 2018 18:16 · Поправил: f13nd · Личное сообщение · #3 Kindly пишет: существует ли алгоритм, который позволяет закодировать ленту чисел в одно свое "магическое" число Ну так ты сам ответ дал. Взять поле оффсета и поле количества байт не кратное 8 битам. Пусть алгоритм оценивает какой оффсет получился максимальный, какое количество байт максимальное, сохраняет максимальные количества бит этих значений. Скажем 5 бит на длину оффсета (до 32 двоичных разрядов, максимальный оффсет 0xFFFFFFFF), 3 на размер (максимальный размер 255), итого 1 байт описывает "магическое число". Потом на сдвигах заполняешь свое магическое число, пусть (0;0) плюс выравнивание последнего байта будет означать конец этой структуры. Сразу за ним в том же порядке данные. ----- 2 оттенка серого ![]() |
|
Создано: 26 сентября 2018 18:43 · Личное сообщение · #4 Может хранить в формате VCDIFF? ![]() ![]() |
|
Создано: 26 сентября 2018 19:32 · Личное сообщение · #5 TryAga1n пишет: Если патчить РЕ файл, то для каждой секции находить "нулевой" адрес. патчиться будут любые форматы. TryAga1n пишет: Можно маленький пример diff, буквально на одну строчку, с описанием, что откуда? Чтобы нагляднее было думать) на данный момент: 30 10 00 00 30 10 00 00 A0 00 00 00 40 00 00 00 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF 60 01 00 00 10 00 00 00 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF 00 02 00 00 20 00 00 00 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF где первые два дворда это размеры сравниваемых файлов (могут отличаться), далее: A0 00 00 00 - offset 40 00 00 00 - size of diffs FF-ки - различительные байты с указанным размером, после них все идентично: оффсет/размер/набор новых байтов и т.д. да, можно еще сделать так: от начала файла с нуля считать расстояние, но по факту получается то же самое, если записывать: 3,10,15,20 и лепить отличающиеся байты в один массив AAA1A2A3A4A5A60102030405 то получается: от 3 позиции до 10 длина 7 байтов, стало быть по оффсету: 3 запишем: AAA1A2A3A4A5A6 теперь считаем вторую пару 20-15: по оффсету 15 запишем следующие пять байт: 0102030405 как ни крути, надо записывать пару, а пара это два дворда с учетом больших файлов до 4Гб, поэтому расстояние до смещения может быть не в один байт. так что относительно "нулевого" смещения или писать оффсеты с размером - по сути одинаково затратно на выхлопе. rthax пишет: Может хранить в формате VCDIFF? инструменты такие уже есть, с тем же xdelta, который поддерживает этот алго более 15 лет мне не тягаться. хочется чего-то своего ![]() брал для теста 80мб файлы с разным набором байтов - моя поделка выплевывает результат в 20 раз быстрее, чем xdelta. но если сравнивать похожие файлы, например большие exe разных версий, то xdelta хоть и медленнее в 20 раз, но создаст diff-файл меньше как минимум в десятки раз. f13nd тут мне надо попереваривать инфу по поводу битов и сдвигов ![]() ----- Array[Login..Logout] of Life ![]() |
|
Создано: 26 сентября 2018 19:44 · Поправил: f13nd · Личное сообщение · #6 Kindly пишет: тут мне надо попереваривать инфу по поводу битов и сдвигов n-длина оффсета, k-длина размера, (n+k)*i = номер первого бита оффсета, (n+k)*i + n = номер первого бита длины, остается набросать две функции, которые будут выбирать или устанавливать нужное количество бит по нужному смещению: Code:
----- 2 оттенка серого ![]() |
|
Создано: 26 сентября 2018 20:04 · Личное сообщение · #7 |
|
Создано: 26 сентября 2018 20:28 · Личное сообщение · #8 f13nd попробую перевести на асм в дельфе, там видно будет. TryAga1n пишет: Не совсем понял что есть "различительные байты". может не так выразился, отличающиеся, т.е. набор байтов в новом сравниваемом файле, которые будут записаны в diff и в последствии записываться функцией применения патча в старый файл. ----- Array[Login..Logout] of Life ![]() |
|
Создано: 27 сентября 2018 00:24 · Личное сообщение · #9 Используй как в таблице релоков ![]() смещение офсет(равное 1000)байт те 1000.2000.3000 и т.д.р размер(можно коло во перезаписываемых байт) теперь таблица смещение относительно офсета(смещение максимум 0FFF) И последний байт на что заменить (00FF) получается dword ----- Чтобы правильно задать вопрос, нужно знать большую часть ответа. Р.Шекли. ![]() |
|
Создано: 27 сентября 2018 07:57 · Поправил: dosprog · Личное сообщение · #10 |
|
Создано: 28 сентября 2018 18:00 · Личное сообщение · #11 |
![]() |
eXeL@B —› Программирование —› Определить алго для патч-движка |
Эта тема закрыта. Ответы больше не принимаются. |