Updating A Program

Previous topic - Next topic

MrTAToad

This is routine for downloading an update to a program, and with Windows, running a batch file to start the update process.  You need DDGui (in addition to the code below) :

Main Routine :
Code (glbasic) Select

// ---------------------------------
// Project:
// Start: Sunday, August 09, 2009
// IDE Version: 7.073
TYPE tUpdateProgram
updateDir$
tempFile$
tempINIFile$
optionsFile$
webSite$
webPath$
updateMessage$
downloadMessage$
version%
platform$
batchFile$
ENDTYPE

GLOBAL NO_DATA$="NO_DATA"

FUNCTION dummy:
ENDFUNCTION

INLINE
extern "C" int rename ( const char * oldname, const char * newname );
ENDINLINE

FUNCTION initialiseUpdateProgram%:programName$,webSite$,webPath$,updateProgram AS tUpdateProgram,options$,updateMessage$,downloadMessage$,progVersion$
updateProgram.updateDir$=PLATFORMINFO$("DOCUMENTS")+"/"+programName$
IF DOESDIREXIST(updateProgram.updateDir$)=FALSE
CREATEDIR(updateProgram.updateDir$)
ENDIF
updateProgram.updateDir$=updateProgram.updateDir$+"/Update"
IF DOESDIREXIST(updateProgram.updateDir$)=FALSE
CREATEDIR(updateProgram.updateDir$)
ENDIF

updateProgram.webSite$=webSite$
updateProgram.webPath$=webPath$
updateProgram.tempFile$=updateProgram.updateDir$+"/"+"DOWNLOAD.DAT"
updateProgram.tempINIFile$=updateProgram.updateDir$+"/"+"DOWNLOAD.INI"
updateProgram.optionsFile$=options$
updateProgram.platform$=PLATFORMINFO$("")
updateProgram.updateMessage$=updateMessage$
updateProgram.downloadMessage$=downloadMessage$
updateProgram.version%=versionToInt(progVersion$)

IF updateProgram.platform$="WIN32"
updateProgram.batchFile$=updateProgram.updateDir$+"/Update.bat"
ELSE
updateProgram.batchFile$=""
ENDIF

RETURN TRUE
ENDFUNCTION

FUNCTION updateProgram%:updateProgram AS tUpdateProgram
LOCAL proxy$
LOCAL port%
LOCAL messageOfTheDay$
LOCAL SECTION$="DATA"
LOCAL webEntry$
LOCAL webDownloadFiles$[]
LOCAL iniFile$
LOCAL ok%
LOCAL result%
LOCAL fullProg$
LOCAL ok2

iniFile$="/"+updateProgram.webPath$+"/"+"Update.INI"

// Make sure the INI file has been deleted
KILLFILE updateProgram.tempINIFile$
IF DOESFILEEXIST(updateProgram.tempINIFile$)=TRUE
RETURN FALSE
ENDIF

KILLFILE updateProgram.tempFile$
IF DOESFILEEXIST(updateProgram.tempFile$)=TRUE
RETURN FALSE
ENDIF

// Download the INI file
INIOPEN updateProgram.optionsFile$
proxy$ = INIGET$("server", "proxy")
port%  = INIGET$("server", "port")
INIOPEN ""

IF port%=0 OR proxy$=NO_DATA$
DEBUG "HERE\n"
ok%=NETWEBGET(updateProgram.webSite$, iniFile$, 80, updateProgram.tempINIFile$)
ELSE
ok%=NETWEBGET(proxy$, "http://"+updateProgram.webSite$+iniFile$, port%, updateProgram.tempINIFile$)
ENDIF

DEBUG updateProgram.webSite$+"\n"
DEBUG iniFile$+"\n"
DEBUG "OK : "+ok%+"\n"

IF ok%=FALSE OR DOESFILEEXIST(updateProgram.tempINIFile$)=FALSE
RETURN FALSE
ENDIF

