Deja Vu #05
31 мая 1998

CODING - О паковщике MS-PACK.

<b>CODING</b> - О паковщике MS-PACK.
SoundTrack: !-0 ;)-: BY SECTOR AFTER INSTY
__________________________________________


(C) Max/CYBERAX Software
Дополнение: dAn!!L
__________________________________________


                 -- -- --


   Речь пойдет о паковщике MS-PACK, а точ-
нее о DEPACKER'е,  который он присоединяет
к упакованным файлам.
   В исходном виде UNPACKER MS-PACK'а дол-
жен работать при  запрещенных прерываниях.
Также не предусмотрена возможность его от-
деления  от блока (например, в вашей прог-
рамме  много  сжатых  файлов  и нет смысла
всем из них иметь распаковщик - достаточно
одного экземпляра).
   Работа с включенными прерываниями  при-
годится, если необходимо  распаковать что-
либо,не тормозя при этом музыку или анима-
цию.В этом случае музыка вешается на IM 2,
а DEPACKER работает в основном режиме.

   Для  реализации всего  вышеописанного и
предназначены две следующие программы.

   Первая программа -на бейсике. Она пред-
назначена   для  отделения  DEPACKER'a  от
скомпрессированного блока. При запуске она
просит ввести имя файла (не более 7 букв).
Затем она записывает на диск блок без рас-
паковщика. К имени исходного файла  добав-
ляется апостроф. Длина  полученного  блока
будет меньше, чем у блока с DEPACKER'ом на
247 байт.

1  INPUT "Name: ";A$ : RANDOMIZE USR VAL
   "15619" : REM : LOAD A$ CODE
2  LET O=VAL"PEEK 23782 + 256*PEEK 23783":
   LET A=VAL "PEEK (O+233) + 256*PEEK (O+
   234)" : LET L=VAL"3 + PEEK (O+239) +
   256*PEEK(O+240)"
3  FOR J=NOT PI TO VAL "4" : POKE VAL"O +
   238 + J", PEEK VAL "A - 4 + J" : NEXT J
4  RANDOMIZE USR VAL "15619" : REM : SAVE
   A$ + "'" CODE VAL "O + 238", L


   Вторая программа - на ассемблере. Это и
есть, собственно, DEPACKER.
(Честно говоря,я так и не разобрался в ал-
горитме работы распаковщика. Я только  за-
менил в нем все операции со стеком на опе-
рации с регистром IX, а  также  постарался
уместить новый  вариант  DEPACKER'а в  256
байт.)


        ORG  40000
;+---------------------------------------+
;|*** MS-PACK UNPACKER WITH INTERRUPT ***|
;|---------------------------------------|
;|  Originally written by 'MICROSPACE',  |
;|   remixed by Max 'CYBERAX Software'   |
;+---------------------------------------+
UNPACK  LD   C,16
        LD   B,C
        LD   D,3
        EXX
        LD HL,SOURCE
;Адрес запакованного блока без UNPACKER'а.
;(Откуда распаковывать)
;Блок должен быть получен предыдущей прог-
;раммкой на бейсике.
        LD   DE,BUF
        LD   BC,5
        LDIR
        PUSH HL
        POP IX
        LD DE,DESTIN
;Адрес в памяти, куда будет производиться
;распаковка.
        LD   H,B
        EXX
        CALL POP_HL
        JR   ENTRY
FIRST   CALL POP_AF
        EXX
        LD   (DE),A
        INC  DE
        EXX
ENTRY   CALL NEWBIT
        JR   NC,FIRST
        LD   E,2
L1      XOR  A
        CALL NEWBIT
        RLA
        CALL NEWBIT
        RLA
        CP   D
        JR   C,MET1
        ADD  A,E
        LD   E,A
        CP   17
        JR   NZ,L1
        XOR  A
MET1    ADD  A,E
        CP   5
        JR   NC,MET2
        CP   2
        JR   NZ,MET3
        EXX
        LD   C,A
L3      CALL POP_AF
        LD   L,A
        LD   A,E
        SCF
        SBC  A,L
        LD   L,A
        LD   A,D
        SBC  A,H
        LD   H,A
        LDIR
        LD   H,B
        EXX
        JR   ENTRY
L2      EXX
        CALL POP_AF
        INC  A
        JR   Z,END
        INC  A
        JR   NZ,MET4
        CALL POP_BC
        JR   MET5
MET4    ADD  A,15
        JR   NC,MET6
        INC  B
        JR   MET6
MET2    JR   Z,L2
        DEC  A
MET3    EXX
MET6    LD   C,A
MET5    EXX
        CALL NEWBIT
        EXX
        JR   C,L3
        EXX
        XOR  A
        LD   E,D
L4      CALL NEWBIT
        RLA
        DEC  E
        JR   NZ,L4
        CP   2
        JR   NC,MET7
        INC  A
LOOP    EXX
        LD   H,A
        JR   L3
MET7    CALL NEWBIT
        RLA
        CP   8
        JR   NC,MET8
        DEC  A
        JR   LOOP
MET8    CALL NEWBIT
        RLA
        CP   23
        JR   NC,MET9
        SUB  9
        JR   LOOP
MET9    CALL NEWBIT
        RLA
        AND  31
        CP   31
        JR   C,LOOP
        CALL POP_AF
        JR   LOOP
END     LD   HL,BUF
        LD   C,5
        LDIR
;В случае,если вы будете использовать этот
;декомпрессор из бейсика, здесь желательно
;вставить команды  восстановления регистра
;HL' (иначе бейсик сглючит...).
        RET
NEWBIT  ADD  HL,HL
        DJNZ MET
        LD   B,C
POP_HL  LD   L,(IX)
        LD   H,(IX+1)
FIN     INC  IX
        INC  IX
MET     RET
POP_DE  LD   E,(IX)
        LD   D,(IX+1)
        JR   FIN
POP_BC  LD   C,(IX)
        LD   B,(IX+1)
        JR   FIN
POP_AF  LD   A,(IX)
        JR   FIN+2
BUF     DEFS 5
SIZE    EQU $-DEPACK



   Адреса  SOURCE и DESTIN  выбираются  не
произвольно. Вернее произвольно, но по оп-
ределенным правилам. Пусть длина исходного
блока (незапакованного) равна LEN1, а дли-
на  упакованного (без  UNPACKER'а) - LEN2.
Возможны два случая:

1) Допустим задан адрес  DESTIN, тогда ад-
рес  SOURCE  может лежать в  диапазоне  от
16384  до  DESTIN-LEN2  или в диапазоне от
DESTIN+LEN1-LEN2 до 65536-LEN2.


2) Можно зафиксировать адрес SOURCE, тогда
DESTIN  может лежать в диапазоне от  16384
до  SOURCE-LEN1+LEN2 или от SOURCE+LEN2 до
65536-LEN1.


   Это  справедливо при условии, что  LEN1
больше LEN2 (т.е., если блок хоть немного,
но сжался), в противном случае эти формулы
не годятся. Более того,если от такого бло-
ка не отделять  распаковщик, то  последний
вообще не  сможет  распаковать  этот  блок
корректно (например, сбросится).

  В заключении еще несколько слов.

   Переделанный таким образом UNPACKER ра-
ботает несколько медленнее оригинала  (это
еще без учета времени, занимаемого  проце-
дурой обработки IM 2). Если  нужна  макси-
мальная скорость, можно поступить  следую-
щим  образом: запускать  оригинальный  UN-
PACKER при разрешенных прерываниях...

   Для этого необходимо отделить процедуру
распаковки от блока и переделать ее начало
аналогично моему варианту.
   При вызове нужно скорректировать  пара-
метры SOURCE и DESTIN так,чтобы расстояние
между этими блоками увеличилось на столько
байт, сколько  заносит на стек  обработчик
IM 2 (или больше).
   Немного  поясню. Оригинальный  DEPACKER
при запуске ставит стек на запаченный блок
и начинает его распаковывать в адрес  DES-
TIN, при  этом  распакованный блок  растет
вверх, а  запакованный  'убегает' от него,
уменьшаясь  в  длине. Байты  запакованного
блока снимаются командами POP. Самое инте-
ресное, что конец распакованного блока ни-
когда не 'догонит' начало  распаковывающе-
гося, т.к. между  ними  оставлен зазор в 5
байт. Если мы  искусственно  увеличим этот
зазор (изменив SOURCE или DESTIN), то смо-
жем сохранять здесь регистры и адреса воз-
вратов при обработке IM 2.
   Также  отмечу, что  второй  способ я не
проверял, а вот первый успешно  работает в
одной из моих программ.

                  * * *


   В дополнение от редакции или как сдела-
но в DEJA VU.


   Чтобы недолго мучаться  и  не  задавать
вручную адреса и если вам не надо работать
с разрешенными  прерываниями, то выполняем
следующие манипуляции:

1) Пакуем MS-PACK'ом кодовый файл и  круто
тащимся от  коэффициента  компрессии (если
файлов  несколько, то, конечно, пакуем  их
все).

2) Запускаем следующую программку на
   Basic'е:

   10 CLEAR 25000
   20 INPUT "MS:";N$
   22 IF N$="" THEN GO SUB 100:GO TO 20
   25 RANDOMIZE USR 15619:REM:LOAD N$ CODE
   26 IF PEEK 23823 <> 0 THEN GO TO 20
   28 LET LEN=PEEK 23784+256*PEEK 23785
   30 LET AD=PEEK 23782+256*PEEK 23783:
      LET AD2=AD+36:LET AD3=AD+231
   40 POKE AD3,PEEK AD2: POKE AD3+1,
      PEEK (AD2+1)
   50 INPUT "NEW:";M$
   60 IF M$="" THEN GO SUB 100:GO TO 50
   70 RANDOMIZE USR 15619:REM:SAVE M$ CODE
      AD3,LEN-231
   80 GO TO 20
   100 RANDOMIZE USR 15619:REM:CAT
   110 RETURN


   3) Вводим  имя  запкованного MS-PACK'ом
файла (строка  20), если такого файла нет,
то  ничего не произойдет, в противном слу-
чае  запросится  имя  нового  файла; после
ввода  имени запишется новый файл с адреса
СТАРЫЙ АДРЕС+231, длиной СТАРАЯ ДЛИНА-231,
т.е. на 231 байт короче!

   4) Создаем  универсальный  депакер, ас-
семблируя  в  любимом ассемблере следующий
листинг:

        ORG #5B00


LL5B00  LDDR          ;либо LDIR см. ниже
        LD      H,B
        POP     DE
        EXX
        POP     HL
        JR      LL5B0E
LL5B08  DEC     SP
        POP     AF
        EXX
        LD      (DE),A
        INC     DE
        EXX
LL5B0E  ADD     HL,HL
        DJNZ    LL5B13
        POP     HL
        LD      B,C
LL5B13  JR      NC,LL5B08
        LD      E,#02
LL5B17  XOR     A
        ADD     HL,HL
        DJNZ    LL5B1D
        POP     HL
        LD      B,C
LL5B1D  RLA
        ADD     HL,HL
        DJNZ    LL5B23
        POP     HL
        LD      B,C
LL5B23  RLA
        CP      D
        JR      C,LL5B2E
        ADD     A,E
        LD      E,A
        CP      #11
        JR      NZ,LL5B17
        XOR     A
LL5B2E  ADD     A,E
        CP      #05
        JR      NC,LL5B5C
        CP      #02
        JR      NZ,LL5B5F
        EXX
        LD      C,A
LL5B39  DEC     SP
        POP     AF
        LD      L,A
        LD      A,E
        SCF
        SBC     A,L
        LD      L,A
        LD      A,D
        SBC     A,H
        LD      H,A
        LDIR
        LD      H,B
        EXX
        JR      LL5B0E
LL5B49  EXX
        DEC     SP
        POP     AF
        INC     A
        JR      Z,LL5BAA
        INC     A
        JR      NZ,LL5B55
        POP     BC
        JR      LL5B61
