module ZX7::Macros

Public Instance Methods

dzx7_agilercs(name=nil) click to toggle source

“Agile” integrated RCS+ZX7 decoder by Einar Saukas (150 bytes)


Parameters:

HL: source address (compressed data)
DE: destination address (decompressing)

# File lib/zxutils/zx7.rb, line 485
def dzx7_agilercs(name=nil)
    isolate(name) do
                        ld      a, 0x80
    copy_byte_loop1     ex      af, af
                        call    copy_byte         # copy literal byte
    main_loop1          ex      af, af
                        add     a, a                    # check next bit
                        call    Z, load_bits      # no more bits left?
                        jr      NC, copy_byte_loop1 # next bit indicates either literal or sequence
                        jr      len_size_start

    copy_byte_loop      ldi                             # copy literal byte
    main_loop           add     a, a                    # check next bit
                        call    Z, load_bits      # no more bits left?
                        jr      NC, copy_byte_loop # next bit indicates either literal or sequence

    len_size_start      label
    # determine number of bits used for length (Elias gamma coding)
                        push    de
                        ld      bc, 1
                        ld      d, b
    len_size_loop       inc     d
                        add     a, a                    # check next bit
                        call    Z, load_bits      # no more bits left?
                        jr      NC, len_size_loop
                        jp      len_value_start

    # determine length
    len_value_loop      add     a, a                    # check next bit
                        call    Z, load_bits      # no more bits left?
                        rl      c
                        rl      b
                        jr      C, exit0           # check end marker
    len_value_start     dec     d
                        jr      NZ, len_value_loop
                        inc     bc                      # adjust length

    # determine offset
                        ld      e, [hl]                 # load offset flag (1 bit) + offset value (7 bits)
                        inc     hl
                        sll     e                # opcode for undocumented instruction "SLL E" aka "SLS E"
                        jr      NC, offset_end    # if offset flag is set, load 4 extra bits
                        add     a, a                    # check next bit
                        call    Z, load_bits      # no more bits left?
                        rl      d                       # insert first bit into D
                        add     a, a                    # check next bit
                        call    Z, load_bits      # no more bits left?
                        rl      d                       # insert second bit into D
                        add     a, a                    # check next bit
                        call    Z, load_bits      # no more bits left?
                        rl      d                       # insert third bit into D
                        add     a, a                    # check next bit
                        call    Z, load_bits      # no more bits left?
                        ccf
                        jr      C, offset_end
                        inc     d                       # equivalent to adding 128 to DE
    offset_end          rr      e                       # insert inverted fourth bit into E

    # copy previous sequence
                        ex      [sp], hl                # store source, restore destination
                        push    hl                      # store destination
                        sbc     hl, de                  # HL = destination - offset - 1
                        pop     de                      # DE = destination
                        ex      af, af
                        ld      a, h                    # A = 010RRccc
                        cp      0x58
                        jr      C, copy_bytes
                        ldir
                        pop     hl                      # restore source address (compressed data)
                        ex      af, af
                        jp      main_loop

    copy_bytes          push    hl
                        ex      de, hl
                        call    convert
                        ex      de, hl
                        call    copy_byte
                        pop     hl
                        inc     hl
                        jp      PE, copy_bytes
                        pop     hl                      # restore source address (compressed data)
                        jr      main_loop1

    load_bits           ld      a, [hl]                 # load another group of 8 bits
                        inc     hl
                        rla
                        ret

    copy_byte           push    de
                        call    convert
                        ldi
    exit0               pop     de
                        inc     de
                        ret

    # Convert an RCS address 010RRccc ccrrrppp to screen address 010RRppp rrrccccc
    # (Note: replace both EX AF,AF' with PUSH AF/POP AF if you want to preserve AF')
    convert             ld      a, d                    # A = 010RRccc
                        cp      0x58
                        ret     NC
                        xor     e
                        anda    0xf8
                        xor     e                       # A = 010RRppp
                        push    af
                        xor     d
                        xor     e                       # A = ccrrrccc
                        rlca
                        rlca                            # A = rrrccccc
                        pop     de                      # D = 010RRppp
                        ld      e, a                    # E = rrrccccc
                        ret
    # -----------------------------------------------------------------------------
    end
