Miracle #03
16 июля 1999

Кто там кодит? - Packer'ы и Depacker'ы: вся правда о паковщиках, или разглагольствования сэра Kot'а.

<b>Кто там кодит?</b> - Packer'ы и Depacker'ы: вся правда о паковщиках, или разглагольствования сэра Kot'а.
    (c) Kot/North Star group 07.1998
    ---------------------------------

       Компрессоры, декомпрессоры
           и не только они...

  Всем  прювет  от  группы North Star. В
этой  статье  я коснусь ряда проблем ка-
чества  продукции "заводов софтоварения"
нaшего  необъятного СНГ.

  Вероятно,  маломальски  уважающий себя
кодер (хакер) практически всегда пользу-
ется компрессорами данных, будь то скрин
или  код.  В  настоящее время количество
программ данного типа неуклонно растет и
есть что выбрать. Однако сервисные пока-
затели,  а  иногда и програмные характе-
ристики  продукта зачастую оставляют же-
лать лучшего.

  Начнем  с  программных.  Известно, что
профессионально  сделанные  экранные де-
компрессоры  релоцируемы,  то бишь старт
осуществляется  с адреса загрузки. Клас-
сическая  процедурка  "само-пере-адреса-
ции" выглядит примерно так:

         DI          ;!!!
         CALL ret_adr;#0052,#1792,#33C5 etc
    ;e1>
         DEC SP
    ;e2>
         DEC SP
         POP reg_p   ;HL,DE,BC и т.д.
         .......

  Какой-то  умник  (не  будем показывать
пальцем:    смотрите   ZF#7Перспрективы
ПОS.O.T.A.п.п.  Screen Compressor) по-
советовал (и, насколько я помню, называл
ламеризмом)  убрать  команду  DI вначале
всей процедуры. Видите ли,доставляет не-
удовольствие  слышать  торможение музона
во время вызова декомпрессора... Так да-
вайте ж убирать этот вонючий DI или мор-
фировать  его  в  NOP  и программа будет
смотреться  "элитно".  То есть, он хочет
сказать,   что  многоуважаемый  Андрейка
Сендецкий  для общего понту в своем  ASC
поставил вначале  DI потому что он - ла-
мер?  Ан  нет, батенька. Что же мы видим
при  разрешенных  прерываниях? Вы только
подумайте,  какую  херню снимет со стэка
POP  reg_p,  если процессор начнет обра-
ботку  прерывания в точках e1 и e2! Если
кто-то  не понял, почему так происходит,
то  пусть вместо e1 или e2 подставит ка-
кой-нибудь PUSH и такой же POP (эмуляция
прохождения  прерывания).  Вот  и  я тут
"запачил"  картинку  в новом  LAZY_PACK.
Потом  загрузил  в STS: в начале декомп-
рессора   вышеприведенная  "классика"...
только без  DI... А жаль. Вы прикиньте -
а ведь некоторые убирают  DI и в декомп-
рессорах  по  типу MS_PACK'а, где данные
снимаются  стэком...  Я  еще представляю
вариант,  когда  при операциях со стэком
SP  всегда  в результате SP+2, но ведь в
том же декомпрессоре MS_PACK'а имеется:

          .........
          DEC SP
          POP AF
          .........

  Потрассируйте    STS'ом   запакованный
MS_PACK'oм  блок  с его оригинальным де-
компрессором  и  посчитайте, сколько раз
программа  обращается к вышеприведенному
куску  кода. А потом по собственным тео-
риям  рассчитайте: придет прерывание или
не придет в этот момент и успеет ли dec-
runcher за 1/50 секунды... Успехов...

  Ярким   примером  является  TRANCE  MD
(SBG),  где, например, вместе с иерогли-
фами вылезает что-то "более ужасьное"...

  Перейдем к так называемому техническо-
