Hi!

Here is attached a piece of asm code....

>>Hi everybody!
>>
>>Does anyone know the encoding/decoding algorithm for the .cmp format
>>used in age?
>>I can't figure it out. Does it use run length encoding, huffman, both
>>or none of the above? Does it use nybbles, bits, bytes or words?
>>Going crazy here....
>
>It uses something that amounts to a vertical run length... It XOR's the
>lines onto the previous one, and then compresses the zeroes that result 
from
>this operation iff the bytes were equal. Yes, it is byte-based. But it 
uses
>bits for the compression coding.
>
>The code is pretty straightforward, actually. The only weird trick is 
that
>the code uses a "db 0FEh" as sort of a skip-code. Something like this, 
I
>forgot which code it skipped but I'll assume that it's "push af":
>
>    push af    ; A on the stack....
>
>    ...compute stuff
>
>    db 0FEh    ; use as a "skip code"
>loop:
>    push af
>
>    ... compute
>
>    pop af
>
>    ... compute
>    jp loop
>
>The "db 0FEh", followed by "push af" translates into "cp 0F5h" when 
executed
>by the Z80 - this means that only the F register is changed, and the
>decruncher uses this to skip the "push af"....
>
>Okay. Back to the algorithm. It has two steps, compressed into a single
>loop.
>
>Step 1. Every byte which is not on the first line, is XOR'd with the 
byte
>precisely above it. In practice this means: if a byte in the picture is 
the
>same as the byte above it, it results in a 0 in the buffer.
>
>"code" (picture is SX bytes by SY lines; screen 5 has 128 bytes per 
line)
>
>rem    move the first line
>for x=0 to SX-1
>    buffer(x)=picture(x)
>next x
>
>rem    move the rest of the picture to the buffer
>for y=1 to SY
>    for x=0 to SX-1
>        buffer(x+y*SX)=picture(x+(y-1)*128) XOR picture(x+y*128)
>    next x
>next y
>
>Step 2. Now, the next step assumes that there are a lot of zeros in the
>buffer. It then uses three streams, which are interleaved (will be 
cleared
>later): two bit streams and a byte stream. Bit stream 1 works like 
this:
>
>"0":    The next 8 bytes in the picture are all zero.
>"1":    Look at bit stream 2 for more information...
>
>Bit stream 2:
>
>"0":    The next byte in the picture is zero.
>"1":    The next byte in the picture is the next byte in the byte 
stream.
>
>Take some time to think about this. The byte stream doesn't contain any 
zero
>bytes at all. It contains precisely those picture bytes which aren't 
zero.
>The information is grouped in batches of 64 bytes, and these end up 
(after
>compression) as anything between a single zero byte (only stream 1, all
>zeros, so 64 zero bytes in the picture) or 64+9 bytes (if there are no 
zero
>bytes in the batch; 64 bytes of data, 1 byte (0FFh) for bit stream 1, 8
>bytes (0FFh) for bit stream 2.).
>
>"Interleaving"
>This is a technique used by many compression algorithms. POPCOM uses it 
too.
>The three streams are merged into one in such a way that the next byte 
in
>the stream always provides the information required by the decompressor 
at
>that point.
>
>Darn, I find that this is actually harder to explain than I'd expected.
>Maybe this compression method even has a name, but I don't know it.
>
>Erm.. if anyone can explain it better or has some actual questions 
about it,
>just mail me.
>
>Cas "Parallax!" Cremers
>[EMAIL PROTECTED]
>
Greets from TRD

http://www.trd.msxnet.org

______________________________________________________
Get Your Private, Free Email at http://www.hotmail.com
; gedisassembleerd(?) door Michiel Spoor
; uitgezocht/wat verbeterd door Roderik Muit

        ORG   0C000H


; ---- AGE-DECRUNCHER ----

; A  - Page to put to
; HL - Start Address of DATA (PIC)
; D  - Y-Offset
; E  - X-Offset (moet even zijn)