end
dzx7_mega(name=nil) click to toggle source

ZX7 decoder by Einar Saukas “Mega” version (244 bytes, 30% faster)


Parameters:

HL: source address (compressed data)
DE: destination address (decompressing)

# File lib/zxutils/zx7.rb, line 196
def dzx7_mega(name=nil)
    isolate(name) do
                        ld      a, 0x80
    copy_byte_loop_ev   ldi                            # copy literal byte
    main_loop_ev        add     a, a                   # check next bit
                        jr      Z, load_bits1          # no more bits left?
                        jr      C, len_size_start_od   # next bit indicates either literal or sequence

    copy_byte_loop_od   ldi                            # copy literal byte
    main_loop_od        add     a, a                   # check next bit
                        jr      NC, copy_byte_loop_ev  # next bit indicates either literal or sequence

    len_size_start_ev   label
    # determine number of bits used for length (Elias gamma coding)
                        push    de
                        ld      bc, 1
                        ld      d, b
    len_size_loop_ev    inc     d
                        add     a, a                   # check next bit
                        jr      Z, load_bits2_ev       # no more bits left?
                        jr      NC, len_size_loop_ev
                        jp      len_value_start_ev

    len_size_start_od   label
    # determine number of bits used for length (Elias gamma coding)
                        push    de
                        ld      bc, 1
                        ld      d, b
    len_size_loop_od    inc     d
                        add     a, a                   # check next bit
                        jr      Z, load_bits2_od       # no more bits left?
                        jr      NC, len_size_loop_od
                        jp      len_value_start_od

    # determine length
    len_value_loop_ev   add     a, a                   # check next bit
                        jr      Z, load_bits3_ev       # no more bits left?
                        rl      c
                        rl      b
                        jr      C, exit_ev             # check end marker
    len_value_start_ev  dec     d
                        jr      NZ, len_value_loop_ev
                        inc     bc                     # adjust length
    offset_start_od     label
    # determine offset
                        ld      e, [hl]                # load offset flag (1 bit) + offset value (7 bits)
                        inc     hl
                        sll     e                      # opcode for undocumented instruction "SLL E" aka "SLS E"
                        jr      NC, offset_end_od      # if offset flag is set, load 4 extra bits
                        add     a, a                   # check next bit
                        rl      d                      # insert first bit into D
                        add     a, a                   # check next bit
                        jr      Z, load_bits4          # no more bits left?
                        rl      d                      # insert second bit into D
                        add     a, a                   # check next bit
                        rl      d                      # insert third bit into D
                        add     a, a                   # check next bit
                        jr      Z, load_bits5          # no more bits left?
                        ccf
                        jr      C, offset_end_od
    offset_inc_od       inc     d                      # equivalent to adding 128 to DE
    offset_end_od       rr      e                      # insert inverted fourth bit into E
    # copy previous sequence
                        ex      [sp], hl               # store source, restore destination
                        push    hl                     # store destination
                        sbc     hl, de                 # HL = destination - offset - 1
                        pop     de                     # DE = destination
                        ldir
                        pop     hl                     # restore source address (compressed data)
                        jp      main_loop_od

    load_bits1          ld      a, [hl]                # load another group of 8 bits
                        inc     hl
                        rla
                        jr      C, len_size_start_od   # next bit indicates either literal or sequence
                        jp      copy_byte_loop_od

    load_bits2_ev       ld      a, [hl]                # load another group of 8 bits
                        inc     hl
                        rla
                        jr      NC, len_size_loop_ev
                        jp      len_value_start_ev

    load_bits2_od       ld      a, [hl]                # load another group of 8 bits
                        inc     hl
                        rla
                        jr      NC, len_size_loop_od
                        jp      len_value_start_od

    load_bits3_ev       ld      a, [hl]                # load another group of 8 bits
                        inc     hl
                        rla
                        rl      c
                        rl      b
                        jp      NC, len_value_start_ev # check end marker
    exit_ev             pop     de
                        ret

    load_bits4          ld      a, [hl]                # load another group of 8 bits
                        inc     hl
                        rla
                        rl      d                      # insert second bit into D
                        add     a, a                   # check next bit
                        rl      d                      # insert third bit into D
                        add     a, a                   # check next bit
                        ccf
                        jr      C, offset_end_od
                        jp      offset_inc_od

    load_bits5          ld      a, [hl]                # load another group of 8 bits
                        inc     hl
                        rla
                        ccf
                        jr      C, offset_end_od
                        jp      offset_inc_od

    # determine length
    len_value_loop_od   add     a, a                   # check next bit
                        jr      Z, load_bits3_od       # no more bits left?
                        rl      c
                        rl      b
                        jr      C, exit_od             # check end marker
    len_value_start_od  dec     d
                        jr      NZ, len_value_loop_od
                        inc     bc                     # adjust length
    offset_start_ev     label
    # determine offset
                        ld      e, [hl]                # load offset flag (1 bit) + offset value (7 bits)
                        inc     hl
                        sll     e                      # opcode for undocumented instruction "SLL E" aka "SLS E"
                        jr      NC, offset_end_ev      # if offset flag is set, load 4 extra bits
                        add     a, a                   # check next bit
                        jr      Z, load_bits6          # no more bits left?
                        rl      d                      # insert first bit into D
                        add     a, a                   # check next bit
                        rl      d                      # insert second bit into D
                        add     a, a                   # check next bit
                        jr      Z, load_bits7          # no more bits left?
                        rl      d                      # insert third bit into D
                        add     a, a                   # check next bit
                        ccf
                        jr      C, offset_end_ev
    offset_inc_ev       inc     d                      # equivalent to adding 128 to DE
    offset_end_ev       rr      e                      # insert inverted fourth bit into E
    # copy previous sequence
                        ex      [sp], hl               # store source, restore destination
                        push    hl                     # store destination
                        sbc     hl, de                 # HL = destination - offset - 1
                        pop     de                     # DE = destination
                        ldir
                        pop     hl                     # restore source address (compressed data)
                        jp      main_loop_ev

    load_bits3_od       ld      a, [hl]                # load another group of 8 bits
                        inc     hl
                        rla
                        rl      c
                        rl      b
                        jp      NC, len_value_start_od # check end marker
    exit_od             pop     de
                        ret

    load_bits6          ld      a, [hl]                # load another group of 8 bits
                        inc     hl
                        rla
                        rl      d                      # insert first bit into D
                        add     a, a                   # check next bit
                        rl      d                      # insert second bit into D
                        add     a, a                   # check next bit
                        rl      d                      # insert third bit into D
                        add     a, a                   # check next bit
                        ccf
                        jr      C, offset_end_ev
                        jp      offset_inc_ev

    load_bits7          ld      a, [hl]                # load another group of 8 bits
                        inc     hl
                        rla
                        rl      d                      # insert third bit into D
                        add     a, a                   # check next bit
                        ccf
                        jr      C, offset_end_ev
                        jp      offset_inc_ev

    # -----------------------------------------------------------------------------
    end
