Updating A Program

Previous topic - Next topic

FutureCow

#15
This may be of more help if anyone has the time to look at this for me than the heaps of links on the last post.

This page
http://www.lammertbies.nl/comm/info/crc-calculation.html?crc=abc&method=ascii
generates the "correct" CRC32 value. It also has source, so I would assume the source matches the results the page gives you.

The source is in
[/url]http://www.lammertbies.nl/download/lib_crc.zip[/url] Relevant bits reproduced here. CRC Library :-
Code (glbasic) Select



    /*******************************************************************\
    *                                                                   *
    *   #define P_xxxx                                                  *
    *                                                                   *
    *   The CRC's are computed using polynomials. The  coefficients     *
    *   for the algorithms are defined by the following constants.      *
    *                                                                   *
    \*******************************************************************/

#define                 P_32        0xEDB88320L




    /*******************************************************************\
    *                                                                   *
    *   static int crc_tab...init                                       *
    *   static unsigned ... crc_tab...[]                                *
    *                                                                   *
    *   The algorithms use tables with precalculated  values.  This     *
    *   speeds  up  the calculation dramaticaly. The first time the     *
    *   CRC function is called, the table for that specific  calcu-     *
    *   lation  is set up. The ...init variables are used to deter-     *
    *   mine if the initialization has taken place. The  calculated     *
    *   values are stored in the crc_tab... arrays.                     *
    *                                                                   *
    *   The variables are declared static. This makes them  invisi-     *
    *   ble for other modules of the program.                           *
    *                                                                   *
    \*******************************************************************/


static int              crc_tab32_init          = FALSE;


static unsigned long    crc_tab32[256];



    /*******************************************************************\
    *                                                                   *
    *   static void init_crc...tab();                                   *
    *                                                                   *
    *   Three local functions are used  to  initialize  the  tables     *
    *   with values for the algorithm.                                  *
    *                                                                   *
    \*******************************************************************/

static void             init_crc32_tab( void );



    /*******************************************************************\
    *                                                                   *
    *   unsigned long update_crc_32( unsigned long crc, char c );       *
    *                                                                   *
    *   The function update_crc_32 calculates a  new  CRC-32  value     *
    *   based  on  the  previous value of the CRC and the next byte     *
    *   of the data to be checked.                                      *
    *                                                                   *
    \*******************************************************************/

unsigned long update_crc_32( unsigned long crc, char c ) {

    unsigned long tmp, long_c;

    long_c = 0x000000ffL & (unsigned long) c;

    if ( ! crc_tab32_init ) init_crc32_tab();

    tmp = crc ^ long_c;
    crc = (crc >> 8) ^ crc_tab32[ tmp & 0xff ];

    return crc;

}  /* update_crc_32 */





    /*******************************************************************\
    *                                                                   *
    *   static void init_crc32_tab( void );                             *
    *                                                                   *
    *   The function init_crc32_tab() is used  to  fill  the  array     *
    *   for calculation of the CRC-32 with values.                      *
    *                                                                   *
    \*******************************************************************/

static void init_crc32_tab( void ) {

    int i, j;
    unsigned long crc;

    for (i=0; i<256; i++) {

        crc = (unsigned long) i;

        for (j=0; j<8; j++) {

            if ( crc & 0x00000001L ) crc = ( crc >> 1 ) ^ P_32;
            else                     crc =   crc >> 1;
        }

        crc_tab32[i] = crc;
    }

    crc_tab32_init = TRUE;

}  /* init_crc32_tab */


Test code (Hopefully I've trimmed all the appropriate bits!!!)
Code (glbasic) Select
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include "lib_crc.h"

#define MAX_STRING_SIZE 2048



void main( int argc, char *argv[] ) {

    char input_string[MAX_STRING_SIZE];
    char *ptr, *dest, hex_val, prev_byte;
    unsigned short crc_16, crc_16_modbus, crc_ccitt_ffff, crc_ccitt_0000, crc_ccitt_1d0f, crc_dnp, crc_sick, crc_kermit;
    unsigned short low_byte, high_byte;
    unsigned long crc_32;
    int a, ch, do_ascii, do_hex;
    FILE *fp;

    do_ascii = TRUE;


    if ( do_ascii  ) {

        printf( "Input: " );
        fgets( input_string, MAX_STRING_SIZE-1, stdin );
    }

    if ( do_ascii ) {

        ptr = input_string;
        while ( *ptr  &&  *ptr != '\r'  &&  *ptr != '\n' ) ptr++;
        *ptr = 0;
    }




    a = 1;

    do {

        crc_32         = 0xffffffffL;



        if ( do_ascii ) {

            prev_byte = 0;
            ptr       = input_string;

            while ( *ptr ) {

                crc_32         = update_crc_32(     crc_32,         *ptr            );

                prev_byte = *ptr;
                ptr++;
            }
        }



            else printf( "%s : cannot open file\n", argv[a] );
        }



        crc_32    ^= 0xffffffffL;

        printf( "%s%s%s :\nCRC32              = 0x%08lX  /  %lu\n"
                    , crc_32,         crc_32     );

        a++;

    } while ( a < argc );

}  /* main (tst_crc.c) */


Here's the section of my code that should do the same thing
Code (glbasic) Select
// ------------------------------------------------------------- //
// ---  CALC_CRC32_METHOD5  ---
// ------------------------------------------------------------- //
FUNCTION Calc_CRC32_Method5: CurrentChar%
// Algorithm
//     crc = (crc >> 8) ^ crc_tab32[ tmp & 0xff ];

LOCAL AA%,BB%,CC%,DD%,EE%

AA%=ASR(CRCValue%,8)
BB%=bAND(CurrentChar%,0xFF)
CC%=CRC32_Table[BB%]
CRCValue=bXOR(AA,CC)