// Display any "message of the day" message
INIOPEN updateProgram.tempINIFile$
messageOfTheDay$=INIGET$(SECTION$,"MOTD")
DEBUG "MOTD:"+messageOfTheDay$+"\n"
IF messageOfTheDay$<>NO_DATA$ AND LEN(messageOfTheDay$)>0
// Display any message of the day
DDgui_msg(messageOfTheDay$,FALSE)
ENDIF

// Now to get the information about this platform
webEntry$=INIGET$(SECTION$,updateProgram.platform$)
IF webEntry$=NO_DATA$
DDgui_msg("This platform has no updates availiable for it.  Try again in a few weeks",FALSE)
RETURN FALSE
ENDIF
INIOPEN ""

// Now we split the entry - the left side is the version, middle is the filename and right is the filename size
DIM webDownloadFiles$[0]
IF SPLITSTR(webEntry$,webDownloadFiles$[],",")<>3
DDgui_msg("Invalid number of entry files",FALSE)
RETURN FALSE
ENDIF

// And delete any previous files
fullProg$=updateProgram.updateDir$+"/"+webDownloadFiles$[1]
KILLFILE fullProg$
IF DOESFILEEXIST(fullProg$)=TRUE
DDgui_msg("Unable to delete a previous update program",FALSE)
RETURN FALSE
ENDIF

IF versionToInt(webDownloadFiles$[0])>updateProgram.version%
IF DDgui_msg(updateProgram.updateMessage$,TRUE)
// Download the file

IF port%=0 OR proxy$=NO_DATA$
ok%=NETWEBGET(updateProgram.webSite$, "/"+updateProgram.webPath$+"/"+webDownloadFiles$[1], 80, updateProgram.tempFile$)
ELSE
ok%=NETWEBGET(proxy$, "http://"+updateProgram.webSite$+"/"+updateProgram.webPath$+"/"+webDownloadFiles$[1], port%, updateProgram.tempFile$)
ENDIF

IF ok%=FALSE OR DOESFILEEXIST(updateProgram.tempFile$)=FALSE OR isThereA404Error(updateProgram.tempFile$)=TRUE
DDgui_msg("File could not be downloaded - it may not exist yet.",FALSE)
RETURN FALSE
ENDIF

// Now we check the CRC32 value
result%=calculateCRC32( updateProgram.tempFile$)
IF result%=webDownloadFiles$[2]
// DDgui_msg("Here",FALSE)
// Now we rename the file
IF doRename(updateProgram.tempFile$,fullProg$)=0
// If we're on a Windows machine, then call the batch file
IF updateProgram.batchFile$<>""
SELECT updateProgram.platform$
CASE "WIN32"
IF DDgui_msg("Do you want to start the update process now ?",TRUE)=TRUE
SHELLEND CHR$(34)+updateProgram.batchFile$+CHR$(34)+" "+CHR$(34)+fullProg$+CHR$(34)
ENDIF
ENDSELECT
ELSE
DDgui_msg("The update is availiable in your documents folder",FALSE)
ENDIF
ELSE
DDgui_msg("Unable to rename the download file",FALSE)
ENDIF
ELSE
DDgui_msg("The file seems to be corrupt - please re-downloading again",FALSE)
ENDIF

RETURN TRUE
ENDIF
ELSE
DDgui_msg("There are no updates availiable.  Try again in a few weeks",FALSE)
ENDIF

RETURN FALSE
ENDFUNCTION

FUNCTION isThereA404Error%:fileName$
LOCAL handle%
LOCAL line$

handle%=GENFILE()
IF OPENFILE(handle%,fileName$,1)
READLINE handle%,line$
WHILE ENDOFFILE(handle%)=FALSE
IF INSTR(line$,"Error 404 - Not found")>=0 OR _
(INSTR(line$,"The document name you requested")>=0 AND INSTR(line$,"could not be found on this server")>=0)
CLOSEFILE handle%
RETURN TRUE
ENDIF

READLINE handle%,line$
WEND
ENDIF

CLOSEFILE handle%
RETURN FALSE
ENDFUNCTION

FUNCTION doRename:old$,new$
INLINE
return rename(old_Str.c_str(),new_Str.c_str());
ENDINLINE
ENDFUNCTION


Calculate a CRC32 value for the file (to make sure it downloaded okay)
Code (glbasic) Select