end
dzx7_smartrcs(name=nil) click to toggle source

“Smart” integrated RCS+ZX7 decoder by Einar Saukas (110 bytes)


Parameters:

HL: source address (compressed data)
DE: destination address (decompressing)

# File lib/zxutils/zx7.rb, line 390
def dzx7_smartrcs(name=nil)
    isolate(name) do
                        ld      a, 0x80
    copy_byte_loop      call    copy_byte          # copy literal byte
    main_loop           call    next_bit
                        jr      NC, copy_byte_loop # next bit indicates either literal or sequence

    # determine number of bits used for length (Elias gamma coding)
                        push    de
                        ld      bc, 0
                        ld      d, b
    len_size_loop           inc     d
                        call    next_bit
                        jr      NC, len_size_loop

    # determine length
    len_value_loop      call    NC, next_bit
                        rl      c
                        rl      b
                        jr      C, exit0           # check end marker
                        dec     d
                        jr      NZ, len_value_loop
                        inc     bc                 # adjust length

    # determine offset
                        ld      e, [hl]            # load offset flag (1 bit) + offset value (7 bits)
                        inc     hl
                        sll     e                  # opcode for undocumented instruction "SLL E" aka "SLS E"
                        jr      NC, offset_end     # if offset flag is set, load 4 extra bits
                        ld      d, 0x10            # bit marker to load 4 bits
    rld_next_bit        call    next_bit
                        rl      d                  # insert next bit into D
                        jr      NC, rld_next_bit   # repeat 4 times, until bit marker is out
                        inc     d                  # add 128 to DE
                        srl d                      # retrieve fourth bit from D
    offset_end          rr      e                  # insert fourth bit into E

    # copy previous sequence
                        ex      [sp], hl           # store source, restore destination
                        push    hl                 # store destination
                        sbc     hl, de             # HL = destination - offset - 1
                        pop     de                 # DE = destination
    copy_bytes          push    hl
                        ex      de, hl
                        call    convert
                        ex      de, hl
                        call    copy_byte
                        pop     hl
                        inc     hl
                        jp      PE, copy_bytes
                        pop     hl                 # restore source address (compressed data)
                        jr      main_loop

    next_bit            add     a, a               # check next bit
                        ret     NZ                 # no more bits left?
                        ld      a, [hl]            # load another group of 8 bits
                        inc     hl
                        rla
                        ret

    copy_byte           push    de
                        call    convert
                        ldi
    exit0               pop     de
                        inc     de
                        ret

    # Convert an RCS address 010RRccc ccrrrppp to screen address 010RRppp rrrccccc
    # (note: replace both EX AF,AF' with PUSH AF/POP AF if you want to preserve AF')
    convert             ex      af, af
                        ld      a, d               # A = 010RRccc
                        cp      0x58
                        jr      NC, skip
                        xor     e
                        anda    0xf8
                        xor     e                  # A = 010RRppp
                        push    af
                        xor     d
                        xor     e                  # A = ccrrrccc
                        rlca
                        rlca                       # A = rrrccccc
                        pop     de                 # D = 010RRppp
                        ld      e, a               # E = rrrccccc
    skip                ex      af, af
                        ret
    # -----------------------------------------------------------------------------
    end