му  сервису.  Вот  все  пишут:  мы, мол,
прогрессивные  пиплы  и т.д., однако за-
частую вся числовая индикация в прогах -
десятичная  (это касается sys-прогов лю-
бого  назначения).  Меня  (я  уверен, не
только  меня)  этот факт "выводит из се-
бя",  грубо  говоря,  бесит.  Интересно,
много ли таких "пиплов", которые за пару
секунд  скажут,  что  #B700 это 46848? Я
думаю, таких немного и я не из их числа.
Неужели  нельзя  сделать ввод (и индика-
цию)  числовых  значений  и  в HEX'е и в
DEC'е.

  О самих decruncher'ах особый разговор.
Давно  бы  уже пора, извините за баналь-
ность, "принять за стандарт" запрос типа
"А  хотите  ли  вы  подшить decruncher?"
(Decompressor  ON/OFF).  Ведь, например,
как удобно запачить все файлы (части MD,
уровни  игр  или оверлеи систем) в комп-
рессоре  и отгрузить их без дcrnchr'а, а
в процессе распаковки пользоваться одним
единственным  декомпрессором. Это позво-
ляют делать  PCD, MegaLZ и DSQ, хотя это
касается  компрессоров  любых видов дан-
ных, в том числе и экранных. Желательно
в  комплекте  давать два (или более) де-
компрессора - на выбор, отвечающих, нап-
ример, следующим условиям: с использова-
нием  стэка  при запрещенных прерываниях
:-) или без использования стэка и IY при
любом  статусе прерываний и т.д. Вариан-
тов  может  быть сколько угодно, но если
таковой  всего  один, то он должен рабо-
тать  при  разрешенных  прерываниях (это
лично мое мнение). Некоторые скажут: вот
у  DSQ декомпресор тоже работает при лю-
бом  статусе прерываний, поэтому он, на-
верное,  такой  тормозной.  Отвечаю: что
касается  DSQ, так там данные хрянятся в
непрерывном виде и эти самые данные име-
ют  разнобитную величину (см. рис), да и
сам декомпрессор имеет довольно компакт-
ные размеры.

     bit 76543210|76543210|76543210|
         -----------------------------
     l)  000|1101|0101010|01|01110110|
         ─────────────────────────────
     f)  00011010|10101001|01110110|

 l)  - логические данные, полученные при
компресси  (в таком виде принимаются де-
компрессором);  НЕПРЕРЫВНЫ, т.е. началь-
ный бит лог. единицы данных не совапада-
ет  с  начальным  битом физ. ед. данных,
что дает эффект экономии битов сообразно
размеру файла (прямопропорционально);
 f) - физический вид, т.е. таким образом
данные расположены в памяти компьютера;
 Логически мысля, можно прийти к выводу,
что для трансформации данных из вида  l)
в вид f) нужно применять сдвиги (RR,RL и
т.д.). Вот на это и уходит львинная доля
времени  у  декомпрессора DSQ, хотя есть
смысл его оптимизировать.

  Ну, уж если речь пошла о DSQ, то оста-
новимся на нем поподробнее. Как вы знае-
те, в DSQ предусмотрена возможность отк-
лючения декомпрессора. Но это полдела. В
проге  DSQ_INFO,  как  это часто бывает,
вместо  описания  - приветы, коминсуны и
всякая такая дребедень. Так вот, если вы
решили  использовать кастрированный (без
дкмпрср'a) датасквизнутый блочок, то из-
вольте  знать следующие вещи: оказывает-
ся, у этого блока есть заголовок (len: 6
byte, но по идее должно быть 7 - см. да-
лее), в котором указаны:
  N0 (byte) - количество    "вырезаемых"
оконных битов (очень, кстати, подходящее
определение);
  N1 (word) - адрес, введенный на запрос
DECRUNCH  CODE TO:NNNN ;
  N2 (word) - адрес, N1-1+реальная длина
файла, другими словами - адрес последне-
го  байта файла (именно последнего, а не
следующего за ним) ;
  N3 (byte, а должен быть word) - сильно
не смейтесь, но это младший байт адреса,
введенного  на  запрос  AUTOSTART: NNNN,
просто маленький глюк DSQ;
  Итого: byte+word+word+byte = 6 byte.

  На  самом  деле, кроме байта N0 больше
ни хрена не надо, тем более младший байт
запуска :-). Можно, в принципе, оставить
на  месте N1 полную длину исходного фай-
ла.  Но  это - рекомендации для тех, кто
может  быть переделает  DSQ на новый лад
(с  крутым  сервисом  и  т.д.). Резонный
вопрос: а куда девать N0?

           .........
           LD B,NN     ;nuf
           LD H,#02
           ADD HL,DE
           CALL NNNN
           ADD HL,BC
           POP BC
           LDDR
           LD HL,XXXX  ;nif
           SBC HL,DE
           JR C,NNNN
           POP HL
           EXX
           RET
           ..........

  Аргумент  рег.  B  в строке nuf и есть
