| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212 |
- IMPLEMENTATION MODULE MemCompress;
- (*
- * REPERTOIRE
- * Release 1.6
- * By Charles Bradford and Cole Brecheen
- * (c) Copyright 1985-1992 PMI
- * Green Bay, Wisconsin
- * All rights reserved
- * (414) 468-6040
- *
- * $Header: D:/logfiles/mods/memcompr.mov 1.5 10 Mar 1991 15:29:32 coleb $
- *
- *
- * Written and contributed by Doug Whitfield of Hornby Island,
- * British Columbia.
- *
- *)
- IMPORT SYSTEM;
- IMPORT LowLevel;
- IMPORT VStorage;
- VAR
- Initialized : BOOLEAN;
- PROCEDURE Init();
- BEGIN
- IF Initialized THEN
- RETURN;
- ELSE
- Initialized := TRUE;
- END;
- LowLevel.Init();
- VStorage.Init();
- END Init;
- (* These procedures perform run-length coding compression and
- decompression of memory blocks. InAddress and InSize are input
- parameters specifing the starting address and length (in bytes)
- of the memory block to be compressed or decompressed. If
- OutAlloc is TRUE, OutAddress and OutSize are taken as input
- parameters by Compress and the compressed block is put at the
- specified location. If OutAlloc is FALSE, Compress attempts to
- allocate memory for the compressed block. If the allocation
- fails, the compression is abandoned and Compress returns the
- value FALSE with ErrorFlag set to AllocationFailed. If the
- allocation is successful, Compress returns the allocated area's
- address and size. The maximum size of memory block it will
- allocate is InSize bytes. If, during compression, the compressed
- block exceeds the specified OutSize (when OutAlloc is TRUE) or
- InSize (when OutAlloc is FALSE), the compression is abandoned and
- Compress returns the value FALSE, with ErrorFlag set to
- CompressedTooLarge. (A compressed block can exceed the size of
- the uncompressed block from which it is derived if the latter
- contains characters with ordinal value 254, as this value is used
- as a designator for the start of a run, and isolated occurences
- of this character must be translated into two successive
- characters to avoid ambiguity.) If compression is successfully
- completed, Compress returns the value TRUE with ErrorFlag set to
- NoCompressError.
- Decompress performs no error testing, and thus assumes that the
- size of memory specified to receive the decompressed block is
- sufficiently large. If Decompress is called with OutSize equal
- to the value of InSize used during compression, this will be
- true.
- Compress will yield a useful degree of compression if the input
- memory block contains runs of successive bytes containing the
- same value. Such may be the case, for example, in CGA and EGA
- graphics mode screen images. *)
- TYPE
- Address8086 =
- RECORD
- CASE : CARDINAL OF
- 1 :
- a : SYSTEM.ADDRESS;
- |2 :
- b : POINTER TO CHAR;
- END;
- END;
- VAR
- NewCharOrd, OldCharOrd, TempOutSize: CARDINAL;
- InCount, OutCount, RunCount, MaxRunCount, CharOrd, Index:
- CARDINAL;
- InAddress, OutAddress: SYSTEM.ADDRESS;
- InCharPointer, OutCharPointer: Address8086;
- Char: CHAR;
- PROCEDURE GetChar():CARDINAL;
- BEGIN
- Char := InCharPointer.b^;
- LowLevel.IncAddr( InCharPointer.a, 1 );
- INC (InCount);
- RETURN ORD(Char);
- END GetChar;
- PROCEDURE PutChar (CharOrd:CARDINAL);
- BEGIN
- Char := CHR (CharOrd);
- OutCharPointer.b^ := Char;
- LowLevel.IncAddr( OutCharPointer.a, 1 );
- INC(OutCount);
- END PutChar;
- PROCEDURE CompOut (CharOrd:CARDINAL;RunCount:CARDINAL);
- BEGIN
- IF CharOrd = 254 THEN
- IF RunCount > 1 THEN
- PutChar(254); PutChar(RunCount); PutChar(254)
- ELSE
- PutChar(254); PutChar(254)
- END (*IF*);
- ELSE
- IF RunCount = 1 THEN
- PutChar(CharOrd)
- ELSIF RunCount = 2 THEN
- PutChar(CharOrd); PutChar(CharOrd)
- ELSE
- PutChar(254); PutChar(RunCount);PutChar(CharOrd)
- END (*IF*);
- END (*IF*);
- END CompOut;
- PROCEDURE Compress (InAddress: SYSTEM.ADDRESS; InSize:CARDINAL;
- VAR OutAddress: SYSTEM.ADDRESS; VAR OutSize:CARDINAL;
- OutAlloc:BOOLEAN):BOOLEAN;
- BEGIN
- ErrorFlag := Corruption;
- IF NOT OutAlloc THEN
- IF VStorage.DosAvail (InSize + 5) THEN
- VStorage.DosAlloc(OutAddress, InSize + 5);
- TempOutSize := InSize
- ELSE
- ErrorFlag := AllocationFailed;
- RETURN FALSE;
- END;
- ELSE
- TempOutSize := OutSize
- END;
- InCharPointer.a := InAddress; OutCharPointer.a := OutAddress;
- InCount := 0; OutCount :=0;
- OldCharOrd := GetChar();
- LOOP
- RunCount := 1;
- MaxRunCount := InSize - InCount + 1;
- IF MaxRunCount > 253 THEN MaxRunCount := 253 END;
- LOOP
- NewCharOrd :=GetChar();
- IF NewCharOrd = OldCharOrd THEN
- INC (RunCount);
- IF RunCount = MaxRunCount THEN EXIT END
- ELSE
- EXIT
- END (*IF*)
- END (*LOOP*);
- CompOut (OldCharOrd,RunCount);
- IF OutCount >= TempOutSize THEN;
- IF NOT OutAlloc THEN
- VStorage.DosDealloc(OutAddress,InSize + 5);
- END;
- ErrorFlag := CompressedTooLarge;
- RETURN FALSE
- END;
- OldCharOrd := NewCharOrd;
- IF InCount = InSize THEN
- IF RunCount # MaxRunCount THEN CompOut (OldCharOrd,1) END;
- EXIT
- END (*IF*)
- END (*LOOP*);
- IF NOT OutAlloc THEN
- OutSize := OutCount;
- VStorage.DosDealloc(OutCharPointer.a,InSize + 5 - OutSize);
- END;
- ErrorFlag := NoCompressError;
- RETURN TRUE;
- END Compress;
- PROCEDURE Decompress (InAddress: SYSTEM.ADDRESS; InSize:CARDINAL;
- OutAddress: SYSTEM.ADDRESS; OutSize:CARDINAL);
- BEGIN
- InCharPointer.a := InAddress; OutCharPointer.a := OutAddress;
- InCount := 0; OutCount := 0;
- WHILE InCount < InSize DO
- CharOrd := GetChar();
- IF CharOrd = 254 THEN
- RunCount := GetChar();
- IF RunCount = 254 THEN
- PutChar (254)
- ELSE
- CharOrd := GetChar();
- FOR Index := 1 TO RunCount DO
- PutChar (CharOrd);
- END (*FOR*)
- END (*IF*);
- ELSE
- PutChar (CharOrd)
- END (*IF*)
- END (*WHILE*);
- OutSize := OutCount;
- END Decompress;
- BEGIN
- Initialized := FALSE;
- Init();
- END MemCompress.
|