end
dzx7_standard(name = nil) click to toggle source

ZX7 decoder by Einar Saukas, Antonio Villena & Metalbrain “Standard” version (69 bytes only)


Parameters:

HL: source address (compressed data)
DE: destination address (decompressing)

# File lib/zxutils/zx7.rb, line 61
def dzx7_standard(name = nil)
    isolate(name) do
                    ld      a, 0x80
    copy_byte_loop  ldi                             # copy literal byte
    main_loop       call    next_bit
                    jr      NC, copy_byte_loop      # next bit indicates either literal or sequence

    # determine number of bits used for length (Elias gamma coding)
                    push    de
                    ld      bc, 0
                    ld      d, b
    len_size_loop   inc     d
                    call    next_bit
                    jr      NC, len_size_loop

    # determine length
    len_value_loop  call    NC, next_bit
                    rl      c
                    rl      b
                    jr      C, exit0                # check end marker
                    dec     d
                    jr      NZ, len_value_loop
                    inc     bc                      # adjust length

    # determine offset
                    ld      e, [hl]                 # load offset flag (1 bit) + offset value (7 bits)
                    inc     hl
                    sll     e                       # opcode for undocumented instruction "SLL E" aka "SLS E"
                    jr      NC, offset_end          # if offset flag is set, load 4 extra bits
                    ld      d, 0x10                 # bit marker to load 4 bits
    rld_next_bit    call    next_bit
                    rl      d                       # insert next bit into D
                    jr      NC, rld_next_bit        # repeat 4 times, until bit marker is out
                    inc     d                       # add 128 to DE
                    srl d                           # retrieve fourth bit from D
    offset_end      rr      e                       # insert fourth bit into E

    # copy previous sequence
                    ex      [sp], hl                # store source, restore destination
                    push    hl                      # store destination
                    sbc     hl, de                  # HL = destination - offset - 1
                    pop     de                      # DE = destination
                    ldir
    exit0           pop     hl                      # restore source address (compressed data)
                    jr      NC, main_loop
    next_bit        add     a, a                    # check next bit
                    ret     NZ                      # no more bits left?
                    ld      a, [hl]                 # load another group of 8 bits
                    inc     hl
                    rla
                    ret
    # -----------------------------------------------------------------------------
    end
