diff options
Diffstat (limited to 'private/windows/diamond/quantum')
31 files changed, 5168 insertions, 0 deletions
diff --git a/private/windows/diamond/quantum/arc.h b/private/windows/diamond/quantum/arc.h new file mode 100644 index 000000000..3e196da50 --- /dev/null +++ b/private/windows/diamond/quantum/arc.h @@ -0,0 +1,28 @@ +// ARC.H +// +// Quantum file archiver and compressor +// Advanced data compression +// +// Copyright (c) 1993,1994 David Stafford +// All rights reserved. + +#ifndef __ARC +#define __ARC + +#include <stdio.h> +#include "quantum.h" + + +typedef struct + { + FILE *ArcFile, *TxtFile; + APARMS *AParms; + int OpenCounter; + } ARC; + + +void Arc_Header_Read( APARMS *AParms ); +void Arc_Create( APARMS *AParms ); +void Arc_Extract( APARMS *AParms, BOOL ExtractFlag ); + +#endif // arc.h diff --git a/private/windows/diamond/quantum/arith.c b/private/windows/diamond/quantum/arith.c new file mode 100644 index 000000000..bc30a0e89 --- /dev/null +++ b/private/windows/diamond/quantum/arith.c @@ -0,0 +1,364 @@ +// ARITH.C +// +// Quantum file archiver and compressor +// Advanced data compression +// +// Copyright (c) 1993,1994 Cinematronics +// All rights reserved. +// +// This file contains trade secrets of Cinematronics. +// Do NOT distribute! + +#include "arith.h" +#include "bit.h" + + +#define CODE_VALUE_BITS 16 // number of bits in a code value + +#define TOP_VALUE ((1L << CODE_VALUE_BITS)-1) // largest code value + + +#ifdef PAQ + +struct + { + unsigned short Low, High; + unsigned short Code; + int UnderflowBits; + } Arith; + + +void FAST Arith_Init( void ) + { + Bit_Init(); + + Arith.Low = 0; + Arith.High = TOP_VALUE; + Arith.UnderflowBits = 0; + } + + +// Flush the remaining significant bits. + +void FAST Arith_Close( void ) + { + Bit_Write( Arith.Low & 0x4000 ); + + Arith.UnderflowBits++; + + while( Arith.UnderflowBits > 0 ) + { + Bit_Write( ~Arith.Low & 0x4000 ); + + Arith.UnderflowBits--; + } + + // Just output enough bits to fill another word so we don't + // run out of bits in the final call to Arith_Remove_Symbol. + + Bit_Write( 0 ); Bit_Write( 0 ); Bit_Write( 0 ); Bit_Write( 0 ); + Bit_Write( 0 ); Bit_Write( 0 ); Bit_Write( 0 ); Bit_Write( 0 ); + Bit_Write( 0 ); Bit_Write( 0 ); Bit_Write( 0 ); Bit_Write( 0 ); + Bit_Write( 0 ); Bit_Write( 0 ); Bit_Write( 0 ); Bit_Write( 0 ); + + Bit_Flush(); + } + + +void FAST Arith_Encode_Bits( int Value, int NumBits ) + { +#ifdef BIT_CONSTANTS + Bit_Delayed_Write( CODE_VALUE_BITS + Arith.UnderflowBits, Value, NumBits ); +#else + SYMBOL Symbol; + int V; + + if( NumBits >= 12 ) + { + NumBits -= 12; + + V = Value >> NumBits; + + Symbol.Scale = 1 << 12; + Symbol.Low = V & ((1 << 12) - 1); + Symbol.High = Symbol.Low + 1; + + Arith_Encode_Symbol( &Symbol ); + } + + if( NumBits ) + { + Symbol.Scale = 1 << NumBits; + Symbol.Low = Value & (Symbol.Scale - 1); + Symbol.High = Symbol.Low + 1; + + Arith_Encode_Symbol( &Symbol ); + } +#endif + } + + +void FAST Arith_Encode_Symbol( SYMBOL *Symbol ) + { + unsigned long Range; + + // These three lines rescale high and low for the new symbol. + + Range = (unsigned long) (Arith.High - Arith.Low) + 1L; + Arith.High = Arith.Low + + (unsigned short)((Range * Symbol->High) / Symbol->Scale - 1); + Arith.Low = Arith.Low + + (unsigned short)((Range * Symbol->Low) / Symbol->Scale); + + // This loop turns out new bits until high and low are far enough + // apart to have stabilized. + + while( 1 ) + { + // If this test passes, it means that the MSDigits match, and can + // be sent to the output stream. + + if( (Arith.High & 0x8000) == (Arith.Low & 0x8000) ) + { + Bit_Write( Arith.High & 0x8000 ); + + while( Arith.UnderflowBits > 0 ) + { + Bit_Write( ~Arith.High & 0x8000 ); + + Arith.UnderflowBits--; + } + } + else + { + // If this test passes, the numbers are in danger of underflow, because + // the MSDigits don't match, and the 2nd digits are just one apart. + + if( (Arith.Low & 0x4000) && !(Arith.High & 0x4000) ) + { + Arith.UnderflowBits++; + + Arith.Low &= 0x3FFF; + Arith.High |= 0x4000; + } + else + { + return; + } + } + + Arith.Low <<= 1; + Arith.High <<= 1; + + Arith.High++; + } + } + +#else // UNPAQ + +#ifdef UNPAQLIB + +extern char *pbSource; +extern int cbSource; +extern int fSourceOverflow; + +static int BitsValid; +static int BitsValue; + +#define Bit_Init() /* void Bit_Init(void) */ \ + ( /* { */ \ + BitsValid = 0 /* BitsValid = 0; */ \ + ) /* } */ + +#define Bit_Read() /* int Bit_Read(void) */ \ + ( /* { */ \ + BitsValid ? /* if (BitsValid != 0) */ \ + ( /* { */ \ + BitsValid--, /* BitsValid--; */ \ + BitsValue <<= 1, /* BitsValue <<= 1; */ \ + (BitsValue & 0x0100) /* return(BitsValue & 0x0100); */ \ + ) /* } */ \ + : /* else */ \ + ( /* { */ \ + cbSource ? /* if (cbSource != 0) */ \ + ( /* { */ \ + cbSource--, /* cbSource--; */ \ + BitsValid = 7, /* BitsValid = 7; */ \ + BitsValue = *pbSource++, /* BitsValue = *pbSource++; */ \ + BitsValue <<= 1, /* BitsValue <<= 1; */ \ + (BitsValue & 0x0100) /* return(BitsValue & 0x0100); */ \ + ) /* } */ \ + : /* else */ \ + ( /* { */ \ + fSourceOverflow = 1, /* fSourceOverflow = 1; */ \ + 0 /* return(0); */ \ + ) /* } */ \ + ) /* } */ \ + ) /* } */ + +#endif /* def UNPAQLIB */ + +struct + { + unsigned short Low, High; + unsigned short Code; + } Arith; + + +void FAST Arith_Init( void ) + { + int i; + + Bit_Init(); + + for( i = sizeof( Arith.Code ) * 8; i; i-- ) + { + Arith.Code <<= 1; + if (Bit_Read()) + { + Arith.Code |= 1; + } + } + + Arith.Low = 0; + Arith.High = TOP_VALUE; + } + + +long FAST Arith_Decode_Bits( int NumBits ) + { +#ifdef BIT_CONSTANTS + register long Value = 0; + + while( NumBits-- ) + { + Value <<= 1; + + if (Bit_Read()) + { + Value |= 1; + } + } + + return( Value ); +#else + long Value = 0; + SYMBOL Symbol; + int i; + + if( NumBits >= 12 ) + { + NumBits -= 12; + + Symbol.Scale = 1 << 12; + + Value = Arith_GetCount( Symbol.Scale ); + + Symbol.Low = Value; + Symbol.High = Value + 1; + + Arith_Remove_Symbol( Symbol ); + } + + if( NumBits ) + { + Symbol.Scale = 1 << NumBits; + + i = Arith_GetCount( Symbol.Scale ); + + Symbol.Low = i; + Symbol.High = i + 1; + + Arith_Remove_Symbol( Symbol ); + + Value = (Value << NumBits) + i; + } + + return( Value ); +#endif + } + + +/* + * When decoding, this routine is called to figure out which symbol + * is presently waiting to be decoded. This routine expects to get + * the current model scale in the s->scale parameter, and it returns + * a count that corresponds to the present floating point code: + * + * code = count / s->scale + */ + +int FAST2 Arith_GetCount( unsigned short Scale ) + { + unsigned long Range; + short int Count; + + Range = (unsigned long) (Arith.High - Arith.Low) + 1L; + Count = (short) ( (( + (unsigned long)(Arith.Code - Arith.Low) + 1L) * Scale - 1) / Range); + + return( Count ); + } + + +void FAST Arith_Close( void ) + { + } + + +/* + * Just figuring out what the present symbol is doesn't remove + * it from the input bit stream. After the character has been + * decoded, this routine has to be called to remove it from the + * input stream. + */ + +void FAST2 Arith_Remove_Symbol( SYMBOL Symbol ) + { + unsigned long Range; + + // First, the range is expanded to account for the symbol removal. + + Range = (unsigned long) (Arith.High - Arith.Low) + 1L; + Arith.High = Arith.Low + + (unsigned short)((Range * Symbol.High) / Symbol.Scale - 1); + Arith.Low = Arith.Low + + (unsigned short)((Range * Symbol.Low) / Symbol.Scale); + + // Next, any possible bits are shipped out. + + while( 1 ) + { + // If the MSDigits match, the bits will be shifted out. + + if ((Arith.High ^ Arith.Low) & 0x8000) + { + // Else, if underflow is threatening, shift out the 2nd MSDigit. + + if( (Arith.Low & 0x4000) && (Arith.High & 0x4000) == 0 ) + { + Arith.Code ^= 0x4000; + Arith.Low &= 0x3FFF; + Arith.High |= 0x4000; + } + else + { + // Otherwise, nothing can be shifted out, so I return. + + return; + } + } + + Arith.Low <<= 1; + Arith.High <<= 1; + Arith.High |= 1; + Arith.Code <<= 1; + + if (Bit_Read()) + { + Arith.Code |= 1; + } + } + } + +#endif /* PAQ */ diff --git a/private/windows/diamond/quantum/arith.h b/private/windows/diamond/quantum/arith.h new file mode 100644 index 000000000..c80bf349a --- /dev/null +++ b/private/windows/diamond/quantum/arith.h @@ -0,0 +1,32 @@ +// ARITH.H +// +// Quantum file archiver and compressor +// Advanced data compression +// +// Copyright (c) 1993,1994 David Stafford +// All rights reserved. + +#ifndef __ARITH +#define __ARITH + +#include "defs.h" + +typedef struct + { + unsigned short Low, High; + unsigned short Scale; + } SYMBOL; + + +void FAST Arith_Init( void ); +void FAST Arith_Close( void ); + +void FAST Arith_Encode_Symbol( SYMBOL *Symbol ); +void FAST Arith_Encode_Bits( int Value, int NumBits ); + +long FAST Arith_Decode_Bits( int NumBits ); + +int FAST2 Arith_GetCount( unsigned short Scale ); +void FAST2 Arith_Remove_Symbol( SYMBOL Symbol ); + +#endif // arith.h diff --git a/private/windows/diamond/quantum/bit.c b/private/windows/diamond/quantum/bit.c new file mode 100644 index 000000000..ebf9b8d65 --- /dev/null +++ b/private/windows/diamond/quantum/bit.c @@ -0,0 +1,201 @@ +// BIT.C +// +// Quantum file archiver and compressor +// Advanced data compression +// +// Copyright (c) 1993,1994 Cinematronics +// All rights reserved. +// +// This file contains trade secrets of Cinematronics. +// Do NOT distribute! + +#include <stdio.h> +#include <stdlib.h> + +#ifndef PAQLIB //msliger +#include "arc.h" +#endif //msliger + +#ifdef PAQLIB //msliger +#include "quantum.h" //msliger +#endif //msliger + +#include "bit.h" + +#ifndef PAQLIB //msliger +extern ARC Arc; //msliger +#endif //msliger + +#ifdef PAQLIB //msliger +extern char *pbTarget; //msliger +extern int cbTarget; //msliger +extern int fTargetOverflow; //msliger +extern int cbResult; //msliger +#endif //msliger + + +#define DELAYED_WRITE_QUEUE_SIZE 512 + +typedef struct _DELAYED_WRITE + { + long BitCounter; // when TotalBits == BitCounter, write it out + int Value; + int NumBits; + struct _DELAYED_WRITE *Next; // for the circular queue + } DELAYED_WRITE; + + +struct + { + int NumBits; + long TotalBits; + short This; + +#ifdef BIT_CONSTANTS + DELAYED_WRITE *Head, *Tail; // circular queue of delayed writes + DELAYED_WRITE Queue[ DELAYED_WRITE_QUEUE_SIZE ]; + long QueueSize; // number of bits waiting in the queue +#endif + } Bit; + + +#ifdef PAQ //msliger +#ifndef PAQLIB //msliger +long Bit_GetTotal( void ) + { + return( Bit.TotalBits ); + } +#endif //PAQLIB //msliger +#endif //PAQ //msliger + + +void Bit_Init( void ) + { +#ifdef BIT_CONSTANTS //msliger + int i; +#endif //msliger + + Bit.TotalBits = Bit.NumBits = 0; + +#ifdef BIT_CONSTANTS + for( i = 0; i < DELAYED_WRITE_QUEUE_SIZE - 1; i++ ) + { + Bit.Queue[ i ].Next = &Bit.Queue[ i + 1 ]; + } + + Bit.Queue[ DELAYED_WRITE_QUEUE_SIZE - 1 ].Next = Bit.Queue; + + Bit.Head = Bit.Tail = Bit.Queue; + Bit.QueueSize = 0; +#endif + } + +#ifdef UNPAQ //msliger + +int Bit_Read( void ) + { + if( !Bit.NumBits ) + { + Bit.NumBits = 8; + + if( (Bit.This = fgetc( Arc.ArcFile )) == EOF ) + { + puts( "ERR: Premature EOF in input." ); + exit( -1 ); + } + } + + Bit.This <<= 1; + Bit.NumBits--; + + return( Bit.This & 0x0100 ); + } + +#endif /* UNPAQ */ //msliger + +#ifdef PAQ //msliger + +void Bit_Write( int Value ) + { + Bit.This <<= 1; + + if( Value ) Bit.This++; + + Bit.TotalBits++; + + if( ++Bit.NumBits == 8 ) + { + Bit.NumBits = 0; +#ifndef PAQLIB //msliger + putc( Bit.This, Arc.ArcFile ); +#else //msliger + if (cbTarget) //msliger + { //msliger + cbTarget--; //msliger + *pbTarget++ = (BYTE) Bit.This; //msliger + cbResult++; //msliger + } //msliger + else //msliger + { //msliger + fTargetOverflow = 1; //msliger + } //msliger +#endif //msliger + } + +#ifdef BIT_CONSTANTS + // Write out any bits that have been buffered. + + while( Bit.QueueSize && Bit.Head->BitCounter == Bit.TotalBits ) + { + Bit.QueueSize -= Bit.Head->NumBits; + + while( Bit.Head->NumBits-- ) + { + Bit_Write( Bit.Head->Value & (1L << Bit.Head->NumBits) ); + } + + Bit.Head = Bit.Head->Next; + } +#endif + } + + +#ifdef BIT_CONSTANTS +void Bit_Delayed_Write( int Delay, int Value, int NumBits ) + { + if( NumBits ) + { + Bit.Tail->BitCounter = Bit.TotalBits + Bit.QueueSize + Delay; + Bit.Tail->Value = Value; + Bit.Tail->NumBits = NumBits; + + Bit.Tail = Bit.Tail->Next; + + Bit.QueueSize += NumBits; + + if( Bit.Tail == Bit.Head ) + { + puts( "ERR: Delayed-write buffer overflowed." ); + exit( -1 ); + } + } + } +#endif + + +void Bit_Flush( void ) + { + while( Bit.NumBits ) + { + Bit_Write( 0 ); + } + +#ifdef BIT_CONSTANTS + if( Bit.QueueSize ) + { + puts( "ERR: Delayed-write buffer underflowed." ); + exit( -1 ); + } +#endif + } +#endif /* PAQ */ //msliger diff --git a/private/windows/diamond/quantum/bit.h b/private/windows/diamond/quantum/bit.h new file mode 100644 index 000000000..fe3fc6ddc --- /dev/null +++ b/private/windows/diamond/quantum/bit.h @@ -0,0 +1,20 @@ +// BIT.H +// +// Quantum file archiver and compressor +// Advanced data compression +// +// Copyright (c) 1993,1994 David Stafford +// All rights reserved. + +#ifndef __BITIO +#define __BITIO + + +void Bit_Init( void ); +int Bit_Read( void ); +void Bit_Write( int Value ); +void Bit_Delayed_Write( int Delay, int Value, int NumBits ); +void Bit_Flush( void ); +long Bit_GetTotal( void ); + +#endif // bit.h diff --git a/private/windows/diamond/quantum/comp.c b/private/windows/diamond/quantum/comp.c new file mode 100644 index 000000000..1d066fdee --- /dev/null +++ b/private/windows/diamond/quantum/comp.c @@ -0,0 +1,1103 @@ +// COMP.C +// +// Quantum file archiver and compressor +// Advanced data compression +// +// Copyright (c) 1993,1994 Cinematronics +// All rights reserved. +// +// This file contains trade secrets of Cinematronics. +// Do NOT distribute! + +/* + * History + * + * 06-Jul-1994 msliger fixes for MIPS + */ + +#include <stdio.h> +#include <stdlib.h> + +#ifdef STAFFORD +#include <alloc.h> +#include <mem.h> +#else +#include <string.h> // Get memmove() +#endif // STAFFORD + +#include "quantum.h" +#ifndef PAQLIB //msliger +#include "arc.h" +#endif //msliger +#include "rtl.h" +#include "comp.h" +#include "lz.h" + +#ifdef PAQLIB //msliger +#include "arith.h" //msliger +#endif //msliger + + +#ifndef PAQLIB //msliger +extern ARC Arc; +#endif //msliger + + +#define HASH_SHIFT 6 +#define HASH_BITS (HASH_SHIFT * 3) + +#define HASH_MASK ((1L << HASH_BITS) - 1) +#define HASH_UPDATE( x ) \ + (Comp.HashVal = (WORD)(((Comp.HashVal << HASH_SHIFT) ^ (x)) & HASH_MASK)) + //4 1 1321 1 1 12 34 + + +#define HASH_TABLE_SIZE (1L << HASH_BITS) + +#define MAX_MOVES 8 +#define MAX_MATCHES (MAX_MOVES-1) + + +typedef struct + { +#ifndef PAQLIB //msliger + FILE *TxtFile; // the current file being compressed +#else //msliger + BYTE *pbSource; //msliger the source data buffer + int cbSource; //msliger available source data size + BYTE WindowBits; //msliger needed in Comp_Reset() +#endif //msliger + + BYTE *Buf; // the file buffer + int Cur; // current position in the buffer + int Left; // left and right edges in the buffer + int Right; + + long BufSize; // size of the buffer + + DWORD FileSize; // size of the file being compressed + DWORD Compressed; // bytes compressed so far + + int *MatchTable; // hash table for identifying matches + int *MatchChain; // match chain + + long WindowSize; // size of the history window + + long ValidDistances[ MATCH_MAX + 1 ]; // valid distances for each match len + + WORD HashVal; // current hash value + + int MatchFutilityCutoff; + int MaxMatches; + +#ifndef PAQLIB //msliger + BOOL ShowStatus; + + WORD Checksum; +#endif //msliger + //msliger + int ReachedEOF; //msliger track EOF, don't refill after + //msliger + int CompressionLevel; //msliger selected compression level + } COMP; + + +COMP Comp; + + +// Fills the buffer for compression. + +void Comp_FillBuf( void ) + { + static int c; + int i; + + // Need to move the characters down the buffer? + + if( Comp.Left > 0 ) + { + memmove( Comp.Buf, Comp.Buf + Comp.Left, Comp.Right - Comp.Left ); + + memmove( Comp.MatchChain, + Comp.MatchChain + Comp.Left, + (Comp.Right - Comp.Left) * sizeof( *Comp.MatchChain ) ); + + for( i = 0; i < HASH_TABLE_SIZE; i++ ) + { + Comp.MatchTable[ i ] -= Comp.Left; + + if( Comp.MatchTable[ i ] < 0 ) Comp.MatchTable[ i ] = -1; + } + + Comp.Cur -= Comp.Left; + Comp.Right -= Comp.Left; + + for( i = 0; i < Comp.Cur; i++ ) + { + if (Comp.MatchChain[ i ] >= 0) //msliger + { //msliger + Comp.MatchChain[ i ] -= Comp.Left; + //msliger + if( Comp.MatchChain[ i ] < 0 ) Comp.MatchChain[ i ] = -1; //msliger + } //msliger + } + + Comp.Left = 0; + } + + // Fill the rest of the buffer from the input file. + + c = ~EOF; //msliger + + while( Comp.Right < Comp.BufSize && +#ifndef PAQLIB //msliger + (c = getc( Comp.TxtFile )) != EOF ) +#else //msliger + (c = Comp.cbSource ? //msliger + (Comp.cbSource--, *Comp.pbSource++) : EOF) != EOF) //msliger +#endif //msliger + { + Comp.Buf[ Comp.Right++ ] = c; + +#ifndef PAQLIB //msliger + Comp.Checksum ^= c; + + if( Comp.Checksum & 0x8000 ) // simulate a ROL in C, yucky! + { + Comp.Checksum <<= 1; + Comp.Checksum++; + } + else + { + Comp.Checksum <<= 1; + } +#endif // !PAQLIB //msliger + } + if (c == EOF) //msliger + { //msliger + Comp.ReachedEOF = 1; //msliger + } //msliger + } + + +#include <sys\stat.h> + +void Comp_Init( BYTE WindowBits, int CompressionLevel ) //msliger + { + int i; + long MinBufSize; + BYTE *TotalBuf; + void *Reserved; +#ifndef PAQLIB //msliger + struct stat statbuf; + + // If stdout is redirected to a file don't + // display the percent-complete info. + + fstat( fileno( stdout ), &statbuf ); + Comp.ShowStatus = (statbuf.st_mode & S_IFCHR); +#endif //msliger + + Comp.WindowSize = 1 << WindowBits; + Comp.CompressionLevel = CompressionLevel; //msliger + +#ifdef PAQLIB //msliger + Comp.WindowBits = WindowBits; //msliger +#endif //msliger + + Comp.ValidDistances[ MATCH_MIN ] = (1L << TINY_WINDOW_MAX); + Comp.ValidDistances[ MATCH_MIN + 1 ] = (1L << SHORT_WINDOW_MAX); + + for( i = MATCH_MIN + 2; i <= MATCH_MAX; i++ ) + { + Comp.ValidDistances[ i ] = (1L << WINDOW_MAX) - 1; + } + + Lz_Init( WindowBits ); //msliger + + // Set aside 64K of reserved space so we don't use all + // available memory for the history buffer. This is just + // to make sure there is room for file buffers, growing + // the stack etc later. + + Reserved = Rtl_Malloc( 64 * 1024L ); + + Comp.MatchTable = Rtl_Malloc( HASH_TABLE_SIZE * sizeof( int ) ); + + MinBufSize = Comp.WindowSize + MATCH_MAX + 1024; + +#if 1 + for( Comp.BufSize = MinBufSize * 2; + Comp.BufSize >= MinBufSize; + Comp.BufSize -= 0x8000 ) + { + TotalBuf = Rtl_Malloc( Comp.BufSize * (sizeof( int ) + 1) ); + + if( TotalBuf ) break; + } +#else + Comp.BufSize = MinBufSize * 5 / 4; + + TotalBuf = Rtl_Malloc( Comp.BufSize * (sizeof( int ) + 1) ); +#endif + + if( !TotalBuf || !Reserved || !Comp.MatchTable ) + { + puts( "ERR: Out of memory." ); + exit( -1 ); + } + + Rtl_Free( Reserved ); + + /* moved the int's first to dodge a MIPS alignment fault */ + + Comp.MatchChain = (int *) TotalBuf; + Comp.Buf = TotalBuf + Comp.BufSize * sizeof(int); + + if( Comp.BufSize < MinBufSize * 4 / 3 ) + { + if( Comp.BufSize < MinBufSize * 8 / 7 ) + { + puts( "\nCritically short of memory." ); + puts( "Compression will be much slower." ); + } + else + { + puts( "\nA few quarts low on memory." ); + puts( "Compression will be slower." ); + } + } + +//BUGBUG 25-May-94 msliger Init of hash tables should be done with memset + for( i = 0; i < HASH_TABLE_SIZE; i++ ) + { + Comp.MatchTable[ i ] = -1; + } + + for( i = 0; i < Comp.BufSize; i++ ) + { + Comp.MatchChain[ i ] = -1; + } + + Comp.Left = Comp.Cur = Comp.Right = 0; + } + + +// Searches for the longest match in the buffer. +// Returns the match length. + +int Comp_FindLongestMatch( MATCH *Match ) + { + BYTE *Str; + BYTE *Cur; + int Rover; + int More = Comp.MatchFutilityCutoff; + int Len; + int Max; + + Match->Len = 0; + + if( (Rover = Comp.MatchTable[ Comp.HashVal ]) < 0 ) + { + return( 0 ); + } + + Max = min( Comp.Right - Comp.Cur, MATCH_MAX ); + + if( Max >= MATCH_MIN ) + { + while( Rover >= Comp.Left ) + { + Cur = Comp.Buf + Comp.Cur; + Str = Comp.Buf + Rover; + Len = 0; + + while( *Str == *Cur && Len < Max ) + { + Len++; + Str++; + Cur++; + } + + if( Len > Match->Len && Len >= MATCH_MIN ) + { + if( Cur - Str <= Comp.ValidDistances[ Len ] ) + { + More = Comp.MatchFutilityCutoff; + + Match->Len = Len; + Match->Dist = Cur - Str; + + if( Len == Max ) return( Len ); + } + } + + if( !--More ) return( Match->Len ); + + Rover = Comp.MatchChain[ Rover ]; + } + } + + return( Match->Len ); + } + + +// Searches for the longest matches in the buffer. +// Returns the number of matches found. +// +// The matches are returned in order of length, that is, +// Match[ 0 ] is the longest. + +int New_Comp_FindLongestMatches( MATCH Match[ MAX_MATCHES ] ) + { + BYTE *Str, *Cur; + int i, NumMatches = 0, Rover, More = Comp.MatchFutilityCutoff; + int Len; + int Max; + + Match[ 0 ].Len = 0; + + if( (Rover = Comp.MatchTable[ Comp.HashVal ]) < 0 ) + { + return( 0 ); + } + + Max = min( Comp.Right - Comp.Cur, MATCH_MAX ); + + if( Max >= MATCH_MIN ) + { + while( Rover >= Comp.Left ) + { + Cur = Comp.Buf + Comp.Cur; + Str = Comp.Buf + Rover; + Len = 0; + + while( *Str == *Cur && Len < Max ) + { + Len++; + Str++; + Cur++; + } + + if( Len > Match[ 0 ].Len && Len >= MATCH_MIN ) + { + if( Cur - Str <= Comp.ValidDistances[ Len ] ) + { + More = Comp.MatchFutilityCutoff; + + // Move the other matches down + for( i = Comp.MaxMatches - 1; i > 0; i-- ) + { + Match[ i ] = Match[ i - 1 ]; + } + + Match[ 0 ].Len = Len; + Match[ 0 ].Dist = Cur - Str; + + if( NumMatches < Comp.MaxMatches ) NumMatches++; + + if( Len == Max ) break; + } + } + + if( !--More ) break; + + Rover = Comp.MatchChain[ Rover ]; + } + } + + return( NumMatches ); + } + + +int Comp_FindLongestMatches( MATCH Match[ MAX_MATCHES ] ) + { + int i, j, Num; + + Num = New_Comp_FindLongestMatches( Match ); + + if( Num == 0 || Num == Comp.MaxMatches ) return( Num ); + + // OK, here's a trick. If there are fewer than Comp.MaxMatches matches try + // to synthesize shorter matches by copying matches and reducing their + // lengths by one. + + for( i = 0; i < Num - 1 && Num < Comp.MaxMatches; i++ ) + { + if( Match[ i ].Len > Match[ i + 1 ].Len + 1 ) + { + if( Match[ i ].Dist <= Comp.ValidDistances[ Match[ i ].Len - 1 ] ) + { + // Move the other matches down + for( j = Num; j > i; j-- ) + { + Match[ j ] = Match[ j - 1 ]; + } + + Match[ i + 1 ].Len--; + + Num++; + } + } + } + + for( i = 1; i < Comp.MaxMatches; i++ ) + { + if( i == Num ) + { + Match[ i ] = Match[ i - 1 ]; + + Match[ i ].Len--; + + if( Match[ i ].Dist <= Comp.ValidDistances[ Match[ i ].Len ] ) + { + Num++; + } + } + } + + return( Num ); + } + + +void Comp_Advance( int NumBytes ) + { + Comp.Compressed += NumBytes; + + while( NumBytes-- ) + { + Comp.MatchChain[ Comp.Cur ] = Comp.MatchTable[ Comp.HashVal ]; + + #ifdef DEBUG + if( Comp.MatchChain[ Comp.Cur ] >= Comp.Cur ) + { + puts( "ERR: Advance." ); + exit( -1 ); + } + #endif + + Comp.MatchTable[ Comp.HashVal ] = Comp.Cur; + + Comp.Cur++; + + HASH_UPDATE( Comp.Buf[ Comp.Cur + 2 ] ); + } + + if( Comp.Cur > Comp.WindowSize ) + { + Comp.Left = Comp.Cur - Comp.WindowSize; + } + else + { + Comp.Left = 0; + } + +//BUGBUG 25-May-94 msliger (fixed) needed buffer refill before WindowSize +// So I moved the refill call down to make it not conditional on +// Cur > WindowSize. +//BUGBUG 25-May-94 msliger (fixed) Source data overshoot +// This code must limit itself to the amount of data currently in +// the window. The size of the buffer is immaterial at this point. + if (( Comp.Cur >= Comp.Right - MATCH_MAX ) //msliger + && (!Comp.ReachedEOF)) //msliger no needless memmove + { //msliger + Comp_FillBuf(); //msliger + } //msliger + } + + +int Comp_FindBetterMatch( int OldMatchLen ) + { + MATCH Match; + WORD OldHashVal = Comp.HashVal; + + Comp.Cur++; + + HASH_UPDATE( Comp.Buf[ Comp.Cur + 2 ] ); + + Comp_FindLongestMatch( &Match ); + + Comp.Cur--; + Comp.HashVal = OldHashVal; + + return( Match.Len > OldMatchLen ); + } + + +typedef double CostType; + + +typedef struct + { + CostType Cost; // cost, in bits (scaled if an int) + short int Literal; // -1 if it's really a match + MATCH Match; // if it's a literal then Match.Len == 1 + } MOVE; + + +typedef struct + { + short int Best; // best move + short int Cur; // current move being tried, may become Best + short int NumMoves; // number of moves, 1 to MAX_MOVES + MOVE Moves[ MAX_MOVES ]; + } OPT_ITEM; + +#define TREE_SIZE (MATCH_MAX * 5) + +struct + { + int Len; // number of items + #ifdef DEBUG + int NumSolutions; + #endif + CostType TotalCost[ TREE_SIZE + 1 ]; + OPT_ITEM List[ TREE_SIZE + 1 ]; + } Opt; + + +void Search( int Node, CostType CostSoFar ) + { + int i; + + if( Node >= Opt.Len ) // finished? + { + #ifdef DEBUG + if( Node > Opt.Len ) + { + puts( "ERR: Exceeded table size limit." ); + exit( -1 ); + } + #endif + + if( CostSoFar < Opt.TotalCost[ Node ] ) + { + #ifdef DEBUG + Opt.NumSolutions++; + #endif + + Opt.TotalCost[ Node ] = CostSoFar; + + // save the best path + + for( i = 1; i < Opt.Len; i++ ) + { + Opt.List[ i ].Best = -1; + } + + for( i = 0; i < Opt.Len; ) + { +#if 0 + x = Opt.List[ i ].Cur; + + Opt.List[ i ].Best = x; + + i += Opt.List[ i ].Moves[ x ].Match.Len; +#else + i += Opt.List[ i ].Moves[ Opt.List[ i ].Best = + Opt.List[ i ].Cur ].Match.Len; +#endif + } + } + } + else + { + if( CostSoFar < Opt.TotalCost[ Node ] ) + { + if( CostSoFar < Opt.TotalCost[ Opt.Len ] ) + { + if( Opt.List[ Node ].Best >= 0 ) + { + static CostType Diff; + + // Aha! We have found an intersection into a best-path. + // Saves us a lot of time! + + // First, update the costs from the point of intersection + // to the goal. + + Diff = Opt.TotalCost[ Node ] - CostSoFar; + + for( i = Node; i < Opt.Len; ) + { + Opt.TotalCost[ i ] -= Diff; + + i += Opt.List[ i ].Moves[ Opt.List[ i ].Best ].Match.Len; + } + + Opt.TotalCost[ i ] -= Diff; // Opt.Len + + // Second, this IS the best path so eliminate any others. + + for( i = 1; i < Node; i++ ) + { + Opt.List[ i ].Best = -1; + } + + // Third, update the best path to the point of intersection. + + for( i = 0; i < Node; ) + { +#if 0 + x = Opt.List[ i ].Cur; + + Opt.List[ i ].Best = x; + + i += Opt.List[ i ].Moves[ x ].Match.Len; +#else + i += Opt.List[ i ].Moves[ Opt.List[ i ].Best = + Opt.List[ i ].Cur ].Match.Len; +#endif + } + } + else + { + Opt.TotalCost[ Node ] = CostSoFar; + + for( i = Opt.List[ Node ].NumMoves - 1; i >= 0; i-- ) // try each move + { + Opt.List[ Node ].Cur = i; + + Search( Opt.List[ Node ].Moves[ i ].Match.Len + Node, + Opt.List[ Node ].Moves[ i ].Cost + CostSoFar ); + } + } + } + } + } + } + + +// this outputs the final result + +void GenerateOutput( void ) + { + int i, Best; + + for( i = 0; i < Opt.Len; ) + { + Best = Opt.List[ i ].Best; + + #ifdef DEBUG + if( Best < 0 || Best >= MAX_MOVES ) + { + puts( "ERR: 'Best' range." ); + exit( -1 ); + } + #endif + + if( Opt.List[ i ].Moves[ Best ].Literal < 0 ) + { + Lz_Encode_Match( &Opt.List[ i ].Moves[ Best ].Match ); + } + else + { + Lz_Encode_Literal( Opt.List[ i ].Moves[ Best ].Literal ); + } + + i += Opt.List[ i ].Moves[ Best ].Match.Len; + } + + #ifdef DEBUG + if( i != Opt.Len ) + { + puts( "ERR: Misaligned output." ); + exit( -1 ); + } + #endif + } + + +void Optimize( void ) + { + int i; + CostType Total; + + Total = 0.1; + + Opt.TotalCost[ 0 ] = Total; + + for( i = 0; i < Opt.Len; i++ ) + { + Opt.List[ i ].Best = -1; + + Total += Opt.List[ i ].Moves[ 0 ].Cost; // assume a simple literal + + Opt.TotalCost[ i + 1 ] = Total; + } + + #ifdef DEBUG + Opt.NumSolutions = 0; + #endif + + Search( 0, 0 ); + + #ifdef DEBUG + if( Opt.NumSolutions == 0 ) + { + puts( "ERR: No solution." ); + exit( -1 ); + } + #endif + + GenerateOutput(); + } + + +// Compresses a file. + +void Comp_Compress_Slow( void ) + { + int i, j, Len, Cut, NumMatches; + MATCH Match[ MAX_MATCHES ]; +#ifndef PAQLIB //msliger + unsigned Counter = 1024; +#endif //msliger + LONGDOUBLE DeltaCost = 0.0; + + while( Comp.Compressed < Comp.FileSize ) + { + Cut = 1; + Opt.Len = 0; + + while( Cut ) + { +#ifndef PAQLIB //msliger + if( --Counter == 0 ) // Reassure the user that + { // something is really happening. + Counter = 2048; + + if( Comp.ShowStatus ) + { + printf( "\b\b\b\b\b%4.1f%%", + Comp.Compressed * 99.9 / (double)Comp.FileSize ); + } + } +#endif //msliger + + Cut--; + + Opt.List[ Opt.Len ].NumMoves = 1; + + Opt.List[ Opt.Len ].Moves[ 0 ].Literal = Comp.Buf[ Comp.Cur ]; + Opt.List[ Opt.Len ].Moves[ 0 ].Match.Len = 1; + Opt.List[ Opt.Len ].Moves[ 0 ].Cost = + Lz_Encode_Literal_Cost( Comp.Buf[ Comp.Cur ] ) + DeltaCost; + + if( (NumMatches = Comp_FindLongestMatches( Match )) != 0 ) + { + Opt.List[ Opt.Len ].NumMoves = NumMatches + 1; + + i = 0; + + do + { + Opt.List[ Opt.Len ].Moves[ NumMatches ].Literal = -1; + Opt.List[ Opt.Len ].Moves[ NumMatches ].Match = Match[ i ]; + Opt.List[ Opt.Len ].Moves[ NumMatches ].Cost = + Lz_Encode_Match_Cost( &Match[ i ] ) + DeltaCost; + + i++; + } + while( --NumMatches ); + + if( Match[ 0 ].Len > Cut ) Cut = Match[ 0 ].Len - 1; + } + + Opt.Len++; + + DeltaCost = Opt.Len / (TREE_SIZE / 4.1); + + Comp_Advance( 1 ); + + if( Opt.Len == TREE_SIZE ) + { + // We've reached the end of the list so set up an artificial + // cutting point. This degrades compression but only very + // slightly. In practice, I expect this code to execute only + // on long run-lengths which should be pretty much optimized + // anyway. + + Cut = 0; + + // We need too make sure that no matches overlap beyond + // the end of the list. + + for( i = Opt.Len - 1; i > Opt.Len - MATCH_MAX; i-- ) + { + for( j = 1; j < Opt.List[ i ].NumMoves; j++ ) + { + Len = Opt.Len - i; + + if( Opt.List[ i ].Moves[ j ].Match.Len > Len ) + { + // OK, now we have a match which is too long. + // Try to truncate it. + + if( Len < MATCH_MIN || Opt.List[ i ].Moves[ j ].Match.Dist > + Comp.ValidDistances[ Len ] ) + { + // Truncating it makes it too short so just ditch + // the whole thing by replacing it with its literal. + + // Assume the literal is stored as the first move. + + Opt.List[ i ].Moves[ j ] = Opt.List[ i ].Moves[ 0 ]; + } + else + { + Opt.List[ i ].Moves[ j ].Match.Len = Len; + } + } + } + } + } + } + + Optimize(); + } + } + + +// Compresses a file. + +void Comp_Compress_Fast( void ) + { + MATCH Match; +#ifndef PAQLIB //msliger + unsigned Counter = 2048; +#endif //msliger + + while( Comp.Compressed < Comp.FileSize ) + { +#ifndef PAQLIB //msliger + if( --Counter == 0 ) // Reassure the user that + { // something is really happening. + Counter = 4096; + + if( Comp.ShowStatus ) + { + printf( "\b\b\b\b\b%4.1f%%", + Comp.Compressed * 99.9 / (double)Comp.FileSize ); + } + } +#endif //msliger + + if( Comp_FindLongestMatch( &Match ) ) + { + if( Comp.CompressionLevel == 1 || //msliger + !Comp_FindBetterMatch( Match.Len ) ) + { + Lz_Encode_Match( &Match ); + + Comp_Advance( Match.Len ); + } + else + { + Lz_Encode_Literal( Comp.Buf[ Comp.Cur ] ); + + Comp_Advance( 1 ); + } + } + else + { + Lz_Encode_Literal( Comp.Buf[ Comp.Cur ] ); + + Comp_Advance( 1 ); + } + } + } + + +#include "bit.h" + +#ifndef PAQLIB //msliger +WORD Comp_Compress( char *FileName, long FileSize ) + { + long BitsOutput = Bit_GetTotal(); + + Comp.FileSize = FileSize; + Comp.Compressed = 0; + Comp.Checksum = 0; + Comp.TxtFile = fopen( FileName, "rb" ); + Comp.ReachedEOF = 0; //msliger + + if (setvbuf(Comp.TxtFile,NULL,_IOFBF,131072)) //msliger + { //msliger + printf("source setvbuf failed.\n"); //msliger + } //msliger + //msliger + Comp_FillBuf(); + +//BUGBUG 25-May-94 msliger trouble for size < 3 ? + HASH_UPDATE( Comp.Buf[ 0 ] ); + HASH_UPDATE( Comp.Buf[ 1 ] ); + HASH_UPDATE( Comp.Buf[ 2 ] ); + + if( Comp.ShowStatus ) + { + printf( " 0.0%%" ); //BUGBUG 24-May-94 msliger (fixed) "%" to "%%" + } + + switch( Comp.CompressionLevel ) //msliger + { + case 1: + Comp.MatchFutilityCutoff = 5; + Comp_Compress_Fast(); + break; + case 2: + Comp.MatchFutilityCutoff = 50; + Comp_Compress_Fast(); + break; + case 3: + Comp.MatchFutilityCutoff = 250; + Comp_Compress_Fast(); + break; + case 4: + Comp.MatchFutilityCutoff = 100; + Comp.MaxMatches = MAX_MATCHES - 3; + Comp_Compress_Slow(); + break; + case 5: + Comp.MatchFutilityCutoff = 200; + Comp.MaxMatches = MAX_MATCHES - 2; + Comp_Compress_Slow(); + break; + case 6: + Comp.MatchFutilityCutoff = 400; + Comp.MaxMatches = MAX_MATCHES - 1; + Comp_Compress_Slow(); + break; + case 7: + Comp.MatchFutilityCutoff = 1000; + Comp.MaxMatches = MAX_MATCHES; + Comp_Compress_Slow(); + } + + fclose( Comp.TxtFile ); + + if( Comp.ShowStatus ) + { + printf( "\b\b\b\b\b\b100.0%%" ); + } + + BitsOutput = Bit_GetTotal() - BitsOutput; + + if( BitsOutput == 0 ) BitsOutput = 8; + if( FileSize == 0 ) FileSize = 1; + + printf( " %5.1f%%", ((double)BitsOutput / (double)FileSize) * (100.0/8.0) ); + + return( Comp.Checksum ); + } +#endif /* not PAQLIB */ //msliger + + +#ifdef PAQLIB //msliger (entire function) + +int cbTarget; // public (to BIT.C) +char *pbTarget; +int fTargetOverflow; +int cbResult; + +WORD Comp_CompressBlock( void *pbSource, UINT cbSource, + void *pbDest, UINT cbDest, UINT *pcbResult ) + { + Comp.FileSize = cbSource; + Comp.Compressed = 0; + Comp.pbSource = pbSource; + Comp.cbSource = cbSource; + Comp.ReachedEOF = 0; //msliger + + cbTarget = cbDest; // hack these along to BIT.C + pbTarget = pbDest; + fTargetOverflow = 0; + cbResult = 0; + + Arith_Init(); // start each block clean + + Comp_FillBuf(); + +//BUGBUG 25-May-94 msliger trouble for size < 3 ? + HASH_UPDATE( Comp.Buf[ 0 ] ); + HASH_UPDATE( Comp.Buf[ 1 ] ); + HASH_UPDATE( Comp.Buf[ 2 ] ); + + switch( Comp.CompressionLevel ) //msliger + { + case 1: + Comp.MatchFutilityCutoff = 5; + Comp_Compress_Fast(); + break; + case 2: + Comp.MatchFutilityCutoff = 50; + Comp_Compress_Fast(); + break; + case 3: + Comp.MatchFutilityCutoff = 250; + Comp_Compress_Fast(); + break; + case 4: + Comp.MatchFutilityCutoff = 100; + Comp.MaxMatches = MAX_MATCHES - 3; + Comp_Compress_Slow(); + break; + case 5: + Comp.MatchFutilityCutoff = 200; + Comp.MaxMatches = MAX_MATCHES - 2; + Comp_Compress_Slow(); + break; + case 6: + Comp.MatchFutilityCutoff = 400; + Comp.MaxMatches = MAX_MATCHES - 1; + Comp_Compress_Slow(); + break; + case 7: + Comp.MatchFutilityCutoff = 1000; + Comp.MaxMatches = MAX_MATCHES; + Comp_Compress_Slow(); + } + + Arith_Close(); // flush out remaining bits + + *pcbResult = cbResult; + + return( fTargetOverflow ); + } +#endif /* PAQLIB */ //msliger + + +void Comp_Close( void ) + { + Lz_Close(); + + Rtl_Free( Comp.MatchTable ); + Rtl_Free( Comp.MatchChain ); /* Comp.Buf goes with it */ + } + + +#ifdef PAQLIB //msliger (entire function) + +// this code is only suitable for use with Comp_CompressBlock() + +void Comp_Reset( void ) + { + int i; + + Lz_Close(); + Lz_Init( Comp.WindowBits ); + +//BUGBUG 25-May-94 msliger Init of hash tables should be done with memset + for( i = 0; i < HASH_TABLE_SIZE; i++ ) + { + Comp.MatchTable[ i ] = -1; + } + + for( i = 0; i < Comp.BufSize; i++ ) + { + Comp.MatchChain[ i ] = -1; + } + + Comp.Left = Comp.Cur = Comp.Right = 0; + } +#endif /* PAQLIB */ //msliger diff --git a/private/windows/diamond/quantum/comp.h b/private/windows/diamond/quantum/comp.h new file mode 100644 index 000000000..0226e40fd --- /dev/null +++ b/private/windows/diamond/quantum/comp.h @@ -0,0 +1,28 @@ +// COMP.H +// +// Quantum file archiver and compressor +// Advanced data compression +// +// Copyright (c) 1993,1994 David Stafford +// All rights reserved. + +#ifndef __COMP +#define __COMP + +#include <stdio.h> +#include "defs.h" + +void Comp_Init( BYTE WindowBits, int CompressionLevel ); //msliger +void Comp_Close( void ); + +#ifndef PAQLIB //msliger +WORD Comp_Compress( char *FileName, long FileSize ); +#endif //msliger + +#ifdef PAQLIB //msliger +WORD Comp_CompressBlock( void *pbSrc, UINT cbSrc, //msliger + void *pbDst, UINT cbDst, UINT *pcbResult ); //msliger +void Comp_Reset( void ); //msliger +#endif //msliger + +#endif // comp.h diff --git a/private/windows/diamond/quantum/crc32.h b/private/windows/diamond/quantum/crc32.h new file mode 100644 index 000000000..25da8ce55 --- /dev/null +++ b/private/windows/diamond/quantum/crc32.h @@ -0,0 +1,4 @@ +extern void CRC32Reset(void); +extern void CRC32Restore(long); +extern void CRC32Update(unsigned char *,unsigned); +extern long CRC32Result(void); diff --git a/private/windows/diamond/quantum/dcomp.c b/private/windows/diamond/quantum/dcomp.c new file mode 100644 index 000000000..6985c09c5 --- /dev/null +++ b/private/windows/diamond/quantum/dcomp.c @@ -0,0 +1,764 @@ +/* + * Microsoft Confidential + * Copyright (C) Microsoft Corporation 1994 + * Copyright (c) 1993,1994 Cinematronics + * All Rights Reserved. + * + * DCOMP.C: decompressor core + * + * History: + * 08-Jul-1994 msliger Added disk-based ring buffer support. + * 14-Jul-1994 msliger Fixed build of UNPAQ app. + * 30-Aug-1994 msliger Fixed marking buffer dirty if newest. + * 01-Feb-1995 msliger Fixed reporting ring init failures. + */ + +// DCOMP.C +// +// Quantum file archiver and compressor +// Advanced data compression +// +// Copyright (c) 1993,1994 Cinematronics +// All rights reserved. +// +// This file contains trade secrets of Cinematronics. +// Do NOT distribute! + +#include <stdio.h> +#include <stdlib.h> + +#ifdef STAFFORD +#include <alloc.h> +#endif // STAFFORD + +#include "quantum.h" + +#ifndef UNPAQLIB //msliger +#include "arc.h" +#endif //msliger + +#include "dcomp.h" +#include "lz.h" +#include "rtl.h" + +#ifndef UNPAQLIB //msliger +extern ARC Arc; +#endif //msliger + +#ifdef UNPAQLIB //msliger +#include "arith.h" +#endif + +#ifdef UNPAQLIB +#define DISK_RING /* enable DISK_RING support code */ +#endif + +#ifdef DISK_RING +#include <fcntl.h> /* for disk ring buffer code */ +#include <sys\stat.h> + +#include "qdi.h" /* for RINGNAME, file functions */ +#include "qdi_int.h" /* lastContext */ +#endif //msliger + + +typedef struct + { + BYTE HUGE *Buf; // history buffer: NULL -> using disk ring buffer + BYTE HUGE *BufEnd; // last byte in history buffer + 1 + + BYTE HUGE *CurPtr; // pointer to oldest byte in history buffer + unsigned long Cur; // current position in the history buffer + long WindowMask; // used to normalize Cur for wrapping + long WindowSize; // size of the history window +#ifndef UNPAQLIB //msliger + long NumBytes; // total number of bytes to decompress + FILE *OutFile; // the output file + WORD Checksum; +#else //msliger + unsigned short NumBytes; // total number of bytes to decompress + BYTE *OutBuffer; //msliger the output buffer + int fOutOverflow; //msliger if too little space in output buffer + BYTE WindowBits; //msliger needed in DComp_Reset() + int fRingFault; // if disk callbacks fail +#endif //msliger + } DCOMP; + + +DCOMP DComp; + +void (FAST2 NEAR *DComp_Token_Match)( MATCH Match ); +void (FAST2 NEAR *DComp_Token_Literal)( int Chr ); + +static void FAST2 DComp_Internal_Match( MATCH Match ); +static void FAST2 DComp_Internal_Literal( int Chr ); + + +#ifdef DISK_RING /* virtual ring manager */ + +#define BUFFER_SIZE (4096) /* must be 2^Nth */ + +#define MIN_BUFFERS 3 /* minimum number we want */ + + +typedef struct aBuffer +{ + struct aBuffer FAR *pLinkNewer; /* link to more recently used */ + struct aBuffer FAR *pLinkOlder; /* link to less recently used */ + int BufferPage; /* what page this is, -1 -> invalid */ + int BufferDirty; /* NZ -> needs to be written */ + BYTE Buffer[BUFFER_SIZE]; /* content */ +} BUFFER, FAR *PBUFFER; + + +typedef struct +{ + PBUFFER pBuffer; /* pointer to buffer, NULL if not present */ + int fDiskValid; /* NZ -> this page has been written to disk */ +} PAGETABLEENTRY; + + +static struct +{ + int Handle; /* ring file handle */ + PBUFFER RingBuffer; /* current output ring buffer */ + BYTE FAR *RingPointer; /* current output pointer (into RingBuffer) */ + BYTE FAR *RingPointerLimit; /* address of last byte of RingBuffer + 1 */ + int RingPages; /* how many pages there are total */ + PBUFFER pNewest; /* pointer to most recently used buffer */ + PBUFFER pOldest; /* pointer to least recently used buffer */ + PAGETABLEENTRY FAR *PageTable; /* pointer to array of pointers */ +} Disk; + + +static int FAST DComp_Ring_Init(void); +static void FAST DComp_Ring_Reset(void); +static PBUFFER FAST DComp_Ring_Load(int page,int fWrite); +static void FAST2 DComp_Ring_Match( MATCH Match ); +static void FAST2 DComp_Ring_Literal( int Chr ); +static void FAST DComp_Ring_Close(void); + +#endif /* DISK_RING */ + + +int FAST DComp_Init( BYTE WindowBits ) //msliger + { + DComp.WindowSize = 1L << WindowBits; //msliger + DComp.WindowMask = DComp.WindowSize - 1; + DComp.Cur = 0; + +#ifdef UNPAQLIB //msliger + DComp.fRingFault = 0; + DComp.WindowBits = WindowBits; //msliger +#endif //msliger + + if( (DComp.Buf = Rtl_Malloc( DComp.WindowSize )) != NULL ) + { + DComp_Token_Match = DComp_Internal_Match; /* use internal buffering */ + DComp_Token_Literal = DComp_Internal_Literal; + + DComp.CurPtr = DComp.Buf; + DComp.BufEnd = DComp.Buf + DComp.WindowSize; + } +#ifdef DISK_RING + else if (DComp_Ring_Init()) /* try disk ring buffer */ + { + DComp_Token_Match = DComp_Ring_Match; /* use disk buffering */ + DComp_Token_Literal = DComp_Ring_Literal; + } +#endif + else + { + return(1); /* if can't create ring buffer */ + } + + Lz_Init( WindowBits ); //msliger + + return(0); + } + + +void FAST2 DComp_Internal_Match( MATCH Match ) + { + BYTE HUGE *SrcPtr; + register BYTE Chr; + + if (DComp.NumBytes >= (unsigned) Match.Len) + { + SrcPtr = DComp.Buf + ((DComp.Cur - Match.Dist) & DComp.WindowMask); + + DComp.NumBytes -= Match.Len; + DComp.Cur += Match.Len; + + while (Match.Len--) + { +#ifdef UNPAQLIB + Chr = *SrcPtr; + + *DComp.CurPtr = Chr; + + *DComp.OutBuffer++ = Chr; +#else + Chr = *SrcPtr; + + *DComp.CurPtr = Chr; + + putc( Chr, DComp.OutFile ); + + DComp.Checksum ^= Chr; + + if( DComp.Checksum & 0x8000 ) // simulate a ROL in C, yucky! + { + DComp.Checksum <<= 1; + DComp.Checksum++; + } + else + { + DComp.Checksum <<= 1; + } +#endif + + if (++SrcPtr == DComp.BufEnd) + { + SrcPtr = DComp.Buf; + } + + if (++DComp.CurPtr == DComp.BufEnd) + { + DComp.CurPtr = DComp.Buf; + } + } + } + else /* match too large to fit */ + { + DComp.NumBytes = 0; +#ifdef UNPAQLIB + DComp.fOutOverflow = 1; +#endif + } + } + + +void FAST2 DComp_Internal_Literal( int Chr ) + { + DComp.NumBytes--; + DComp.Cur++; + +#ifndef UNPAQLIB + putc( (BYTE) Chr, DComp.OutFile ); + + DComp.Checksum ^= (BYTE) Chr; + + if( DComp.Checksum & 0x8000 ) // simulate a ROL in C, yucky! + { + DComp.Checksum <<= 1; + DComp.Checksum++; + } + else + { + DComp.Checksum <<= 1; + } +#else + *DComp.OutBuffer++ = (BYTE) Chr; +#endif + + *DComp.CurPtr = (BYTE) Chr; + + if (++DComp.CurPtr == DComp.BufEnd) + { + DComp.CurPtr = DComp.Buf; + } + } + + +#ifndef UNPAQLIB +WORD FAST DComp_Decompress( FILE *OutputFile, long NumBytes ) + { + DComp.OutFile = OutputFile; + DComp.NumBytes = NumBytes; + DComp.Checksum = 0; + + { + while( DComp.NumBytes ) + { + Lz_NextToken(); + } + } + + if( DComp.NumBytes < 0 ) + { + puts( "ERR: Incorrect file size." ); + exit( -1 ); + } + + return( DComp.Checksum ); + } +#endif /* not UNPAQLIB */ //msliger + +#ifdef UNPAQLIB + +char *pbSource; +int cbSource; +int fSourceOverflow; + +WORD FAST DComp_DecompressBlock( void *pbSrc,UINT cbSrc,void *pbDst,UINT cbDst ) + { + DComp.NumBytes = cbDst; + DComp.OutBuffer = pbDst; + DComp.fOutOverflow = 0; + + pbSource = pbSrc; // pass these along to BIT.C + cbSource = cbSrc; + fSourceOverflow = 0; + + Arith_Init(); + + while( (DComp.NumBytes) && (!fSourceOverflow) ) + { + Lz_NextToken(); + } + + Arith_Close(); + + return( fSourceOverflow || DComp.fOutOverflow || DComp.fRingFault); + } +#endif + + +void FAST DComp_Close( void ) + { +#ifdef DISK_RING + if (DComp.Buf == NULL) + { + DComp_Ring_Close(); /* if using a disk-based ring buffer */ + } + else + { + Rtl_Free( DComp.Buf ); /* if using memory-based ring buffer */ + } +#else + Rtl_Free( DComp.Buf ); /* always memory-based */ +#endif + + Lz_Close(); + } + + +#ifdef UNPAQLIB + +// this code is only for use with DComp_DecompressBlock() + +void FAST DComp_Reset( void ) + { + Lz_Close(); + + DComp.Cur = 0; + DComp.CurPtr = DComp.Buf; + DComp.fRingFault = 0; + +#ifdef DISK_RING + if (DComp.Buf == NULL) + { + DComp_Ring_Reset(); + } +#endif + + Lz_Init( DComp.WindowBits ); + } +#endif /* UNPAQLIB */ + + +#ifdef DISK_RING + +// disk-based ring buffer support code + +static int FAST DComp_Ring_Init(void) +{ + RINGNAME ringName; + PBUFFER pBuffer; + int cBuffers; + + if (lastContext->pfnOpen == NULL) + { + return(0); /* failed, no disk services */ + } + + ringName.wildName[0] = '*'; + ringName.wildName[1] = '\0'; + ringName.fileSize = DComp.WindowSize; + + Disk.Handle = lastContext->pfnOpen((char FAR *) &ringName, + (_O_BINARY|_O_RDWR|_O_CREAT),(_S_IREAD|_S_IWRITE)); + + if (Disk.Handle == -1) + { + return(0); /* failed, can't make disk file */ + } + + Disk.RingPages = (int) (DComp.WindowSize / BUFFER_SIZE); + if (Disk.RingPages < MIN_BUFFERS) + { + Disk.RingPages = MIN_BUFFERS; /* if DComp.WindowSize < BUFFER_SIZE */ + } + + Disk.PageTable = Rtl_Malloc(sizeof(PAGETABLEENTRY) * Disk.RingPages); + if (Disk.PageTable == NULL) + { + lastContext->pfnClose(Disk.Handle); /* close the file */ + + return(0); /* failed, can't get page table */ + } + + Disk.pNewest = NULL; + + /* DComp_Ring_Close() can be used to abort from this point on */ + + for (cBuffers = 0; cBuffers < Disk.RingPages; cBuffers++) + { + pBuffer = Rtl_Malloc(sizeof(BUFFER)); + + if (pBuffer != NULL) + { + pBuffer->pLinkNewer = NULL; /* none are newer */ + pBuffer->pLinkOlder = Disk.pNewest; /* all the others older now */ + + if (Disk.pNewest != NULL) + { + Disk.pNewest->pLinkNewer = pBuffer; /* old guy now knows about new */ + } + else /* if nobody else */ + { + Disk.pOldest = pBuffer; /* guess I'm the oldest too */ + } + + Disk.pNewest = pBuffer; /* I'm the newest */ + } + else /* if pBuffer == NULL */ + { + if (cBuffers < MIN_BUFFERS) /* less than minimum? */ + { + DComp_Ring_Close(); /* give it up */ + + return(0); /* failed, can't get min buffers */ + } + else /* if we got the minimum */ + { + break; /* got enough, quit trying */ + } + } + } + + DComp_Ring_Reset(); /* init everything else */ + + return(1); /* ring buffer created */ +} + + +static void FAST DComp_Ring_Reset(void) +{ + PBUFFER walker; + int iPage; + + for (walker = Disk.pNewest; walker != NULL; walker = walker->pLinkOlder) + { + walker->BufferPage = -1; /* buffer is not valid */ + walker->BufferDirty = 0; /* and doesn't need writing */ + } + + for (iPage = 0; iPage < Disk.RingPages; iPage++) + { + Disk.PageTable[iPage].pBuffer = NULL; /* not in memory */ + Disk.PageTable[iPage].fDiskValid = 0; /* not on disk */ + } + + Disk.RingBuffer = DComp_Ring_Load(0,1); /* make a page 0 for writing */ + + if (Disk.RingBuffer != NULL) /* always will pass */ + { + Disk.RingPointer = Disk.RingBuffer->Buffer; + Disk.RingPointerLimit = Disk.RingPointer + BUFFER_SIZE; + } +} + + +static void FAST2 DComp_Ring_Match( MATCH Match ) +{ + long SrcOffset; /* offset into output ring */ + int SrcPage; /* page # where that offset lies */ + int Chunk; /* number of bytes this pass */ + BYTE FAR *SrcPtr; /* pointer to source bytes */ + BYTE Chr; /* data character */ + PBUFFER SrcBuffer; /* buffer where source data is */ + int SrcBufferOffset; /* offset within the buffer */ + int newPage; + + if (DComp.NumBytes >= (unsigned) Match.Len) + { + SrcOffset = (DComp.Cur - Match.Dist) & DComp.WindowMask; + DComp.NumBytes -= Match.Len; + DComp.Cur += Match.Len; + + /* promote current output page to make sure it's never discarded */ + + if (DComp_Ring_Load(Disk.RingBuffer->BufferPage,0) == NULL) + { + DComp.NumBytes = 0; + + DComp.fRingFault = 1; + + return; + } + + while (Match.Len) + { + /* Limit: number of bytes requested */ + + Chunk = Match.Len; /* try for everything */ + + /* Limit: space remaining on current output page */ + + if ((Disk.RingPointerLimit - Disk.RingPointer) < Chunk) + { + Chunk = Disk.RingPointerLimit - Disk.RingPointer; + } + + SrcPage = (int) (SrcOffset / BUFFER_SIZE); + SrcBufferOffset = (int) (SrcOffset % BUFFER_SIZE); + + SrcBuffer = DComp_Ring_Load(SrcPage,0); /* for reading */ + if (SrcBuffer == NULL) + { + DComp.NumBytes = 0; + + DComp.fRingFault = 1; + + return; + } + + SrcPtr = SrcBuffer->Buffer + SrcBufferOffset; + + /* Limit: number of source bytes on current output page */ + + if ((BUFFER_SIZE - SrcBufferOffset) < Chunk) + { + Chunk = (BUFFER_SIZE - SrcBufferOffset); + } + + SrcOffset += Chunk; + SrcOffset &= DComp.WindowMask; + Match.Len -= Chunk; + + while (Chunk--) /* copy this chunk */ + { + Chr = *SrcPtr++; + + *Disk.RingPointer++ = Chr; + + *DComp.OutBuffer++ = Chr; + } + + if (Disk.RingPointer == Disk.RingPointerLimit) + { + newPage = (Disk.RingBuffer->BufferPage + 1); + if (newPage >= Disk.RingPages) + { + newPage = 0; + } + + Disk.RingBuffer = DComp_Ring_Load(newPage,1); /* for writing */ + if (Disk.RingBuffer == NULL) + { + DComp.NumBytes = 0; + + DComp.fRingFault = 1; + + return; + } + + Disk.RingPointer = Disk.RingBuffer->Buffer; + Disk.RingPointerLimit = Disk.RingPointer + BUFFER_SIZE; + } + } /* while Match.Len */ + } /* if Match.Len size OK */ + else /* match too large to fit */ + { + DComp.NumBytes = 0; + + DComp.fOutOverflow = 1; + } +} + + +static void FAST2 DComp_Ring_Literal( int Chr ) +{ + int newPage; + + DComp.NumBytes--; + DComp.Cur++; + + *DComp.OutBuffer++ = (BYTE) Chr; + + *Disk.RingPointer = (BYTE) Chr; + + if (++Disk.RingPointer == Disk.RingPointerLimit) + { + newPage = (Disk.RingBuffer->BufferPage + 1); + if (newPage >= Disk.RingPages) + { + newPage = 0; + } + + Disk.RingBuffer = DComp_Ring_Load(newPage,1); /* for writing */ + if (Disk.RingBuffer == NULL) + { + DComp.NumBytes = 0; + + DComp.fRingFault = 1; + + return; + } + + Disk.RingPointer = Disk.RingBuffer->Buffer; + Disk.RingPointerLimit = Disk.RingPointer + BUFFER_SIZE; + } +} + + +/* Bring page into a buffer, return a pointer to that buffer. fWrite */ +/* indicates the caller's intentions for this buffer, NZ->consider it */ +/* dirty now. Returns NULL if there is a paging fault (callback */ +/* failed) or if any internal assertions fail. */ + +static PBUFFER FAST DComp_Ring_Load(int page,int fWrite) +{ + PBUFFER pBuffer; + long iPagefileOffset; + + pBuffer = Disk.PageTable[page].pBuffer; /* look up this page */ + + if (pBuffer != NULL) /* if it's in the table */ + { + if (pBuffer != Disk.pNewest) /* promote if not newest */ + { + pBuffer->pLinkNewer->pLinkOlder = pBuffer->pLinkOlder; + + if (pBuffer->pLinkOlder != NULL) /* if there is someone older */ + { + pBuffer->pLinkOlder->pLinkNewer = pBuffer->pLinkNewer; + } + else + { + Disk.pOldest = pBuffer->pLinkNewer; + } + + /* link into head of chain */ + + Disk.pNewest->pLinkNewer = pBuffer; /* newest now knows one newer */ + pBuffer->pLinkNewer = NULL; /* nobody's newer */ + pBuffer->pLinkOlder = Disk.pNewest; /* everybody's older */ + Disk.pNewest = pBuffer; /* I'm the newest */ + } + + pBuffer->BufferDirty |= fWrite; /* might already be dirty */ + + return(pBuffer); /* return my handle */ + } + + /* desired page is not in the table; discard oldest & use it */ + + /* assertion check: current output buffer appears to be the oldest */ + + if (Disk.pOldest == Disk.RingBuffer) + { + return(NULL); + } + + pBuffer = Disk.pOldest; /* choose the oldest buffer */ + + if (pBuffer->BufferPage != -1) /* take it out of page table */ + { + Disk.PageTable[pBuffer->BufferPage].pBuffer = NULL; /* not here now */ + + if (pBuffer->BufferDirty) /* write on eject, if dirty */ + { + iPagefileOffset = (long) pBuffer->BufferPage * BUFFER_SIZE; + + if (lastContext->pfnSeek(Disk.Handle,iPagefileOffset,SEEK_SET) != + iPagefileOffset) + { + return(NULL); + } + + if (lastContext->pfnWrite(Disk.Handle,pBuffer->Buffer,BUFFER_SIZE) != + BUFFER_SIZE) + { + return(NULL); + } + + Disk.PageTable[pBuffer->BufferPage].fDiskValid = 1; + } + } + + Disk.pOldest = Disk.pOldest->pLinkNewer; /* newer is now oldest */ + Disk.pOldest->pLinkOlder = NULL; /* oldest knows none older */ + + Disk.pNewest->pLinkNewer = pBuffer; + pBuffer->pLinkNewer = NULL; /* link into head of chain */ + pBuffer->pLinkOlder = Disk.pNewest; + Disk.pNewest = pBuffer; + + /* add new buffer to paging table */ + + Disk.PageTable[page].pBuffer = pBuffer; /* add new to paging table */ + + /* if this disk page is valid, load it */ + + if (Disk.PageTable[page].fDiskValid) + { + iPagefileOffset = (long) page * BUFFER_SIZE; + + if (lastContext->pfnSeek(Disk.Handle,iPagefileOffset,SEEK_SET) != + iPagefileOffset) + { + return(NULL); + } + + if (lastContext->pfnRead(Disk.Handle,pBuffer->Buffer,BUFFER_SIZE) != + BUFFER_SIZE) + { + return(NULL); + } + } + else if (!fWrite) + { + /* assertion failure, trying to load a never-written page from disk */ + + return(NULL); + } + + pBuffer->BufferDirty = fWrite; /* might be dirty now */ + pBuffer->BufferPage = page; /* our new page number */ + + return(pBuffer); /* return new handle */ +} + + +static void FAST DComp_Ring_Close(void) +{ + PBUFFER pBuffer, pNext; /* buffer walk pointer */ + + Rtl_Free(Disk.PageTable); /* discard page table */ + + pBuffer = Disk.pNewest; + + while (pBuffer != NULL) /* discard buffer chain */ + { + pNext = pBuffer->pLinkOlder; + Rtl_Free(pBuffer); + pBuffer = pNext; + } + + lastContext->pfnClose(Disk.Handle); /* close that file (and delete) */ +} + +#endif /* DISK_RING */ diff --git a/private/windows/diamond/quantum/dcomp.h b/private/windows/diamond/quantum/dcomp.h new file mode 100644 index 000000000..9877cfb64 --- /dev/null +++ b/private/windows/diamond/quantum/dcomp.h @@ -0,0 +1,32 @@ +// DCOMP.H +// +// Quantum file archiver and compressor +// Advanced data compression +// +// Copyright (c) 1993,1994 David Stafford +// All rights reserved. + +#ifndef __DCOMP +#define __DCOMP + +#include <stdio.h> +#include "defs.h" //msliger +#include "lz.h" + +int FAST DComp_Init( BYTE WindowBits ); //msliger +void FAST DComp_Close( void ); + +#ifndef UNPAQLIB //msliger +WORD FAST DComp_Decompress( FILE *OutputFile, long NumBytes ); +#endif //msliger + +#ifdef UNPAQLIB //msliger +WORD FAST DComp_DecompressBlock( void FAR *pbSrc, UINT cbSrc, //msliger + void FAR *pbDst, UINT cbDst ); //msliger +void FAST DComp_Reset( void ); //msliger +#endif //msliger + +extern void (FAST2 *DComp_Token_Match)( MATCH Match ); +extern void (FAST2 *DComp_Token_Literal)( int Chr ); + +#endif // dcomp.h diff --git a/private/windows/diamond/quantum/decomp.h b/private/windows/diamond/quantum/decomp.h new file mode 100644 index 000000000..fbeab0ab9 --- /dev/null +++ b/private/windows/diamond/quantum/decomp.h @@ -0,0 +1,30 @@ +/* + * Microsoft Confidential + * Copyright (c) 1994 Microsoft Corporation + * Copyright (c) 1993,1994 Cinematronics + * Copyright (c) 1993,1994 David Stafford + * All Rights Reserved. + * + * Quantum file archiver and compressor + * Advanced data compression + * + * Copyright (c) 1993,1994 David Stafford + * All rights reserved. + * + * This file contains trade secrets of Cinematronics. + * Do NOT distribute! + */ + +/* + * DECOMP.H: QDI core header + * + * History: + * 09-Jul-1994 msliger Built from DCOMP.H + * 18-Aug-1994 msliger Renamed these to allow both compressors. + */ + +extern int FAST DComp386_Init( BYTE WindowBits ); +extern UINT FAST DComp386_DecompressBlock( void FAR *pbSrc, UINT cbSrc, + void FAR *pbDst, UINT cbDst ); +extern void FAST DComp386_Reset( void ); +extern void FAST DComp386_Close( void ); diff --git a/private/windows/diamond/quantum/defs.h b/private/windows/diamond/quantum/defs.h new file mode 100644 index 000000000..4aa478a7f --- /dev/null +++ b/private/windows/diamond/quantum/defs.h @@ -0,0 +1,43 @@ +#ifndef __DEFS +#define __DEFS + +typedef unsigned char BYTE; +typedef unsigned short WORD; +typedef unsigned long DWORD; +typedef int BOOL; +typedef unsigned int UINT; //msliger + +#ifndef NEAR +#ifdef BIT16 +#define NEAR __near +#else +#define NEAR +#endif +#endif + +#ifndef FAR +#ifdef BIT16 +#define FAR __far +#else +#define FAR +#endif +#endif + +#ifndef HUGE +#ifdef BIT16 +#define HUGE __huge +#else +#define HUGE +#endif +#endif + + +#ifdef BIT16 +#define FAST __near __pascal +#define FAST2 __near __fastcall +#else +#define FAST +#define FAST2 __fastcall +#endif + +#endif // defs.h diff --git a/private/windows/diamond/quantum/dirs b/private/windows/diamond/quantum/dirs new file mode 100644 index 000000000..65bcdc5e7 --- /dev/null +++ b/private/windows/diamond/quantum/dirs @@ -0,0 +1 @@ +DIRS=qci.nt qdi.nt diff --git a/private/windows/diamond/quantum/dirwalk.h b/private/windows/diamond/quantum/dirwalk.h new file mode 100644 index 000000000..54c34955d --- /dev/null +++ b/private/windows/diamond/quantum/dirwalk.h @@ -0,0 +1,88 @@ +/* ---------------------------------------------------------------------------------------------------------------------------- */ +/* */ +/* DIRWALK.H */ +/* */ +/* Definitions for the DirectoryWalk function found in DIRWALK.C, and the related processing calls needed. */ +/* */ +/* ---------------------------------------------------------------------------------------------------------------------------- */ + +/* int DirectoryWalk(path,Directory,File,DirectoryEnd) */ + +extern int DirectoryWalk(const char *, /* path to search, ie, "C:\" */ + int (*)(void *,const char *,const char *,void **), /* pointer to Directory() or NULL */ + int (*)(void *,const char *,const char *,unsigned,unsigned,unsigned,long), /* pointer to File() or NULL */ + int (*)(void *,const char *,const char *,void *)); /* pointer to DirectoryEnd() or NULL */ + +#define DW_MEMORY -10 /* unable to malloc() for internal use */ +#define DW_ERROR -11 /* find first/next reported an error */ +#define DW_DEPTH -12 /* path name became too long */ +#define DW_NO_ERROR 0 /* no error detected */ + +/* + User function definitions: + + The parentID and childID values are "void *"s to DirectoryWalk. They are not used internally. The user may assign + any meaning desired to the value. DirectoryWalk simply requests an assignment via the Directory(), and reports the + corresponding assignment with each file reported to File(), then to DirectoryEnd(). + + + int Directory(parentID,directory,path,childID) + void *parentID; / the handle for the directory where this directory was found / + const char *directory; / the name of the directory found, ie, "DOS" / + const char *path; / the full name of the directory, ie, "C:\DOS" / + void **childID; / Directory() assigns this directory a handle, and passes it back through here / + + If Directory() returns a non-zero value, DirectoryWalk will terminate and return that value. If NULL is passed + to DirectoryWalk() for a Directory() pointer, subdirectories will not be searched. For subdirectory searching + without specific per-directory processing, create a simple function which always returns DW_NO_ERROR (any other + return will terminate the search.) + + + int File(parentID,filename,path,attributes,filetime,filedate,filesize) + void *parentID; / the handle for the directory where this file was found / + const char *filename; / the name of the file found, ie, "ANSI.SYS" / + const char *path; / the full name of the directory where file was found, ie, "C:\DOS" / + unsigned attributes; / the file's attribute bits / + unsigned filetime; / the file's "last modification" time / + unsigned filedate; / the file's "last modification" date / + long filesize; / the file's size in bytes / + + If File() returns a value other than DW_NO_ERROR, DirectoryWalk will terminate and return that value. NULL can + be passed to DirectoryWalk() for a File() pointer; file entries found will be ignored. + + + int DirectoryEnd(parentID,directory,path,childID) + void *parentID; / the handle for the directory where this directory was found / + const char *directory; / the name of the directory found, ie, "DOS" / + const char *path; / the full name of the directory, ie, "C:\DOS" / + void *childID; / the handle assigned this directory by Directory() / + + If NULL is passed to DirectoryWalk for the DirectoryEnd() pointer, no report of end of directories will be made. + If DirectoryEnd returns a value other than DW_NO_ERROR, DirectoryWalk will terminate and return that value. + + + The attributes field bits are defined as follows: (see the #define's below) + + ---- ---- ---- ---1 file is read-only + ---- ---- ---- --1- file is hidden + ---- ---- ---- -1-- file is a "system" file + ---- ---- --1- ---- file's "modified" ("archive") bit is set + xxxx xxxx xx-x x--- undefined (should be masked by user) + + The filetime field is in the MS-DOS format: + + ---- ---- ---x xxxx seconds / 2 (0..29) + ---- -xxx xxx- ---- minutes (0..59) + xxxx x--- ---- ---- hours (0..23) + + The filedate field is in the MS-DOS format: + + ---- ---- ---x xxxx day of month (1..31) + ---- ---x xxx- ---- month (1..12) + xxxx xxx- ---- ---- year-1980 (0..127) +*/ + +#define ATTR_READONLY 0x0001 +#define ATTR_HIDDEN 0x0002 +#define ATTR_SYSTEM 0x0004 +#define ATTR_ARCHIVE 0x0020 diff --git a/private/windows/diamond/quantum/dummy.h b/private/windows/diamond/quantum/dummy.h new file mode 100644 index 000000000..b41150f11 --- /dev/null +++ b/private/windows/diamond/quantum/dummy.h @@ -0,0 +1,46 @@ +#include "defs.h" + +#define WINAPI __stdcall __import + +#define PAGE_NOACCESS 0x01 +#define PAGE_READONLY 0x02 +#define PAGE_READWRITE 0x04 +#define PAGE_WRITECOPY 0x08 +#define PAGE_EXECUTE 0x10 +#define PAGE_EXECUTE_READ 0x20 +#define PAGE_EXECUTE_READWRITE 0x40 +#define PAGE_EXECUTE_WRITECOPY 0x80 +#define PAGE_GUARD 0x100 +#define PAGE_NOCACHE 0x200 +#define MEM_COMMIT 0x1000 +#define MEM_RESERVE 0x2000 +#define MEM_DECOMMIT 0x4000 +#define MEM_RELEASE 0x8000 +#define MEM_FREE 0x10000 +#define MEM_PRIVATE 0x20000 +#define MEM_MAPPED 0x40000 +#define MEM_TOP_DOWN 0x100000 +#define SEC_FILE 0x800000 +#define SEC_IMAGE 0x1000000 +#define SEC_RESERVE 0x4000000 +#define SEC_COMMIT 0x8000000 +#define SEC_NOCACHE 0x10000000 +#define MEM_IMAGE SEC_IMAGE + + +void * +WINAPI +VirtualAlloc( + void *lpAddress, + DWORD dwSize, + DWORD flAllocationType, + DWORD flProtect + ); + +BOOL +WINAPI +VirtualFree( + void *lpAddress, + DWORD dwSize, + DWORD dwFreeType + ); diff --git a/private/windows/diamond/quantum/log.h b/private/windows/diamond/quantum/log.h new file mode 100644 index 000000000..373c5fda1 --- /dev/null +++ b/private/windows/diamond/quantum/log.h @@ -0,0 +1,7 @@ +#ifdef STAFFORD +#define LONGDOUBLE long double +#else +#define LONGDOUBLE double +#endif + +LONGDOUBLE MYLOG( LONGDOUBLE x ); diff --git a/private/windows/diamond/quantum/lz.c b/private/windows/diamond/quantum/lz.c new file mode 100644 index 000000000..4d91da0a0 --- /dev/null +++ b/private/windows/diamond/quantum/lz.c @@ -0,0 +1,719 @@ +// LZ.C +// +// Quantum file archiver and compressor +// Advanced data compression +// +// Copyright (c) 1993,1994 Cinematronics +// All rights reserved. +// +// This file contains trade secrets of Cinematronics. +// Do NOT distribute! + + +#ifdef STAFFORD +#define ASM asm +#else +#define ASM __asm +#endif + + +#ifndef __PCC__ + #pragma auto_inline(on) +#endif + +#include <stdlib.h> +#include "arith.h" +#include "quantum.h" //msliger +#include "lz.h" +#include "comp.h" +#include "dcomp.h" + +#ifdef __PCC__ //msliger +#include "log.h" +#endif //msliger + +typedef struct + { + unsigned Freq; + unsigned Symbol; + } COUNT; + + +typedef struct + { + int Num; // Number of symbols in this table, max of 64 +#ifdef PAQ + int Lookup[ 65 ]; // Given a symbol identifies its index +#endif + int SortCountdown; + COUNT Table[ 65 ]; // Yucky but 64+1 is the largest we ever need... + } COUNT_RECORD; + + +struct + { + COUNT_RECORD TokenType; + COUNT_RECORD Literal1; + COUNT_RECORD Literal2; + COUNT_RECORD Literal3; + COUNT_RECORD Literal4; + + COUNT_RECORD MatchCode; + + COUNT_RECORD WindowCode; + COUNT_RECORD TinyWindowCode; + COUNT_RECORD ShortWindowCode; + } Count; + + +typedef struct + { +#ifdef PAQ + unsigned MatchCodeTrans[ MATCH_NUM ]; +#endif + unsigned MatchCodeBase[ MATCH_CODES ]; + +#ifdef PAQ + unsigned WindowCodeTrans[ 2048 + (1 << (WINDOW_MAX-10)) ]; +#endif + long WindowCodeBase[ WINDOW_CODES ]; + +#ifdef DEBUG + long Stat[ 7 ]; +#endif + } LZ; + +LZ Lz; + +// Extra bits for each match length code + +unsigned MatchCodeExtra[ MATCH_CODES ] = + { 0,0,0,0,0,0,1,1,1,1,2,2,2,2,3,3,3,3,4,4,4,4,5,5,5,5,0 }; + +// Extra bits for each distance code + +unsigned WindowCodeExtra[ WINDOW_CODES ] = + { 0,0,0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7,8,8,9,9,10,10,11,11, + 12,12,13,13,14,14,15,15,16,16,17,17,18,18,19,19 }; + + +extern LONGDOUBLE FAST MYLOG( LONGDOUBLE x ); + + +void FAST Lz_Init( BYTE WindowBits ) //msliger + { + int i, k; + long Base, WindowSize; + + WindowSize = 1L << WindowBits; //msliger + + for( Base = i = 0; i < MATCH_CODES; i++ ) + { + Lz.MatchCodeBase[ i ] = (unsigned) Base; + + for( k = 0; k < (1 << MatchCodeExtra[ i ]); k++ ) + { +#ifdef PAQ + Lz.MatchCodeTrans[ Base++ ] = i; +#else + Base++; +#endif + } + } + + for( Base = i = 0; i < WINDOW_CODES; i++ ) + { + if( Base < WindowSize ) + { + Count.WindowCode.Num = i + 1; + + if( Base < 1 << (TINY_WINDOW_MAX) ) + { + Count.TinyWindowCode.Num = i + 1; + } + + if( Base < 1L << (SHORT_WINDOW_MAX) ) + { + Count.ShortWindowCode.Num = i + 1; + } + } + + Lz.WindowCodeBase[ i ] = Base; + + Base += (1L << WindowCodeExtra[ i ]); + } + +#ifdef PAQ + for( i = 0; i < 2048; i++ ) + { + for( k = 0; Lz.WindowCodeBase[ k ] <= i; k++ ) + ; + + Lz.WindowCodeTrans[ i ] = k - 1; + } + + Base = 2; + + for( k = k - 1; k < WINDOW_CODES; k++ ) + { + for( i = 0; i < (1 << (WindowCodeExtra[ k ] - 10)); i++ ) + { + Lz.WindowCodeTrans[ 2048 + Base++ ] = k; + } + } +#endif + + Count.TokenType.Num = 7; + Count.TokenType.SortCountdown = 4; + + for( i = 0; i <= 7; i++ ) + { + Count.TokenType.Table[ i ].Freq = 7 - i; + Count.TokenType.Table[ i ].Symbol = i; + +#ifdef PAQ + Count.TokenType.Lookup[ i ] = i; +#endif + } + + Count.Literal1.Num = + Count.Literal2.Num = + Count.Literal3.Num = + Count.Literal4.Num = 64; + + Count.Literal1.SortCountdown = + Count.Literal2.SortCountdown = + Count.Literal3.SortCountdown = + Count.Literal4.SortCountdown = 4; + + for( i = 0; i <= 64; i++ ) + { + Count.Literal1.Table[ i ].Freq = 64 - i; + Count.Literal2.Table[ i ].Freq = 64 - i; + Count.Literal3.Table[ i ].Freq = 64 - i; + Count.Literal4.Table[ i ].Freq = 64 - i; + + Count.Literal1.Table[ i ].Symbol = i; + Count.Literal2.Table[ i ].Symbol = i; + Count.Literal3.Table[ i ].Symbol = i; + Count.Literal4.Table[ i ].Symbol = i; + +#ifdef PAQ + Count.Literal1.Lookup[ i ] = i; + Count.Literal2.Lookup[ i ] = i; + Count.Literal3.Lookup[ i ] = i; + Count.Literal4.Lookup[ i ] = i; +#endif + } + + Count.MatchCode.Num = MATCH_CODES; + Count.MatchCode.SortCountdown = 4; + + for( i = 0; i <= MATCH_CODES; i++ ) + { + Count.MatchCode.Table[ i ].Freq = MATCH_CODES - i; + Count.MatchCode.Table[ i ].Symbol = i; + +#ifdef PAQ + Count.MatchCode.Lookup[ i ] = i; +#endif + } + + Count.WindowCode.SortCountdown = 4; + Count.TinyWindowCode.SortCountdown = 4; + Count.ShortWindowCode.SortCountdown = 4; + + for( i = 0; i <= WINDOW_CODES; i++ ) + { + Count.WindowCode.Table[ i ].Freq = Count.WindowCode.Num - i; + Count.TinyWindowCode.Table[ i ].Freq = Count.TinyWindowCode.Num - i; + Count.ShortWindowCode.Table[ i ].Freq = Count.ShortWindowCode.Num - i; + + Count.WindowCode.Table[ i ].Symbol = i; + Count.TinyWindowCode.Table[ i ].Symbol = i; + Count.ShortWindowCode.Table[ i ].Symbol = i; + +#ifdef PAQ + Count.WindowCode.Lookup[ i ] = i; + Count.TinyWindowCode.Lookup[ i ] = i; + Count.ShortWindowCode.Lookup[ i ] = i; +#endif + } + +#ifndef UNPAQLIB //msliger + Arith_Init(); +#endif //msliger + } + + +void FAST Lz_Close( void ) + { + #ifdef DEBUG + #ifdef PAQ + printf( "\n\n" ); + printf( "Stats:\n" ); + printf( "Literal 0 = %ld\n", Lz.Stat[ 0 ] ); + printf( "Literal 1 = %ld\n", Lz.Stat[ 1 ] ); + printf( "Literal 2 = %ld\n", Lz.Stat[ 2 ] ); + printf( "Literal 3 = %ld\n", Lz.Stat[ 3 ] ); + printf( "Match 3 = %ld\n", Lz.Stat[ 4 ] ); + printf( "Match 4 = %ld\n", Lz.Stat[ 5 ] ); + printf( "Match 5+ = %ld\n", Lz.Stat[ 6 ] ); + #endif + #endif + +#ifndef PAQLIB //msliger +#ifndef UNPAQLIB //msliger + Arith_Close(); +#endif //msliger +#endif //msliger + } + + +void FAST Lz_Bump( COUNT_RECORD NEAR *Rec ) + { + COUNT NEAR *pTab; + int Num; + int i, j; + COUNT Scratch; + + pTab = Rec->Table; + Num = Rec->Num; + + if( --Rec->SortCountdown == 0 ) + { + Rec->SortCountdown = 50; + + // Change all the frequencies to their absolute values divided by two. + + for( i = 0; i < Num; i++ ) + { + pTab[ i ].Freq -= pTab[ i + 1 ].Freq; + + pTab[ i ].Freq++; + pTab[ i ].Freq >>= 1; + } + + // Sort them. + // Yes, this could be a faster sort but the list is never + // more than 64 items and it spends very little time here. + + for( i = 0; i < Num; i++ ) + { + for( j = i + 1; j < Num; j++ ) + { + if( pTab[ j ].Freq > pTab[ i ].Freq ) + { + Scratch = pTab[ i ]; + pTab[ i ] = pTab[ j ]; + pTab[ j ] = Scratch; + } + } + } + + // Recreate the relative frequencies. + + for( i = Num - 1; i >= 0; i-- ) + { + pTab[ i ].Freq += pTab[ i + 1 ].Freq; + } + +#ifdef PAQ + // Rebuild the lookup table. + + for( i = 0; i < Num; i++ ) + { + Rec->Lookup[ pTab[ i ].Symbol ] = i; + } +#endif + } + else /* SortCountDown != 0 */ + { + for( i = Num - 1; i >= 0; i-- ) + { + pTab[ i ].Freq >>= 1; + + if( pTab[ i ].Freq <= pTab[ i + 1 ].Freq ) + { + pTab[ i ].Freq = pTab[ i + 1 ].Freq + 1; + } + } + } + } + + +#ifdef PAQ + +// Maps a distance into a window code + +int FAST Lz_MapDistanceToWindowCode( long Distance ) + { + if( Distance < 2048 ) + { + return( Lz.WindowCodeTrans[ Distance ] ); + } + else + { + return( Lz.WindowCodeTrans[ 2048 + (Distance >> 10) ] ); + } + } + + +LONGDOUBLE FAST EstimateBits( long Occur, long Total ) + { + #ifdef DEBUG + if( Occur <= 0 || Total <= 0 ) + { + puts( "ERR: Domain" ); + exit( -1 ); + } + #endif + + return( MYLOG( (LONGDOUBLE)Total / (LONGDOUBLE)Occur ) ); + } + + +void FAST Lz_Encode_Symbol( COUNT_RECORD *Rec, int Sym ) + { + register COUNT NEAR *pTab; + SYMBOL Symbol; + int Index = Rec->Lookup[ Sym ]; + + Symbol.High = Rec->Table[ Index ].Freq; + Symbol.Low = Rec->Table[ Index + 1 ].Freq; + Symbol.Scale = Rec->Table[ 0 ].Freq; + + Arith_Encode_Symbol( &Symbol ); + + pTab = (COUNT NEAR *) Rec->Table; + + do + { + pTab->Freq += MAGIC_INC; + pTab++; + } + while( Index-- ); + + if( Rec->Table[ 0 ].Freq > MAGIC_MAX ) + { + Lz_Bump( Rec ); + } + } + + +LONGDOUBLE FAST Lz_Encode_Symbol_Cost( COUNT_RECORD *Rec, int Sym ) + { + int Index = Rec->Lookup[ Sym ]; + + return( EstimateBits( + Rec->Table[ Index ].Freq - Rec->Table[ Index + 1 ].Freq, + Rec->Table[ 0 ].Freq ) ); + } + + +LONGDOUBLE FAST Lz_Encode_Match_Cost( MATCH *Match ) + { + int Code; + LONGDOUBLE Total; + + switch( Match->Len ) + { + case 3: + Total = Lz_Encode_Symbol_Cost( &Count.TokenType, 4 ); + Code = Lz_MapDistanceToWindowCode( Match->Dist - 1 ); + Total += Lz_Encode_Symbol_Cost( &Count.TinyWindowCode, Code ); + break; + case 4: + Total = Lz_Encode_Symbol_Cost( &Count.TokenType, 5 ); + Code = Lz_MapDistanceToWindowCode( Match->Dist - 1 ); + Total += Lz_Encode_Symbol_Cost( &Count.ShortWindowCode, Code ); + break; + default: + Total = Lz_Encode_Symbol_Cost( &Count.TokenType, 6 ); + Code = Lz.MatchCodeTrans[ Match->Len - 5 ]; + Total += Lz_Encode_Symbol_Cost( &Count.MatchCode, Code ); + Total += MatchCodeExtra[ Code ]; + Code = Lz_MapDistanceToWindowCode( Match->Dist - 1 ); + Total += Lz_Encode_Symbol_Cost( &Count.WindowCode, Code ); + } + + Total += WindowCodeExtra[ Code ]; + + return( Total ); + } + + +void FAST Lz_Encode_Match( MATCH *Match ) + { + int Code; + + switch( Match->Len ) + { + case 3: + #ifdef DEBUG + Lz.Stat[ 4 ]++; + #endif + + Lz_Encode_Symbol( &Count.TokenType, 4 ); + Code = Lz_MapDistanceToWindowCode( Match->Dist - 1 ); + Lz_Encode_Symbol( &Count.TinyWindowCode, Code ); + break; + + case 4: + #ifdef DEBUG + Lz.Stat[ 5 ]++; + #endif + + Lz_Encode_Symbol( &Count.TokenType, 5 ); + Code = Lz_MapDistanceToWindowCode( Match->Dist - 1 ); + Lz_Encode_Symbol( &Count.ShortWindowCode, Code ); + break; + + default: + #ifdef DEBUG + Lz.Stat[ 6 ]++; + #endif + + Lz_Encode_Symbol( &Count.TokenType, 6 ); + Code = Lz.MatchCodeTrans[ Match->Len - 5 ]; + Lz_Encode_Symbol( &Count.MatchCode, Code ); + Arith_Encode_Bits( Match->Len - 5 - Lz.MatchCodeBase[ Code ], + MatchCodeExtra[ Code ] ); + Code = Lz_MapDistanceToWindowCode( Match->Dist - 1 ); + Lz_Encode_Symbol( &Count.WindowCode, Code ); + } + + Arith_Encode_Bits( Match->Dist - 1 - Lz.WindowCodeBase[ Code ], + WindowCodeExtra[ Code ] ); + } + + +LONGDOUBLE FAST Lz_Encode_Literal_Cost( int Chr ) + { + LONGDOUBLE Total; + + if( Chr < 64 ) + { + Total = Lz_Encode_Symbol_Cost( &Count.TokenType, 0 ) + + Lz_Encode_Symbol_Cost( &Count.Literal1, Chr ); + } + else + { + if( Chr < 128 ) + { + Total = Lz_Encode_Symbol_Cost( &Count.TokenType, 1 ) + + Lz_Encode_Symbol_Cost( &Count.Literal2, Chr - 64 ); + } + else + { + if( Chr < 192 ) + { + Total = Lz_Encode_Symbol_Cost( &Count.TokenType, 2 ) + + Lz_Encode_Symbol_Cost( &Count.Literal3, Chr - 128 ); + } + else + { + Total = Lz_Encode_Symbol_Cost( &Count.TokenType, 3 ) + + Lz_Encode_Symbol_Cost( &Count.Literal4, Chr - 192 ); + } + } + } + + return( Total ); + } + + +void FAST Lz_Encode_Literal( int Chr ) + { + if( Chr < 64 ) + { + #ifdef DEBUG + Lz.Stat[ 0 ]++; + #endif + Lz_Encode_Symbol( &Count.TokenType, 0 ); + Lz_Encode_Symbol( &Count.Literal1, Chr ); + } + else + { + if( Chr < 128 ) + { + #ifdef DEBUG + Lz.Stat[ 1 ]++; + #endif + Lz_Encode_Symbol( &Count.TokenType, 1 ); + Lz_Encode_Symbol( &Count.Literal2, Chr - 64 ); + } + else + { + if( Chr < 192 ) + { + #ifdef DEBUG + Lz.Stat[ 2 ]++; + #endif + Lz_Encode_Symbol( &Count.TokenType, 2 ); + Lz_Encode_Symbol( &Count.Literal3, Chr - 128 ); + } + else + { + #ifdef DEBUG + Lz.Stat[ 3 ]++; + #endif + Lz_Encode_Symbol( &Count.TokenType, 3 ); + Lz_Encode_Symbol( &Count.Literal4, Chr - 192 ); + } + } + } + } + + +#else //UNPAQ + +#define LZ_DECODE_SYMBOL(Rec,Sym) \ + { \ +/* SYMBOL Symbol; / I defined these at the top of */ \ +/* unsigned Counter; / the calling function because */ \ +/* int Index; / the compiler wasn't re-using */ \ +/* register COUNT NEAR *pTab; / the local variable space. */ \ + \ + Symbol.Scale = Rec.Table[ 0 ].Freq; \ + \ + Counter = Arith_GetCount( Symbol.Scale ); \ + \ + Index = 0; \ + \ + while ( Rec.Table[ Index + 1 ].Freq > Counter ) \ + { \ + Index++; \ + } \ + \ + Sym = Rec.Table[ Index ].Symbol; \ + \ + Symbol.High = Rec.Table[ Index ].Freq; \ + Symbol.Low = Rec.Table[ Index + 1 ].Freq; \ + \ + Arith_Remove_Symbol( Symbol ); \ + \ + pTab = (COUNT NEAR *) &Rec.Table; \ + \ + do \ + { \ + pTab->Freq += MAGIC_INC; \ + pTab++; \ + } \ + while( Index-- ); \ + \ + if( Rec.Table[ 0 ].Freq > MAGIC_MAX ) \ + { \ + Lz_Bump((COUNT_RECORD NEAR *)&Rec ); \ + } \ + } + + +void FAST Lz_NextToken( void ) + { + int Code; + MATCH Match; + SYMBOL Symbol; /* ref'd from macro */ + unsigned Counter; /* ref'd from macro */ + int Index; /* ref'd from macro */ + register COUNT NEAR *pTab; /* ref'd from macro */ + + LZ_DECODE_SYMBOL(Count.TokenType,Code); + + switch( Code ) + { + case 0: + LZ_DECODE_SYMBOL(Count.Literal1,Code); + DComp_Token_Literal( Code ); + break; + + case 1: + LZ_DECODE_SYMBOL(Count.Literal2,Code); + DComp_Token_Literal( Code + 64 ); + break; + + case 2: + LZ_DECODE_SYMBOL(Count.Literal3,Code); + DComp_Token_Literal( Code + 128 ); + break; + + case 3: + LZ_DECODE_SYMBOL(Count.Literal4,Code); + DComp_Token_Literal( Code + 192 ); + break; + + case 4: + Match.Len = 3; + LZ_DECODE_SYMBOL(Count.TinyWindowCode,Code); + Match.Dist = Lz.WindowCodeBase[ Code ] + + Arith_Decode_Bits( WindowCodeExtra[ Code ] ) + 1; + DComp_Token_Match( Match ); + break; + + case 5: + Match.Len = 4; + LZ_DECODE_SYMBOL(Count.ShortWindowCode,Code); + Match.Dist = Lz.WindowCodeBase[ Code ] + + Arith_Decode_Bits( WindowCodeExtra[ Code ] ) + 1; + DComp_Token_Match( Match ); + break; + + case 6: + LZ_DECODE_SYMBOL(Count.MatchCode,Code); + Match.Len = Lz.MatchCodeBase[ Code ] + + (short) Arith_Decode_Bits( MatchCodeExtra[ Code ] ) + 5; + LZ_DECODE_SYMBOL(Count.WindowCode,Code); + Match.Dist = Lz.WindowCodeBase[ Code ] + + Arith_Decode_Bits( WindowCodeExtra[ Code ] ) + 1; + DComp_Token_Match( Match ); + break; + } + } + +#endif + + +#ifdef PAQ + +// Estimates the number of bits required to represent a symbol +// given the total number of occurances of this symbol and the +// total number of occurances of all symbols (an order-0 probability). + +#ifndef __PCC__ + +#undef HUGE /* defined by MATH.H */ + +#include <math.h> + +//#if defined(_MIPS_) || defined(_ALPHA_) +#ifndef _X86_ +#ifndef logl +#define logl(x) ((LONGDOUBLE)log((double)(x))) +#endif +#ifndef M_LN2 +#define M_LN2 0.6931471805599 +#endif +#endif + +LONGDOUBLE FAST MYLOG( LONGDOUBLE x ) + { +//#if defined(_MIPS_) || defined(_ALPHA_) +#ifndef _X86_ + return( logl( x ) / M_LN2 ); +#else + + ASM fldln2 // st(0) = log( x ) + ASM fld x + ASM fyl2x + + ASM fldln2 // st(0) = st(0) / log( 2 ) + ASM fdivp st(1),st + + ASM fstp x + + return( x ); +#endif /* 0 */ + } +#endif /* ! PCC */ + +#endif /* PAQ */ diff --git a/private/windows/diamond/quantum/lz.h b/private/windows/diamond/quantum/lz.h new file mode 100644 index 000000000..a19994abf --- /dev/null +++ b/private/windows/diamond/quantum/lz.h @@ -0,0 +1,60 @@ +// LZ.H +// +// Quantum file archiver and compressor +// Advanced data compression +// +// Copyright (c) 1993,1994 David Stafford +// All rights reserved. + +#ifndef __LZ +#define __LZ + +#include "defs.h" + +#define MATCH_NUM 257 +#define MATCH_MIN 3 +#define MATCH_MAX (MATCH_NUM + MATCH_MIN - 1) +#define MATCH_CODES 27 + +#define WINDOW_MIN 10 // the sliding window size +#define WINDOW_DEFAULT 20 // 2**N bits +#define WINDOW_MAX 21 +#define WINDOW_CODES 42 +#define WINDOW_SHIFT 8 +#define WINDOW_BREAK (1 << WINDOW_SHIFT) +#define WINDOW_TOTAL ((1 << (WINDOW_MAX - WINDOW_SHIFT))+WINDOW_BREAK) + +// Matches of length MATCH_MIN use a shorter window because: +// +// 1. Encoding them with very large distances is inefficient. +// 2. They occur pretty often and deserve their own frequency table. + +#define TINY_WINDOW_MAX 12 // 4K max +#define SHORT_WINDOW_MAX 18 // 256K max + +#define MAGIC_MAX 3800 // was 4000 in 0.18 and earlier versions +#define MAGIC_INC 8 + +typedef struct + { + short Len; + long Dist; + } MATCH; + + +#ifdef STAFFORD +#define LONGDOUBLE long double +#else +#define LONGDOUBLE double +#endif + +void FAST Lz_Init( BYTE WindowBits ); //msliger +void FAST Lz_NextToken( void ); +void FAST Lz_Encode_Match( MATCH *Match ); +LONGDOUBLE FAST Lz_Encode_Match_Cost( MATCH *Match ); +void FAST Lz_Encode_Literal( int Ch ); +LONGDOUBLE FAST Lz_Encode_Literal_Cost( int Ch ); +void FAST Lz_Close( void ); + + +#endif diff --git a/private/windows/diamond/quantum/mem.h b/private/windows/diamond/quantum/mem.h new file mode 100644 index 000000000..9a476ba0e --- /dev/null +++ b/private/windows/diamond/quantum/mem.h @@ -0,0 +1,11 @@ +// MEM.H +// +// Quantum file archiver and compressor +// Advanced data compression +// +// Copyright (c) 1993,1994 David Stafford +// All rights reserved. + + +void *Mem_Malloc( long x ); +void Mem_Free( void *x ); diff --git a/private/windows/diamond/quantum/qci.c b/private/windows/diamond/quantum/qci.c new file mode 100644 index 000000000..50b00d0bf --- /dev/null +++ b/private/windows/diamond/quantum/qci.c @@ -0,0 +1,249 @@ +/* + * Microsoft Confidential + * Copyright (C) Microsoft Corporation 1994 + * All Rights Reserved. + * + * QCI.C: Quantum Compression Interface + * + * History: + * 20-Jan-1994 msliger Initial version (stub). + * 23-Jan-1994 msliger Real version (not a stub). + * 11-Feb-1994 msliger Changed M*ICreate() to adjust size. + * 13-Feb-1994 msliger revised type names, ie, UINT16 -> UINT. + * changed handles to HANDLEs. + * normalized MCI_MEMORY type. + * 24-Feb-1994 msliger Changed alloc,free to common typedefs. + * Changed MCI_MEMORY to MI_MEMORY. + * Restructured allocation/destruction. + * 15-Mar-1994 msliger Changes for 32 bits. + * 22-Mar-1994 msliger Changed interface USHORT to UINT. + * 26-May-1994 msliger Adapted to Quantum compression from MCI.C + * 27-May-1994 msliger Added configuration parameter. + * 30-May-1994 msliger Changed to QCI* names. + * 15-Jun-1994 msliger Use passed in alloc/free everywhere + */ + +/* --- preprocessor ------------------------------------------------------- */ + +#include <stdio.h> /* for NULL */ +#include <string.h> /* for memcpy() */ + +#include "qci.h" /* types, prototype verification, error codes */ + +#include "comp.h" /* features in COMP.C */ + +#include "rtl.h" /* Rtl_Malloc/Free definitions */ + +#define MAX_GROWTH 10240 /* don't know what it will really be */ + + +/* MAKE_SIGNATURE - Construct a structure signature + * + * Entry: + * a,b,c,d - four characters + * + * Exit: + * Returns constructed SIGNATURE + * + * Example: + * strct->signature = MAKE_SIGNATURE('b','e','n','s') + */ + +#define MAKE_SIGNATURE(a,b,c,d) (a + (b<<8) + (c<<16) + (d<<24)) +#define BAD_SIGNATURE (0L) +#define QCI_SIGNATURE MAKE_SIGNATURE('Q','C','I','C') + +/* --- QCI context structure ---------------------------------------------- */ + +typedef ULONG SIGNATURE; /* structure signature */ + +struct QCI_CONTEXT /* private structure */ +{ + SIGNATURE signature; /* for validation */ + PFNALLOC pfnAlloc; /* memory alloc function */ + PFNFREE pfnFree; /* memory free function */ + UINT cbDataBlockMax; /* promised max data size */ +}; + +typedef struct QCI_CONTEXT FAR *PMCC_CONTEXT; /* a pointer to one */ + +#define PMCCfromHMC(h) ((PMCC_CONTEXT)(h)) /* handle to pointer */ +#define HMCfromPMCC(p) ((QCI_CONTEXT_HANDLE)(p)) /* pointer to handle */ + + +/* --- local variables ---------------------------------------------------- */ + +/* + * pmccLast - Remember last QCI context for use by Rtl_Malloc + * and Rtl_Free. + */ +static PMCC_CONTEXT pmccLast; + + +/* --- QCICreateCompression() --------------------------------------------- */ + +int DIAMONDAPI QCICreateCompression( + UINT * pcbDataBlockMax, /* max uncompressed data block */ + void FAR * pvConfiguration, /* implementation-defined */ + PFNALLOC pfnma, /* Memory allocation function */ + PFNFREE pfnmf, /* Memory free function */ + UINT * pcbDstBufferMin, /* gets required output buffer */ + QCI_CONTEXT_HANDLE * pmchHandle) /* gets newly-created handle */ +{ + PMCC_CONTEXT context; /* new context */ + int FAR *pConfiguration; /* to get configuration details */ + BYTE cWindowBits; /* for Quantum implementation */ + int iCompressionLevel; /* for Quantum implementation */ + + *pmchHandle = (QCI_CONTEXT_HANDLE) 0; /* wait until it's valid */ + + pConfiguration = pvConfiguration; /* get a pointer we can use */ + cWindowBits = (BYTE) pConfiguration[0]; /* get window bits config */ + iCompressionLevel = pConfiguration[1]; /* get compress level config */ + + if ((cWindowBits < 10) || (cWindowBits > 21)) + { + return(MCI_ERROR_CONFIGURATION); /* can't accept that */ + } + + if ((iCompressionLevel < 1) || (iCompressionLevel > 7)) + { + return(MCI_ERROR_CONFIGURATION); /* can't accept that */ + } + + if (pConfiguration[2] != -1) + { + return(MCI_ERROR_CONFIGURATION); /* don't know any others */ + } + + if ((*pcbDataBlockMax == 0) || (*pcbDataBlockMax > 32768u)) + { + *pcbDataBlockMax = 32768u; /* help with source block size */ + } + + context = pfnma(sizeof(struct QCI_CONTEXT)); + if (context == NULL) + { + return(MCI_ERROR_NOT_ENOUGH_MEMORY); /* if can't allocate */ + } + + context->pfnAlloc = pfnma; + context->pfnFree = pfnmf; + context->cbDataBlockMax = *pcbDataBlockMax; /* remember agreement */ + context->signature = QCI_SIGNATURE; + pmccLast = context; /* Set for Rtl_Malloc/Free */ + + *pcbDstBufferMin = /* we'll expand sometimes */ + *pcbDataBlockMax + MAX_GROWTH; + + Comp_Init(cWindowBits,iCompressionLevel); /* setup compressor */ + + /* pass context back to caller */ + + *pmchHandle = HMCfromPMCC(context); + + return(MCI_ERROR_NO_ERROR); /* tell caller all is well */ +} + +/* --- QCICompress() ------------------------------------------------------ */ + +int DIAMONDAPI QCICompress( + QCI_CONTEXT_HANDLE hmc, /* compression context */ + void FAR * pbSrc, /* source buffer */ + UINT cbSrc, /* source actual size */ + void FAR * pbDst, /* target buffer */ + UINT cbDst, /* size of target buffer */ + UINT * pcbResult) /* gets target actual size */ +{ + PMCC_CONTEXT context; /* pointer to the context */ + int result; /* return code */ + + context = PMCCfromHMC(hmc); /* get pointer from handle */ + pmccLast = context; /* Save for Rtl_Malloc/Free */ + + if (context->signature != QCI_SIGNATURE) + { + return(MCI_ERROR_BAD_PARAMETERS); /* missing signature */ + } + + if (cbSrc > context->cbDataBlockMax) + { + return(MCI_ERROR_BAD_PARAMETERS); /* violated max block promise */ + } + + if (cbDst < (context->cbDataBlockMax + MAX_GROWTH)) + { + return(MCI_ERROR_BAD_PARAMETERS); /* violated min buffer request */ + } + + result = Comp_CompressBlock(pbSrc,cbSrc,pbDst,cbDst,pcbResult); + + if (result == 0) + { + return(MCI_ERROR_NO_ERROR); /* report no failure */ + } + else + { + return(MCI_ERROR_FAILED); /* report failure */ + } +} + +/* --- QCIResetCompression() ---------------------------------------------- */ + +int DIAMONDAPI QCIResetCompression(QCI_CONTEXT_HANDLE hmc) +{ + PMCC_CONTEXT context; /* pointer to the context */ + + context = PMCCfromHMC(hmc); /* get pointer from handle */ + pmccLast = context; /* Save for Rtl_Malloc/Free */ + + if (context->signature != QCI_SIGNATURE) + { + return(MCI_ERROR_BAD_PARAMETERS); /* missing signature */ + } + + Comp_Reset(); /* do it */ + + return(MCI_ERROR_NO_ERROR); /* if tag is OK */ +} + +/* --- QCIDestroyCompression() -------------------------------------------- */ + +int DIAMONDAPI QCIDestroyCompression(QCI_CONTEXT_HANDLE hmc) +{ + PMCC_CONTEXT context; /* pointer to context */ + + context = PMCCfromHMC(hmc); /* get pointer from handle */ + pmccLast = context; /* Save for Rtl_Malloc/Free */ + + if (context->signature != QCI_SIGNATURE) + { + return(MCI_ERROR_BAD_PARAMETERS); /* missing signature */ + } + + Comp_Close(); /* shut down compressor */ + + context->signature = BAD_SIGNATURE; /* destroy signature */ + + context->pfnFree(context); /* self-destruct */ + pmccLast = NULL; /* No context for Rtl_Malloc/Free */ + + return(MCI_ERROR_NO_ERROR); /* success */ +} + +/* --- Rtl_Malloc() ------------------------------------------------------- */ + +void * FAST Rtl_Malloc( long x ) + { + return pmccLast->pfnAlloc((ULONG) x); + } + + +/* --- Rtl_Free() --------------------------------------------------------- */ + +void FAST Rtl_Free( void *x ) + { + pmccLast->pfnFree(x); + } + +/* ------------------------------------------------------------------------ */ diff --git a/private/windows/diamond/quantum/qci.h b/private/windows/diamond/quantum/qci.h new file mode 100644 index 000000000..27eeda50b --- /dev/null +++ b/private/windows/diamond/quantum/qci.h @@ -0,0 +1,268 @@ +/* + * Microsoft Confidential + * Copyright (C) Microsoft Corporation 1993,1994 + * All Rights Reserved. + * + * QCI.H - Diamond Memory Compression Interface (QCI) + * + * History: + * 30-May-1994 msliger Created from MCI.H by global replace. + * 31-May-1994 msliger Documented the configuration info. + * 08-Aug-1994 msliger pragma pack'd configuration array. + * + * Functions: + * QCICreateCompression - Create and reset an QCI compression context + * QCICloneCompression - Make a copy of a compression context + * QCICompress - Compress a block of data + * QCIResetCompression - Reset compression context + * QCIDestroyCompression - Destroy QCI compression context + * + * Types: + * QCI_CONTEXT_HANDLE - Handle to an QCI compression context + * PFNALLOC - Memory allocation function for QCI + * PFNFREE - Free memory function for QCI + */ + +/* --- types -------------------------------------------------------------- */ + +#ifndef DIAMONDAPI +#define DIAMONDAPI __cdecl +#endif + +#ifndef _BYTE_DEFINED +#define _BYTE_DEFINED +typedef unsigned char BYTE; +#endif + +#ifndef _UINT_DEFINED +#define _UINT_DEFINED +typedef unsigned int UINT; +#endif + +#ifndef _ULONG_DEFINED +#define _ULONG_DEFINED +typedef unsigned long ULONG; +#endif + +#ifndef FAR +#ifdef BIT16 +#define FAR far +#else +#define FAR +#endif +#endif + +#ifndef HUGE +#ifdef BIT16 +#define HUGE huge +#else +#define HUGE +#endif +#endif + +#ifndef _MI_MEMORY_DEFINED +#define _MI_MEMORY_DEFINED +typedef void HUGE * MI_MEMORY; +#endif + +#ifndef _MHANDLE_DEFINED +#define _MHANDLE_DEFINED +typedef unsigned long MHANDLE; +#endif + +/* --- QCI-defined types -------------------------------------------------- */ + +/* QCI_CONTEXT_HANDLE - Handle to an QCI compression context */ + +typedef MHANDLE QCI_CONTEXT_HANDLE; /* hmc */ + + +/*** PFNALLOC - Memory allocation function for QCI + * + * Entry: + * cb - Size in bytes of memory block to allocate + * + * Exit-Success: + * Returns !NULL pointer to memory block + * + * Exit-Failure: + * Returns NULL; insufficient memory + */ +#ifndef _PFNALLOC_DEFINED +#define _PFNALLOC_DEFINED +typedef MI_MEMORY (FAR DIAMONDAPI *PFNALLOC)(ULONG cb); /* pfnma */ +#endif + + +/*** PFNFREE - Free memory function for QCI + * + * Entry: + * pv - Memory block allocated by matching PFNALLOC function + * + * Exit: + * Memory block freed. + */ +#ifndef _PFNFREE_DEFINED +#define _PFNFREE_DEFINED +typedef void (FAR DIAMONDAPI *PFNFREE)(MI_MEMORY pv); /* pfnmf */ +#endif + +/* --- prototypes --------------------------------------------------------- */ + +/*** QCICreateCompression - Create QCI compression context + * + * Entry: + * pcbDataBlockMax *largest uncompressed data block size desired, + * gets largest uncompressed data block allowed + * pvConfiguration passes implementation-specific info to compressor. + * pfnma memory allocation function pointer + * pfnmf memory free function pointer + * pcbDstBufferMin gets required compressed data buffer size + * pmchHandle gets newly-created context's handle + * + * Exit-Success: + * Returns MCI_ERROR_NO_ERROR; + * *pcbDataBlockMax, *pcbDstBufferMin, *pmchHandle filled in. + * + * Exit-Failure: + * MCI_ERROR_NOT_ENOUGH_MEMORY, could not allocate enough memory. + * MCI_ERROR_BAD_PARAMETERS, something wrong with parameters. + */ +int FAR DIAMONDAPI QCICreateCompression( + UINT FAR * pcbDataBlockMax, /* max uncompressed data block size */ + void FAR * pvConfiguration, /* See QUANTUMCONFIGURATION */ + PFNALLOC pfnma, /* Memory allocation function ptr */ + PFNFREE pfnmf, /* Memory free function ptr */ + UINT FAR * pcbDstBufferMin, /* gets required output buffer size */ + QCI_CONTEXT_HANDLE FAR *pmchHandle); /* gets newly-created handle */ + + +/*** QCICloneCompression - Make a copy of a compression context + * + * Entry: + * hmc handle to current compression context + * pmchHandle gets newly-created handle + * + * Exit-Success: + * Returns MCI_ERROR_NO_ERROR; + * *pmchHandle filled in. + * + * Exit-Failure: + * Returns: + * MCI_ERROR_BAD_PARAMETERS, something wrong with parameters. + * MCI_ERROR_NOT_ENOUGH_MEMORY, could not allocate enough memory. + * + * NOTES: + * (1) This API is intended to permit "roll-back" of a sequence of + * of QCICompress() calls. Before starting a sequence that may need + * to be rolled-back, use QCICloneCompression() to save the state of + * the compression context, then do the QCICompress() calls. If the + * sequence is successful, the "cloned" hmc can be destroyed with + * QCIDestroyCompression(). If the sequence is *not* successful, then + * the original hmc can be destroyed, and the cloned one can be used + * to restart as if the sequence of QCICompress() calls had never + * occurred. + */ +int FAR DIAMONDAPI QCICloneCompression( + QCI_CONTEXT_HANDLE hmc, /* current compression context */ + QCI_CONTEXT_HANDLE *pmchHandle); /* gets newly-created handle */ + + +/*** QCICompress - Compress a block of data + * + * Entry: + * hmc handle to compression context + * pbSrc source buffer (uncompressed data) + * cbSrc size of data to be compressed + * pbDst destination buffer (for compressed data) + * cbDst size of destination buffer + * pcbResult receives compressed size of data + * + * Exit-Success: + * Returns MCI_ERROR_NO_ERROR; + * *pcbResult has size of compressed data in pbDst. + * Compression context possibly updated. + * + * Exit-Failure: + * MCI_ERROR_BAD_PARAMETERS, something wrong with parameters. + */ +int FAR DIAMONDAPI QCICompress( + QCI_CONTEXT_HANDLE hmc, /* compression context */ + void FAR * pbSrc, /* source buffer */ + UINT cbSrc, /* source buffer size */ + void FAR * pbDst, /* target buffer */ + UINT cbDst, /* target buffer size */ + UINT FAR * pcbResult); /* gets target data size */ + + +/*** QCIResetCompression - Reset compression history (if any) + * + * De-compression can only be started on a block which was compressed + * immediately following a QCICreateCompression() or QCIResetCompression() + * call. This function forces such a new "compression boundary" to be + * created (only by causing the compressor to ignore history, can the data + * output be decompressed without history.) + * + * Entry: + * hmc - handle to compression context + * + * Exit-Success: + * Returns MCI_ERROR_NO_ERROR; + * Compression context reset. + * + * Exit-Failure: + * Returns MCI_ERROR_BAD_PARAMETERS, invalid context handle. + */ +int FAR DIAMONDAPI QCIResetCompression(QCI_CONTEXT_HANDLE hmc); + + +/*** QCIDestroyCompression - Destroy QCI compression context + * + * Entry: + * hmc - handle to compression context + * + * Exit-Success: + * Returns MCI_ERROR_NO_ERROR; + * Compression context destroyed. + * + * Exit-Failure: + * Returns MCI_ERROR_BAD_PARAMETERS, invalid context handle. + */ +int FAR DIAMONDAPI QCIDestroyCompression(QCI_CONTEXT_HANDLE hmc); + +/* --- constants ---------------------------------------------------------- */ + +/* return codes */ + +#define MCI_ERROR_NO_ERROR 0 +#define MCI_ERROR_NOT_ENOUGH_MEMORY 1 +#define MCI_ERROR_BAD_PARAMETERS 2 +#define MCI_ERROR_BUFFER_OVERFLOW 3 +#define MCI_ERROR_FAILED 4 +#define MCI_ERROR_CONFIGURATION 5 + +/* --- Quantum configuration details ------------------------------------- */ + +/*** Quantum pvConfiguration structure + * + * For the Quantum compressor, two parameters are configurable, the + * "compression level", which controls the compressor's aggression, + * and "window bits", which defines the size of the buffer needed by + * the decompressor (which affects the compressor's output). + */ + +#pragma pack (2) + +typedef struct { + int WindowBits; // log2(buffersize), 10..21 (1K..2M) + int CompressionLevel; // 1..3 = fast/less compression + // 4..7 = slow/more compression +//BUGBUG 01-Jun-1994 bens What is this 3rd int for? + int HackHack; // Has to be -1, why? +} QUANTUMCONFIGURATION; /* qcfg */ + +#pragma pack () + +typedef QUANTUMCONFIGURATION *PQUANTUMCONFIGURATION; /* pqcfg */ + +/* ----------------------------------------------------------------------- */ diff --git a/private/windows/diamond/quantum/qci.nt/makefile b/private/windows/diamond/quantum/qci.nt/makefile new file mode 100644 index 000000000..8fe92222f --- /dev/null +++ b/private/windows/diamond/quantum/qci.nt/makefile @@ -0,0 +1,2 @@ +!include $(NTMAKEENV)\makefile.def +
\ No newline at end of file diff --git a/private/windows/diamond/quantum/qci.nt/sources b/private/windows/diamond/quantum/qci.nt/sources new file mode 100644 index 000000000..b9c2209b1 --- /dev/null +++ b/private/windows/diamond/quantum/qci.nt/sources @@ -0,0 +1,16 @@ +MAJORCOMP=diamond +MINORCOMP=quantum_qci + +TARGETNAME=qci +TARGETPATH=$(BASEDIR)\public\sdk\lib +TARGETTYPE=LIBRARY + +C_DEFINES=-DBIT_CONSTANTS -DPAQ -DPAQLIB + +SOURCES=..\qci.c \ + ..\comp.c \ + ..\arith.c \ + ..\lz.c \ + ..\bit.c + +UMTYPE=console diff --git a/private/windows/diamond/quantum/qdi.c b/private/windows/diamond/quantum/qdi.c new file mode 100644 index 000000000..b9e27bbcd --- /dev/null +++ b/private/windows/diamond/quantum/qdi.c @@ -0,0 +1,446 @@ +/* + * Microsoft Confidential + * Copyright (C) Microsoft Corporation 1994 + * All Rights Reserved. + * + * QDI.C: Quantum Decompression Interface + * + * History: + * 20-Jan-1994 msliger Initial version. + * 11-Feb-1994 msliger Changed M*ICreate() to adjust size. + * 13-Feb-1994 msliger revised type names, ie, UINT16 -> UINT. + * changed handles to HANDLEs. + * 24-Feb-1994 msliger Changed alloc,free to common typedefs. + * 22-Mar-1994 msliger Changed interface USHORT to UINT. + * 28-May-1994 msliger Created from MDI.C for Quantum. + * Added configuration parameter. + * 30-May-1994 msliger Changed to QDI* names. + * 08-Jul-1994 msliger Support for disk-based ring buffer. + * 27-Jul-1994 msliger Changed to allow ASM decompressor. + * 10-Aug-1994 msliger Changed to assert the requested decompress + * size for improved resistance to corrupted + * input data. + * 18-Aug-1994 msliger Implemented 286 decompress option. + * 31-Jan-1995 msliger Supported QDICreateDecompression query. + * 01-Feb-1995 msliger QDICreate no longer reserves memory. + */ + +/* --- preprocessor ------------------------------------------------------- */ + +/* + * Quantum Decompression is a very complicated, time consuming process, so + * we wrote a hand tuned 386 version. Unfortunately, some environments + * (80286 Win3.x machines and the Windows NT x86 emulation for Mips, Alpha, + * etc.) cannot run 386 code. So, we need to build different flavors of + * QDI.LIB: + * 16-bit QDI.LIB - has 286 & 386 versions + * 16-bit QDI3.LIB - 386-only version + * 32-bit QDI.LIB - 32-bit only version (for Win32 apps) + * + * There are two symbols which can be defined to affect how this code is + * built, USE_C_SRC and USE_386_ASM: + * + * USE_386_ASM Links the 386 assembler source (for i386+ non-Win32 only!) + * + * USE_C_SRC Links the C source. For any application. For + * 16-bit applications, this forces use of large memory model, + * and will generate externs for certain compiler run-time + * helpers, like __aFulmul. + * This is the DEFAULT if neither symbol is defined. + * + * These symbols can be defined in the following combinations: + * USE_386_ASM Only the 386 ASM code for 16-bit environments is available. + * ==> This is intended for Chicago setup, since Chicago only + * runs on i386 or better CPUs. + * + * USE_C_SRC Only the "portable" C code is available. + * ==> For Win32 builds, used by NT setup and Win32 EXTRACT.EXE, + * and Win32 ACME Setup. + * + * <both> Both "portable" C and the 16-bit 386 are available. The + * caller can force the use of the C code (compiled for 286, + * for compatibility purposes) or the 386 code, *or* can allow + * QDI to detect the CPU type and select the appropriate code. + * For 16-bit applications, this forces use of large memory + * model, and will generate externs for certain compiler run- + * time helpers, like __aNulshr. + * ==> For 16-bit ACME, which has to pass down the CPU type as + * determined by calling the Win16 API, since our CPU + * detection code is not reliable in 286-prot mode! + * ==> For 16-bit EXTRACT.EXE, which will rely upon the CPU + * detection code! + * + * <neither> Same as USE_C_SRC + */ + +#include <stdio.h> /* for NULL */ + +#ifdef USE_386_ASM +#ifdef USE_C_SRC +#define USE_BOTH /* means both are present */ +#endif +#else /* if not USE_386_ASM */ +#ifndef USE_C_SRC +#define USE_C_SRC /* make sure USE_C_SRC is defined if not USE_386_ASM */ +#endif +#endif + +#include "qdi.h" /* types, prototype verification, error codes */ +#include "qdi_int.h" /* QDI internal structures */ + +#ifdef USE_C_SRC +#include "dcomp.h" /* features in DCOMP.C */ +#include "rtl.h" /* functions we gotta do for you */ +#endif + +#ifdef USE_386_ASM +#include "decomp.h" /* features in DECOMP.ASM */ +#endif + +#ifdef USE_BOTH +static int GetCPUtype(void); /* internal CPU determination */ +#endif + +#define MAX_GROWTH 10240 /* don't know what it will really be */ + +#pragma warning(disable:4704) /* because of in-line asm code */ + +/* MAKE_SIGNATURE - Construct a structure signature + * + * Entry: + * a,b,c,d - four characters + * + * Exit: + * Returns constructed SIGNATURE + * + * Example: + * strct->signature = MAKE_SIGNATURE('b','e','n','s') + */ + +#define MAKE_SIGNATURE(a,b,c,d) (a + (b<<8) + (c<<16) + (d<<24)) +#define BAD_SIGNATURE (0L) +#define QDI_SIGNATURE MAKE_SIGNATURE('Q','D','I','C') + +/* --- QDI context structure ---------------------------------------------- */ + +PMDC_CONTEXT lastContext; /* needed for callbacks */ + +#define PMDCfromHMD(h) ((PMDC_CONTEXT)(h)) /* handle to pointer */ +#define HMDfromPMDC(p) ((QDI_CONTEXT_HANDLE)(p)) /* pointer to handle */ + +/* --- QDICreateDecompression() ------------------------------------------- */ + +int FAR DIAMONDAPI QDICreateDecompression( + UINT FAR * pcbDataBlockMax, /* max uncompressed data block */ + void FAR * pvConfiguration, /* implementation-defined */ + PFNALLOC pfnma, /* Memory allocation function */ + PFNFREE pfnmf, /* Memory free function */ + UINT FAR * pcbSrcBufferMin, /* gets required input buffer */ + QDI_CONTEXT_HANDLE FAR * pmdhHandle, /* gets newly-created handle */ + PFNOPEN pfnopen, /* open a file callback */ + PFNREAD pfnread, /* read a file callback */ + PFNWRITE pfnwrite, /* write a file callback */ + PFNCLOSE pfnclose, /* close a file callback */ + PFNSEEK pfnseek) /* seek in file callback */ +{ + PMDC_CONTEXT context; /* new context */ + PFQUANTUMDECOMPRESS pConfig; /* to get configuration details */ + + pConfig = pvConfiguration; /* get a pointer we can use */ + + if ((pConfig->WindowBits < 10) || (pConfig->WindowBits > 21)) + { + return(MDI_ERROR_CONFIGURATION); /* can't accept that */ + } + + if ((*pcbDataBlockMax == 0) || (*pcbDataBlockMax > 32768u)) + { + *pcbDataBlockMax = 32768u; /* help with source block size */ + } + + *pcbSrcBufferMin = /* we'll expand sometimes */ + *pcbDataBlockMax + MAX_GROWTH; + + if (pmdhHandle == NULL) /* if no context requested, */ + { + return(MDI_ERROR_NO_ERROR); /* return from query mode */ + } + +#ifdef USE_BOTH + if (pConfig->fCPUtype == QDI_CPU_UNKNOWN) + { + pConfig->fCPUtype = GetCPUtype(); /* figure out if not told */ + } + else if ((pConfig->fCPUtype != QDI_CPU_80286) && + (pConfig->fCPUtype != QDI_CPU_80386)) + { + return(MDI_ERROR_CONFIGURATION); /* bogus parameter used */ + } +#else /* not USE_BOTH */ +#ifdef USE_386_ASM + if (pConfig->fCPUtype == QDI_CPU_UNKNOWN) + { + pConfig->fCPUtype = QDI_CPU_80386; + } + else if (pConfig->fCPUtype != QDI_CPU_80386) + { + return(MDI_ERROR_CONFIGURATION); /* bogus parameter used */ + } +#else /* must be USE_C_SRC only */ + /** Nothing to do -- we just call the C code, which was either compiled */ + /* 16-bit or 32-bit. We could validate the parms, but no real need to */ +#endif /* USE_386_ASM */ +#endif /* USE_BOTH */ + + *pmdhHandle = (QDI_CONTEXT_HANDLE) 0; /* wait until it's valid */ + + context = pfnma(sizeof(struct QDI_CONTEXT)); + if (context == NULL) + { + return(MDI_ERROR_NOT_ENOUGH_MEMORY); /* if can't allocate */ + } + + context->pfnAlloc = pfnma; /* remember where alloc() is */ + context->pfnFree = pfnmf; /* remember where free() is */ + context->pfnOpen = pfnopen; /* remember where pfnopen() is */ + context->pfnRead = pfnread; /* remember where pfnread() is */ + context->pfnWrite = pfnwrite; /* remember where pfnwrite() is */ + context->pfnClose = pfnclose; /* remember where pfnclose() is */ + context->pfnSeek = pfnseek; /* remember where pfnseek() is */ + context->cbDataBlockMax = *pcbDataBlockMax; /* remember agreement */ + context->fCPUtype = pConfig->fCPUtype; /* remember CPU type */ + + context->signature = QDI_SIGNATURE; /* install signature */ + + lastContext = context; /* hand off to memory wrapper */ + +#ifdef USE_C_SRC +#ifdef USE_BOTH + if (context->fCPUtype == QDI_CPU_80286) +#endif /* USE_BOTH */ + { + /** Do the C source init **/ + if (DComp_Init((BYTE) (pConfig->WindowBits)) != 0) /* setup decompressor */ + { + pfnmf(context); /* self-destruct */ + + return(MDI_ERROR_NOT_ENOUGH_MEMORY); + } + } +#endif /* USE_C_SRC */ + +#ifdef USE_386_ASM +#ifdef USE_BOTH + else /* if (context->fCPUtype == QDI_CPU_80386) */ +#endif /* USE_BOTH */ + { + /** Do the 386 ASM init **/ + if (DComp386_Init((BYTE) (pConfig->WindowBits)) != 0) /* setup decompressor */ + { + pfnmf(context); /* self-destruct */ + + return(MDI_ERROR_NOT_ENOUGH_MEMORY); + } + } +#endif /* USE_386_ASM */ + + /* pass context back to caller */ + + *pmdhHandle = HMDfromPMDC(context); + + return(MDI_ERROR_NO_ERROR); /* tell caller all is well */ +} + +/* --- QDIDecompress() ---------------------------------------------------- */ + +int FAR DIAMONDAPI QDIDecompress( + QDI_CONTEXT_HANDLE hmd, /* decompression context */ + void FAR * pbSrc, /* source buffer */ + UINT cbSrc, /* source actual size */ + void FAR * pbDst, /* target buffer */ + UINT FAR * pcbResult) /* gets actual target size */ +{ + PMDC_CONTEXT context; /* pointer to the context */ + int result; /* return code */ + + context = PMDCfromHMD(hmd); /* get pointer from handle */ + + if (context->signature != QDI_SIGNATURE) + { + return(MDI_ERROR_BAD_PARAMETERS); /* missing signature */ + } + + lastContext = context; /* hand off to memory wrapper */ + + if (*pcbResult > context->cbDataBlockMax) + { + return(MDI_ERROR_BUFFER_OVERFLOW); /* violated max block promise */ + } + +#ifdef USE_C_SRC +#ifdef USE_BOTH + if (context->fCPUtype == QDI_CPU_80286) +#endif /* USE_BOTH */ + { + result = DComp_DecompressBlock(pbSrc,cbSrc,pbDst,*pcbResult); + } +#endif /* USE_C_SRC */ + +#ifdef USE_386_ASM +#ifdef USE_BOTH + else /* (context->fCPUtype == QDI_CPU_80386) */ +#endif /* USE_BOTH */ + { + result = DComp386_DecompressBlock(pbSrc,cbSrc,pbDst,*pcbResult); + } +#endif /* USE_386_ASM */ + + if (result == 0) + { + return(MDI_ERROR_NO_ERROR); /* report no failure */ + } + else + { + return(MDI_ERROR_FAILED); /* report failure */ + } +} + +/* --- QDIResetDecompression() -------------------------------------------- */ + +int FAR DIAMONDAPI QDIResetDecompression(QDI_CONTEXT_HANDLE hmd) +{ + PMDC_CONTEXT context; /* pointer to the context */ + + context = PMDCfromHMD(hmd); /* get pointer from handle */ + + if (context->signature != QDI_SIGNATURE) + { + return(MDI_ERROR_BAD_PARAMETERS); /* missing signature */ + } + + lastContext = context; /* hand off to memory wrapper */ + +#ifdef USE_C_SRC +#ifdef USE_BOTH + if (context->fCPUtype == QDI_CPU_80286) +#endif /* USE_BOTH */ + { + DComp_Reset(); /* do it */ + } +#endif /* USE_C_SRC */ + +#ifdef USE_386_ASM +#ifdef USE_BOTH + else /* if (context->fCPUtype == QDI_CPU_80386) */ +#endif /* USE_BOTH */ + { + DComp386_Reset(); /* do it */ + } +#endif /* USE_386_ASM */ + + return(MDI_ERROR_NO_ERROR); /* if tag is OK */ +} + +/* --- QDIDestroyDecompression() ------------------------------------------ */ + +int FAR DIAMONDAPI QDIDestroyDecompression(QDI_CONTEXT_HANDLE hmd) +{ + PMDC_CONTEXT context; /* pointer to the context */ + + context = PMDCfromHMD(hmd); /* get pointer from handle */ + + if (context->signature != QDI_SIGNATURE) + { + return(MDI_ERROR_BAD_PARAMETERS); /* missing signature */ + } + + lastContext = context; /* hand off to memory wrapper */ + +#ifdef USE_C_SRC +#ifdef USE_BOTH + if (context->fCPUtype == QDI_CPU_80286) +#endif /* USE_BOTH */ + { + DComp_Close(); /* shut down decompressor */ + } +#endif /* USE_C_SRC */ + +#ifdef USE_386_ASM +#ifdef USE_BOTH + else /* if (context->fCPUtype == QDI_CPU_80386) */ +#endif /* USE_BOTH */ + { + DComp386_Close(); /* shut down decompressor */ + } +#endif /* USE_386_ASM */ + + context->signature = BAD_SIGNATURE; /* destroy signature */ + + context->pfnFree(context); /* self-destruct */ + + return(MDI_ERROR_NO_ERROR); /* success */ +} + + +#ifdef USE_C_SRC + +/* --- Rtl_Malloc() ------------------------------------------------------- */ + +void * FAST Rtl_Malloc( long x ) + { + return(lastContext->pfnAlloc((ULONG) x)); + } + +/* --- Rtl_Free() --------------------------------------------------------- */ + +void FAST Rtl_Free( void *x ) + { + lastContext->pfnFree(x); + } + +#endif /* USE_C_SRC */ + +#ifdef USE_BOTH + +/* --- GetCPUtype() ------------------------------------------------------- */ + +#define ASM __asm + +/*** GetCPUtype - Determine CPU type (286 vs. 386 or better) + * + * [Logic taken from emm386/smartdrv.] + * + * Entry: + * none: + * + * Exit: + * Returns QDI_CPU_80286 if on i286 or compatible. + * Returns QDI_CPU_80386 if on i386 or better (or compatible). + */ +static int GetCPUtype(void) +{ + int f286; + + ASM pushf /* preserve original flags */ + ASM mov ax,7000h /* try to set some special flags bits */ + ASM push ax /* put up for popf */ + ASM popf /* pull number into flags */ + ASM pushf /* push flags back */ + ASM pop ax /* pull flags into AX */ + ASM popf /* restore original flags */ + ASM and ax,7000h /* check for 386-specific bits */ + ASM mov f286,ax /* return the result */ + + if (f286 != 0) + { + return(QDI_CPU_80386); + } + else + { + return(QDI_CPU_80286); + } +} + +#endif /* USE_BOTH */ + +/* ------------------------------------------------------------------------ */ diff --git a/private/windows/diamond/quantum/qdi.h b/private/windows/diamond/quantum/qdi.h new file mode 100644 index 000000000..e3a635290 --- /dev/null +++ b/private/windows/diamond/quantum/qdi.h @@ -0,0 +1,445 @@ +/* + * Microsoft Confidential + * Copyright (C) Microsoft Corporation 1993,1994 + * All Rights Reserved. + * + * QDI.H - Diamond Memory Decompression Interface (QDI) + * + * History: + * 01-Dec-1993 bens Initial version. + * 16-Jan-1994 msliger Split into MCI, MDI. + * 11-Feb-1994 msliger Changed M*ICreate() to adjust size. + * 13-Feb-1994 msliger revised type names, ie, UINT16 -> UINT. + * changed handles to HANDLEs. + * normalized MDI_MEMORY type. + * 24-Feb-1994 msliger Changed alloc,free to common typedefs. + * Changed HANDLE to MHANDLE. + * Changed MDI_MEMORY to MI_MEMORY. + * 22-Mar-1994 msliger Changed !INT32 to BIT16. + * Changed interface USHORT to UINT. + * 28-May-1994 msliger Added configuration parms, error code. + * 30-May-1994 msliger Created from MDI.H by global replace. + * 31-May-1994 msliger Documented the configuration info. + * 01-Jul-1994 msliger Added support for ring buffer on disk. + * 27-Jul-1994 msliger Added more def's to support ASM build. + * 08-Aug-1994 msliger pragma pack'd configuration array. + * 18-Aug-1994 msliger Added CPU type to configuration array. + * 22-Aug-1994 msliger Clarified *pcbResult in QDIDecompress(), + * changed it's name to pcbDecompressed. + * 31-Jan-1995 msliger Supported MDICreateDecompression query. + * + * Functions: + * QDICreateDecompression - Create and reset an QDI decompression context + * QDIDecompress - Decompress a block of data + * QDIResetDecompression - Reset QDI decompression context + * QDIDestroyDecompression - Destroy QDI Decompression context + * + * Types: + * QDI_CONTEXT_HANDLE - Handle to an QDI decompression context + * PFNALLOC - Memory allocation function for QDI + * PFNFREE - Free memory function for QDI + */ + +/* --- types -------------------------------------------------------------- */ + +#ifndef DIAMONDAPI +#define DIAMONDAPI __cdecl +#endif + +#ifndef _BYTE_DEFINED +#define _BYTE_DEFINED +typedef unsigned char BYTE; +#endif + +#ifndef _UINT_DEFINED +#define _UINT_DEFINED +typedef unsigned int UINT; +#endif + +#ifndef _ULONG_DEFINED +#define _ULONG_DEFINED +typedef unsigned long ULONG; +#endif + +#ifndef NEAR +#ifdef BIT16 +#define NEAR __near +#else +#define NEAR +#endif +#endif + +#ifndef FAR +#ifdef BIT16 +#define FAR __far +#else +#define FAR +#endif +#endif + +#ifndef HUGE +#ifdef BIT16 +#define HUGE __huge +#else +#define HUGE +#endif +#endif + +#ifndef FAST +#ifdef BIT16 +#define FAST __near __pascal +#else +#define FAST +#endif +#endif + +#ifndef FAST2 +#ifdef BIT16 +#define FAST2 __near __fastcall +#else +#define FAST2 __fastcall +#endif +#endif + +#ifndef _MI_MEMORY_DEFINED +#define _MI_MEMORY_DEFINED +typedef void HUGE * MI_MEMORY; +#endif + +#ifndef _MHANDLE_DEFINED +#define _MHANDLE_DEFINED +typedef unsigned long MHANDLE; +#endif + +#ifndef UNALIGNED +#ifndef NEEDS_ALIGNMENT +#define UNALIGNED +#else +#define UNALIGNED __unaligned +#endif +#endif + + +/* + * QDI will try to create a virtual ring buffer on disk if the pfnalloc call + * to create the buffer fails. These functions provide QDI the disk access + * features needed. + * + * These are modeled after the C run-time routines _open, _read, + * _write, _close, and _lseek. The values for the PFNOPEN oflag + * and pmode calls are those defined for _open. QDI expects error + * handling to be identical to these C run-time routines. + * + * As long as you faithfully copy these aspects, you can supply + * any functions you like! + * + * For PFNOPEN, the pszFile parameter will take on a special form for QDI's + * temporary file. The special form appears as a file named "*". Such a + * name field should be cast into the struct below, which contains the + * required file's size as shown in the RINGNAME structure below. + * + * Example open and close callbacks are provided. It is assumed that the + * client will provide more adaptive code for determining the temporary + * file's name and drive location, based on environment variables and the + * amount of free disk space. This sample code has hard-coded the actual + * path and fails if there is not enough free space. This code creates the + * file, then attempts to expand it to the requested size by writing a byte + * (any byte) at the requested size - 1. (This approach is not suitable for + * a file system which can support sparse files.) + * + * The callback routine may create this file on any path, and with any name, + * as appropriate. If the file cannot be created with the requested size, + * the PFNOPEN should fail. The file really should be placed on a local + * fixed disk. It would not be appropriate for the file to be placed on a + * compressed drive or a floppy disk. If the client has access to alternate + * memory, such as XMS or EMS, these operations could be emuluated. + * + * static int tempHandle = -1; + * + * int FAR DIAMONDAPI MyOpen(char FAR *pszFile,int oflag,int pmode) + * { + * if (*pszFile == '*') + * { + * PRINGNAME pringDescriptor; + * + * pringDescriptor = (PRINGNAME) pszFile; + * + * tempHandle = _open("C:\\qdi_temp.$$$",oflag,pmode); + * + * if (tempHandle != -1) + * { + * _lseek(tempHandle,(pringDescriptor->fileSize - 1),SEEK_SET); + * + * if (_write(tempHandle,&tempHandle,1) != 1) + * { + * _close(tempHandle); + * remove("C:\\qdi_temp.$$$"); + * tempHandle = -1; + * } + * } + * + * return(tempHandle); + * } + * else + * { + * * QDI only will call with *pszFile == '*' * + * } + * } + * + * The callback provider must watch for the corresponding PFNCLOSE call on + * the returned handle, and delete the created file after closing. (The + * file handle and file name assigned to the temporary file must be tracked; + * a close operation on that handle must be trapped, so the temporary file + * can be deleted as well.) + * + * The client does not need to worry about multiple concurrent opens of the + * temporary file, or more than a single temporary file (from QDI). + * + * int FAR DIAMONDAPI MyClose(int handle) + * { + * int result; + * + * result = _close(handle); + * + * if (handle == tempHandle) + * { + * remove("C:\\qdi_temp.$$$"); + * tempHandle = -1; + * } + * + * return(result); + * } + */ + +typedef int (FAR DIAMONDAPI *PFNOPEN) (char FAR *pszFile,int oflag,int pmode); +typedef UINT (FAR DIAMONDAPI *PFNREAD) (int hf, void FAR *pv, UINT cb); +typedef UINT (FAR DIAMONDAPI *PFNWRITE)(int hf, void FAR *pv, UINT cb); +typedef int (FAR DIAMONDAPI *PFNCLOSE)(int hf); +typedef long (FAR DIAMONDAPI *PFNSEEK) (int hf, long dist, int seektype); + +#pragma pack (1) + +typedef struct +{ + char wildName[2]; /* set to { '*', '\0' } */ + unsigned long fileSize; /* the required file size in bytes */ +} RINGNAME, FAR *PRINGNAME; + +#pragma pack () + +/* --- QDI-defined types -------------------------------------------------- */ + +/* QDI_CONTEXT_HANDLE - Handle to a QDI decompression context */ + +typedef MHANDLE QDI_CONTEXT_HANDLE; /* hmd */ + + +/*** PFNALLOC - Memory allocation function for QDI + * + * Entry: + * cb - Size in bytes of memory block to allocate + * + * Exit-Success: + * Returns !NULL pointer to memory block + * + * Exit-Failure: + * Returns NULL; insufficient memory + */ +#ifndef _PFNALLOC_DEFINED +#define _PFNALLOC_DEFINED +typedef MI_MEMORY (FAR DIAMONDAPI *PFNALLOC)(ULONG cb); /* pfnma */ +#endif + + +/*** PFNFREE - Free memory function for QDI + * + * Entry: + * pv - Memory block allocated by matching PFNALLOC function + * + * Exit: + * Memory block freed. + */ +#ifndef _PFNFREE_DEFINED +#define _PFNFREE_DEFINED +typedef void (FAR DIAMONDAPI *PFNFREE)(MI_MEMORY pv); /* pfnmf */ +#endif + +/* --- prototypes --------------------------------------------------------- */ + +/*** QDICreateDecompression - Create QDI decompression context + * + * Entry: + * pcbDataBlockMax *largest uncompressed data block size expected, + * gets largest uncompressed data block allowed + * pvConfiguration passes implementation-specific info to decompressor. + * pfnma memory allocation function pointer + * pfnmf memory free function pointer + * pcbSrcBufferMin gets max compressed buffer size + * pmdhHandle gets newly-created context's handle + * pfnopen file open function pointer (or NULL) + * pfnread file read function pointer (or don't care) + * pfnwrite file write function pointer (or don't care) + * pfnclose file close function pointer (or don't care) + * pfnseek file seek function pointer (or don't care) + * + * If NULL is provided for pfnopen, and the ring buffer cannot be + * created via pfnma, QDICreateDecompression will fail. + * + * If pmdhHandle==NULL, *pcbDataBlockMax and *pcbSrcBufferMin will be + * filled in, but no context will be created. This query will allow + * the caller to determine required buffer sizes before creating a + * context. + * + * Exit-Success: + * Returns MDI_ERROR_NO_ERROR; + * *pcbDataBlockMax, *pcbSrcBufferMin, *pmdhHandle filled in. + * + * Exit-Failure: + * MDI_ERROR_NOT_ENOUGH_MEMORY, could not allocate enough memory. + * MDI_ERROR_BAD_PARAMETERS, something wrong with parameters. + * *pcbDataBlockMax, *pcbSrcBufferMin, *pmdhHandle undefined. + */ +int FAR DIAMONDAPI QDICreateDecompression( + UINT FAR * pcbDataBlockMax, /* max uncompressed data block size */ + void FAR * pvConfiguration, /* implementation-defined */ + PFNALLOC pfnma, /* Memory allocation function ptr */ + PFNFREE pfnmf, /* Memory free function ptr */ + UINT FAR * pcbSrcBufferMin, /* gets max. comp. buffer size */ + QDI_CONTEXT_HANDLE FAR * pmdhHandle, /* gets newly-created handle */ + PFNOPEN pfnopen, /* open a file callback */ + PFNREAD pfnread, /* read a file callback */ + PFNWRITE pfnwrite, /* write a file callback */ + PFNCLOSE pfnclose, /* close a file callback */ + PFNSEEK pfnseek); /* seek in file callback */ + + +/*** QDIDecompress - Decompress a block of data + * + * Entry: + * hmd handle to decompression context + * pbSrc source buffer (compressed data) + * cbSrc compressed size of data to be decompressed + * pbDst destination buffer (for decompressed data) + * *pcbDecompressed (ptr to UINT) the expected de-compressed size + * of this data block. (same as cbSrc from the + * QCICompress() call.). + * + * Exit-Success: + * Returns MDI_ERROR_NO_ERROR; + * *pcbDecompressed has size of decompressed data in pbDst. + * Decompression context updated. + * + * Exit-Failure: + * MDI_ERROR_BAD_PARAMETERS, something wrong with parameters. + * MDI_ERROR_BUFFER_OVERFLOW, cbSrc is too small to yield the + * requested *pcbDecompressed count. cbSrc before QDIDecompressed + * should always equal *pcbResult after QCICompress(), and + * *pcbDecompressed before QDIDecompress should always equal the + * cbSrc before QCICompress(). + * MDI_ERROR_FAILED, either cbSrc is too small, *pcbDecompressed is too + * large, or *pbSrc is corrupt. + * + * Note: + * Set your cbDecompressed to the expected de-compressed size of this + * data block, then call QDIDecompress() with the address of your + * cbDecompressed. + */ +int FAR DIAMONDAPI QDIDecompress( + QDI_CONTEXT_HANDLE hmd, /* decompression context */ + void FAR * pbSrc, /* source buffer */ + UINT cbSrc, /* source data size */ + void FAR * pbDst, /* target buffer */ + UINT FAR * pcbDecompressed); /* target data size */ + + +/*** QDIResetDecompression - Reset decompression history (if any) + * + * De-compression can only be started on a block which was compressed + * immediately following a MCICreateCompression() or MCIResetCompression() + * call. This function provides notification to the decompressor that the + * next compressed block begins on a compression boundary. + * + * Entry: + * hmd - handle to decompression context + * + * Exit-Success: + * Returns MDI_ERROR_NO_ERROR; + * Decompression context reset. + * + * Exit-Failure: + * Returns MDI_ERROR_BAD_PARAMETERS, invalid context handle. + */ +int FAR DIAMONDAPI QDIResetDecompression(QDI_CONTEXT_HANDLE hmd); + + +/*** QDIDestroyDecompression - Destroy QDI decompression context + * + * Entry: + * hmd - handle to decompression context + * + * Exit-Success: + * Returns MDI_ERROR_NO_ERROR; + * Decompression context destroyed. + * + * Exit-Failure: + * Returns MDI_ERROR_BAD_PARAMETERS, invalid context handle. + */ +int FAR DIAMONDAPI QDIDestroyDecompression(QDI_CONTEXT_HANDLE hmd); + +/* --- constants ---------------------------------------------------------- */ + +/* return codes */ + +#define MDI_ERROR_NO_ERROR 0 +#define MDI_ERROR_NOT_ENOUGH_MEMORY 1 +#define MDI_ERROR_BAD_PARAMETERS 2 +#define MDI_ERROR_BUFFER_OVERFLOW 3 +#define MDI_ERROR_FAILED 4 +#define MDI_ERROR_CONFIGURATION 5 + +/* --- Quantum configuration details ------------------------------------- */ + +/*** Quantum pvConfiguration structure + * + * For the Quantum decompressor, two parameters are configurable, the + * "window bits", which defines the size of the buffer needed by the + * the decompressor (must match the value used to compress), and the CPU + * type, which controls whether 386 opcodes will be used or not. If + * "unknown" is provided for the fCPUtype, QDI will attempt to determine + * the CPU type itself, which could fail or produce system faults on + * non-DOS platforms (like Windows.) Windows apps should use GetWinFlags() + * or a similiar method, and never pass "unknown". + * + * pvConfiguration points to this structure. + */ + +#pragma pack (1) + +typedef struct { + int WindowBits; /* log2(buffersize), 10..21 (1K..2M) */ + int fCPUtype; /* controls internal code selection */ +} QUANTUMDECOMPRESS; /* qdec */ + +#pragma pack () + +typedef QUANTUMDECOMPRESS *PQUANTUMDECOMPRESS; /* pqdec */ +typedef QUANTUMDECOMPRESS FAR *PFQUANTUMDECOMPRESS; /* pfqdec */ + +/* WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING + * + * QDI_CPU_UNKNOWN detection does *not* work when running under Windows + * in 286 protected mode! Call GetWinFlags() to determine + * the CPU type and pass it explicitly! + */ + +#define QDI_CPU_UNKNOWN (-1) /* internally determined */ + +/* + * WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING + */ + +#define QDI_CPU_80286 (0) /* '286 opcodes only */ +#define QDI_CPU_80386 (1) /* '386 opcodes used */ +#define QDI_CPU_CONSERVATIVE (QDI_CPU_80286) + +/* ----------------------------------------------------------------------- */ diff --git a/private/windows/diamond/quantum/qdi.nt/makefile b/private/windows/diamond/quantum/qdi.nt/makefile new file mode 100644 index 000000000..8fe92222f --- /dev/null +++ b/private/windows/diamond/quantum/qdi.nt/makefile @@ -0,0 +1,2 @@ +!include $(NTMAKEENV)\makefile.def +
\ No newline at end of file diff --git a/private/windows/diamond/quantum/qdi.nt/sources b/private/windows/diamond/quantum/qdi.nt/sources new file mode 100644 index 000000000..be6d54685 --- /dev/null +++ b/private/windows/diamond/quantum/qdi.nt/sources @@ -0,0 +1,15 @@ +MAJORCOMP=diamond +MINORCOMP=quantum_qdi + +TARGETNAME=qdi +TARGETPATH=$(BASEDIR)\public\sdk\lib +TARGETTYPE=LIBRARY + +C_DEFINES=-DBIT_CONSTANTS -DUNPAQ -DUNPAQLIB + +SOURCES=..\qdi.c \ + ..\dcomp.c \ + ..\arith.c \ + ..\lz.c + +UMTYPE=console diff --git a/private/windows/diamond/quantum/qdi_int.h b/private/windows/diamond/quantum/qdi_int.h new file mode 100644 index 000000000..dab9ad01b --- /dev/null +++ b/private/windows/diamond/quantum/qdi_int.h @@ -0,0 +1,35 @@ +/* + * Microsoft Confidential + * Copyright (C) Microsoft Corporation 1994 + * All Rights Reserved. + * + * QDI_INT.H: Quantum Decompression Interface private data + * + * History: + * 20-Jun-1994 msliger Initial version. + * 18-Aug-1994 msliger Added CPU type. + */ + +/* --- QDI context structure ---------------------------------------------- */ + +typedef ULONG SIGNATURE; /* structure signature */ + +struct QDI_CONTEXT /* private structure */ +{ + SIGNATURE signature; /* for validation */ + PFNALLOC pfnAlloc; /* where the alloc() is */ + PFNFREE pfnFree; /* where the free() is */ + PFNOPEN pfnOpen; /* open a file callback or NULL */ + PFNREAD pfnRead; /* read a file callback */ + PFNWRITE pfnWrite; /* write a file callback */ + PFNCLOSE pfnClose; /* close a file callback */ + PFNSEEK pfnSeek; /* seek in file callback */ + UINT cbDataBlockMax; /* promised max data size */ + UINT fCPUtype; /* CPU we're running on, QDI_CPU_xxx */ +}; + +typedef struct QDI_CONTEXT FAR *PMDC_CONTEXT; /* a pointer to one */ + +extern PMDC_CONTEXT lastContext; /* needed for memory callbacks */ + +/* ------------------------------------------------------------------------ */ diff --git a/private/windows/diamond/quantum/quantum.h b/private/windows/diamond/quantum/quantum.h new file mode 100644 index 000000000..8de238c95 --- /dev/null +++ b/private/windows/diamond/quantum/quantum.h @@ -0,0 +1,71 @@ +// QUANTUM.H +// +// Quantum file archiver and compressor +// Advanced data compression +// +// Copyright (c) 1993,1994 David Stafford +// All rights reserved. + +#ifndef __QUANTUM +#define __QUANTUM + + +typedef unsigned char BYTE; +typedef unsigned short WORD; +typedef unsigned long DWORD; +typedef int BOOL; + +#ifndef FALSE + #define FALSE 0 + #define TRUE !FALSE +#endif + +#define VERSION_MAJOR 0 +#define VERSION_MINOR 23 + +#define FILES_MAX 1024 // maximum number of files in an archive + +#define ARCHIVE_SIGNATURE 0x5344 // 'DS', used to identify a Quantum archive + + +// The archive file header + +typedef struct + { + WORD Signature; + BYTE VersionMajor; + BYTE VersionMinor; + WORD NumFiles; + BYTE WindowBits; + BYTE CompFlags; + } AHEADER; + + +// The archive header is immediately followed by the list of files + +typedef struct + { + char *Name; + char *Alias; // if not NULL, the alias name to put in a new archive + char *Comment; + DWORD Size; + WORD Time; + WORD Date; + WORD Checksum; + } AFILE; + + +typedef struct + { + char *ArchiveName; + WORD NumFiles; + AFILE *Files; + BYTE VersionMajor; + BYTE VersionMinor; + BYTE WindowBits; // number of bits to address the history window + int CompressionLevel; + long SizeLimit; // limit of an archive size, for multiple volumes + } APARMS; + + +#endif // quantum.h diff --git a/private/windows/diamond/quantum/rtl.h b/private/windows/diamond/quantum/rtl.h new file mode 100644 index 000000000..d8dfff685 --- /dev/null +++ b/private/windows/diamond/quantum/rtl.h @@ -0,0 +1,23 @@ +// RTL.H +// +// Quantum file archiver and compressor +// Advanced data compression +// +// Copyright (c) 1993,1994 David Stafford +// All rights reserved. + +#ifndef __RTL +#define __RTL + +#include <io.h> +#include "defs.h" + +char * FAST Rtl_GetPathNameOnly( char *PathName, char *FileName ); +char * FAST Rtl_GetFileNameOnly( char *FileName ); +char * FAST Rtl_GetFileNameSuffixOnly( char *FileName ); +void FAST Rtl_DOS_to_ftime( WORD Date, WORD Time, struct ftime *FTime ); +int FAST Rtl_ftime_to_DOS( WORD *Date, WORD *Time, struct ftime *FTime ); +void * FAST Rtl_Malloc( long x ); +void FAST Rtl_Free( void *x ); + +#endif diff --git a/private/windows/diamond/quantum/view.h b/private/windows/diamond/quantum/view.h new file mode 100644 index 000000000..ad3a81104 --- /dev/null +++ b/private/windows/diamond/quantum/view.h @@ -0,0 +1,15 @@ +// VIEW.H +// +// Quantum file archiver and compressor +// Advanced data compression +// +// Copyright (c) 1993,1994 David Stafford +// All rights reserved. + +#ifndef __VIEW +#define __VIEW + + +void View( char *ArchiveName ); + +#endif // view.h |