** ** $Id: CompressBlock.S,v 21.3 92/05/18 02:20:39 chris Exp $ ** $Revision: 21.3 $ ** ** $Filename: CompressBlock.S $ ** $Author: chris $ ** $Date: 92/05/18 02:20:39 $ ** ** iff.library/IFFL_CompressBlock ** ** COPYRIGHT (C) 1987-1992 BY CHRISTIAN A. WEBER, BRUGGERWEG 2, ** CH-8037 ZUERICH, SWITZERLAND. ALL RIGHTS RESERVED. NO PART ** OF THIS SOFTWARE MAY BE COPIED, REPRODUCED, OR TRANSMITTED ** IN ANY FORM OR BY ANY MEANS, WITHOUT THE PRIOR WRITTEN PER- ** MISSION OF THE AUTHOR. USE AT YOUR OWN RISK. ** IDNT IFFL_CompressBlock SECTION text,CODE INCLUDE "IffLib.i" XREF SetError XDEF CompressBlockFunc XDEF Compress_NONE,Compress_BYTERUN1 ;,Compress_FIBDELTA ******* iff.library/IFFL_CompressBlock ************************************** * * NAME * IFFL_CompressBlock -- Compress a memory block * * SYNOPSIS * result = IFFL_CompressBlock( source, destination, size, mode ) * A0 A1 D0 D1 * * ULONG IFFL_CompressBlock( APTR, APTR, ULONG, ULONG ) * * FUNCTION * Compress the memory block using the appropriate compression mode. * If the compressed data would become longer than the uncompressed, * an error is returned. * * INPUTS * source - Pointer to data to compress * destination - Target address for compression * size - Number of data bytes to compress * mode - Compression mode. Currently, the following modes * are supported: * * IFFL_COMPR_NONE - Vanilla copy * IFFL_COMPR_BYTERUN1 - CmpByteRun1 (ILBM BODY data) * IFFL_COMPR_FIBDELTA - Fibonacci Delta (8SVX BODY data) * * RESULTS * Length of compressed data or 0 if an error occurred. * IFFL_IFFError() returns IFFL_ERROR_BADCOMPRESSION if you ask for * an unsupported compression mode. * * BUGS * In IFFL_COMPR_BYTERUN1, if the compressed data would become longer, * the buffer will be overwritten, and no error is returned. So be * sure to supply a destination buffer which is big enough! * * SEE ALSO * IFFL_DecompressBlock() * ***************************************************************************** CompressBlockFunc: subq.l #1,d1 beq.b Compress_BYTERUN1 ; Modus == 1 bmi.b Compress_NONE ; Modus == 0 *** Unbekannter Modus --> Error setzen movem.l a5-a6,-(SP) movea.l a6,a5 ; A5 : IFFBase für SetError() moveq.l #IFFL_ERROR_BADCOMPRESSION,d0 bsr SetError ; Setzt auch D0 auf 0 movem.l (SP)+,a5-a6 rts ***************************************************************************** ** Kopiermodus (für CompressBlock() UND DecompressBlock() benutzt) Compress_NONE: movem.l d0/a6,-(SP) movea.l iffb_SysBase(a6),a6 JSRLIB CopyMem movem.l (SP)+,d0/a6 rts ***************************************************************************** ** CmpByteRun1 komprimieren Compress_BYTERUN1: movem.l d2-d3/a2-a3,-(SP) lea 0(a0,d0.l),a2 ; A2 : Source-Endadresse moveq #0,d3 ; Byte-Zähler crunchloop: bsr.b CountEq ; wieviele gleiche Bytes folgen ? cmp.w #3,d0 ; genug gleiche Bytes zum runnen ? blt.b countdump ; nee, lohnt sich nicht -> Dumpen addq.l #2,d3 ; Markierbyte & Anzahl move.b (a0),d1 ; Wert adda.w d0,a0 ; Source anpassen subq.w #1,d0 ; muss .w sein und nicht .b !!!!!!! neg.b d0 ; negieren (= "Run"-Code) move.b d0,(a1)+ ; und eintragen move.b d1,(a1)+ ; Wert eintragen bra.b crunchcont ; weitermachen countdump: movea.l a0,a3 ; Source-Pointer retten moveq #0,d2 ; D2 : Länge des Dump-Blocks 1$: addq.b #1,d2 bmi.b 2$ ; höchstens 127 Bytes pro Block addq.l #1,a0 cmpa.l a2,a0 ; Ende der Daten erreicht ? bhs.b 3$ ; ja -> abbrechen bsr.b CountEq cmp.w #3,d0 ; Ende des Dump-Blocks ? blt.b 1$ ; noch nicht bra.b 3$ ; Ende 2$: moveq #127,d2 3$: movea.l a3,a0 ; Source-Pointer restaurieren add.l d2,d3 ; zur Gesamtanzahl dazuzählen addq.l #1,d3 ; Markierbyte nicht vergessen subq.w #1,d2 ; aus 1..128 mach 0..127 move.b d2,(a1)+ ; Markierbyte eintragen 4$: move.b (a0)+,(a1)+ ; Datenbytes eintragen dbf d2,4$ crunchcont: cmpa.l a2,a0 ; Ende der Linie erreicht ? blo.b crunchloop ; noch nicht! move.l d3,d0 ; Return: Anzahl Destination-Bytes movem.l (SP)+,d2-d3/a2-a3 rts *** Anzahl gleicher Zeichen ab (a0) zählen und nach D0 CountEq: move.l a0,-(SP) moveq #1,d0 ; D0 : Anzahl gleiche Bytes 1$: move.b (a0)+,d1 ; erstes Byte 2$: cmp.b (a0)+,d1 ; Byte gleich wie letztes Byte ? bne.b 3$ ; nein -> abbrechen cmp.w #128,d0 bge.b 3$ ; höchstens 128 gleiche addq.w #1,d0 ; Anzahl erhöhen cmpa.l a2,a0 ; Ende des Buffers erreicht ? blo.b 2$ ; noch nicht -> weiterzählen 3$: move.l (SP)+,a0 rts END