ENDFUNCTION // CALC_CRC32_METHOD5


And trying Method 5 in my code against a test file, I still get a different CRC to all the testing programs *sigh*

MrTAToad

As long as it produces a correct result for a file, I dont think it would matter whether it matches an online system.

I want to move over to SHA-2, so it might all become moot anyway :)

FutureCow

But that's exactly the reason I've spent so much time trying to get it working. How do you know it
Quoteproduces a correct result for a file
if you can't get it to match working implementations? If I can get the expected results, then I know I'm producing a checksum with a very good unique result rate. If I am using effectively my own algorithm (which is what I'm doing if I'm not matching results from working implementations) then for all I know my code might be capable of producing only e.g. 10 unique values rather than thousands/millions, and that's not the point of using a checksum routine.

MrTAToad

I'll have to see what the source code to the CRC32 code is like - see if I can get it working for you

FutureCow

Thanks, I've tried everything I can think of.

Kitty Hello

It has to do with signed/unsigned from what I quickly checked.
Very bad.
Can you use inline, if you really want the exact same values?

FutureCow

Thanks Gernot, at least I know why it doesn't work now!!! THANKS!  :nw:
I tried to use inline, but I have very little idea of what I"m doing!!! I get all sorts of compiler errors!   *laugh*

I went looking for a "beginners" guide on how to do inline (eg. getting values back from your C code etc) and couldn't find anything. I can do basic C but haven't worked out how to interface C and GLBasic yet. I'll figure it out at some later when I don't have lots of work on my board game to do.

If I declared a variable inline as a unsigned long then used it in GLBasic would that work or would the first GLBasic command I did on it typecast it? (I'm 99% sure it would typecast, but I'll ask anyway!)

Kitty Hello

Code (glbasic) Select



LOCAL text$
text$ = "The quick borwn fox jumps over the lazy dog"

STDOUT "CRC of:"+text$+"\nCRC:"+Calc_crc32(text$)+"\n"
KEYWAIT




FUNCTION Calc_crc32%: ascii$
INLINE
extern unsigned long update_crc_32(unsigned long, char);
unsigned long crc = 0xffffffff;

int lng = LEN(ascii_Str);
const char* pC = ascii_Str.c_str();
for(int i=0; i<lng; ++i)
{
crc = update_crc_32(crc, *pC++);
}
return crc;
ENDINLINE
ENDFUNCTION



INLINE

    /*******************************************************************\
    *                                                                   *
    *   #define P_xxxx                                                  *
    *                                                                   *
    *   The CRC's are computed using polynomials. The  coefficients     *
    *   for the algorithms are defined by the following constants.      *
    *                                                                   *
    \*******************************************************************/

#define                 P_32        0xEDB88320L




    /*******************************************************************\
    *                                                                   *
    *   static int crc_tab...init                                       *
    *   static unsigned ... crc_tab...[]                                *
    *                                                                   *
    *   The algorithms use tables with precalculated  values.  This     *
    *   speeds  up  the calculation dramaticaly. The first time the     *
    *   CRC function is called, the table for that specific  calcu-     *
    *   lation  is set up. The ...init variables are used to deter-     *
    *   mine if the initialization has taken place. The  calculated     *
    *   values are stored in the crc_tab... arrays.                     *
    *                                                                   *
    *   The variables are declared static. This makes them  invisi-     *
    *   ble for other modules of the program.                           *
    *                                                                   *
    \*******************************************************************/


static int              crc_tab32_init          = FALSE;


static unsigned long    crc_tab32[256];



    /*******************************************************************\
    *                                                                   *
    *   static void init_crc...tab();                                   *
    *                                                                   *
    *   Three local functions are used  to  initialize  the  tables     *
    *   with values for the algorithm.                                  *
    *                                                                   *
    \*******************************************************************/

static void             init_crc32_tab( void );



    /*******************************************************************\
    *                                                                   *
    *   unsigned long update_crc_32( unsigned long crc, char c );       *
    *                                                                   *
    *   The function update_crc_32 calculates a  new  CRC-32  value     *
    *   based  on  the  previous value of the CRC and the next byte     *
    *   of the data to be checked.                                      *
    *                                                                   *
    \*******************************************************************/

unsigned long update_crc_32( unsigned long crc, char c ) {

    unsigned long tmp, long_c;

    long_c = 0x000000ffL & (unsigned long) c;

    if ( ! crc_tab32_init ) init_crc32_tab();

    tmp = crc ^ long_c;
    crc = (crc >> 8) ^ crc_tab32[ tmp & 0xff ];

    return crc;

}  /* update_crc_32 */





    /*******************************************************************\
    *                                                                   *
    *   static void init_crc32_tab( void );                             *
    *                                                                   *
    *   The function init_crc32_tab() is used  to  fill  the  array     *
    *   for calculation of the CRC-32 with values.                      *
    *                                                                   *
    \*******************************************************************/

static void init_crc32_tab( void ) {

    int i, j;
    unsigned long crc;

    for (i=0; i<256; i++) {

        crc = (unsigned long) i;

        for (j=0; j<8; j++) {

            if ( crc & 0x00000001L ) crc = ( crc >> 1 ) ^ P_32;
            else                     crc =   crc >> 1;
        }

        crc_tab32[i] = crc;
    }

    crc_tab32_init = TRUE;

}  /* init_crc32_tab */
ENDINLINE


This works and returns the same crc as the C program you posted. (obviously)
You can load a file into a string (GLBasic can handle '\0' (null) characters in a string w/o problems) and then calculate the CRC or if.

FutureCow

AWESOME! I'll test it tomorrow (busy on my board game right now!!!)
As always Gernot, you're the greatest!!!!  Come to Australia and I'll buy you a beer or 10! :booze: