'=========================================================================== ' Subject: GENERATES 32-BIT CRC Date: 03-19-99 (23:35) ' Author: Greg Turgeon Code: PBCC ' Origin: gturgeon@compuserve.com Packet: PBCC.ABC '=========================================================================== $IF 0 +--------------------------------------------------------------------------+ | WESTFORD CUSTOM PC/FX -*- CRC32_CC.BAS -*- 3/19/99 | | gturgeon@compuserve.com |------------------------------------------------+ | 978-692-8163 |----------+ +--------------+ This file contains the following routines: SUB CRC32Init() SUB BuildCRC32TABLE() SUB CRC32(BYVAL pBuffer???, BYVAL BuffLen&) FUNCTION CRC32Retrieve???() The CRC function employs the CCITT-32 polynomial 0EDB88320h and therefore generates the same CRC values as do PKZIP and ARJ. The code requires PBCC.EXE to compile. This file can be simply $INCLUDEd at the top of the main module file for any PBCC project. To use: The first call to CRC32Init() initializes the required table of values. It also initializes CRC_CURRENT???, which should not be manipulated directly by the application. Subsequent calls to CRC32Init() reinitialize CRC_CURRENT???. The primary CRC process is executed in the subroutine CRC32(BYVAL pBuffer???, BYVAL BuffLen&), which accepts a pointer to the target data and long integer specifying data length. The function CRC32Retrieve???() returns the current CRC value (properly normalized) but does not clear or reinitialize the current value. Reinitializing is accomplished only through CRC32Init(). $ENDIF DEFLNG A-Z '============ $IF NOT %DEF(%NULL) %NULL = 0 $ENDIF GLOBAL CRC32TABLE???(), pTABLE???, CRC_CURRENT??? DECLARE SUB CRC32Init() DECLARE SUB BuildCRC32TABLE() DECLARE SUB CRC32(BYVAL pBuffer???, BYVAL BuffLen&) DECLARE FUNCTION CRC32Retrieve??? '==================== SUB CRC32Init() if pTABLE??? = %NULL then redim CRC32TABLE???(255) call BuildCRC32TABLE pTABLE??? = varptr(CRC32TABLE???(0)) end if CRC_CURRENT??? = &h0ffffffff END SUB '==================== FUNCTION CRC32Retrieve??? function = NOT CRC_CURRENT??? END FUNCTION '========================= SUB CRC32(BYVAL pBuffer???, BYVAL BuffLen&) ! push ebx ! push esi ! push edi ! mov edx, CRC_CURRENT??? ;edx holds current CRC throughout ! mov ecx, BuffLen& ! test ecx, ecx ! jz short CRCDone ! mov edi, pTABLE??? ! mov esi, pBuffer??? ! inc ecx ;add 1 ! shr ecx, 1 ; \2 ! jc short CRCTop ;if originally even number of bytes to process ! mov al, byte ptr [esi] ;do odd byte here ! inc esi ! xor ebx, ebx ! mov bl, dl ! xor bl, al ! shr edx, 8 ! xor edx, [edi + 4 * ebx] ! dec ecx ! jz short CRCDone CRCTop: ! mov ax, [esi] ;al = [byte ptr esi] ! xor ebx, ebx ! mov bl, dl ! xor bl, al ! shr edx, 8 ! xor edx, [edi + 4 * ebx] ! mov al, ah ;al = [byte ptr esi+1] ! xor ebx, ebx ! mov bl, dl ! xor bl, al ! shr edx, 8 ! xor edx, [edi + 4 * ebx] ! inc esi ! inc esi ! dec ecx ! jz short CRCDone ! jmp short CRCTop CRCDone: ! mov CRC_CURRENT???, edx ! pop edi ! pop esi ! pop ebx END SUB '========================= SUB BuildCRC32TABLE() '-- Builds necessary table of dword values '-- The table itself is never altered and thus '-- must be constructed only once REGISTER b&, value??? LOCAL CRC32Polynomial???, a& LOCAL ppoly AS DWORD PTR, parray AS DWORD PTR CRC32Polynomial??? = &hEDB88320 ppoly = varptr(CRC32Polynomial???) parray = varptr(CRC32TABLE???(0)) for a& = 0 to 255 value??? = a& for b& = 8 to 1 step -1 if istrue(value??? AND 1) then value??? = (value??? \ 2) XOR CRC32Polynomial??? else shift right value???, 1 end if next b& @parray[a&] = value??? '-- CRC32TABLE???(a&) = value??? next a& END SUB '-- END CRC32_CC.BAS