LL5B55  ADD     A,#0F
        JR      NC,LL5B60
        INC     B
        JR      LL5B60
LL5B5C  JR      Z,LL5B49
        DEC     A
LL5B5F  EXX
LL5B60  LD      C,A
LL5B61  EXX
        ADD     HL,HL
        DJNZ    LL5B67
        POP     HL
        LD      B,C
LL5B67  EXX
        JR      C,LL5B39
        EXX
        XOR     A
        LD      E,D
LL5B6D  ADD     HL,HL
        DJNZ    LL5B72
        POP     HL
        LD      B,C
LL5B72  RLA
        DEC     E
        JR      NZ,LL5B6D
        CP      #02
        JR      NC,LL5B7F
        INC     A
LL5B7B  EXX
        LD      H,A
        JR      LL5B39
LL5B7F  ADD     HL,HL
        DJNZ    LL5B84
        POP     HL
        LD      B,C
LL5B84  RLA
        CP      #08
        JR      NC,LL5B8C
        DEC     A
        JR      LL5B7B
LL5B8C  ADD     HL,HL
        DJNZ    LL5B91
        POP     HL
        LD      B,C
LL5B91  RLA
        CP      #17
        JR      NC,LL5B9A
        SUB     #09
        JR      LL5B7B
LL5B9A  ADD     HL,HL
        DJNZ    LL5B9F
        POP     HL
        LD      B,C
LL5B9F  RLA
        AND     #1F
        CP      #1F
        JR      C,LL5B7B
        DEC     SP
        POP     AF
        JR      LL5B7B
LL5BAA  LD      HL,LL5BBC
        LD      C,#05
        LDIR
        LD      HL,#0000
LL5BB2  EQU     $-#02
        EXX
        LD      SP,#0000
LL5BB6  EQU     $-#02
        EI                ; либо DI
        RET               ;
        NOP               ; либо JP #nnnn        NOP               ;/
LL5BBC  NOP
        NOP
        NOP
        NOP
LL5BC0  NOP


;запуск депакера на входе hl=адрес файла
;без депакера
DEPACK  DI
        LD      (LL5BB6),SP
        EXX
        LD      (LL5BB2),HL
        LD      C,#10
        LD      B,C
        LD      D,#03
        EXX
        LD      SP,HL
        POP     HL
        LD      (LL5BE2),HL
        POP     HL
        LD      DE,LL5BC0
        LD      BC,#0005
        LDDR
        POP     HL
        POP     DE
        POP     BC
        LD      SP,#0000
LL5BE2  EQU     $-#02
        JP      LL5B00


   Комментарии: универсальный  распаковщик
занимает меньше 256 байт! Традиционно рас-
полагается  в  буфере  принтера  с  адреса
#5B00. (в  этом случае адрес запуска будет
равен #5BC1=метка DEPACK). На входе в пару
HL  необходимо  задать  адрес загруженного
блока кодов  без депакера (то, что получи-
лось в пункте 3). Чтобы избежать проблем с
наложением распаковывающихся данных на еще
не распакованные, советую грузить файл  по
адресу, заданному  в  каталоге! Распаковка
будет происходить в тот адрес, который был
задан в MS-PACK'е.

   Например, имеем запакованный MS-PACK'ом
файл:

         "FILE" CODE 49152,10000;


   Обработав  его  BASIC'ом (пункты 2 и 3)
получим новый файл без депакера:

         "FILE+" CODE 49383,9769;


   Чтобы распаковать данный файл, помещаем
распаковщик по адресу #5B00 и распаковыва-
ем следующим образом:

        LD HL,49383
        JP #5BC1   ;метка DEPACK

   Файл  распакуется  по  адресу заданному
при упаковке в MS-PACK'е (например #C000).


   И, наконец, маленький нюанс - если  при
упаковке  файл  получился больше исходного
(а такое может быть,если мы пакуем малень-
кий  файл  или  уже  запаченный файл - это
видно  по коэффициенту компрессии заданно-
му  в  процентах), то  необходимо изменить
депакер, по адресу #5B00 поместить не LDDR
а  LDIR!  Таким  образом имеет смысл пако-
вать и маленькие файлы (2 сектора).

   В итоге, если ориентироваться по  коли-