тот  самый  N0,  а для полного понимания
формулировки  про "оконные биты" потрас-
сируйте  декомпрессор debugger'ом. Пара-
метр  N0 зависит от того, каков был выб-
ран размер окна при паковке файла.

  А как вообще распаковать блок "не род-
ным" декомпрессором? Во-первых,  DSQ во-
обще является неординарным компрессором.
Объясню,  почему. Если вы знаете порядок
трансляции данных "родными" декомпрессо-
рами  паковщиков  LPC, PCD, CC, MS_PACK,
то могли наблюдать следующую картину:

       1) block LDIR (LDDR) on body file
    (для выполнения end_block = end_file)
       2) source (HL) = start_block
       3) destination (DE) = start_file
    LP 4) translate (HL)bits to (DE)bytes
       5) inc HL, inc DE
       6) go to LP if DE<(end_file+1)

           У DSQ все "up side down":

       1) block LDIR (LDDR) on body file
    (для выполнения start_block=start_file)
       2) source (HL) = еnd_block
       3) destination (DE) = end_file
    LP 4) translate (HL)bits to (DE)bytes
       5) dec HL, dec DE
       6) go to LP if DE<(start_file-1)

 Ненормативная лексика:

   file       - исходный файл;
   block      - результат компрессии;
   source     - откуда берем;
   destin     - куда кладем;
   start_file - адрес начала дкмпрсируе-
мых данных;
   end_file   - адрес  последнего  байта
дкмпрсируемых данных;
   start_block - начало данных block'а;
   end_block  -  адрес  последнего байта
block'а;
   inc,  dec - увеличение, уменьшение на
NNNN байтов (вопреки легенде - не только
на единицу);
   body file - некоторый участок памяти,
резервируемый под file;

   Вообще же, эти схемы приведены в иде-
але.  На  самом же деле в отношении  DSQ
есть  некоторые  внушительные  поправки.
Если вы вообще пользовались  DSQ, то ве-
роятно помните нечто (-2). Это возникает
потому,  что  destin'ация  идет быстрее,
чем  sour'сирование, в результате, когда
остается  распаковать 1-3 байта destina-
tion  равен source, а на следующем цикле
вообще  опережает его. Здесь и возникает
ситуация когда, например, вместо маркера
конца берется "нечто", вероятность кото-
рого  стать маркером конца 1/256... Поэ-
тому  LDIR'ить  или  LDDR'ить  надо так,
чтобы  start_blok=start_file-2 (-2, -3 и
более, но не менее -2), а если block DSQ
с  заголовком,  то start_block=start_fi-
le-2-6 (-8, -9 и более, но не менее -8).
Все это, конечно, славы DSQ не прибавля-
ет,  а  ведь  можно  было как в  PCD или
MS_PACK'е  с использованием буфера - там
все  работает  по  вышеприведенной схеме
как  с  "родными",  так  и  "не родными"
дкмпрсрами.  Примечание: nif в куске ди-
зассемблера дехрюнчера поставлен не слу-
чайно  -  здесь  обязательно должно быть
start_file-1 !!

  Покончим  с  DSQ  и  вернемся к #1B00,