// --------------------------------- //
// Project:
// Start: Monday, August 10, 2009
// IDE Version: 7.078
// --------------------------------- //
// Project:
// Start: Monday, August 10, 2009
// IDE Version: 7.078

//! This calculates a CRC-32 value for a file
//\param fileName$ - This is the filename that you want to calculate a CRC value for
//\return - A signed 32-bit CRC value
FUNCTION calculateCRC32%:fileName$
LOCAL channel% = 1
LOCAL bufferSize% = 1024
LOCAL d%[]; DIM d%[bufferSize%]
LOCAL amount%
LOCAL crc%
LOCAL loop%
LOCAL length

crc%=0
IF DOESFILEEXIST(fileName$)=TRUE
length=GETFILESIZE(fileName$)
IF OPENFILE(channel%,fileName$,1)
DEBUG "length : "+length+"\n"

// Read in bytes
FILESEEK channel%,0,0
amount%=readInBytes(channel%,d%[],bufferSize%,length)
WHILE amount%>0
FOR loop%=0 TO amount%-1
crc%=calcCRC32(d%[loop%],crc%)
NEXT

amount%=readInBytes(channel%,d%[],bufferSize%,length)
DEBUG "."
WEND

crc%=calcCRC32End(crc%)
CLOSEFILE channel%
ELSE
DEBUG "Error : "+GETLASTERROR$()+"\n"
ENDIF
ENDIF

RETURN crc%
ENDFUNCTION

@FUNCTION readInBytes%:handle%,d%[],size%,length
LOCAL loop%
LOCAL pos
LOCAL diff

loop%=0
WHILE ENDOFFILE(handle%)=FALSE AND loop%<size%
pos=FILEPOSITION(handle%)
diff=length-pos
SELECT diff
CASE 1
READUBYTE handle%,d%[loop%]
CASE 2
READUWORD handle%,d%[loop%]
CASE 3
READUBYTE handle%,d%[loop%]
INC loop%,1
IF loop%<size% AND ENDOFFILE(handle%)=FALSE THEN READUWORD handle%,d%[loop%]
CASE >3
READULONG handle%,d%[loop%]
ENDSELECT
INC loop%,1
WEND

RETURN loop%
ENDFUNCTION

INLINE
const unsigned long CRC[]={
0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f,
0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988,
0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91, 0x1db71064, 0x6ab020f2,
0xf3b97148, 0x84be41de, 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7,
0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9,
0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172,
0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, 0x35b5a8fa, 0x42b2986c,
0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59,
0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423,
0xcfba9599, 0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924,
0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, 0x76dc4190, 0x01db7106,
0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433,
0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d,
0x91646c97, 0xe6635c01, 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e,
0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950,
0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65,
0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, 0x4adfa541, 0x3dd895d7,
0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0,
0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa,
0xbe0b1010, 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f,
0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, 0x2eb40d81,
0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a,
0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683, 0xe3630b12, 0x94643b84,
0x0d6d6a3e, 0x7a6a5aa8, 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1,
0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb,
0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc,
0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, 0xd6d6a3e8, 0xa1d1937e,
0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b,
0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55,
0x316e8eef, 0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236,
0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe, 0xb2bd0b28,
0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d,
0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a, 0x9c0906a9, 0xeb0e363f,
0x72076785, 0x05005713, 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38,
0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242,
0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777,
0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, 0x8f659eff, 0xf862ae69,
0x616bffd3, 0x166ccf45, 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2,
0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc,
0x40df0b66, 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,
0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, 0xcdd70693,
0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94,
0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d
};
ENDINLINE

@FUNCTION calcCRC32%:value%,crc%
INLINE
return (CRC[(unsigned char) (crc^(unsigned long) value)]^((crc<<8) & 0x00FFFFFF));
ENDINLINE
ENDFUNCTION

@FUNCTION calcCRC32End%:crc%
INLINE
return (crc^0xFFFFFFFF);
ENDINLINE
ENDFUNCTION


Convert a version string to a 32-bit number
Code (glbasic) Select
// Convert version information (in the form of x.x.x.x to an integer)
FUNCTION versionToInt%:version$
LOCAL string$[]
LOCAL count%
LOCAL p%
LOCAL total%
LOCAL value%

DIM string$[0]
count%=SPLITSTR(version$,string$[],".")
total%=0
IF count%>0
p%=24
FOR loop%=0 TO MIN(count%,4)-1
INC total%,ASL(bAND(string$[loop%],255),p%)
DEC p%,8
NEXT
ENDIF

RETURN total%
ENDFUNCTION


And the test program :

Code (glbasic) Select
SETSCREEN 640,480,0

GLOBAL updateProg AS tUpdateProgram

DEBUG "Part 1\n"
initialiseUpdateProgram("test","www.miscthings.co.uk","Update",updateProg,"OPTIONS.INI","Do you want to download the update now","Downloading","0.0.0.1")
DEBUG "Part 2\n"
DEBUG "Result : "+updateProgram(updateProg)
DEBUG "Part 3\n"
END

bigsofty

Missed this one! Good stuff!  :good:
Cheers,

Ian.

"It is practically impossible to teach good programming style to students that have had prior exposure to BASIC.  As potential programmers, they are mentally mutilated beyond hope of regeneration."
(E. W. Dijkstra)

Kitty Hello

Oh! Very sophisticated! Excellent code.

MrTAToad


FutureCow

#4
I've been trying to get my CRC32 working for hours now (I didn't find this on my initial search). I don't think it's possible to do it without inline.

Can you please check your code though? I tested the CRC generated for one of my files against 2 different CRC checkers off the internet, and the values generated from your code don't match the others.

From looking at the code and comparing it to pages like http://www.koders.com/c/fid699AFE0A656F0022C9D6B9D1743E697B69CE5815.aspx?s=crc32#L19 or http://www.algorithm-code.com/wiki/CRC32_Algorithm it appears that

1) You are not setting the CRC to 0xFFFFFFFF at the start
2) You are left shifting 8 places instead of right shifting.

I made those changes on my copy and still can't get the numbers to match though.

Sebastian

#5
Why use CRC and not MD5?
I wrote an MD5 hash generator in VBA not so long ago (long story short: wasn't satisfied with the Access user control - yes, I have to do the stuff in Access, don't get me startet about THAT - so I wrote my own which uses MD5 hashes for password handling) and if I find the time I might just adapt it for GLBasic. Don't want to promise anything though because my VBA solution uses Windows internal DLLs which would mean no multiplatform support  :(

MrTAToad

MD5 was a bit of an overkill.

I'm not surprised the CRC32 value doesn't equal other routines as each does it in a different way.  The link you provided does show probably a better way of doing it, which will be worth looking at.

FutureCow

#7
Okay, this is driving me nuts!  :rant:
I've tried I don't know how many different versions of the algorithm over the past 3 days to try to get my program to return the same results as any CRC32 checker I can find on the internet, and no matter how I modify the code, I can never get a matching CRC value. I have a sneaking suspicion it's being caused by typecasting and signed integer size limits in GLBasic, but I can't see how to get around it without making 99% of the code inline C and having a very GLBasic small wrapper for it. I can't even get that to work as I think that it's every time I read a char from the file and pass that to the program that it's the typecasting of that character that's "breaking" everything else.
I don't know that a GLBasic implementation is possible without an native data type to "unsigned long". I'll happily be proved wrong if anyone wants to try their hand at CRC32 generation. Until then, I'm just going to have to figure out some other solution for verifying 2 files are identical *sigh*

In case anyone does attempt this at a later stage, here's a handy program that generates ~92 types of checksums, including 4 different CRC32 algorithms. http://fsumfe.sourceforge.net/

MrTAToad

Without knowing what routine the CRC32 checker uses, you've got no chance in getting the same value.  And I wouldn't worry about it too much either - if the CRC generating routine and the checking routine produce exactly the same value, then you'll be fine.

You will need to use some INLINE (or even REQUIRE), if only for the more compact code.


FutureCow

There's plenty of information about what Polynomial will give which CRC32 result, matching the code to expected result isn't a problem.