честву секторов то в 90%  случаев  удается
сэкономить один сектор в файле!

   Если использовать метод, который приво-
дит  MAX, то  в  96% случаев экономим один
сектор! А самое главное - есть возможность
выбора!
   MS-PACK  хорошо  пакует небольшие текс-
товые  файлы. Если  вы пакуете большие ко-
довые  блоки, то  используйте   HRUST 1.0,
наверняка  он покажет лучший результат, да
и  возможность  сохранения  файла без упа-
ковщика предусмотрена автором.

   Дальше передаю слово MAX'у.

------------------------------------------
******************************************
------------------------------------------


     Загрузка и запуск бейсик-файлов.



   Думаю все знают, как в  boot'ах  обычно
запускаются программы. Имя файла  кидается
в строку бейсика (вместо пробелов в коман-
де RUN "        " ), затем  эта строка за-
пускается.
   В данной статье я  расскажу, как  можно
загрузить и запустить бейсик-программу без
использования подобного рода фокусов.
   Программа в листинге написана с  актив-
ным использованием фрагментов ПЗУ  TR-DOS,
поэтому не удивляйтесь ее корявому виду.

   Пусть есть конкретный файл,который нуж-
но запустить. Также допустим, что мы  зна-
ем заголовок  этого  файла  (16 байт). Для
загрузки будем использовать некий драйвер,
умеющий читать 'B' секторов в адрес 'HL' с
дорожки и сектора 'DE' (метка LOAD). Опос-
ля загрузки, драйвер  должен заносить пос-
ледний трек и сектор в переменную #5CF4.
   CLEAR желательно иметь установленным на
65367.
   Первым делом перекинем заголовок  в ад-
рес HEADER, равный 23773. Номер файла  же-
лательно занести в #5D1E. Затем  запускаем
следующую прогу:


BAS_RUN LD    DE,(23635);начало бейс. пр.
        LD    HL,(23641);обл. ред. строки
        DEC   HL
        PUSH  HL
        PUSH  DE
        AND   A
        SBC   HL,DE
;в HL получили длину старой  беисик-проги,
;т.е той, что находится (или не находится)
;в памяти до загрузки.
        LD    DE,(HEADER+9)
;в DE взяли из заголовка длину нового бей-
;сика, т.е. того, который нужно грузить.
        PUSH  DE
        PUSH  HL
        LD    HL,5
        ADD   HL,DE
;длину новой проги увеличили на 5 байт.
        LD    (23771),HL
;засунули в переменную, как в TR-DOS.
        POP   HL
        POP   BC
        POP   DE
        POP   HL
        PUSH  BC
        CALL  #19E5
;удаляем старый бейсик, сдвигая память.
        POP   BC
        CALL  #1655
;резервируем место для нового.
        INC   HL
        LD    BC,(HEADER+11)
;взяли из заголовка длину нового бейсика
;без программных переменных.
        ADD   HL,BC
;прибавили адрес начала.
        LD    (23627),HL
;установили системную переменную VARS.
        LD    HL,(23635)
;HL - куда будем грузить.
        LD    A,(23772)
;старший байт длины.
        LD    B,A
        LD    DE,(HEADER+14)
