** ** $Id: CompressBlock.S,v 2.1 92/05/13 01:48:05 chris Exp $ ** $Revision: 2.1 $ ** ** $Filename: CompressBlock.S $ ** $Author: chris $ ** $Release: $ ** $Date: 92/05/13 01:48:05 $ ** ** 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 ClearError XDEF CompressBlockFunc ******* 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: * $$$ * * RESULTS * Length of compressed data or 0 if an error occurred. * * SEE ALSO * IFFL_DecompressBlock() * ***************************************************************************** CompressBlockFunc: tst.l d1 ; Modus == 0 ? beq.b Mode_Copy subq.l #1,d1 ; Modus == 1 ? beq.b Mode_CmpByteRun1 moveq.l #0,d0 rts ***************************************************************************** ** Kopiermodus Mode_Copy: movem.l d0/a6,-(SP) movea.l iffb_SysBase(a6),a6 JSRLIB CopyMem movem.l (SP)+,d0/a6 rts ***************************************************************************** ** CmpByteRun1 komprimieren Mode_CmpByteRun1: movem.l d2-d3/a2-a3,-(SP) lea (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 Linie erreicht ? bge.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 ? blt.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