ZX0 decompressor

ZX0 I/O stream decompressor. (last update: 29/03/21)

CODE: xxl
ENTRY: destination adress store in ZX0_OUTPUT, ( no stream? source in ZX0_INPUT )

ZX0_OUTPUT      equ ZP
copysrc         equ ZP+2

            mwa #packed_data ZX0_INPUT
            mwa #destination ZX0_OUTPUT
            jsr unZX0

FORMAT V2 !!! (last update: 10/10/21)

dzx0_standard
              lda   #$ff
              sta   offsetL
              sta   offsetH
              ldy   #$00
              sty   lenL
              sty   lenH
              lda   #$80

dzx0s_literals
              jsr   dzx0s_elias
              pha
cop0          jsr   get_byte
              ldy   #$00
              sta   (ZX0_OUTPUT),y
              inw   ZX0_OUTPUT
              lda   #$ff
lenL          equ   *-1
              bne   @+
              dec   lenH
@             dec   lenL
              bne   cop0
              lda   #$ff
lenH          equ   *-1
              bne   cop0
              pla
              asl   @
              bcs   dzx0s_new_offset
              jsr   dzx0s_elias
dzx0s_copy    pha
              lda   ZX0_OUTPUT
              clc
              adc   #$ff
offsetL       equ   *-1
              sta   copysrc
              lda   ZX0_OUTPUT+1
              adc   #$ff
offsetH       equ   *-1
              sta   copysrc+1
              ldy   #$00
              ldx   lenH
              beq   Remainder
Page          lda   (copysrc),y
              sta   (ZX0_OUTPUT),y
              iny
              bne   Page
              inc   copysrc+1
              inc   ZX0_OUTPUT+1
              dex
              bne   Page
Remainder     ldx   lenL
              beq   copyDone
copyByte      lda   (copysrc),y
              sta   (ZX0_OUTPUT),y
              iny
              dex
              bne   copyByte
              tya
              clc
              adc   ZX0_OUTPUT
              sta   ZX0_OUTPUT
              bcc   copyDone
              inc   ZX0_OUTPUT+1
copyDone      stx   lenH
              stx   lenL
              pla
              asl   @
              bcc   dzx0s_literals
dzx0s_new_offset
              ldx   #$fe
              stx   lenL
              jsr   dzx0s_elias_loop
              pha
              ldx   lenL
              inx
              stx   offsetH
              bne   @+
              pla
              rts           ; koniec
@             jsr   get_byte
              sta   offsetL
              ror   offsetH
              ror   offsetL
              ldx   #$00
              stx   lenH
              inx
              stx   lenL
              pla
              bcs   @+
              jsr   dzx0s_elias_backtrack
@             inc   lenL
              bne   @+
              inc   lenH
@             jmp   dzx0s_copy
dzx0s_elias   inc   lenL
dzx0s_elias_loop
              asl   @
              bne   dzx0s_elias_skip
              jsr   get_byte
              rol   @
dzx0s_elias_skip
              bcc   dzx0s_elias_backtrack
              rts
dzx0s_elias_backtrack
              asl   @
              rol   lenL
              rol   lenH
              jmp   dzx0s_elias_loop

———————————————————————————————————————
———————————————————————————————————————
FORMAT V1 Stary !!! (last update: 29/03/21)

ZX0_OUTPUT      equ ZP
copysrc         equ ZP+2

unZX0        lda   #$ff
             sta   offsetL
             sta   offsetH
             ldy   #$00
             sty   lenL
             sty   lenH
             lda   #$80

; Literal (copy next N bytes from compressed file)
; 0  Elias(length)  byte[1]  byte[2]  ...  byte[N]
dzx0s_literals
              jsr   dzx0s_elias
              pha

cop0          jsr   xBIOS_GET_BYTE
              ldy   #$00
              sta   (ZX0_OUTPUT),y
              inw   ZX0_OUTPUT
              lda   #$ff
lenL          equ   *-1
              bne   @+
              dec   lenH
@             dec   lenL
              bne   cop0
              lda   #$ff
lenH          equ   *-1
              bne   cop0

              pla
              asl   @
              bcs   dzx0s_new_offset

; Copy from last offset (repeat N bytes from last offset)
; 0  Elias(length)
              jsr   dzx0s_elias
dzx0s_copy
              pha
              lda   ZX0_OUTPUT
              clc
              adc   #$ff
offsetL       equ   *-1
              sta   copysrc
              lda   ZX0_OUTPUT+1
              adc   #$ff
offsetH       equ   *-1
              sta   copysrc+1

              ldy   #$00
              ldx   lenH
              beq   Remainder
Page          lda   (copysrc),y
              sta   (ZX0_OUTPUT),y
              iny
              bne   Page
              inc   copysrc+1
              inc   ZX0_OUTPUT+1
              dex
              bne   Page
Remainder     ldx   lenL
              beq   copyDone
copyByte      lda   (copysrc),y
              sta   (ZX0_OUTPUT),y
              iny
              dex
              bne   copyByte
              tya
              clc
              adc   ZX0_OUTPUT
              sta   ZX0_OUTPUT
              bcc   copyDone
              inc   ZX0_OUTPUT+1
copyDone      stx   lenH
              stx   lenL

              pla
              asl   @
              bcc   dzx0s_literals

; Copy from new offset (repeat N bytes from new offset)
; 1  Elias(MSB(offset))  LSB(offset)  Elias(length-1)
dzx0s_new_offset
              jsr   dzx0s_elias
              pha
              php
              lda   #$00
              sec
              sbc   lenL
              sta   offsetH
              bne   @+
              plp
              pla
              rts           ; koniec
@             jsr   xBIOS_GET_BYTE
              plp
              sta   offsetL
              ror   offsetH
              ror   offsetL
              ldx   #$00
              stx   lenH
              inx
              stx   lenL
              pla
              bcs   @+
              jsr   dzx0s_elias_backtrack
@             inc   lenL
              bne   @+
              inc   lenH
@             jmp   dzx0s_copy

dzx0s_elias   inc   lenL
dzx0s_elias_loop
              asl   @
              bne   dzx0s_elias_skip
              jsr   xBIOS_GET_BYTE
              sec   ; można usunąć jeśli dekompresja z pamięci a nie pliku
              rol   @
dzx0s_elias_skip
              bcc   dzx0s_elias_backtrack
              rts
dzx0s_elias_backtrack
              asl   @
              rol   lenL
              rol   lenH
              jmp   dzx0s_elias_loop

Jeśli dane znajdują się w pamięci a nie w pliku należy wymienić odwołania:

jsr xBIOS_GET_BYTE na jsr GET_BYTE

GET_BYTE          lda    $ffff
ZX0_INPUT         equ    *-2
                  inw    ZX0_INPUT
                  rts

zobacz:
https://github.com/einar-saukas/ZX0