;DE - трек и сектор.
        LD    (#5CF4),DE
        DEC   B
        INC   B
        CALL  NZ,LOAD
;если есть что грузить - грузим.
        LD    A,(23771)
        AND   A
        JR    Z,NOLOW
;равен ли нулю младший байт длины?
        PUSH  HL
        LD    DE,(#5CF4)
        LD    HL,BUF
        LD    B,1
        CALL  LOAD
;грузанули последний сектор в буфер.
        POP   DE
        LD    BC,(23771)
        LD    B,0
        LD    HL,BUF
        LDIR
;остаток перебросили куда надо.
NOLOW   LD    HL,(23641)
        DEC   HL
        LD    (HL),128
;занесли на всякий случай маркер конца.
        INC   HL
        INC   HL
        LD    E,(HL)
        INC   HL
        LD    D,(HL)
;взяли строку автостарта
        LD    (23618),DE
;и занесли ее в соотв. переменную.
        XOR   A
        LD    (23620),A
;занулили номер оператора в строке.
        LD    (23824),A
        CALL  #16B0
;точно не помню что такое, кажется очистка
;стека калькулятора.
        LD    HL,(23635)
        DEC   HL
        LD    (23639),HL
;сделали RESTORE.
        LD    HL,(23613)
        LD    (23827),HL
        EXX
        LD    HL,10072
        EXX
        LD    IY,#5C3A
        LD    (IY),255
        SET   7,(IY+1)
        RES   5,(IY+1)
;прочие установки.
        JP    7037;запуск...
BUF     DEFS  256;буфер загрузки.

   Располагать сию программу лучше  в  эк-
ранной области. Неплохо бы почистить скрин
перед передачей управления в  ПЗУ, как это
делает TR-DOS.
   Например, вместо JP 7037:


        LD    HL,7037
        PUSH  HL
        JP 3435


   В заключении  хочу  выразить  благодар-
ность Федину П.Ю. за книгу "Полное  описа-
ние и  полный  дизассемблер  TR-SOS  5.04T
(5.03)".



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

Аперативчик - О новой оболочке журнала.

Аперативчик - Вступление и авторы.

Тема - DIGITAL звук, как он есть (проигрыватель .wav файлов).

Тема - Проект спасения и развития сцены.

Тема - Устав ассоциации AMAZING SOFT MAKING.

Тема - Теория журналостроения.

Капля припоя - GENERAL SOUND: PLUG & PLAY.

Капля припоя - Профессиональная обработка звука на PC.

SOFTWARE - О новинках из Самары: MAX SOFT SCREEN PACKER v1.4 , МИНЕР, FILE COMMANDER v4.04, SLIDE SHOW,WALKER demo,S-LIGHT BBS, S-TERMINAL v1.0, LOGO.SYS (для PC).

SOFTWARE - Описание проходилка игры "Операция Р.Р."

SOFTWARE - Новинки демосцены: HAPPY NEW 1998 YEAR, BURDENSOME, DREAM, CONDEMED, CONFUSION.

CODING - Процедуры: FULL SCREEN SCROLL UP, Сломанный телевизор.

CODING - Использование стека при разрешенных прерываниях.

CODING - О паковщике MS-PACK.

CODING - Кодить хочу - процедуры вывода спрайтов без атрибутов, быстрая и универсальная процедура вывода спрайтов, процедура умножения и вычисления квадратного корня.

ANOTHER WORLD - Мультимедия - синтез трех стихий.

ANOTHER WORLD - AMIGA vs PC.

Доска почета - Интервью с PROGRESS.

Доска почета - О группе ETERNITY INDUSTRY.

Доска почета - О международном фестивале ART COMP-98.

Доска почета - Опpеделения принятые на демосцене и спектруме.

Доска почета - использование мышки в журналах и другом софте (о криворуких кодерах).

Доска почета - о способе конверсии триколорных картинок для спектрума.

Доска почета - такой ли рулез Amiga? Пц для пцшников, а спектрум для спектрумистов?

Семь и 1/2 - Армейские маразмы.

Семь и 1/2 - Программирование снизу вверх на искосок.

Семь и 1/2 - Инструкция по технике безопасного секса.

Семь и 1/2 - Особенности национального рулеза.

Семь и 1/2 - отчет с тусовки Кемеровских спектрумистов и сохдателей журнала Deja vu.

Проба пера - Приключения Винни Пуха часть 2.

Проба пера - Фэнтази и фантастика.

Реклама - Реклама и объявления ...

Новости - новый журнал AMIGA RULES.


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

Похожие статьи:
Лучшие солюшены SOSG - The Trap Door.
Анекдоты - юмор.
Part 5 - Emulate quiz.

В этот день...   17 октября