I had another flash of inspiration late today which I tried and I'll test against the various routines again on Monday. Usually - at least for the file I was using - the CRC returned was a negative value. I was trying several different techniques (based on web information and various ideas of my own) to convert that back to an unsigned number, and then to hexadecimal. None of them ever returned the expected CRC string, but maybe I was converting the number wrongly. What I tried late today, and I'll try on the various algorithms again (after this I'm out of ideas!) is to do extract each digit individually taking my conversion out of the picture. i.e.
Code (glbasic) Select

for loop = 0 to 7
    array[7-loop]=bAND(CRC32Result,F)
    ASR(CRC32Result,1)
next

That way I have each digit taken from the underlying binary, without having to worry about the things I was trying to figure out, like whether the signed ints were ones complement, twos complement, wrapping around etc. With any luck that will give the correct result with one of the algorithms. I really don't want to let this beat me as it looks like it really should work!!!

Kitty Hello

do use integers! The CRC32 relies on the overflow of them I think.

FutureCow

Another few hours wasted trying to get an algorithm where the result matches the expected results. GAAAAAAAAA!!!!!!!!

I can get the results to match for the first two characters, any more than that and I get a different result to the "correct" algorithm's results. I haven't worked out what's different between an implementation in GLBasic and one done in straight C. Things I've thought of that it may be that I now have to try to rule out
* Bits not wrapTping where they would in another language when shifts are used
* Endian problems
* Overflow bit?
* 1's complement vs 2's complement
* Typecasting done on one of the binary operations that's not done on one of the others (bAND, bXOR, ASL or ASR)

This is REALLY stressing me now!

Kitty Hello

Why do you want the exact same results? And what program did you use to get the first crc codes? Maybe we can adapt that source then.

MrTAToad

Indeed - we need to know what program you are using to "verify" the results.  Hopefully they will have the source code available.

At some point, I'm going to have to create a program to allow users to create VID's for when more people start putting in "Update this program" options  =D

FutureCow

#14
See the next post for a C program which should give a result matching that from a webpage. When I try to recode it in basic, I don't get the same result (using method 5 in my code) the webpage returns.

Unfortunately I don't have any other language compilers, and my C (VB, Python etc) skills aren't what they used to be anyway. So unfortunately I don't have a program I can run in another language to then compare the results with after porting. My alternative is finding code on the net that people say will work, porting that and testing the results against results from CRC generation programs on the net. I know it's not the best solution, but without installing other compilers etc it's the best I can do.

Firstly, to find the results I'm trying to match :

The main programs I'm using to "verify" the results (and I admit that these programs may be the ones giving the wrong results themselves) are
fsum frontend - http://fsumfe.sourceforge.net/. It supports 4 different CRC32 algorithms.
http://www.lammertbies.nl/comm/info/crc-calculation.html
CRC online test http://www.pvlteam.com/doc/crc/testonline.aspx
RapidCRC - http://sourceforge.net/projects/rapidcrc/ - only supports the main CRC32 algorithm
Also trying the same text that I'm putting into the file I'm testing on this page - the result for CRC32b matches the two CRC32 results above - http://www.whatsmyip.org/hash_generator/

All of the above generate a consistant CRC32, so that suggests to me that I should be able to generate that result.
I'm trying to match the results for the algorithm that seems to be the standard (ie. the one specified as CRC32 in the first three links, and as CRC32 in the third link) - also known as CRC-32-IEEE 802.3 (see. http://en.wikipedia.org/wiki/Cyclic_redundancy_check)


My test program - you will see there are 4 different algorithms in there (separate functions for each one). 2-4 give the same results, but the results don't match any of the CRCs generated from the above programs.
Code (glbasic) Select
// --------------------------------- //
// Project: checksum3
// Start: Tuesday, November 17, 2009
// IDE Version: 7.170


// GLOBALS
GLOBAL CRC32_Table#[]
DIM CRC32_Table#[256]
GLOBAL CRCValue% // Our CRC32 result



// ------------------------------------------------------------- //
// ---  MAIN  ---
// ------------------------------------------------------------- //

GOSUB CRC32_Create_Lookup_Table // Create Lookup table

Generate_CRC32_From_File("c:/temp/a.txt") // Generate results

GOSUB Print_Results // Display results
// MAIN




// ------------------------------------------------------------- //
// ---  CRC32_CREATE_LOOKUP_TABLE  ---
// ------------------------------------------------------------- //
SUB CRC32_Create_Lookup_Table:

RESTORE CRC32_Table_Data // Move data pointer to data

FOR ASCIILoop=0 TO 255
READ CRC32_Table[ASCIILoop] // Read data into table
NEXT
ENDSUB // CRC32_CREATELOOKUPTABLE




// ------------------------------------------------------------- //
// ---  GENERATE_CRC32_FROM_FILE  ---
// ------------------------------------------------------------- //
FUNCTION Generate_CRC32_From_File: FileName$

LOCAL AmountToProcess%
LOCAL FileHandle,FileOpened, FileSize, FileLocation
LOCAL Buffer%[]

DIM Buffer%[1024]

CRCValue%=0xFFFFFFFF // Set initial value FOR CRC TO $FFFFFFFF

FileSize=GETFILESIZE(FileName$) // Get the file size of the file to process

FileOpened=OPENFILE(FileHandle,FileName$,1) // Open file for reading
IF FileOpened=TRUE


// -------------------------------------------------
// How big is the next chunk of data to process?
WHILE ENDOFFILE(FileHandle) = FALSE
FileLocation=FILEPOSITION(FileHandle) // Where are we in the file?
IF FileSize-FileLocation>1024 // There's more than 1kb of the file left so
AmountToProcess=1023 // Read 1kb
ELSE
AmountToProcess=FileSize-FileLocation-1 // Process the <1024b of the file that's left
ENDIF
// -------------------------------------------------
// Read in the next chunk (1kb usually) of data into the buffer
FOR Loop=0 TO AmountToProcess
READUBYTE FileHandle, Buffer[Loop]
NEXT

// -------------------------------------------------
// Calculate the CRC32 value
DEBUG "."
FOR Loop=0 TO AmountToProcess
// Calc_CRC32_Method1(Buffer[Loop]) // Calculate CRC32
// Calc_CRC32_Method2(Buffer[Loop]) // Calculate CRC32
// Calc_CRC32_Method3(Buffer[Loop]) // Calculate CRC32
// Calc_CRC32_Method4(Buffer[Loop]) // Calculate CRC32
// Calc_CRC32_Method5(Buffer[Loop]) // Calculate CRC32
NEXT
WEND
ELSE
STDERR "Couldnt open file " + FileName$ + "\n"
STDOUT "Couldnt open file " + FileName$ + "\n"
ENDIF
CLOSEFILE FileHandle



CRCValue=bXOR(CRCValue,0xFFFFFFFF) // Return 1s complement



RETURN CRCValue
ENDFUNCTION // GENERATE_CRC32_FROM_FILE




// ------------------------------------------------------------- //
// ---  PRINT_RESULTS  ---
// ------------------------------------------------------------- //
SUB Print_Results:
LOCAL HexString$="0123456789ABCDEF" // String of HEX characters
LOCAL Result_String$, Temp, RChar$

DEBUG "CRC = " + CRCValue%
Result_String$=""
FOR MyLoop=0 TO 7 // Loop through the 32 bits 8 times - ie. 4 bit chunks
Temp=bAND(CRCValue%,0xF) // Return  the last 4 bits

RChar$=MID$(HexString$,Temp,1) // Find their value in HEX

Result_String$=RChar$ + Result_String$ // Add the HEX value to our Results String

CRCValue%=ASR(CRCValue%,4) // Shift CRC to get the next 4 bits

DEBUG "+"
NEXT
DEBUG "\n"+Result_String$+"\n" // Output Result

ENDSUB // PRINT_RESULTS



// ------------------------------------------------------------- //
// ---  CALC_CRC32_METHOD1  ---
// ------------------------------------------------------------- //
FUNCTION Calc_CRC32_Method1: CurrentChar
// Algorithm
//crc = ((crc >> 8) & 0x00FFFFFF) ^ crc_tab[(crc ^ *block++) & 0xFF];
LOCAL AA%,BB%,CC%,DD%,EE%

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

ENDFUNCTION // CALC_CRC32_METHOD1

// ------------------------------------------------------------- //
// ---  CALC_CRC32_METHOD2  ---
// ------------------------------------------------------------- //
FUNCTION Calc_CRC32_Method2: CurrentChar

// Algorithm
// crc = crc32_tab[(crc ^ *p++) & 0xFF] ^ (crc >> 8)
LOCAL AA%,BB%,CC%,DD%,EE%

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


ENDFUNCTION // CALC_CRC32_METHOD2

// ------------------------------------------------------------- //
// ---  CALC_CRC32_METHOD3  ---
// ------------------------------------------------------------- //
FUNCTION Calc_CRC32_Method3: CurrentChar
// Algorithm
//    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;
LOCAL AA%,BB%,CC%,DD%,EE%

AA%=bAND(0x000000FF ,CurrentChar)
BB%=bXOR(CRCValue,AA)
DD%=ASR(CRCValue,8)
EE%=bAND(BB,0xFF)
CRCValue=bXOR(DD,CRC32_Table[EE%])
ENDFUNCTION // CALC_CRC32_METHOD3

// ------------------------------------------------------------- //
// ---  CALC_CRC32_METHOD4  ---
// ------------------------------------------------------------- //
FUNCTION Calc_CRC32_Method4: CurrentChar
// Algorithm
// CRCValue=(CRCValue Shr 8) Xor CRC32_table[CurrentByte Xor (CRCValue AND $FF)]
LOCAL AA%,BB%,CC%,DD%,EE%

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

ENDFUNCTION // CALC_CRC32_METHOD4




// ------------------------------------------------------------- //
// ---  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

// ------------------------------------------------------------- //
// ---  DATA_BLOCK  ---
// ------------------------------------------------------------- //

STARTDATA CRC32_Table_Data:
DATA 0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f
DATA 0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988
DATA 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91, 0x1db71064, 0x6ab020f2
DATA 0xf3b97148, 0x84be41de, 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7
DATA 0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9
DATA 0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172
DATA 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, 0x35b5a8fa, 0x42b2986c
DATA 0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59
DATA 0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423
DATA 0xcfba9599, 0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924
DATA 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, 0x76dc4190, 0x01db7106
DATA 0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433
DATA 0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d
DATA 0x91646c97, 0xe6635c01, 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e
DATA 0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950
DATA 0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65
DATA 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, 0x4adfa541, 0x3dd895d7
DATA 0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0
DATA 0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa
DATA 0xbe0b1010, 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f
DATA 0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, 0x2eb40d81
DATA 0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a
DATA 0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683, 0xe3630b12, 0x94643b84
DATA 0x0d6d6a3e, 0x7a6a5aa8, 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1
DATA 0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb
DATA 0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc
DATA 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, 0xd6d6a3e8, 0xa1d1937e
DATA 0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b
DATA 0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55
DATA 0x316e8eef, 0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236
DATA 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe, 0xb2bd0b28
DATA 0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d
DATA 0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a, 0x9c0906a9, 0xeb0e363f
DATA 0x72076785, 0x05005713, 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38
DATA 0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242
DATA 0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777
DATA 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, 0x8f659eff, 0xf862ae69
DATA 0x616bffd3, 0x166ccf45, 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2
DATA 0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc
DATA 0x40df0b66, 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9
DATA 0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, 0xcdd70693
DATA 0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94
DATA 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d
ENDDATA


Some of the many source code pages I've looked at
The start of this forum post.
http://www.glbasic.com/forum/index.php?topic=2788.msg20519#msg20519
http://www.networkdls.com/Software.Asp?Review=22
http://www.koders.com/c/fid699AFE0A656F0022C9D6B9D1743E697B69CE5815.aspx?s=crc32#L19
http://www.hackersdelight.org/crc.pdf (Method 1)
http://www.cl.cam.ac.uk/research/srg/bluebook/21/crc/node6.html#SECTION00060000000000000000