123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240 |
- zlz_comp:
- ;Inputs:
- ; HL points to the input data
- ; DE points to the output
- ; BC is the size of the input
- ;Outputs:
- ; HL points to the byte after the input
- ; DE points to the byte afterthe compressed data
- ; BC is 0
- ;Destroys:
- ; AF,IX
- ;
- ;This routine has input and output like LDIR,
- ;except if LDIR as compressing as it goes.
- ;
- ld a,ZLZ_MIN_RUN
- inc b
- dec b
- jr nz,+_
- cp c
- jr z,$+4
- jr c,+_
- ld a,c
- ld (de),a
- inc de
- inc c
- dec c
- ret z
- ldir
- ret
- _:
- ld (zlz_base),hl
- ld (zlz_runstart),hl
- add a,l
- ld l,a
- jr nc,$+3
- inc h
- ld a,c
- sub ZLZ_MIN_RUN
- ld c,a
- jr nc,$+3
- dec b
- zlz_comp_loop:
- push bc
- ld (zlz_head),hl
- call zlz_findmatch
- inc b
- dec b
- jr nz,zlz_matched
- ld a,c
- cp ZLZ_MIN_RUN
- jr nc,zlz_matched
- ld hl,(zlz_head)
- pop bc
- cpi
- jp pe,zlz_comp_loop
- zlz_write_run:
- ;need to write the run from (zlz_head), size HL-(zlz_head)
- push hl
- push bc
- ld hl,(zlz_head)
- ld bc,(zlz_runstart)
- or a
- sbc hl,bc
- jr z,zlz_write_run_done
- ld b,h
- ld c,l
- ld a,l
- add a,a \ rl h
- add a,a \ rl h
- jr z,+_
- scf
- _:
- rra
- rra
- ld (de),a
- inc de
- jr z,+_
- ld a,h
- ld (de),a
- inc de
- _:
- ld hl,(zlz_runstart)
- ldir
- zlz_write_run_done:
- pop bc
- pop hl
- ld (zlz_runstart),hl
- ret
- zlz_matched:
- push bc
- call zlz_write_run
- pop bc
- push bc
- ;size then pointer
- ;Make sure the size doesn't exceed 13 bits
- ld a,c
- add a,a \ rl b
- add a,a \ rl b
- jr z,+_
- scf
- _:
- rra
- scf
- rra
- ld (de),a
- inc de
- jr z,+_
- ld a,b
- ld (de),a
- inc de
- _:
- ;Now we need to write the pointer
- ;this is an offset back from the data
- ;we want (zlz_head)-HL
- ld b,h
- ld c,l
- ld hl,(zlz_head)
- ;or a ;the rra above will reset the carry since the bottom bit of A was 0
- sbc hl,bc
- ld a,l
- add a,a \ rl h
- jr z,+_
- scf
- _:
- rra
- ld (de),a
- inc de
- jr z,+_
- ld a,h
- ld (de),a
- inc de
- _:
- pop bc
- ld hl,(zlz_head)
- add hl,bc
- ex (sp),hl
- ;or a
- sbc hl,bc
- ld b,h
- ld c,l
- pop hl
- ld (zlz_runstart),hl
- jp nz,zlz_comp_loop
- ret
- zlz_findmatch:
- push de
- ld (zlz_match_base),hl
- add hl,bc
- ld (zlz_top),hl
- sbc hl,bc
- ld de,(zlz_base)
- xor a
- ld (zlz_match_size),a
- ld (zlz_match_size+1),a
- sbc hl,de
- ld bc,1-ZLZ_MIN_RUN
- add hl,bc
- ld b,h
- ld c,l
- ex de,hl
- jr zlz_findmatch_loop_begin
- zlz_findmatch_loop:
- push hl
- push bc
- call +_
- pop bc
- pop hl
- zlz_findmatch_loop_begin:
- ;DE points to the data to find
- ;HL points to the data to search
- ;BC is the size of the data to search
- ld de,(zlz_match_base)
- ld a,(de)
- cpir
- jp pe,zlz_findmatch_loop
- zlz_findmatch_done:
- ld bc,(zlz_match_size)
- ld hl,(zlz_match_loc)
- pop de
- ret
- _:
- ;now we compare the rest of the string
- push hl
- inc de
- ld hl,(zlz_top)
- or a
- sbc hl,de
- ld b,h
- ld c,l
- pop hl
- jr z,zlz_match_complete
- push hl
- _:
- ld a,(de)
- inc de
- cpi
- jp po,+_
- jr z,-_
- _:
- ld hl,(zlz_match_base)
- ex de,hl
- ;or a
- sbc hl,de
- ld bc,(zlz_match_size)
- ;if HL>=BC, save the new match (if it is the same size as the previous match, then this one is closer, which can be better)
- scf
- sbc hl,bc
- pop de
- ret c
- add hl,bc
- ld (zlz_match_size),hl
- dec de
- ld (zlz_match_loc),de
- ret
- zlz_match_complete:
- ;can't get better than this, so we'll exit early
- ld hl,(zlz_match_base)
- ex de,hl
- ;or a
- sbc hl,de
- ld b,h
- ld c,l
- pop af ;return address
- pop af ;size left
- pop hl ;pointer to match
- pop de ;saved DE
- ret
|