end
dzx7_turbo(name = nil) click to toggle source

ZX7 decoder by Einar Saukas & Urusergi “Turbo” version (88 bytes, 25% faster)


Parameters:

HL: source address (compressed data)
DE: destination address (decompressing)

# File lib/zxutils/zx7.rb, line 123
def dzx7_turbo(name = nil)
    isolate(name) do
                    ld      a, 0x80
    copy_byte_loop  ldi                             # copy literal byte
    main_loop       add     a, a                    # check next bit
                    call    Z, load_bits            # no more bits left?
                    jr      NC, copy_byte_loop      # next bit indicates either literal or sequence

    # determine number of bits used for length (Elias gamma coding)
                    push    de
                    ld      bc, 1
                    ld      d, b
    len_size_loop   inc     d
                    add     a, a                    # check next bit
                    call    Z, load_bits            # no more bits left?
                    jr      NC, len_size_loop
                    jp      len_value_start

    # determine length
    len_value_loop  add     a, a                    # check next bit
                    call    Z, load_bits            # no more bits left?
                    rl      c
                    rl      b
                    jr      C, exit0                # check end marker
    len_value_start dec     d
                    jr      NZ, len_value_loop
                    inc     bc                      # adjust length

    # determine offset
                    ld      e, [hl]                 # load offset flag (1 bit) + offset value (7 bits)
                    inc     hl
                    sll     e                       # opcode for undocumented instruction "SLL E" aka "SLS E"
                    jr      NC, offset_end          # if offset flag is set, load 4 extra bits
                    add     a, a                    # check next bit
                    call    Z, load_bits            # no more bits left?
                    rl      d                       # insert first bit into D
                    add     a, a                    # check next bit
                    call    Z, load_bits            # no more bits left?
                    rl      d                       # insert second bit into D
                    add     a, a                    # check next bit
                    call    Z, load_bits            # no more bits left?
                    rl      d                       # insert third bit into D
                    add     a, a                    # check next bit
                    call    Z, load_bits            # no more bits left?
                    ccf
                    jr      C, offset_end
                    inc     d                       # equivalent to adding 128 to DE
    offset_end      rr      e                       # insert inverted fourth bit into E

    # copy previous sequence
                    ex      [sp], hl                # store source, restore destination
                    push    hl                      # store destination
                    sbc     hl, de                  # HL = destination - offset - 1
                    pop     de                      # DE = destination
                    ldir
    exit0           pop     hl                      # restore source address (compressed data)
                    jp      NC, main_loop

    load_bits       ld      a, [hl]                 # load another group of 8 bits
                    inc     hl
                    rla
                    ret
    # -----------------------------------------------------------------------------
    end
end