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