т.е.  к  скриновым  пакерам. Выдвину еще
одно  предложение:  а  почему  бы даже в
компрессорах   экрана  не  предусмотреть
возможность  смены  адреса распаковки? О
чем  это  ты,  батенька?  Вы,  вероятно,
сталкивались  с  ситуацией,  когда  надо
распаковать  картинку  на  SCR1  (в 7-ой
странице), т.е. под адрес #C0 или вообще
распаковать и не в #40 и не в #C0, а ку-
да-нибудь  "вообще  ни  туда" (например,
при  реализации всяких гасилок/зажигалок
и  других "проявлений"). Мое предложение
заключается в том, чтобы можно было выб-
рать  хотя бы старшую часть destin'ации,
a  младшая будет нулевой "по умолчанию",
например,  #70,#67,#BF,#9A,#DE  и т.д. А
затем  после распаковки каким-либо обра-
зом ее (картинку) "проявить" (можно даже
LDIR'ом :-)).

  Теперь  вернемся к "релоцируемому" за-
пуску  программ.  Я  приведу некий набор
маленьких  процедур, которые дают "само-
определение местонахождения":

    1) DI            ;обязательно! (см. выше)
       CALL ROM_RET  ;#52, #7C, #33C5 и т.д.
       DEC SP
       DEC SP
       POP reg_p     ;HL, DE, BC, IX и т.д.
       ........      ;length: 7-8 байтов

    2) LD HL,#E9E1   ;POP HL (#E1)
       LD (#4000),HL ;JP (HL)(#E9)
       CALL #4000    ;
       ..........    ;результат в HL
                     ;length: 9 байтов

    3) LD HL,#4000   ;<- start_1
       PUSH HL       ;<- start_2
       LD (HL),#E1
       INC HL
       LD (HL),#E9
       DEC HL
       CALL ROM_JHL  ;JP (HL): #162C, #6F
       ........      ;результат в HL
       POP reg_p     ;length: 14 байтов

  Первый  вариант  работает  только  при
запрещенных  прерываниях,  однако  адрес
может  быть помещен в любую из регистро-
вых пар. Используется ПЗУ-48.

  Второй вариант больше на 1-2 байтa, но
работает при любом статусе прервываний и
не использует ПЗУ.

  Третий  вариант явяется универсальным,
но опять используется ПЗУ. Здесь имеется
две точки входа start_1 и start_2. Через
start_1  осуществляется  привязка распа-
ковки данных к фиксированному адресу па-
мяти,  при  использовании же  start_2 вы
сами  вольны  в выборе адреса, но важно,
чтобы   младшая  тоже  была  равна  нулю
(смотря  каким образом происходит перес-
чет "экранных" адресов дкмпрсром - усло-
вие: (не)допустимо использование ненуле-
вой младшей части).

  Вобщем,  вариантов  может быть сколько
