www.pudn.com > ControlRemote.zip > HuffCompress.c
#include#include #include #include "HuffCompress.h" #include "Client.h" DWORD dwWeight[256]; DWORD dwCounts[256]; DWORD dwByte[256]; DWORD dwCodes[512]; DWORD dwSymbols[256]; DWORD dwMapping[256]; DWORD dwByteTree[765]; WORD wByteTree[765]; char dwBitTree[765]; DWORD dwRootIndex,dwCodeCount,dwStorage; WORD wTreeSize; int iElements,iTotalElements; void HuffmanInitArrays() { __asm { MOV EDI,OFFSET dwWeight[0] MOV ECX,256 _InitWeight: MOV DWORD PTR [EDI],0 ADD EDI,4 DEC ECX JNZ _InitWeight } __asm { MOV EDI,OFFSET dwBitTree[0] MOV EAX,0 MOV ECX,255 _InitBitTree: MOV char PTR [EDI + EAX],2 ADD EAX,3 DEC ECX JNZ _InitBitTree } } void HuffmanBuildArrays() { __asm { MOV ESI,OFFSET dwWeight[0] MOV EDI,OFFSET dwByte[0] MOV ECX,256 _BuildByte: LODSD CMP EAX,0 JZ _SkipByte MOV EAX,256 SUB EAX,ECX STOSD _SkipByte: DEC ECX JNZ _BuildByte MOV ESI,OFFSET dwWeight[0] MOV ECX,256 MOV EDI,OFFSET dwCounts[0] _BuildCount: LODSD CMP EAX,0 JZ _SkipCount STOSD _SkipCount: DEC ECX JNZ _BuildCount MOV ESI,OFFSET dwCounts[0] // Use the Pointers to get the Number of Elements SUB EDI,ESI MOV ECX,EDI SHR ECX,2 // Check for only 1 Element in the Byte Array CMP ECX,1 JNE _Exit // Point to the Byte Array MOV EDI,OFFSET dwByte[0] // Add the Dummy Byte (256 Can't Exist, so it is Fine) MOV EAX,256 MOV [EDI + ECX * 4],EAX // Point to the Counts Array MOV EDI,OFFSET dwCounts[0] // Add the Dummy Count of 1 MOV [EDI + ECX * 4],DWORD PTR 1 // Increment the Number of Elements INC ECX // Finished Building the Arrays _Exit: // Update the Number of Elements MOV iElements,ECX MOV iTotalElements,ECX } } // Build the Byte Tree void HuffmanBuildByteTree() { DWORD dwParentWeight,dwParentDesc; int iStartPos = -3; BOOL fInsert = TRUE; // Arbitrary Value of the First Parent Combined Parent Description dwParentDesc = 1000; // While we don't have a Root Node while (iElements > 1) { // Quick Sort the Array HuffmanQuickSortD(&dwCounts[0],&dwByte[0],0,iElements - 1); // Build the Huffman Tree __asm { /* Step 1: Create a Parent for the Children with the two lowest Weights and a Descriptor for the Parent from the Children Bytes */ // Point to the Count Array MOV ESI,OFFSET dwCounts[0] // Compute the New End of Array MOV EBX,iElements DEC EBX // Update the Number of Elements MOV iElements,EBX // Index the two Lowest Weights MOV EAX,EBX DEC EAX // Create a Parent from the Two Lowest Weights MOV EDX,[ESI + EAX * 4] ADD EDX,[ESI + EBX * 4] // Save the Parent MOV dwParentWeight,EDX // Compute the Start Position in the Tree MOV ECX,iStartPos ADD ECX,3 // Update the Start Position in the Tree MOV iStartPos,ECX /* Step 3: Add to the Byte Conversion Tree */ // Point to the Byte Array MOV ESI,OFFSET dwByte[0] // Point to the Byte Table Conversion Tree MOV EDI,OFFSET dwByteTree[0] // Move the New Parent Descriptor to the First Spot in Tree MOV EDX,dwParentDesc MOV [EDI + ECX * 4],EDX // Move the First Child Byte to the Second Spot in Tree MOV EDX,[ESI + EAX * 4] MOV [EDI + ECX * 4 + 4],EDX // Move the Second Child Byte to the Third Spot in Tree MOV EDX,[ESI + EBX * 4] MOV [EDI + ECX * 4 + 8],EDX /* Step 4: Update the Counts Array, Removing the Children and Adding the Parent */ // Point to the Count Array MOV ESI,OFFSET dwCounts[0] // Restore the New Weight Value of the Parent MOV EDX,dwParentWeight // Insert the Parent to the Counts Array MOV [ESI + EAX * 4],EDX // Point to the Byte Array MOV ESI,OFFSET dwByte[0] // Restore the New Weight Value of the Parent MOV EDX,dwParentDesc // Insert the Combined Parent to the End of the Byte Array MOV [ESI + EAX * 4],EDX // Update the Parent Descriptor for the Next New Parent INC dwParentDesc } } // Get the Index to the Root in the Tree __asm { MOV ECX,iStartPos MOV dwRootIndex,ECX ADD ECX,3 MOV wTreeSize,CX } } // Quick Sort the Array in Ascending Order void HuffmanQuickSortA(DWORD *pArray1,DWORD *pArray2,int iBegin,int iEnd) { int iLow,iHigh,iTemp; __asm { // Set the Low and High Elements MOV EAX,iBegin MOV EBX,iEnd // Point the Input Array MOV ESI,pArray1 // Get the List Separator MOV ECX,EAX ADD ECX,EBX SHR ECX,1 MOV EDX,[ESI + ECX * 4] // The Main Loop _DoLoop: // Point the Input Array MOV ESI,pArray1 // Order the Low Elements _OrderLow: MOV EDI,EAX INC EAX CMP [ESI + EDI * 4],EDX JB _OrderLow MOV EAX,EDI // Order the High Elements _OrderHigh: MOV EDI,EBX DEC EBX CMP [ESI + EDI * 4],EDX JA _OrderHigh MOV EBX,EDI // Check for Swapping Array[Low] with Array[High] CMP EAX,EBX JG _NoSwap // Swap dwCounts[Low] with dwCounts[High] MOV ECX,[ESI + EAX * 4] MOV EDI,[ESI + EBX * 4] MOV [ESI + EAX * 4],EDI MOV [ESI + EBX * 4],ECX // Swap the Byte Array MOV ESI,pArray2 MOV ECX,[ESI + EAX * 4] MOV EDI,[ESI + EBX * 4] MOV [ESI + EAX * 4],EDI MOV [ESI + EBX * 4],ECX // Update the Low and High Indexes INC EAX DEC EBX // Test for Looping Back _NoSwap: MOV iTemp,EBX CMP EAX,iTemp JLE _DoLoop // Update the Low and High Values MOV iLow,EAX MOV iHigh,EBX } // Check for Sorting Elements between Begin and High (New Lower Range) if (iBegin < iHigh) HuffmanQuickSortA(pArray1,pArray2,iBegin,iHigh); // Check for Sorting Elements between Low and End (New Upper Range) if (iLow < iEnd) HuffmanQuickSortA(pArray1,pArray2,iLow,iEnd); } // Quick Sort the Array in Descending Order void HuffmanQuickSortD(DWORD *pArray1,DWORD *pArray2,int iBegin,int iEnd) { int iLow,iHigh,iTemp; __asm { // Set the Low and High Elements MOV EAX,iBegin MOV EBX,iEnd // Point the Input Array MOV ESI,pArray1 // Get the List Separator MOV ECX,EAX ADD ECX,EBX SHR ECX,1 MOV EDX,[ESI + ECX * 4] // The Main Loop _DoLoop: // Point the Input Array MOV ESI,pArray1 // Order the Low Elements _OrderLow: MOV EDI,EAX INC EAX CMP [ESI + EDI * 4],EDX JA _OrderLow MOV EAX,EDI // Order the High Elements _OrderHigh: MOV EDI,EBX DEC EBX CMP [ESI + EDI * 4],EDX JB _OrderHigh MOV EBX,EDI // Check for Swapping Array[Low] with Array[High] CMP EAX,EBX JG _NoSwap // Swap dwCounts[Low] with dwCounts[High] MOV ECX,[ESI + EAX * 4] MOV EDI,[ESI + EBX * 4] MOV [ESI + EAX * 4],EDI MOV [ESI + EBX * 4],ECX // Swap the Byte Array MOV ESI,pArray2 MOV ECX,[ESI + EAX * 4] MOV EDI,[ESI + EBX * 4] MOV [ESI + EAX * 4],EDI MOV [ESI + EBX * 4],ECX // Update the Low and High Indexes INC EAX DEC EBX // Test for Looping Back _NoSwap: MOV iTemp,EBX CMP EAX,iTemp JLE _DoLoop // Update the Low and High Values MOV iLow,EAX MOV iHigh,EBX } // Check for Sorting Elements between Begin and High (New Lower Range) if (iBegin < iHigh) HuffmanQuickSortD(pArray1,pArray2,iBegin,iHigh); // Check for Sorting Elements between Low and End (New Upper Range) if (iLow < iEnd) HuffmanQuickSortD(pArray1,pArray2,iLow,iEnd); } // Navigate the Binary Tree void HuffmanBuildCodes() { DWORD dwCodeBits; DWORD dwLeafNode; __asm { // Initialize the Count of Codes MOV dwCodeCount,0; // Initialize the Bit Code MOV ECX,0 // Initialize the Index MOV EDX,dwRootIndex // Point to the Bit and Byte Tree Arrays MOV ESI,OFFSET dwBitTree[0] MOV EDI,OFFSET dwByteTree[0] // Initialize the Number of Bits in the Code MOV dwCodeBits,0 // While We Still Have Children for the Parent _WhileLoop: // Get the Number of Children MOV EAX,0 MOV AL,[ESI + EDX] // Decrement the Parents Number of Children DEC [ESI + EDX] // Check for Children CMP EAX,0 JE _FindParent // Get the Last Child of the Current Parent ADD EDX,EAX MOV EBX,[EDI + EDX * 4] SUB EDX,EAX // Increment the Code Bits ADD ECX,ECX // For a Move to the Right in the Tree Add a 1 to the Code CMP EAX,2 JNE _SkipOr OR ECX,1 _SkipOr: // Increment the Number of Bits in the Code INC dwCodeBits // Check for a Leaf Node CMP EBX,256 JLE _LeafNode // Get the Parent Index of the Child Node Starting // with the Previous Parent of the Current Parent _SubIndex: SUB EDX,3 CMP EBX,[EDI + EDX * 4] JNE _SubIndex // Loop Back for Another Node JMP _WhileLoop // Process a Leaf Node _LeafNode: // Save the Index PUSH EDX // Point to the Codes Array MOV EAX,OFFSET dwCodes[0] // Set the Bit Count of the Symbol to the Code Array MOV EDX,dwCodeBits MOV [EAX + 1024 + EBX * 4],EDX // Set the Symbol to the Code Array MOV [EAX + EBX * 4],ECX // Save the Leaf Node PUSH ECX MOV ECX,EBX MOV dwLeafNode,ECX // Get the Current Index to the Codes Array MOV EBX,dwCodeCount // Point to the Symbol Mapping Array MOV EAX,OFFSET dwMapping[0] // Set the Mapping of the Symbol to the Code Array MOV [EAX + EBX * 4],ECX // Restore the Leaf Node POP ECX // Point to the Code Symbol Array MOV EAX,OFFSET dwSymbols[0] // Set the Symbol to the Code Array MOV [EAX + EBX * 4],ECX // Increment the Code Count INC EBX MOV dwCodeCount,EBX // Restore the Leaf Node MOV EBX,dwLeafNode // Restore the Index POP EDX // Decrement the Number of Bits in the Code DEC dwCodeBits // Decrement the Bits SHR ECX,1 // Loop Back for Another Node JMP _WhileLoop // Find the Parent Index of the Parent _FindParent: // Get the Current Parent MOV EAX,dwRootIndex MOV EBX,[EDI + EDX * 4] // Check the Children of the Parent for a Match _AddIndex: ADD EDX,3 // Check for Completion CMP EDX,EAX JG _Exit CMP EBX,[EDI + (EDX + 4) * 4] JE _SkipAdd CMP EBX,[EDI + (EDX + 8) * 4] JNE _AddIndex // Found the Index _SkipAdd: // Decrement the Number of Bits in the Code DEC dwCodeBits // Decrement the Bits SHR ECX,1 // Go back for Another Node JMP _WhileLoop _Exit: } } // Build the Byte Tree and Codes Table and Return the Tree Size WORD HuffmanDictionary(BYTE *pInput,DWORD dwCount,DWORD *pByteTree,DWORD *pCodes) { // Byte Tree Storage Requirement DWORD dwStorage; // Initialize the Weights Array HuffmanInitArrays(); // Sum the Occurences of the Data to the Weights Array __asm { // Point to the Source Data MOV ESI,pInput // Point to the Destination Data MOV EDI,OFFSET dwWeight[0] // Set the Loop Count MOV ECX,dwCount MOV EAX,0 // Increment Each Occurence of the Byte _SumOccurences: LODSB // The Byte is an Index to the Weight Array INC DWORD PTR [EDI + EAX * 4] DEC ECX JNZ _SumOccurences } // Build the Byte and Count Arrays HuffmanBuildArrays(); // Build the Byte Tree HuffmanBuildByteTree(); // Compute the Byte Tree Storage Requirements __asm { // Multiply the Tree Size by 4, for DWORD Access to the Byte Tree Array MOV EDX,0 MOV DX,wTreeSize // Compute the Tree Storage Requirements SHL EDX,2 MOV dwStorage,EDX } // Copy the Byte Tree memblast(pByteTree,&dwByteTree[0],dwStorage); // Build the Code List HuffmanBuildCodes(); // Copy the Codes memblast(pCodes,&dwCodes[0],2048); // Return the Tree Size return wTreeSize; } // Compute the Compression Size of the Input Data DWORD HuffmanCountCompress(BYTE *pInput,DWORD dwCount,WORD iTreeSize,DWORD *pCodes) { // Variables Used for Code Shifting BOOL fOutput = FALSE; // Compressed Size with Initial Space for Codes DWORD dwNewCount; // Loop Variable DWORD dwLoop; // Get the Tree Size and Table Storage Requirement __asm { // Get the Tree Size MOV EAX,0 MOV AX,iTreeSize // Get the Table Storage SHL EAX,2 MOV dwStorage,EAX // Add 6 for the DWORD and WORD that Stores the UnCompressed Count and Number of Tree Entries ADD EAX,6 // Initialize the Base Storage Requirement MOV dwNewCount,EAX } // Encode the Input Data __asm { // Point to the Source Data MOV ESI,pInput // Set the Loop Count MOV EDX,dwCount MOV dwLoop,EDX // Point to the Codes Array MOV EDX,pCodes // Clear the Count of Used Bits MOV EDI,0 // Main Loop for Reading Bytes _LoopInput: // Clear the EAX Register for the Input Character MOV EAX,0 // Read the Input Byte and Increment the Input Pointer LODSB // Get the Compression Code (Bytes 0 - 255 in Array) MOV EBX,[EDX + EAX * 4] // Get the Compression Code Bit Count (Bytes 256 - 511 in Array) MOV ECX,[EDX + 1024 + EAX * 4] // See How Many Bits Can be Shifted to the Output DWORD ADD EDI,ECX CMP EDI,32 JLE _ShiftBits // See How Many Bits of the Last Code Can't Be Used SUB EDI,32 // Adjust ECX to Handle only the Bits that Can Be Used SUB ECX,EDI // Set the Output Flag MOV fOutput,TRUE // Start the Bit Shifting _ShiftBits: // Check for Outputting a full DWORD CMP fOutput,FALSE JE _Continue // Increment the Compression Count ADD dwNewCount,4 // Remove the Bits we Used MOV EAX,32 SUB EAX,EDI MOV ECX,EAX // Reset the Output Flag MOV fOutput,FALSE // Decrement the Main Loop Counter _Continue: DEC dwLoop JNZ _LoopInput // Update Any Remaining Compression data in the Buffer CMP EDI,0 JE _Exit // Left Shift the Remaining Bits MOV EAX,32 SUB EAX,EDI MOV ECX,EAX // Increment the Compression Count ADD dwNewCount,4 // Finished Compressing the Input Data _Exit: } // Return the Compression Count return dwNewCount; } // Compress the Count of Input Data to Output Data returning the new Count DWORD HuffmanCompress(BYTE *pInput,DWORD dwCount,WORD iTreeSize,DWORD *pByteTree,DWORD *pCodes,BYTE *pOutput) { // Allocation Variables BYTE *pStartInput = pInput; BYTE *pStartOutput = pOutput; // Variables Used for Code Shifting DWORD dwUnusedByte = 0; BOOL fOutput = FALSE; // Compressed Size with Initial Space for Codes DWORD dwNewCount = 0; // Loop Variable DWORD dwLoop; // Get the Tree Size and Table Storage Requirement __asm { // Get the Table Storage MOV EAX,0 MOV AX,iTreeSize MOV wTreeSize,AX SHL EAX,2 MOV dwStorage,EAX } // Encode the Input Data __asm { // Point to the Destination Data MOV EDI,pOutput // Store the UnCompressed Count MOV EAX,dwCount MOV [EDI],EAX // Move Past the UnCompressed Count ADD EDI,4 // Move in the Number of Codes to the Output MOV ECX,0 MOV CX,wTreeSize MOV [EDI],CX // Move Past the Number of Codes ADD EDI,2 // Initialize the Base Storage Requirement MOV EDX,dwStorage MOV dwNewCount,EDX // Add 6 for the DWORD and WORD that Stores the UnCompressed Count and Number of Tree Entries ADD dwNewCount,6 // Adjust the Start of the Output Compressed Data, Skipping Byte Tree SHR EDX,1 ADD EDI,EDX // Store the Pointer to the Output MOV pOutput,EDI // Set the Loop Count MOV EDX,dwCount MOV dwLoop,EDX // Point to the Codes Array MOV EDX,pCodes // Clear the Count of Used Bits MOV EDI,0 // Initialize the Storage DWORD XOR ESI,ESI // Main Loop for Reading Bytes _LoopInput: // Clear the EAX Register for the Input Character MOV EAX,0 // Save the ESI Register PUSH ESI // Point to the Source Data MOV ESI,pInput // Read an Input Byte MOV AL,[ESI] // Increment the Pointer to the Source Data INC ESI // Store the Pointer to the Source Data MOV pInput,ESI // Restore the ESI Register POP ESI // Get the Compression Code (Bytes 0 - 255 in Array) MOV EBX,[EDX + EAX * 4] // Get the Compression Code Bit Count (Bytes 256 - 511 in Array) MOV ECX,[EDX + 1024 + EAX * 4] // See How Many Bits Can be Shifted to the Output DWORD ADD EDI,ECX CMP EDI,32 JLE _ShiftBits // See How Many Bits of the Last Code Can't Be Used SUB EDI,32 // Adjust ECX to Handle only the Bits that Can Be Used SUB ECX,EDI // Save the Code MOV dwUnusedByte,EBX // Shift the Input Symbol to the Right PUSH ECX MOV ECX,EDI SHR EBX,CL POP ECX // Set the Output Flag MOV fOutput,TRUE // Start the Bit Shifting _ShiftBits: // Shift the Output Symbol to Handle a New Symbol SHL ESI,CL // OR the Output Symbol with New Symbol OR ESI,EBX // Check for Outputting a full DWORD CMP fOutput,FALSE JE _Continue // Output an Encoded Symbol MOV EAX,ESI PUSH EDI MOV EDI,pOutput MOV [EDI],EAX POP EDI ADD pOutput,4 // Increment the Compression Count ADD dwNewCount,4 // Remove the Bits we Used MOV EAX,32 SUB EAX,EDI MOV ECX,EAX // Restore the Unused Portion of the Code MOV EAX,dwUnusedByte SHL EAX,CL SHR EAX,CL // Update the Code to Have the Left Over Bits MOV ESI,EAX // Initialize the Left Over Bits MOV dwUnusedByte,0 // Reset the Output Flag MOV fOutput,FALSE // Decrement the Main Loop Counter _Continue: DEC dwLoop JNZ _LoopInput // Update Any Remaining Compression data in the Buffer CMP EDI,0 JE _Exit // Left Shift the Remaining Bits MOV EAX,32 SUB EAX,EDI MOV ECX,EAX SHL ESI,CL // Output the Final Encoded Symbol MOV EAX,ESI MOV EDI,pOutput MOV [EDI],EAX // Increment the Compression Count ADD dwNewCount,4 // Finished Compressing the Input Data _Exit: } // Set the Start of the Byte Tree pOutput = pStartOutput + 6; // Copy the DWORD Byte Tree to a WORD Byte Tree D2W(&wByteTree[0],pByteTree,dwStorage/4); // Copy the Byte Tree memblast(pOutput,&wByteTree[0],dwStorage/2); // Restore the Pointer to the Start of the Input pInput = pStartInput; // Restore the Pointer to the Start of the Output pOutput = pStartOutput; // Return the Compression Count return dwNewCount; } // Get the UnCompressed Count of Output Data DWORD HuffmanGetSize(BYTE *pInput) { DWORD dwUnCount; __asm { // Point to the Source Data MOV ESI,pInput // Get the UnCompressed Count MOV EAX,[ESI] MOV dwUnCount,EAX } // Return the UnCompressed Count return dwUnCount; } // UnCompress the Compressed Count of Input Data to Output Data returning the UnCompressed Count DWORD HuffmanUnCompress(BYTE *pInput,BYTE *pOutput) { // UnCompressed Count DWORD dwUnCount; // Allocation Variables BYTE *pStartInput = pInput; BYTE *pStartOutput = pOutput; // UnCompressed Variables DWORD dwLoop; // Initialize the Weights Array HuffmanInitArrays(); // Copy the Decoding Dictionary __asm { // Point to the Source Data MOV ESI,pInput // Get the UnCompressed Count MOV EAX,[ESI] MOV dwUnCount,EAX // Move Past the Uncompressed Count ADD ESI,4 // Get the Tree Size MOV EAX,0 MOV AX,[ESI] MOV wTreeSize,AX // Increment the Pointer to the Encoded Data ADD ESI,2 // Store the Start of the Compressed Data MOV pInput,ESI // Compute the Root Index MOV dwRootIndex,EAX SUB dwRootIndex,3 // Compute the Table Storage Requirement SHL EAX,2 MOV dwStorage,EAX } // Copy the Decoding Byte Tree memblast(&wByteTree[0],pInput,dwStorage/2); // Convert the WORD Byte Tree to a DWORD Byte Tree W2D(&dwByteTree[0],&wByteTree[0],dwStorage/4); // Decode the Input Data __asm { // Increment the Pointer to the Data MOV EAX,dwStorage SHR EAX,1 ADD pInput,EAX // Point to the Byte Code Tree MOV ESI,OFFSET dwByteTree[0] // Set the Loop Count for Amount of Bytes to Uncompress MOV EDX,dwUnCount MOV dwLoop,EDX // Calculate the Index of the Root MOV EBX,dwRootIndex // Main Loop for Reading Bytes _LoopInput: // Point to the Source Data MOV EDI,pInput // Read a DWORD of Encoded Data MOV ECX,[EDI] // Increment the Source Data Pointer by a DWORD ADD pInput,4 // Initialize the Number of Bits to Process MOV EAX,32 // Left Shift the Encoded Data 1 Bit at a Time _LeftShift: // Initialize the Decode Storage MOV EDX,0 // Left Shift the Code into the Decode Storage SHL ECX,1 // Bit + 1 = Number of Children, ie The Direction in Tree to Move ADC EDX,1 // Index the Child of the Parent ADD EBX,EDX // Decrement the Bits Processed DEC EAX // Check for a Leaf Node MOV EDI,[ESI + EBX * 4] CMP EDI,256 JLE _LeafNode // Index the Child's Parent MOV EDI,EBX SUB EDI,EDX // Match the Child to a Parent _TestParent: // Index the Previous Parent in the Tree SUB EDI,3 // Get the Child's Parent MOV EDX,[ESI + EDI * 4] // Compare the Parent with the Child CMP EDX,[ESI + EBX * 4] JNE _TestParent // Update the Parent Index MOV EBX,EDI // Check the Bits Processed upto this Point CMP EAX,0 // Check for More Bits to Process JNZ _LeftShift // Read in another DWORD JMP _LoopInput // Output a Decoded Symbol _LeafNode: // Point to the Destination Data MOV EDI,pOutput // Output the Code MOV EDX,[ESI + EBX * 4] MOV [EDI],DL // Increment the Destination Data by 1 Byte INC pOutput // Calculate the Index of the Root MOV EBX,dwRootIndex // Decrement the Loop Counter DEC dwLoop JZ _Exit // Check for More Bits to Process CMP EAX,0 JNZ _LeftShift // Read a New DWORD JMP _LoopInput // Finished Decompressing _Exit: } // Restore the Pointer to the Start of the Input pInput = pStartInput; // Restore the Pointer to the Start of the Output pOutput = pStartOutput; // Return the Count of UnCompressed Data return dwUnCount; } // Copy a DWORD Array to a WORD Array void D2W(void* dest,void* src,DWORD count) { __asm { MOV ESI,src // Copy the Source Address to the Register MOV EDI,dest // Copy the Destination to the Register MOV ECX,count // Copy the Count to the Register _CopyD2W: MOV EAX,[ESI] MOV [EDI],AX ADD ESI,4 ADD EDI,2 DEC ECX JNZ _CopyD2W } } // Copy a WORD Array to a DWORD Array void W2D(void* dest,void* src,DWORD count) { __asm { MOV ESI,src // Copy the Source Address to the Register MOV EDI,dest // Copy the Destination to the Register MOV ECX,count // Copy the Count to the Register XOR EAX,EAX _CopyW2D: MOV AX,[ESI] MOV [EDI],EAX ADD ESI,2 ADD EDI,4 DEC ECX JNZ _CopyW2D } }