Real Information Packer 0.2x
Автор программы - Роман Петров (Йошкар-
Ола), тёзка и однофамилец йошкар-олинского
композитора Megus'а. Человек-загадка. На-
писав единственную программу, он скрылся в
неизвестность, и тут же возникли вопросы:
откуда такой уровень программирования? ко-
гда и как настолько ювелирно настроены па-
раметры сжатия? почему условия инкремента
длины ссылки с точностью до плюс-минус ба-
йта совпали с аналогичными условиями в фо-
рмате Rar2.x, хотя к моменту появления RIP
этот формат отнюдь не был обнародован?
В любом случае,это один из самых мощных
компрессоров на ZX,победить его сейчас мо-
жет только ZXRar, причём, будь ZXRar напи-
сан раньше RIP, ещё неизвестно,кто бы кого
победил... На маленьких файлах RIP принци-
пиально выгоднее - из-за меньшего объёма
деревьев и длины распаковщика.
Существует 3 распаковщика RIP: оригина-
льный v0.21 размером #121, с параметрами в
HL (откуда) и DE (куда); DERIP+++.H разме-
ром #112 (в отличие от предыдущего, позво-
ляет задать адрес деревьев независимый от
адреса распаковщика); и v0.25, пришиваемый
к упакованному файлу наподобие Hrum, дово-
льно неоптимальный.
Гвоздь формата - настоящие произвольные
деревья, хранящиеся в файле в упакованном
виде, совсем как в архивах Zip, Rar и т.д.
Процедура построения дерева в сущности ге-
ниальна. Приводить её здесь не имеет смыс-
ла,она повторена в исходниках DERIP, mRIP,
RZXSFX и т.п. Без её невероятной лаконич-
ности сама идея использования произвольных
деревьев в кодовых компрессорах осталась
бы бессмысленной. Считалось бы, что таких
деревьев достойны лишь архиваторы.
Вместе с тем, пользователю нового комп-
рессора пришлось привыкнуть к новой проб-
леме: найти #5C0 байт (#5C2 в DERIP+++.H)
памяти под деревья.Это уже не 256 байт под
активную часть распаковщика, как в Hrust1.
Нет, такой крупный объём надо где-то выде-
лять. Например,на экране.Не всегда это до-
пустимо. Вероятно, из-за таких проблем RIP
не получил большого распространения при
сборке электронной прессы.
Другая проблема - скорость распаковки.
Она значительно ниже,чем у старых компрес-
соров, даже ниже, чем у программы UnRar.
Этот недостаток нельзя устранить - он свя-
зан с принципиальным отсутствием в упако-
ванном файле байтового потока. Начинают
влиять циклы обработки деревьев, а ускоре-
ние их возможно лишь ценой существенного
увеличения распаковщика и буфера под де-
ревья.
Биты читаются из байта начиная от 0-го,
т.е. нестандартно.
Формат:
+0(2) - UnpLen, распакованная длина;
+2(2) - PakLen, упакованная длина, считая
со следующей ячейки (+4);
+4 - начало информации о деревьях. 18 че-
тырёхбитных чисел (тетрад), указывающих
количество бит в хаффмановских кодах у
дерева,используемого для извлечения рабо-
чих деревьев. Для каждого из кодов 0...17
хранится длина в битах ( 0 - код не испо-
льзуется; чем чаще код,тем он должен быть
короче).
Из этих тетрад однозначно строится де-
рево,по которому будут считаны аналогичные
данные о 288+32 символах рабочих деревьев.
Конечно, тех аналогичных данных (они лежат
далее) не обязательно 288+32 байт (в смыс-
ле, символов Хаффмана) - они хитро закоди-
рованы: 0..15 - просто код длины, типа тех
тетрад; 16 - конец информации; 17 - повто-
рить ещё 2 раза предыдущую длину.
Дерево из 288 литералов условно назовём
maintree, а дерево из 32 - просто tree.
Деревья строятся из длин по следующим
правилам:
1. Если дерево нарисовать так,что корень
будет сверху, единицы справа,а нули слева,
то левые подветви должны быть не длиннее
правых. Нижняя же кромка веток дерева дол-
жна плавно опускаться (глубина увеличива-
ться) слева направо.
2. Внутри ярусов (совокупностей листьев,
имещих одинаковую глубину) действует сор-
тировка: меньшие коды символов справа от
больших.Т.е.наоборот относительно Rar. Это
связано с сокращением распаковщика.
После того,как вся информация о деревь-
ях считана, извлекаются байты конца архива
(в обратном порядке) по дереву maintree,
сразу же закидываются в стек.Любой литерал
Є256 - конец этого процесса, и начинается
собственно распаковка.
Распаковка происходит циклами,каждый из
которых начинается с чтения символа по де-
реву maintree:
0..255 - просто байт.Поместить его в выхо-
дной поток;
257..260 - puts=1..4. Далее по дереву tree
считывается код длины disp:
0 - использовать старый disp;
1..4 - disp=1..4
5,7,...,31 - disp вида %10.., от 3 до 16
бит.Дочитываются недостающие биты disp,
начиная со старших;
6,8,...,30 - disp вида %11.., от 3 до 15
бит. Аналогично. Отсюда видно, что раз-
мер окна не превышает 49151.
Эта кодировка disp полностью соответству-
ет формату Rar (см. Inferno#4). Более то-
го, почти (256<>257) совпадает следующее:
При dispЄ256 инкрементируется puts. При
dispЄ#2000 ещё раз инкрементируется puts!
Реализуется копирование.
261,263,...,287 - коды длин puts (puts=
=%10..) от 3 до 16. Дополнительно считы-
ваются (соответственно) 1..14 бит для по-
дцепления к %10.. Далее считывается disp,
как выше;
262,264,...,286 - аналогично,но puts=%11..
От 3 до 15 бит. Далее disp, как выше;
256 - окончить распаковку.
После распаковки из стека вынимаются
байты конца файла (максимальное число мне
неизвестно).
mRIP (mrip4.H)
Формат отличается от оригинального RIP
следующими деталями:
1. Нет UnpLen, PakLen в начале;
2. Нет байтов конца файла в начале;
3. Нет кода "повторить предыдущий disp";
4. Нет коррекции puts при dispЄ#2000;
5. Тетрады длин кодов дерева для постро-
ения рабочих деревьев лежат в обратном по-
рядке.
В результате депакер уместился в бей-
сик-блоке,и был создан удобный автосборщик
для системных программ. На маленьких прог-
раммах он выигрывает у RIP'а один сектор
за счёт размера распаковщика. На длинных
теоретически может проиграть. Но на прак-
тике до этого не доходит из-за ограничений
на размер файла, пакуемого mRIP. Вот что
его ограничивает:
mRIP не перемещает блок перед распаков-
кой, поэтому адрес окончания упакованного
блока должен быть выше адреса окончания
распаковки. А адрес окончания упакованного
блока зависит не от вас, а от длины этого
упакованного блока плюс метка OTKUDA. А
эта метка (в текущей версии #AA00 ) в свою
очередь зависит от максимального размера
блока и метки maintree (в текущей версии
#f881 ), т.к. при распаковке генерируются
деревья,которые где-то нужно хранить,а за-
чернить экран не получается: не хватает
места в секторе бейсика.
Ограничения есть не только при распако-
вке, но и при упаковке: при упаковке очень
большого файла может не хватить памяти.
Можете надеяться упаковать память от #6000
до #E000 (pg0), но никак не всю память.
Для подключения mRIP к программе нужно:
1. Определить метки begin, end, GO - ра-
змеры программы и адрес её запуска;
2. Сформировать имя программы в #5CDD;
3. В начале программы установить стек,
раскрасить экран и бордюр, разобраться с
константами клавиатуры: REPPER и REPDEL...
Желательно LD (IY+1),#CC для безбоязненно-
го использования вашей программой памяти
#5bxx. Сам mRIP всего этого не делает;
4. В конце главного исходника поместить
INCLUDE "mrip*".
Рекомендуется писать именно "mrip*", а
не "mrip4", поскольку версия mRIP может
меняться. Если вы будете,например,распрос-
транять свои исходники, у получателя может
оказаться другая версия,ему придётся куда-
то лезть,что-то исправлять... (Большинство
народу терпеть не может всякие телодвиже-
ния.) И вам же будет удобнее обновлять ве-
рсии mRIP на своих дисках.Зачем обновлять?
Иногда очень неприятно рыться,искать САМУЮ
РАСПОСЛЕДНЮЮ версию по всем дискам, а там
сплошь всё старые да древние...
Если определена метка make, сборка про-
изойдёт и без нажатия Caps Shift - можете
использовать для распространения с mkace-
подобными сборщиками.
Для организации отладочного запуска,ко-
торый меняет код программы,вписывайте (ес-
ли нужно) после INCLUDE следующее:
ORG $
CALL 8026
JP NC,nenado
<ваши pokes>
JP GO
Ограничение на размер - не пересекайте
адрес #5c00.
подготовил А. Кодер