; vB:
        LD    A,1             ; Page 0
        LD    DE,00H          ; Coors (0,0)
        LD    HL,8800H        ; Address of Pic

;-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
START:
        SRL   A
        LD    (PAGE),A
        RR    D
        RR    E
        PUSH  DE
        LD    B,(HL)          ; lengte X * 2
        INC   HL
        LD    C,(HL)          ; lengte Y
        INC   HL
        LD    A,(HL)          ; lengte Y van eerste stuk (dat niet ge-XORd moet)
        INC   HL
        EX    AF,AF
        PUSH  BC
        CALL  FILBUF          ; Vul buffer (DE, B, C gezet)
        EXX
        POP   BC              ; BC=lengtes, HL=VRAM-ad.
        POP   HL
        DB    0FEH            ; Sla EX AF,AF over

LOOP1:  EX    AF,AF
        PUSH  BC
        LD    A,(PAGE)
        CALL  SETVDP
        LD    DE,BUFF2
DLIJN1: EXX                   ; Haal volgende byte, zet in BUFF2 en OUT naar
        CALL  GETBYT          ;  VRAM
        EXX
        LD    (DE),A
        INC   DE
        OUT   (98H),A
        DJNZ  DLIJN1
        EI
        LD    C,80H           ; VRAM-adres met 128 verhogen: volgende lijn
        ADD   HL,BC
        POP   BC
        DEC   C
        RET   Z
        EX    AF,AF
        DEC   A               ; Zelfde methode als nog in eerste stuk
        JP    NZ,LOOP1

LOOP2:  PUSH  BC              ; Tweede stuk:
        LD    A,(PAGE)
        CALL  SETVDP
        LD    DE,BUFF2
        EX    DE,HL           ; DE=VRAM-adres
DLIJN2: EXX                   ; Doe zelfde, maar XOR nu met data van vorige
        CALL  GETBYT          ;  lijn
        EXX
        XOR   (HL)
        LD    (HL),A
        INC   HL
        OUT   (98H),A
        DJNZ  DLIJN2
        EI
        EX    DE,HL
        LD    C,80H
        ADD   HL,BC
        POP   BC
        DEC   C
        JP    NZ,LOOP2
        RET

GETBYT: XOR   A
        SLA   B               ; Volgende byte uit geheugen in A,
        JR    NC,SKIP1        ;  of 0 als bitje=0
        LD    A,(HL)
        INC   HL
SKIP1:  DEC   C
        RET   NZ

        PUSH  AF              ; Einde buffer?
        LD    A,E
        CP    BUFF2 AND 0FFH
        JR    NZ,J1

        DB    0FEH            ; Sla PUSH over
FILBUF: PUSH  AF              ; Vul buffer opnieuw
        LD    C,(HL)
        INC   HL
        LD    DE,BUFFER
        LD    B,8
DJRT1:  XOR   A
        SLA   C
        JR    NC,SKOP
        LD    A,(HL)
        INC   HL
SKOP:   LD    (DE),A
        INC   DE
        DJNZ  DJRT1
        LD    DE,BUFFER
J1:     LD    A,(DE)          ; Volgende byte uit buffer
        LD    B,A
        INC   DE
        LD    C,8
        POP   AF
        RET


SETVDP: DI
        LD    C,H
        RL    C
        RLA
        RL    C
        RLA
        OUT   (99H),A
        LD    A,8EH
        OUT   (99H),A
        LD    A,L
        OUT   (99H),A
        LD    A,H
        AND   127
        OR    64
        OUT   (99H),A
        RET

PAGE:   DB    0               ; page van 64K
BUFFER: DS    8               ; Buffer voor statusbytes
BUFF2:  DB    0               ; Hier wordt plaatje ook in RAM opgeslagen


DS    8               ; Buffer voor statusbytes
BUFF2:  DB    0               ; Hier wordt plaatje ook in R

Reply via email to