ldirinpages;Z6542
;hl=откуда (логический адрес в буфере сохранения)
;bc=сколько
;TODO ускорить
LD A,C
OR B
RET Z ;TODO надо ли?
;DI
;CALL 8020
;JP C,_Z6545
; LD A,4
; CALL ON_BANK
; JP START_1
Z6546=$+1 ;сколько байт сохранить (это же текущий адрес в буфере, т.е. куда копировать)
LD DE,0
if depkbuf
push bc
ld bc,depkbuf
add hl,bc
ex de,hl
add hl,bc
ex de,hl
pop bc
ldirinpages0
ld a,(hl)
CALL CRC32_
ldi
jp pe,ldirinpages0
ld hl,-depkbuf
add hl,de
ld (Z6546),hl
ret
;bit 7,h
;ret z
;jp saveblock ;save whole buffer
else
PUSH HL,DE
LD A,D
LD (SAVED+1),A
LD A,H
LD (SAVEH+1),A
if depkbuf
add a,depkbuf/256
LD H,A
else
RLCA
RLCA
AND 3
LD (BANKH+1),A
CALL ON_BANK
LD A,H
OR #C0
LD H,A
endif
LD (ADRH+1),HL
LD A,(HL)
EXA
LD A,D
if depkbuf
add a,depkbuf/256
LD D,A
else
RLCA
RLCA
AND 3
LD (BANKD+1),A
CALL ON_BANK
LD A,D
OR #C0
LD D,A
endif
LD (ADRD+1),DE
EXA
LD (DE),A
CALL CRC32_
POP DE,HL
INC DE
LD A,D
INC A
JR Z,SV1
WOZW1 CPI
JP PO,AFN5
ADRH LD HL,0
ADRD LD DE,0
AFN2 INC L
JR Z,SAVEH
AFN1 INC E
JR Z,SAVED
AFN3 LD A,B
OR C
JR Z,AFN4
if depkbuf==0
BANKH LD A,0
CALL ON_BANK
endif
LD A,(HL)
if depkbuf==0
EXA
BANKD LD A,0
CALL ON_BANK
EXA
endif
LD (DE),A
CALL CRC32_
DEC BC
JP AFN2
SAVEH LD A,0
INC A,A
JR Z,$+3
DEC A
LD H,A
LD (SAVEH+1),A
if depkbuf==0
RLCA
RLCA
AND 3
LD (BANKH+1),A
LD A,H
OR #C0
LD H,A
endif
JR AFN1
SAVED LD A,0
INC A
LD D,A
if buf64k
INC A
else
cp 0x80
endif
JR Z,SV2 ;save whole buffer
WOZWR2 LD A,D
LD (SAVED+1),A
if depkbuf==0
RLCA
RLCA
AND 3
LD (BANKD+1),A
LD A,D
OR #C0
LD D,A
endif
LD (ADRD+2),A
JR AFN3
AFN4 LD A,(SAVED+1)
LD D,A
AFN5 LD (Z6546),DE ;сколько байт сохранить
ret
;LD A,4
;CALL ON_BANK
;CALL COUNT ;процентомер?
;LD A,5
;JP ON_BANK
SV1 CALL SV0
LD A,D
DEC A
LD (SAVED+1),A
if depkbuf==0
RLCA
RLCA
AND 3
LD (BANKD+1),A
LD A,D
OR #C0
LD D,A
endif
LD (ADRD+2),A
LD E,-1 ;на случай выхода в AFN5
JP WOZW1
SV2 CALL SV0
JR WOZWR2
SV0 LD (Z6546),DE ;сколько байт сохранить
;LD A,5
;CALL ON_BANK
CALL saveblock ;save whole buffer
LD DE,(Z6546) ;сколько байт сохранить (=0?)
RET
endif
;запись одного байта в память + обновление CRC32 + при необходимости сохранение
SBYTE
;a=byte
PUSH HL
LD HL,(Z6546) ;сколько байт сохранить (он же текущий адрес, куда писать)
PUSH HL
if depkbuf
exa
ld a,h
add a,depkbuf/256
ld h,a
exa
else
EXA
LD A,H
RLCA
RLCA
AND 3
CALL ON_BANK
LD A,H
OR #C0
LD H,A
EXA
endif
LD (HL),A
CALL CRC32_
POP HL
INC HL
;LD A,H
;AND A
;JR NZ,CON2
;LD A,L
;CP #11
;CALL Z,HOBETA1
;CON2
LD (Z6546),HL ;сколько байт сохранить
;LD A,5
;CALL ON_BANK
LD A,H
if buf64k
INC A
else
cp 0x80
endif
POP HL
RET NZ
jp saveblock
;ИНИЦИАЛИЗАЦИЯ ДЕПAKEPA
initdepk=initCRC;Z6629
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;метод store
ZD102
LD A,B
CP 8
CALL NZ,read_a_bits
EX DE,HL ;??? (hl=0x802b) длина блока
CALL readbyte_d
LD E,D
CALL readbyte_d ;??? (de=0x7fd4)
LD A,D
XOR H
LD D,A
LD A,E
XOR L
AND D
INC A
call NZ,depkqerror ;save whole buffer и выйти
;CALL readbyte_d
EX DE,HL
;ZD11F=$+1
;LD HL,0
;DEC HL
_ZD122
;LD A,(HL)
;INC HL
;push hl
;LD HL,(Z6546)
;bit 7,h
;jr nz,$
;pop hl
ziprdbyte
CALL SBYTE ;запись одного байта в память + обновление CRC32 + при необходимости сохранение
;PUSH HL
;LD BC,#4001
;ADD HL,BC
;POP HL
;JR NC,ZD135
;CALL LBLOKZIP
;LD HL,BUFER
;ZD135
DEC DE
LD A,D
OR E
JR NZ,_ZD122
;LD (ZD11F),HL
POP DE ;снимаем адрес возврата
JR _ZD14D ;читаем следующий блок
;ZD140
INFLATING
;init read buffer, inflate file
XOR A
LD (_ZD159),A ;не последний блок
;CALL LBLOKZIP
;LD HL,0
; LD (U6546),HL ;сколько байт сохранить = текущий адрес в буфере
_ZD14D
;LD HL,(ZD11F)
;LD E,(HL)
;INC HL
;LD (ZD11F),HL
ziprdbyte
ld e,a
CALL readbyte_d ;установит b=8
_ZD158 ;сюда попадаем по коду 256 (end of block)
;push hl
;ld hl,(Z6546)
;jr $
;pop hl
_ZD159=$+1
LD A,0 ;1 = был последний блок
OR A
jp NZ,savelastblock ;save (U6546) bytes, выход
CALL readbit_de ;1 = last block, 0 = not last block
LD HL,_ZD159 ;см. выше
RR (HL)
CALL readtrees;ZD2E4
_ZD168
;push de
;push hl
;LD HL,(Z6546)
;bit 7,h
;jr nz,$ ;почему-то не попадаем сюда
;ld hl,(Z6546)
;ld de,0x53c7;0x546f
;or a
;sbc hl,de
;jr nc,$
;pop hl
;pop de
CALL readcodetree1 ;out: hl=code
;jr $
LD A,H
OR A
JR NZ,_ZD175 ;если код - не байт
LD A,L ;байт
CALL SBYTE ;запись одного байта в память + обновление CRC32 + при необходимости сохранение
JR _ZD168
_ZD175 DEC A
OR L
;256: end of block - stop processing if last block, otherwise start processing next block.
;257-285: combined with extra-bits, a match length of 3-258 bytes.
;286, 287: not used, reserved and illegal but still part of the tree.
;jr z,$ ;не доходим сюда на adv 1,2, а в adv3 его нет в первом блоке
;push hl
;LD HL,(Z6546)
;pop hl
JR Z,_ZD158 ;если 256 (end of block), то назад на чтение заголовка блока и деревьев
;jr $
DEC H
INC HL,HL
PUSH HL ;2+(код-256) = сколько
CALL readcodetree2 ;distance
INC HL
POP AF
PUSH BC,DE,AF
POP BC ;2+(код-256) = сколько
EX DE,HL ;de=код по tree2 (расстояние?)
LD HL,(U6546) ;сколько байт сохранить = текущий адрес в буфере
OR A
SBC HL,DE
JR NC,_ZD1B5 ;расстояние умещается внутри несохранённого блока?
EX DE,HL ;de = -сколько байт не хватает?
LD HL,0
OR A
SBC HL,DE ;сколько байт не хватает?
PUSH HL
LD HL,#2121
TD198=$-2 ;сколько байт сохраняли в прошлый раз
ADD HL,DE ;hl = сколько байт сохраняли - сколько байт не хватает? (получается адрес в прошлом буфере?)
POP DE
EX DE,HL ;de=адрес в прошлом буфере?, hl=сколько байт не хватает?
PUSH HL ;сколько байт не хватает?
CP A
SBC HL,BC ;NC=блок не пересекает границу старого и нового буферов (сколько байт не хватает >= сколько)
POP HL ;сколько байт не хватает?
EX DE,HL
JR NC,_ZD1B5 ;если блок не пересекает границу старого и нового буферов, то откуда = адрес в прошлом буфере?
EX DE,HL
PUSH BC
EX (SP),HL
POP BC ;hl=сколько, bc=сколько байт не хватает?
AND A
SBC HL,BC
PUSH HL ;сколько-сколько байт не хватает
EX DE,HL ;hl=адрес в прошлом буфере, bc=сколько байт не хватает?
CALL ldirinpages ;скопировали первый кусок в текущий адрес в буфере ;TODO разрезать на 2 части при пересечении 32К
LD HL,0 ;продолжение будем копировать из начала нового буфера
POP BC ;длина продолжения (сколько-сколько байт не хватает)
;TODO сделать настоящее скользящее окно 32К, т.к. Relative back-references can be made across any number of blocks, as long as the distance appears within the last 32 KiB of uncompressed data decoded (termed the sliding window)
_ZD1B5
;hl = откуда (логический адрес в буфере)
;bc = сколько
CALL ldirinpages ;копируем в текущий адрес в буфере ;TODO разрезать на 2 части при пересечении 32К
LD A,(Z6546+1) ;(Z6546) = сколько байт сохранить = текущий адрес в буфере
if buf64k
CP -1
else
CP 0x80
endif
CALL NC,saveblock ;save whole buffer ;буфер на [64K]32K, надо сохранить и создать новый буфер ;TODO зациклить окно
POP DE
POP BC
JR _ZD168 ;читаем следующий код
;?
;DS 10
;какие-то стандартные длины кодов
;256: end of block - stop processing if last block, otherwise start processing next block.
;257-285: combined with extra-bits, a match length of 3-258 bytes.
;286, 287: not used, reserved and illegal but still part of the tree.
;TODO почему тут всего 19 стандартных длин, а не 28?
TD1EE db #10,#11
db #12,0
db 8,7
db 9,6
db #A,5
db #B,4
db #C,3
db #D,2
db #E,1
db #F ;,1 ;#F заходил на следующий сегмент, а 1 был частью TD201 ;читается максимум 19 байт, т.е. до #F включительно (в gunzip нет 1)
align 256
db 0 ;чтобы на 1 байт позже
TD201 DB 1,3,7,#F,#1F,#3F,#7F,-1 ;маски
;?
TD209 DS 34;70 ;туда пишется 32 байта (2-байтные счётчики, сколько раз встретилась каждая длина кода 0..15)
TD22B ds 70-34 ;с #xx2d лежат 2-байтные начальные коды для каждой длины кода (1..15)
get_a_bits_tohl;ZD24F
CP 9
JR C,_ZD262
SUB 8
LD H,A
LD A,8
CALL get_a_bits
LD L,A
LD A,H
CALL get_a_bits
LD H,A
RET
_ZD262 CALL get_a_bits
LD H,0
LD L,A
RET
get_a_bits;ZD269
;a=число бит, b=число бит d в наличии, de=данные в наличии
;out: a=число из e (младшие биты по маске количества бит)
LD (_ZD26E),A
EXA
_ZD26E=$+1
LD A,(TD201) ;a=маска 0x01,0x03,0x07...0xff (для 1,2,3...8)
AND E
PUSH AF
EXA
CALL read_a_bits
POP AF
RET
readbit_de;ZD278
;"читать бит" (текущие биты в de, b=число верных битов d)
;out: CY=вылетевший младший бит de
SRL D
RR E
DEC B
RET NZ
readbyte_d;ZD27E
;читать байт в d, установить b=8
;TODO макрос и без push af
PUSH AF
;push HL
;push BC
;LD HL,(ZD11F)
;LD BC,#4001
;ADD HL,BC
;POP BC
;CALL C,LBLOKZIP
;LD HL,(ZD11F)
;LD D,(HL)
;INC HL
;LD (ZD11F),HL
ziprdbyte
ld d,a
LD B,8
;POP HL
pop AF
RET
;a=число бит (бывает 8)
;b=число бит d в наличии
;de=имеющиеся данные (e - самые старые)
read_a_bits;ZD299
CP B ;сколько бит в d
JR C,_ZD2A6 ;в d достаточно бит
_ZD29C SRL D
RR E
DEC A
DJNZ _ZD29C
CALL readbyte_d
;теперь в d имеется 8 бит, b=8, a уменьшено на сколько имелось бит
_ZD2A6 OR A
RET Z ;выходим, когда прочитали нужное количество бит
SRL D
RR E
DEC A
DJNZ _ZD2A6
;сюда можно попасть только при a >= 8+сколько имелось бит
;строим деревья по умолчанию (коды 0..127 по 8 бит, 128..255 по 9 бит и т.д.)
;b=0
;a=сколько бит не хватило (может быть 0)
_ZD2AF PUSH BC,DE
LD HL,ziptrees ;длины кодов первого дерева?
LD BC,#9008
_ZD2B7 LD (HL),C
INC HL
DJNZ _ZD2B7
LD BC,#7009 ;...продолжение
_ZD2BE LD (HL),C
INC HL
DJNZ _ZD2BE
LD BC,#1807
_ZD2C5 LD (HL),C
INC HL
DJNZ _ZD2C5
LD BC,#808
_ZD2CC LD (HL),C
INC HL
DJNZ _ZD2CC
LD HL,ziptrees+#140 ;длины кодов второго дерева?
LD BC,#2005
LD A,B ;32
_ZD2D7 LD (HL),C
INC HL
DJNZ _ZD2D7
LD (ZD3C8),A ;число кодов второго дерева?
LD (ZD3B8),A ;число кодов первого дерева (-256)?
JP gentrees;ZD3B7 ;построить 2 дерева?
readtrees;ZD2E4
LD A,2
CALL get_a_bits ;читаем метод
DEC A
JP M,ZD102 ;00 = stored/raw/literal section, between 0 and 65,535 bytes in length
JR Z,_ZD2AF ;01 = static Huffman compressed block, using a pre-agreed Huffman tree
DEC A
call NZ,depkqerror ;11 = ошибка, save whole buffer и выйти
;10 = compressed block complete with the Huffman table supplied
LD A,5
CALL get_a_bits
INC A
LD (ZD3B8),A ;число кодов первого дерева (-256)
LD A,5
CALL get_a_bits
INC A
LD (ZD3C8),A ;число кодов второго дерева
LD HL,ziptrees+#560 ;почему сюда кладутся длины кодов??? TODO
LD A,#13
_ZD30A LD (HL),0
INC HL
DEC A
JR NZ,_ZD30A
LD A,4
CALL get_a_bits
ADD A,4 ;4..19 кодов
LD C,A
LD HL,TD1EE
_ZD31B LD A,3
CALL get_a_bits
PUSH DE
LD E,(HL)
LD D,0
PUSH HL
LD HL,ziptrees+#560 ;почему сюда кладутся длины кодов??? TODO
ADD HL,DE
LD (HL),A
POP HL,DE
INC HL
DEC C
JR NZ,_ZD31B
PUSH BC
push DE
LD HL,ziptrees+#160 ;там будет лежать первое дерево
LD DE,ziptrees+#560 ;почему отсюда берутся длины кодов??? TODO
LD BC,#13
CALL gentree
LD HL,(ZD3B8) ;число кодов первого дерева
LD DE,(ZD3C8) ;число кодов второго дерева
ADD HL,DE
DEC HL
POP DE
pop BC
LD IX,ziptrees ;длины кодов первого дерева (реально прочитаем оба (там место с запасом), потом перебросим остаток длин)
ZD34D PUSH HL,DE
LD D,0
LD HL,ziptrees+#160 ;первое дерево
ADD HL,DE
ADD HL,DE
LD E,(HL)
LD HL,ziptrees+#560 ;длины кодов???
ADD HL,DE
LD A,(HL)
LD C,E
POP DE
CALL read_a_bits
LD A,C
POP HL
CP #10
JR NC,ZD36C
;< #10: это будет длина кода, пишем её
LD C,A ;длина кода?
LD A,1 ;число повторов
JR _ZD390
ZD36C JR NZ,ZD37A
;= #10: пишем 3..6 предыдущих длин
LD A,2
CALL get_a_bits
ADD A,3 ;число повторов
LD C,(IX-1) ;длина кода?
JR _ZD390
ZD37A CP #11
JR NZ,_ZD387
;= #11: пишем 3..10 длин 0
LD A,3
CALL get_a_bits
ADD A,3
JR _ZD38E
_ZD387
;> #11: пишем 11..138 длин 0
LD A,7
CALL get_a_bits
ADD A,#B ;число повторов
_ZD38E LD C,0
_ZD390 LD (IX),C ;длина кода
INC IX
DEC A
DEC HL
JR Z,ZD3A0
BIT 7,H
call NZ,depkqerror ;save whole buffer и выйти
JR _ZD390
ZD3A0 BIT 7,H
JR Z,ZD34D
PUSH BC
push DE
LD HL,ziptrees ;длины кодов первого дерева
LD DE,(ZD3B8) ;число кодов первого дерева
ADD HL,DE
LD DE,ziptrees+#140 ;длины кодов второго дерева
LD BC,(ZD3C8) ;число кодов второго дерева
LDIR ;TODO lddr и убрать запас после ziptrees, или предавать указатель на длины кодов второго дерева в gentrees
gentrees;ZD3B7
;на стеке de,bc
ZD3B8=$+1 ;пишется 1 байт
LD BC,#100 ;число кодов первого дерева
LD DE,ziptrees ;длины кодов первого дерева
LD HL,ziptrees+#160 ;там будет лежать первое дерево
LD IX,ziptrees+#560
CALL gentree
ZD3C8=$+1
LD BC,0 ;число кодов второго дерева ;обычно 32
LD DE,ziptrees+#140 ;длины кодов второго дерева
LD HL,ziptrees+#360 ;там будет лежать второе дерево
LD IX,ziptrees+#9E0
CALL gentree
POP DE
pop BC
RET
;построение дерева
;de=длины кодов
;hl=адрес, где будет лежать дерево
;ix=? (записывается в (ZD523) - что-то для кодов длиннее 8)
;bc=число кодов = #100+(ZD3B8) для первого дерева, (ZD3C8) для второго (обычно 32)
gentree;ZD3DA
LD A,B
OR C
RET Z
LD (ZD443),BC ;число кодов
LD (ZD4A9),HL
;очищаем, сколько раз встретились коды каждой длины (0..15)
LD HL,TD209
PUSH HL
push BC
LD BC,#2000
_ZD3EC LD (HL),C;0
INC HL
DJNZ _ZD3EC
POP BC
pop HL
PUSH DE ;длины кодов
;считаем, сколько раз встретились коды каждой длины (0..15)
_ZD3F3 LD A,(DE)
INC DE
ADD A,A
ADD A,9 ;TD209
LD L,A
INC (HL)
JR NZ,_ZD3FE
INC HL
INC (HL)
_ZD3FE DEC BC
LD A,B
OR C
JR NZ,_ZD3F3
;теперь в TD209 лежат 2-байтные значения, сколько раз встретились коды каждой длины (0..15)
LD L,#2D ;TD22B+2
LD (HL),C;0
INC HL
LD (HL),C;0 ;начальный код для длины 1 ;TODO ld (TD22B+2),bc
PUSH BC;0 ;текущий код?
LD BC,#F02 ;перебираем длины кодов 1..15
_ZD40C LD A,C ;длина кода*2
ADD A,9 ;TD209
LD L,A
LD E,(HL)
INC HL
LD D,(HL) ;de=сколько раз встретилась эта длина кода
EX (SP),HL
ADD HL,DE
ADD HL,HL
LD E,L
LD D,H ;какой-то магией формируем текущий код из предыдущего
EX (SP),HL
INC C
INC C
LD A,C
ADD A,#2B ;TD22B
LD L,A
LD (HL),E
INC HL
LD (HL),D ;начальный код для заданной длины кода
DJNZ _ZD40C
POP DE ;текущий код?
LD A,D
OR E
JR Z,ZD440 ;последний начальный код должен получиться 0 (т.е. все варианты в бинарном дереве использованы)
;ошибочное дерево?
LD D,B
LD E,B;de=0
LD A,#F
LD L,#B ;TD209+2
_ZD42F LD C,(HL)
INC HL
LD B,(HL) ;сколько раз встретился код этой длины
INC HL
EX DE,HL
ADD HL,BC
EX DE,HL
DEC A
JR NZ,_ZD42F
;de=количество ненулевых длин кодов -2
LD HL,-2
ADD HL,DE
call C,depkqerror ;если кодов более 1, save whole buffer и выйти (ошибочное дерево? в архиве с адвентюрерами - на каждом большом файле)
;всего 1 код используется - считаем, что не ошибка, что не получилось построить дерево из 1 кода?
ZD440
POP DE ;длины кодов
PUSH DE ;длины кодов
ZD443=$+1
LD BC,0 ;число кодов
LD HL,ziptrees+#A60 ;сюда положим все коды по 2 байта на код
_ZD448 LD A,(DE) ;длина кода
INC DE
PUSH DE
ADD A,A
LD E,A
LD D,A
JR Z,__ZD45F ;длина кода=de=0
;берём код номер "длина кода" в de (и инкрементируем его там, где он лежал)
PUSH HL
LD H,TD209/256;UD2
ADD A,#2B ;TD22B
LD L,A
LD E,(HL)
INC HL
LD D,(HL)
INC DE
LD (HL),D
DEC HL
LD (HL),E
DEC DE
POP HL
__ZD45F LD (HL),E
INC HL
LD (HL),D
INC HL
POP DE
DEC BC
LD A,C
OR B
JR NZ,_ZD448
POP DE ;длины кодов
PUSH DE ;длины кодов
LD HL,ziptrees+#A60 ;все коды по 2 байта на код
LD BC,(ZD443) ;число кодов
_ZD472 LD A,(DE)
INC DE
DEC A
JP M,_ZD4A1 ;код длиной 0 (неиспользуемый) - пропускаем
JR Z,_ZD4A1 ;код длиной 1 - пропускаем
PUSH DE
LD E,(HL)
INC HL
LD D,(HL) ;берём код
PUSH HL
LD HL,0
;начинаем переворачивать код, сначала длинакода-1 битиков:
_ZD482 SRL D
RR E
ADC HL,HL
EXA
LD A,D
OR E
JR Z,_ZD493 ;код кончился
EXA
DEC A
JR NZ,_ZD482
INC A ;a=1: сдвинем потом ещё на 1 битик
EXA
_ZD493 EXA
;сдвинем на несколько оставшихся битиков:
RR E
_ZD496 ADC HL,HL
DEC A
JR NZ,_ZD496
EX DE,HL
POP HL
LD (HL),D
DEC HL
LD (HL),E ;записали перевёрнутый код
POP DE
_ZD4A1 INC HL
INC HL
DEC BC
LD A,C
OR B
JR NZ,_ZD472
ZD4A9=$+1
LD HL,0 ;адрес дерева
LD E,L
LD D,H
INC DE
LD BC,#1FF
LD (HL),A;0
LDIR ;очистили 512 байт (TODO почему не больше? литералов может быть больше 256!)
POP HL ;длины кодов
LD BC,(ZD443) ;число кодов
DEC BC
ADD HL,BC
EX DE,HL ;de=указатель на длину последнего кода
LD (ZD523),IX ;какой-то адрес для кодов длиннее 8
LD HL,ziptrees+#A60+1 ;все коды по 2 байта на код (уже перевёрнутые)
ADD HL,BC
ADD HL,BC ;указатель на последний байт последнего кода
;генерируем дерево:
_ZD4C5
;bc=литерал
LD A,(DE)
DEC DE
OR A
JR Z,_ZD503 ;код длиной 0 (неиспользуемый) - пропускаем
CP 9
PUSH DE
LD D,(HL)
DEC HL
LD E,(HL) ;de=код
INC HL
PUSH HL ;TODO выше
JR NC,_ZD50B ;код не умещается в 1 байт - используем буфер ix+...
;код умещается в 1 байт
LD HL,1
INC A ;1..9
_ZD4D8 ADD HL,HL
DEC A
JR NZ,_ZD4D8
EX DE,HL ;de=1<<(1..9)
ADD HL,HL ;код*2
LD A,(ZD4A9) ;адрес дерева
ADD A,L
LD L,A
LD (__ZD4FE),A ;это и...
LD A,(ZD4A9+1)
ADC A,H
LD H,A
INC A,A
LD (__ZD4F7),A ;...это задаёт адрес выхода (адрес дерева + код*2 + 512)
DEC DE
;кладём литерал в дерево
_ZD4F1 LD (HL),C
INC HL
LD (HL),B ;кладём литерал
ADD HL,DE ;какой-то магией находим следующий адрес (адрес литерала + код*2)
LD A,H
__ZD4F7=$+1
CP 0
JR C,_ZD4F1
JR NZ,_ZD501
LD A,L
__ZD4FE=$+1
CP 0
JR C,_ZD4F1 ;пока не дошли до адреса выхода, кладём этот литерал (TODO зачем много раз???)
_ZD501
POP HL,DE
_ZD503
DEC HL
DEC HL ;предыдущий код
DEC BC ;предыдущий литерал
BIT 7,B
JR Z,_ZD4C5
RET
_ZD50B
;код не умещается в 1 байт - используем буфер ix+...
;a=длина кода
;de=код
SUB 8
PUSH BC ;литерал
LD B,A ;длина кода-8
LD A,D
LD D,0
LD HL,(ZD4A9) ;адрес дерева
ADD HL,DE
ADD HL,DE
LD C,1 ;некий бит для проверки старшего байта кода
EXA
_ZD51A LD E,(HL)
INC HL
LD D,(HL) ;берём литерал из дерева по смещению 2*(код-256) (или адрес ix+... после прохода - см. ниже)
DEC HL
LD A,D
OR E
JR NZ,_ZD535 ;литерал уже заполнен!
;нулевой литерал (ещё не заполненный)
ZD523=$+1
LD DE,0 ;сначала туда клали ix
LD (HL),E
INC HL
LD (HL),D ;кладём этот адрес в дерево на место ещё не заполненного литерала
LD H,D
LD L,E
LD (HL),A;0
INC HL
LD (HL),A;0
INC HL
LD (HL),A;0
INC HL
LD (HL),A;0 ;и кладём 4 нуля по этому адресу (на следующем проходе можем использовать первые два или последние два нуля, чтобы положить туда адрес литерала или литерал)
INC HL
LD (ZD523),HL ;обновляем бывший ix
_ZD535
EX DE,HL ;hl=адрес = ix+... (или уже заполненный литерал)
EXA
LD E,A ;старший байт кода
AND C ;проверяем некий бит
LD A,E ;старший байт кода
JR Z,_ZD53E
INC HL,HL ;если установлен, то адрес+2 (TODO а если это был литерал???)
_ZD53E EXA
SLA C ;сдвигаем некий бит
DJNZ _ZD51A ;попробуем следующий адрес или ещё раз этот же (TODO а что если это был литерал, а не ix+..., а битик не совпал - повторим с тем же адресом???)
POP BC
LD (HL),C
INC HL
LD (HL),B ;кладём литерал
JR _ZD501 ;конец текущего кода
readcodetree1;ZD549
;de=имеющиеся данные
;out: hl=code
PUSH DE
XOR A
LD D,A
LD HL,ziptrees+#160+1 ;тут лежит первое дерево
ADD HL,DE
ADD HL,DE ;hl=адрес второго байта кода номер e в дереве
OR (HL)
DEC HL
LD L,(HL)
LD H,A
if ziptrees>=0x8000
else
add a,a
endif
JP M,_ZD58C ;h bit 6 значит дерево, иначе hl=литерал
PUSH HL
LD DE,ziptrees ;длины кодов первого дерева???
ADD HL,DE
LD A,(HL) ;длина добавки кода для имеющегося hl???
POP HL
pop DE
_ZD560
;256: end of block - stop processing if last block, otherwise start processing next block.
;257-285: combined with extra-bits, a match length of 3-258 bytes.
;286, 287: not used, reserved and illegal but still part of the tree.
CALL read_a_bits
LD A,H
OR A
RET Z
LD A,L
CP 9
RET C
CP #1D
LD HL,#200
RET Z
DEC A
LD C,A
SRL C
SRL C
DEC C
AND 3
ADD A,4
LD H,L
LD L,A
LD A,C
_ZD57E ADD HL,HL
DEC C
JR NZ,_ZD57E
INC H
CALL get_a_bits
INC A
ADD A,L
LD L,A
RET NC
INC H
RET
_ZD58C POP DE
CALL ZD5CB ;читать 8 бит и пройти по ним дерево hl
JR _ZD560
readcodetree2;ZD592
;de=имеющиеся данные
;out: hl=code
;The distance tree contains space for 32 symbols:
;0-3: distances 1-4
;4-5: distances 5-8, 1 extra bit
;6-7: distances 9-16, 2 extra bits
;8-9: distances 17-32, 3 extra bits
;...
;26-27: distances 8,193-16,384, 12 extra bits
;28-29: distances 16,385-32,768, 13 extra bits
;30-31: not used, reserved and illegal but still part of the tree.
;Note that for the match distance symbols 2-29, the number of extra bits can be calculated as [n/2]-1.
PUSH DE
XOR A
LD D,A
LD HL,ziptrees+#360+1
ADD HL,DE
ADD HL,DE
OR (HL)
DEC HL
LD L,(HL)
LD H,A ;h bit 6 значит дерево, иначе hl=литерал
if ziptrees>=0x8000
else
add a,a
endif
JP M,_ZD5C5 ;читать 8 бит и пройти по ним дерево hl
PUSH HL
LD DE,ziptrees+#140 ;длины кодов второго дерева???
ADD HL,DE
LD A,(HL) ;длина добавки кода для имеющегося hl???
POP HL,DE
_ZD5A9 CALL read_a_bits ;дочитываем столько бит, сколько прошагали?
LD A,L ;литерал
CP 4
RET C
RRA
DEC A
LD C,A
LD L,H
RL L
INC L,L
ZD5B8 ADD HL,HL
DEC C
JR NZ,ZD5B8
PUSH HL
CALL get_a_bits_tohl
EX DE,HL
EX (SP),HL
ADD HL,DE
POP DE
RET
_ZD5C5 POP DE
CALL ZD5CB ;читать 8 бит и пройти по ним дерево hl
JR _ZD5A9
ZD5CB
;читать 8 бит и пройти по ним дерево hl
;out: a=сколько бит реально прошагали, l=литерал?
LD A,8
CALL read_a_bits
LD C,E ;эквивалентно ld a,8:call get_a_bits:ld c,a ?
;ходим по дереву hl, имея код C (младшие биты сначала)
XOR A
ZD5D2 INC A
RR C
JR NC,ZD5D9
INC HL
inc HL
ZD5D9 LD (ZD5DD),HL
ZD5DD=$+1
LD HL,(0) ;ok
if ziptrees>=0x8000
BIT 7,H
else
BIT 6,H ;h bit 6 значит дерево, иначе l=литерал
endif
JR NZ,ZD5D2
RET
; ENT
;END_DEP=$
U6546=Z6546 ;сколько байт сохранить = текущий адрес в буфере