Код:
; Pro Turbo Cruncher v2.1
; Decompressor
; HL - Адрес начала упакованного фрагмента
OPUL: ; DE - Адрес для распаковки
LD A,(HL) ; A' = (HL) ; Взять первый байт из потока
EX AF,AF' ;
LD B,0 ; B = 0
LD IX,DECO ; IX = DECO ; Константа для быстрого перехода
CALL DECO-1 ; ==> DECO-1 ; В цикл депакера
EX AF,AF' ;
LD (DE),A ; (DE) = A' ; Сохранить последний байт
RET ; Выход
;--------------------------
M5:
RLCA ; C<-A-< ; Сдвинуть A влево, получить бит из потока
JR C,M6 ; Если C = 1, то --> М6 ;
; Метод: LZ, смещение 0..8192, длина 0..255
LD A,(HL) ; A = (HL) ; Получить тот же байт из потока
AND #1F ; A = A and $1F ;
LD B,A ; B = A ; B = 0..31 (старший байт смещения)
INC HL ; HL = HL + 1 ; Перейти к следующему байту
LD C,(HL) ; C = (HL) ; Взять байт из потока (C - длина 0..255)
JR IYP ; --> IYP ; --> Копирование со смещением
M6:
; Метод: LZ, смещение 2048..3071, длина 3..10
AND #C0 ; A = A and 0xC0 ; Оставить старшие 2 бита
XOR 2 ; A = A + 2 ; Бит 1 равен 1
JR M7 ; --> M7 ; --> Подготовка копирования со смещением
LZMET:
RLCA ; C<-A-< ; Сдвинуть A влево, получить бит из потока
JR C,M5 ; Если C = 1, то --> М5 ;
; Медод: LZ, смещение 0..2047, длина 3..10
AND #E0 ; A = A and 0xE0 ; Оставить в A старшие 3 бита
RLCA ; C<-A-< ; Сдвинуть A влево, получить бит из потока
M7: RLCA ; C<-A-< ; Сдвинуть A влево, получить бит из потока
RLCA ; C<-A-< ; Сдвинуть A влево, получить бит из потока
LD B,A ; B = A ; B - старший байт смещения (2 или 3 бита)
LD A,(HL) ; А = (HL) ; Получить тот же байт из потока
AND 7 ; A = A and 7 ; Оставить в A младшие 3 бита
ADD A,3 ; A = A + 3 ;
LD C,A ; C = A ; C - 3..10 (длина копируемого фрагмента)
IYP:
INC HL ; HL = HL + 1 ; Перейти к следующему байту
PUSH HL ; Сохранить HL
LD A,E ; A = E ; HL = DE - B.m(HL)
SUB (HL) ; A = A - (HL) ;
LD L,A ; L = A ;
LD A,D ; A = D ;
SBC A,B ; A = A - B - c ;
LD H,A ; H = A ;
LD B,0 ; B = 0 ;
DACO: LDIR ; (HL)->(DE), len BC ; Копирование фрагмента из (HL) в (DE)
POP HL ; Восстановить HL ;
; ; --> Вход
INC HL ; HL = HL + 1 ; Перейти к следующему байту
; Начало главного цикла
DECO: LD A,(HL) ; A = (HL) ; Взять байт из потока
RLCA ; C<-А-< ; Сдвинуть A влево, получить бит из потока
JR C,LZMET ; Если C = 1, то --> LZNET
RLCA ; C<-A-< ; Сдвинуть A влево на 2 бита, получить
RLCA ; C<-A-< ; два младших бита
AND 3 ; A = A and 3 ;
JR NZ,M1 ; Если A <> 0, то --> M1 ; Если A <> 0, то --> M1
; Метод: копирование блока длиной 1..32
LD C,(HL) ; C = (HL) ; Взять тот же байт из потока (длина фрагмента)
INC C ; C = C + 1 ; Коррекция длины 1..32
INC HL ; HL = HL + 1 ; Перейти к следующему байту
LDIR ; (HL)->(DE), len BC ; Скопировать C байт из (HL) в (DE)
JP (IX) ; --> DECO ; в цикл --> DECO
M1:
DEC A ; A = A - 1 ; A - 0..2
JR NZ,M2 ; Если A <> 0, то --> M2 ; Если A <> 0, то --> M2
XOR (HL) ; A = (HL) ; Взять тот же байть из потока
AND #1F ; A = A and 0x1F ; Сбросить в A бит 5
RET Z ; Если A = 0, то выход --> ; Если A = 0, то конец распаковки -->
; Метод: ниббловое копирование длиной 1..31
LD B,A ; B = A ; B - счетчик (1..31)
INC HL ; HL = HL + 1 ; Перейти к следующему байту
LD C,(HL) ; C = (HL) ; Взять байт из потока (C - базовая константа)
INC HL ; HL = HL + 1 ; Перейти к следующему байту
ML:
XOR A ; A = 0
RLD ; A <- (HL) <- 0 (нибблы) ; Получить ниббл из потока
ADD A,C ; A = A + C ; Сложить байт с базовой константой
LD (DE),A ; (DE) = A ; Записать байт
INC DE ; DE = DE + 1 ; Перейти к следующему байту
XOR A ; A = 0
RLD ; A <- (HL) <- 0 (нибблы) ; Получить ниббл из потока
ADD A,C ; A = A + C ; Сложить байт с базовой константой
LD (DE),A ; (DE) = A ; Записать байт
INC DE ; DE = DE + 1 ; Перейти к следующему байту
INC HL ; HL = HL + 1 ; Перейти к следующему байту
DJNZ ML ; Цикл на B итераций --> ML ;
JP (IX) ; --> DECO ; в цикл --> DECO
M2:
DEC A ; A = A - 2 ; A - 0..1
LD A,(HL) ; A = (HL) ; Взять байт из потока
JR Z,M4 ; Если A^ = 0, то --> M4 ; Если А^ = 0, то --> M3
AND #1F ; A = A and 0x1F ;
LD C,A ; C = A
INC C ; C = C + 1 ; C в диапазоне 1..32
M3: INC HL ; HL = HL + 1 ; Перейти к следующему байту
PUSH HL ; Сохранить HL
LD A,(HL) ; A = (HL) ; Взять байт из потока
LD H,D ; H = D
LD L,E ; L = E ; HL = адрес приемника
INC DE ; DE = DE + 1 ; DE = адрес приемника + 1
LD (HL),A ; (HL) = A ; Записать байт для заливки в (HL)
JR DACO ; --> DACO ; Заливка фрагмента
M4:
AND #1F ; A = A and #1F
LD B,A ; ; B в диапазоне 0..31 (B - старший байт длины)
INC HL ; HL = HL + 1 ; Перейти к следующему байту
LD C,(HL) ; C = (HL) ; Взять байт из потка (C - младший байт длины)
JR M3 ; --> M3 ; --> Заливка фрагмента