угодно,  главное, чтобы это было удобно,
круто и без глюков :-(.

  На  днях  смотрел  инлайтские демы и в
одной  из  них (Art Vision by etc group)
узнал,  что,  дескать,  дема  использует
decruncher  ((c) LAZY) MS_PACK'а, не ис-
пользующий стэк для "выкачивания" данных
и  т.д.  Так  как в MSP не предусмотрено
отключение   декомпрессора,  то  "новый"
дкмпрср работает со стандартными блоками
MSP,  у которых уже есть свой декомпрес-
сор.

    ;MS_PACK blocks decruncher
    ;Written by LAZY/etc group
    ; Entry: IX - adr of block
    ;(wiz standard decruncher)

    INC     HX
    LD      L,(IX-#17)
    LD      H,(IX-#16)
    LD      DE,MSPBUF+4
    LD      BC,#0005
    LDDR
    LD      L,(IX-#15)
    LD      H,(IX-#14)
    LD      E,(IX-#13)
    LD      D,(IX-#12)
    LD      C,(IX-#11)
    LD      B,(IX-#10)
    LDDR
    INC     DE
    INC     DE
    INC     DE
    EX      DE,HL
    LD      E,(HL)
    INC     HL
    LD      D,(HL)
    INC     HL
    EX      DE,HL
    LD      BC,#1010
    EXX
    LD      E,(IX-#0F)
    LD      D,(IX-#0E)
    MSP_LP  CALL    MSPCOD
    JR      C,LL631D
    CALL    MSPBYT
    LD      (DE),A
    INC     DE
    JR      MSP_LP
    LL631D  LD      HL,#0302
    LL6320  LD      B,#02
    CALL    BCOD_A
    CP      H
    JR      C,LL632F
    ADD     A,L
    LD      L,A
    CP      #11
    JR      NZ,LL6320
    XOR     A
    LL632F  ADD     A,L
    CP      #05
    JR      NC,LL6364
    CP      #02
    JR      NZ,LL6367
    LD      C,A
    LL6339  XOR     A
    LL633A  LD      H,A
    CALL    MSPBYT
    LD      L,A
    LD      A,E
    SCF
    SBC     A,L
    LD      L,A
    LD      A,D
    SBC     A,H
    LD      H,A
    LDIR
    JR      MSP_LP
    LL634A  CALL    MSPBYT
    INC     A
    JR      Z,MSPEND
    INC     A
    JR      NZ,LL635D
    CALL    MSPBYT
    LD      C,A
    CALL    MSPBYT
    LD      B,A
    JR      LL6368
    LL635D  ADD     A,#0F
    JR      NC,LL6367
    INC     B
    JR      LL6367
    LL6364  JR      Z,LL634A
    DEC     A
    LL6367  LD      C,A
    LL6368  CALL    MSPCOD
    JR      C,LL6339
    LD      L,B
    LD      B,H
    CALL    BCOD_A
    LD      B,L
    CP      #02
    JR      NC,LL637A
    INC     A
    JR      LL633A
    LL637A  CALL    LL63B1
    CP      #08
    JR      NC,LL6384
    DEC     A
    JR      LL633A
    LL6384  CALL    LL63B1
    CP      #17
    JR      NC,LL638F
    SUB     #09
    JR      LL633A
    LL638F  CALL    LL63B1
    AND     #1F
    CP      #1F
    JR      C,LL633A
    CALL    MSPBYT
    JR      LL633A
    MSPEND  LD      HL,MSPBUF
    LD      BC,#0005
    LDIR
    LD      HL,#2758
    EXX
    RET
    BCOD_A  XOR     A
    CALL    LL63B1
    DJNZ    $-3
    RET
    LL63B1  CALL    MSPCOD
    RLA
    RET
    MSPCOD  EXX
    ADD     HL,HL
    DJNZ    NONEXT
    LD      B,C
    EX      DE,HL
    LD      E,(HL)
    INC     HL
    LD      D,(HL)
    INC     HL
    EX      DE,HL
    NONEXT  EXX
    RET
    MSPBYT  EXX
    LD      A,(DE)
    INC     DE
    EXX
    RET
    MSPBUF  DEFB  0,0,0,0,0

  Ну  вот,  наверное, и все, что я хотел
вам  сообщить.  Если  у кого-то есть ка-
кие-либо  комментарии, пусть пишет в ре-
дакцию MIRACLE или мне (Kot'у).

                       Bye'те!
                       Kot/NSG 07.1998
            Кировск-Апатиты-Оленегорск

----------------------------------------

 





Другие статьи номера:

От редакции - Предисловие: С какой целью мы выпускаем журнал?

От редакции - Оболочка: описание новой оболчки к журналу.

От редакции - письма в журнал: Dr.Sioux/Phantom Family, Fistsoft, Mr.Z/HardWave, Куров Н., Eagle/Computer Ratz Group, Rom Corp/Virtual Vision Group.

От редакции - в этом номере: содержание номера.

Проект года - презентация версии игры Robo от KT-soft/ETC.

Проект года - презентация игры от группы Spark: Городки.

Проект года - презентация игры "12 Тайных книг".

Проект года - несколько слов о готовящейся к выходу игре Chip & Dale.

Проект года - потрясающая новелла к игре "Навигатор".

Проект года - Мир тьмы: описание новой real-time strategy.

Погремушки - свежие и не очень, но смачные читы.

Погремушки - крематорий: игра Сталкер - описание всех предметов.

Погремушки - крематорий: Страна мифов - советы спеца.

Основы SWAP'А - информация для начинающих, а также несколько хитрых извратов, которые можно провернуть с почтой.

Кто там кодит? - Быстрая графика: несколько рецептов от Zetter'а (печать спрайтов, обновление экрана).

Кто там кодит? - Packer'ы и Depacker'ы: вся правда о паковщиках, или разглагольствования сэра Kot'а.

Кто там кодит? - Работаем с MS-DOS: Все о mod файлах - полное описание структуры mod-файла, а также описание всех эффектов.

Кто там кодит? - Работаем с MS-DOS: Ms-Dos дискеты - описание структуры Ms-Dos диска.

Кто там кодит? - Chanky flame: описание алгоритма чанкового огня.

Кто там кодит? - Attribute bump mapping: bump mapping для тех кто не въехал.

Кто там кодит? - Гуру медитирует: оптимизация программ по времени исполнения и по размеру.

Кто там кодит? - Приближенный поиск заданной последовательности байт!

Кто там кодит? - Fast 42 print: быстрая процедура печати 42 символов в строке.

Party zone - KidSoft'98: репортаж с Воронежского фестиваля компьютерного искусства.

Party zone - EarthQuake'99: репортаж с Челябинского фестиваля компьютерного искусства.

Я сама - 128 цветов на Spectrum: схема доработки до 128 цветов от донецкой группы Spark.

Я сама - Чайникам: подключение General Sound к Profi через системный разъем.

Я сама - Бесперебойные блоки питания: информация об UPS-технологии.

Я сама - General Sound Filter: рассказ о новой примочке к GS.

Я сама - Модемы: Схемы, схемы! Схемы Г.Шепелева и М.Кондратьева подключения Hayes модема.

Я сама - Модемы: Описание команд - описание команд терминала.

Я сама - Модемы: Тотальная модемизация - призыв к подключению момедов.

Системный софт - FastCopy 3.0: полное описание навороченного турбо-копировщика.

Системный софт - Pro Tracker глюки!!! несколько глючков в ProTracker'ах.

Системный софт - Pro Tracker 3.4 final презентация ремикса Pro Tracker из Самары.

Новости - Челябинск: X-Raizor вернулся на спектрум, Wocen пишет boot, Blade отдахыет, Steelzer вступил в Triumph, Crite доделал альфа версию "Мира тьмы", Bytic купил GS, Edison делает сайт, Ironman хочет купить спектрум.

Новости - Омск: полный состав и ожидаемы продукты от группы U98.

Новости - Калининград: громкая смерть или тихая жизнь Spectrum в Калининграде.

Techno-nature - Электронная музыка: Dj.Ironman рассказывает о техно (часть 1).

Techno-nature - Электронная музыка: Dj.Ironman рассказывает о техно (часть 2).

Techno-nature - Internet music-sites: куча адресов,где можно узнать нового об электронной музыке.

Techno-nature - Наркомания XX: байка от Dj.Ironman'а.

Без четверти четыре - рассказ из повседневной жизни от X-Raizor'а.

Комната смеха - Запахи вокруг и внутри: прикольный рассказ из журнала ПТЮЧ.

Комната смеха - Пердмен: убийственный рассказ из все того-же ПТЮЧ'а.

Комната смеха - Фитиль: неколько сценариев из киножурнала ФИТИЛЬ.

Комната смеха - Ореол: окончание рассказа опубликованного во втором номере.

Прокламация - реклама и обьявления о поиске друзей на спектруме.

Прокламация - реклама и обьявления о поиске друзей на спектруме.


Темы: Игры, Программное обеспечение, Пресса, Аппаратное обеспечение, Сеть, Демосцена, Люди, Программирование

Похожие статьи:
Outlet editorial - a new concept in electronic magazines for the Spectrum
Технология спрайтов - часть 4: форматы спрайтов с маской.
Реклама - Реклама и объявления ...
Анекдот - 9 анекдотов. Вопросы армянскому радио.
Z80 - несколько недокументированых "жучков" процессора Z80.

В этот день...   27 сентября