home *** CD-ROM | disk | FTP | other *** search
-
- /*******************************************************************************\
-
- hqx decoding module
-
- part of suntar, ⌐1991-92 Sauro & Gabriele Speranza
-
- This program is public domain, feel free to use it or part of it for anything
-
- \*******************************************************************************/
-
-
- /* #include <StdFilePkg.h> */
-
- #include <string.h>
-
- #include "suntar.h"
- #include "windows.h"
-
- #define ASM
-
-
- #define hibyte(x) (((char *) &(x))[0])
- #define lobyte(x) (((char *) &(x))[1])
-
- short current_crc;
- long hqx_length;
- static unsigned char conv_tab[256];
- short show_info;
- unsigned int max_hqx_header;
- short info_file_open=0;
- Boolean save_info;
- int info_file;
- static Boolean EOF_reached;
- static int first_in_buffer=0,last_in_buffer=0;
- static unsigned char hqxbuf[256];
-
- #define RUNCHAR 0x90
-
-
- void raise_hqx_error(void);
-
-
- void close_info_file()
- {
- if(info_file_open>0){
- FSClose(info_file);
- }
- info_file_open=0;
- }
-
- int ci_strcmp(p1,p2)
- register char *p1,*p2;
- /* case-insensitive compare (it's not general purpose: the second string must be
- lowercase, and the return value is 0 if equal, 1 if not) */
- {
- register unsigned char c;
- while(*p2){
- if(!(c=*p1++)) return 1;
- if(c>='A'&&c<='Z') c+= 'a'-'A';
- if(c!= *p2++) return 1;
- }
- return *p1 != '\0';
- }
-
- short is_hqx_name()
- {
- /* returns 0 if the name does not terminate by .hqx, -1 if it does but .hqx is
- preceded by "part" (or "p" preceded by a non-letter) followed by one or two digits,
- 1 otherwise.
- (obviously, files broken in parts can't be extracted on the fly, and it's customary
- to call them contentname.part1.hqx, but we've seen also a_very_long_name.p2.hqx
- or long_application_name1.1p3.hqx, and startup10.hqx probably is not a part)
- The char comparisons are case-insensitive
- */
- register int i,l;
- static char p[]={'p','a','r','t'};
- l=strlen(tarh.name);
- if(l <=4 || ci_strcmp(&tarh.name[l-4],".hqx" ) ) return 0;
-
- /* se sono qui c'era .hqx, ma se c'Å anche part devo non convertire */
-
- if( l < 9 || tarh.name[l-5] <'0' || tarh.name[l-5] >'9' ) return 1;
- if(tarh.name[l-6]>='0'&&tarh.name[l-6]<='9') l--;
-
- if(l<9) return 1;
- if( (tarh.name[l-6]|0x20) == 'p' && ((i=tarh.name[l-7]|0x20)<'a'||i>'z') ) return -1;
- for(i=0;i<4;i++)
- if( (tarh.name[l-9+i]|0x20) != p[i] ) return 1;
- return -1; /* il .hqx Å preceduto da part1 o part2 etc., sarebbe inutile cercare
- di convertire */
- }
-
-
- void check_CRC()
- {
- /* read the stored CRC value from the BinHex file and compare it with the
- computed value
- */
- short calcolato,letto;
-
-
- /* per la veritê non sarebbe necessario, il CRC Å fatto in modo che se si calcola
- su tutti i dati, CRC compreso, il risultato deve essere 0
- -- really, the standard CRC (and CCITT CRC is standard) has this property:
- if you don't compute it on 0 twice (remove the two calls) but compute on the
- two CRC bytes (get the value of current_CRC after the read_hqx(¬_care,2) ),
- then current_CRC is 0 if and only if the computation matches the stored CRC.
- But doing it the same way as the originating routine is easier to understand
- */
- CalcCRC(0);
- CalcCRC(0);
-
- calcolato=current_crc;
- read_hqx(&letto,2);
- /*printf("calcolato=%x,letto=%x,corrente=%x len=%ld:%d\n",calcolato,letto,current_crc,
- hqx_length,last_in_buffer-first_in_buffer);*/
- if( calcolato!=letto ){
- printf("Invalid CRC\n");
- if(!ignore_errors) raise_hqx_error();
- }
- }
-
-
-
- short hqx_header()
- {
- /* read the header of a BinHex file and place all informations in a struct
- which follows the MacBinary format.
- In the file "hqx-format.txt", available in public domain archives, containing
- contributions by Dave Johnson and Tom Coradeschi, one can read:
- >The header format consists of a one byte name length, then the mac
- >file name, then a null. The rest of the header is 20 bytes long,
- >and contains the usual file type, creator/author, file flags, data
- >and resource lengths, and the two byte crc value for the header.
-
- */
- static char msg[]="Invalid BinHex header\n";
-
- EOF_reached=false;
- /* handle all the text before the BinHex data. If there is nothing else,
- return immediately */
- FindStart();
-
- if(!hqx_length) return -1; /* sono giê in fondo, capita se non ho trovato l'inizio */
-
- current_crc=0;
- last_in_buffer=first_in_buffer=0;
- read_hqx(&macbinh.nlen,1); /* file name length */
- if(macbinh.nlen==0 || macbinh.nlen>63){
- printf(msg);
- raise_hqx_error();
- }
- read_hqx(&macbinh.name,macbinh.nlen); /* rest of file name */
-
- if(read_hqx(&macbinh.zero,1),macbinh.zero!=0 && !ignore_errors){ /* a zero byte */
- printf(msg);
- raise_hqx_error();
- }
-
- read_hqx(&macbinh.finfo,10); /* type, creator, Finder flags etc. */
- macbinh.protected=0;
- macbinh.zero=0;
- read_hqx(&macbinh.dflen,8); /* data fork & resource fork lengths (two long ints) */
- /*printf("sizes=%lx %lx\n",macbinh.dflen,macbinh.rflen);*/
-
- /* queste informazioni non c'Å bisogno di settarle, basta modificare la routine
- che chiama PBSetFInfo in modo che rispetti i valori correnti :
- -- the creation and modification dates are missing, but set_binhex will
- fill those fields
-
- *(long*)&macbinh.finfo.fdLocation = 0;
- macbinh.finfo.fdFldr=0;
- GetDateTime (&macbinh.cdate);
- macbinh.mdate=macbinh.cdate;
- */
-
- check_CRC();
- return 0;
-
- }
-
-
-
- /***************** findstart *********************/
-
- void FindStart ()
- {
- /* routine ispirata a quella (in Pascal) di Peter Lewis, ma perfezionata
- -- This routine is vaguely inspired to the Pascal procedure by
- Peter Lewis (deHQX.p), but it does not fail if the start string was modified
- or deleted from the file
- */
-
- OSErr oe;
- int pos,stat;
- unsigned int timeout=file_aperto==ff_binhex?65535:max_hqx_header;
- static char startstr[] = "(This file must be converted with BinHex 4.0)";
- int oldpos=0;
- register int i,b;
- Boolean flush_needed;
- extern Boolean all_listonly;
-
- /* per evitare di scandire centinaia di Kbytes per nulla, ho un "timeout" (20 settori)
- e la possibilitê di gestire anche files in cui la scritta di cui sopra Å stata tolta,
- col che c'Å solo un ":" seguito da uno dei primi codici della stringa hqx (Å la
- lunghezza del nome, in teoria max 63 ma in pratica max 31, diviso per 4 per prendere
- solo 6 bit...) i quali codici sono tutti cose strane da stare dopo un :
- -- a ':' at the start of the line must be followed by one of the first codes
- in the hqx decoding string (the file name length can't be longer than 12*4+3 =51:
- it's not the "official" limit of 63, but ":0" could be meaningful...
- The routine is much more complex than it should be due to the explicit
- handling of buffering with both the file and console output
- */
-
- show_info = SHOWINFO;
- save_info = SAVEINFO;
- if(show_info) disable_autoflush();
- stat=0;
- pos = 0;
- do{
- b = get_hqx_byte(&flush_needed);
-
- /* controllo nel caso manchi la stringa ma ci siano i dati BinHex */
- if(b==LF||b==CR||b=='\f')
- stat=0;
- else if(b==':')
- stat++;
- else if(stat==1 && conv_tab[b]<=12){ /*un ':' a inizio riga seguito da...*/
- unget_char();
- flush_hqx_header(0);
- if( show_info) {
- start_of_line();
- enable_autoflush();
- }
- close_info_file();
- return;
- }
- else if(stat==0 && (b==' '||b=='\t') )
- ;
- else
- stat=2;
- /* controllo per il caso non ci siano nÄ stringa nÄ dati BinHex */
- if(--timeout==0){
- char buffer[512];
- start_of_line();
- printf(in_Italia?"Non ho trovato dati BinHex nei primi %u bytes\n":
- "BinHex header not found within %u bytes\n",
- file_aperto==ff_binhex?(int)65535:max_hqx_header);
- if(show_info) enable_autoflush();
-
- if(! save_info)
- raise_hqx_error();
- else{
- flush_hqx_header(0); /* ora passo in modalita' salvataggio
- normale, vorrê dire che mando tutto nel .info
- -- BinHex data not found => since the .info file
- contains a copy of all what was read, continue
- to fill it, without any further search */
- while(hqx_length>0){
- if(hqx_length>=512L) i=512; else i= (int)hqx_length;
- hqx_length -= i;
- if(readblock(buffer,i)!=0)
- error_message_1("Disk read error %d\n",err_code);
- for(b=0;b<512;b++)
- if(buffer[b]==LF) buffer[b]=CR;
- if(mac_fwrite(buffer,i,info_file)<0)
- error_message("File write error!\n");
- }
- }
- close_info_file();
- return;
- }
- /* controllo presenza stringa */
- if (b == startstr[pos])
- pos ++;
- else
- pos = 0;
- /* copia dei caratteri sulla console e/o file .info */
- if(flush_needed || pos==sizeof(startstr)-1){
- if(save_info && oldpos!=0 && pos!=sizeof(startstr)-1)
- mac_fwrite(startstr,oldpos,info_file); /* Å poco pulito farlo cosô, fidandosi
- che il file Å aperto e contiene quello che deve contenere...*/
-
- if(show_info && oldpos!=0 && pos!=sizeof(startstr)-1){
- for(i=0;i<oldpos;i++)
- put_char(startstr[i]); /* la volta prima avevo erroneamente omesso
- dei caratteri ritenendo fossero parte della start string
- -- when the buffer had to be flushed, I could have seen a part
- of the start string: I didn't save it, but if I'm here than I
- discovered that it was NOT the start string, hence those chars
- had to be written out: for the console, do it here, for the .info
- file it's flush_hqx_header which does that */
- }
- oldpos=pos;
- flush_hqx_header(pos);
- }
-
- }
- while( pos < sizeof(startstr)-1);
-
- close_info_file();
- if(show_info){
- start_of_line();
- enable_autoflush();
- }
-
- do{
- b = get_hqx_byte(&flush_needed);
- }
- while (b!=':');
-
- }
-
-
-
- /*
- io uso tre buffer: quello di uscita Å il solito buffer, quello di ingresso
- contiene il blocco letto dal disco; in pi¥, le conversioni sono fatte a
- gruppi di 4 bytes, col che ho un buffer intermedio che contiene solo ...
- -- The BinHex conversion is performed in two steps, by two routines
- each having its own input buffer
- */
-
- void init_hqx_tab()
- /* initialize the conversion table: need be called only once */
- {
- static unsigned char hqxchars[]=
- "!\"#$%&\'()*+,-012345689@ABCDEFGHIJKLMNPQRSTUVXYZ[`abcdefhijklmpqr";
- register int i;
- for( i= 0 ;i<=255; i++)
- conv_tab[i] = 255;
- for (i = 0;i<64;i++)
- conv_tab[hqxchars[i]]=i;
- conv_tab[LF]=conv_tab[CR]=conv_tab[' ']=conv_tab['\t']=conv_tab['\f']= 254;
- }
-
-
-
- void read_hqx(destination,nbytes)
-
- /* in suntar 1.2, this routine was changed, optimizing for speed: the
- loop present in the callers was moved here, so that register variables
- may hold their values for a while, and are not swapped out of the register
- after being used just a couple of times */
-
- register char *destination;
- int nbytes;
- /* last conversion stage: it handles the RLL encoding in the BinHex format.
- From the file "hqx-format.txt":
-
- >There is some run length encoding, where the character to be repeated
- >is followed by a 0x90 byte then the repeat count. For example, ff9004
- >means repeat 0xff 4 times. The special case of a repeat count of zero
- >means it's not a run, but a literal 0x90. 2b9000 => 2b90.
-
- >*** Note: the 9000 can be followed by a run, which means to repeat the
- >0x90 (not the character previous to that). That is, 2090009003 means
- >a 0x20 followed by 3 0x90's.
- */
-
- {
- register unsigned char b;
-
- register unsigned char *first=&hqxbuf[first_in_buffer];
- register int k=last_in_buffer-first_in_buffer;
-
- while(nbytes--){
- if( k < 4 ){
- /* buffer quasi vuoto: riporta quello che resta in testa e riempi di nuovo
- -- refill the buffer by shifting what remains and calling
- read_3_hqx until the buffer is full or the hqx data is over
- */
- mcopy(hqxbuf,first,k);
- first=hqxbuf;
- k += read_3_hqx(&hqxbuf[k],sizeof(hqxbuf)-k);
- last_in_buffer =k;
- if( k<=0 ){
- beep_in_foreground();
- start_of_line();
- printf("hqx: EOF reached\n");
- raise_hqx_error();
- }
- }
- /* sembra troppo semplice per quello che deve fare, ma ho studiato tutti i casi,
- compresi i run di RUNCHAR e la coppia di RUNCHAR, scritto che si deve fare e fatto
- il merge delle azioni comuni fra pi¥ rami, e questo Å il risultato
- -- I decrement the run length count directly in the input buffer, without
- extracting the RLL code from the buffer until the count goes to 0.
- OK, it's not immediately clear that these instructions work: but I considered
- all possible cases and did a flow graph of the resulting operations, than began
- to merge equal boxes at the end of different paths: I've got a lot of merging
- and the result is this very simple set of instructions */
- b=*first;
- if(b==RUNCHAR){ /* and first[1] surely 0 */
- if(k <4 || first[2]!=RUNCHAR || !first[3] ){
- first += 2; k -=2;
- }
- else
- if ( --first[3] <=1 ) {
- /* see below */
- if(first[3]==0){
- first += 4; k -= 4;
- }
- else{
- first+=2; k-=2;
- first[1]=0;
- }
- }
- }
- else{
- if (k <3 || first[1]!=RUNCHAR || !first[2]){
- first++; k--;
- }
- else{
- /* run length may be repeated, for example A4 90 FF 90 FF 90 0A means A4 is
- repeated 520 times. Unfortunately, suntar 1.1 did not handle those cases correctly */
- if( --first[2] <=1 ){
- if(first[2]==0){
- first+=3; k-=3;
- }
- else{ /* must copy the char to be repeated so that if there is
- a further run length, it appears to be applied to it; it's
- easier to exit from the decrement state when the count is 1
- and copy anyway than exit when it's 0 and copy only if there
- is a further run length */
- first+=2; k-=2;
- *first=b;
- }
- }
- }
- }
-
- *destination++ = b;
-
- #ifndef ASM
- CalcCRC(b);
- #else
- /* save parameter passing + function call */
- asm{
-
- move.w current_crc,d0
-
- move.w #7,d2
- move.w #0x1021,d1 ; CRC CCITT
- loop:
- lsl.b #1,b
- roxl.w #1,d0
- bcc.s @noxor
- eor.w d1,d0
- noxor:
- dbra d2,@loop
-
- move.w d0,current_crc
- }
- #endif
-
-
- }
- first_in_buffer = first - hqxbuf;
- }
-
-
- static char UNEXP_EOF[]="End of BinHex file unexpectedly reached\n";
-
- #define FAST_GET_HQX_BYTE(b) \
- if(!more_in_bytes) \
- b=(unsigned char)get_hqx_byte(&dummy); \
- else{ \
- if((--hqx_length)<0){ \
- printf(UNEXP_EOF); \
- raise_hqx_error(); \
- } \
- b= (unsigned char)disk_buffer[511-(--more_in_bytes)];\
- }
-
-
-
-
- extern int more_in_bytes;
-
-
- int read_3_hqx(obuf,maxsize)
- /* this one too was optimazed by moving here the loop which
- was in the caller */
-
- register unsigned char *obuf;
- register int maxsize;
- {
- /* read four BinHex characters and convert them to three bytes
- From the file "hqx-format.txt":
- >The first and last characters are each a ':'. After the first ':',
- >the rest of the file is just string of 6 bit encoded characters.
- >All newlines and carriage returns are to be ignored.
- That is, data is sliced in 6-bit pieces, and 3 bytes (24 bits) yield 4
- pieces, each encoded by a printable ASCII char (0='!' etc., see the
- conversion table)
- */
-
- Boolean dummy;
- unsigned char ibuf[4];
- register int i,b;
- register int nbytes;
- register unsigned char *pti;
- static char msg[]="Error: not a BinHex character (dec %d)\n";
-
- nbytes=0;
- maxsize -= 3;
-
- while(maxsize>=0 && !EOF_reached){
-
- nbytes += 3;
- pti=ibuf;
- for(i=0;i<4;i++,pti++){
- do{
- FAST_GET_HQX_BYTE(b)
- }
- while((*pti=conv_tab[b])==(unsigned char)254 );
- /* I ignore spaces too: hqx-format.txt does not tell about them,
- but we happened to download a file which did have spaces,
- and neither Stuffit nor Compact Pro succeeded to extract it,
- only Peter Lewis' DeHQX did the job. Now, suntar too does extract
- that file */
- if( *pti==(unsigned char)255){
- if(b==':'){
- EOF_reached=true;
- nbytes += ((i+i+i)>>2)-3; /* i*6/8 -3 */
- for(;i<4;i++)
- ibuf[i]=0;
- break;
- }
- printf(msg,b);
- if(!ignore_errors)
- raise_hqx_error();
- }
- }
- /*printf("<%x %x %x %x>",ibuf[0],ibuf[1],ibuf[2],ibuf[3]);*/
- #ifndef ASM
- *obuf++ = ((ibuf[0] << 2) | (ibuf[1] >> 4)); /* these three instructions */
- *obuf++ = ((ibuf[1] << 4) | (ibuf[2] >> 2)); /* are from Dave Johnson's xbin.c */
- *obuf++ = ((ibuf[2] << 6) | ibuf[3]); /* (for UNIX machines) */
- #else
- /* no speed gain, but since I've written and tested it, it's better to use it... */
- asm{
- lea ibuf,a0
- move.b (a0)+,d0
- lsl.b #2,d0
- move.b (a0)+,d1
- move.b d1,d2
- lsr.b #4,d1
- or.b d1,d0
- move.b d0,(obuf)+
- lsl.b #4,d2
- move.b (a0)+,d1
- move.b d1,d0
- lsr.b #2,d1
- or.b d1,d2
- move.b d2,(obuf)+
- lsl.b #6,d0
- or.b (a0),d0
- move.b d0,(obuf)+
- }
- #endif
-
- /*printf("{%x %x %x}\n",obuf[0],obuf[1],ibuf[2]);*/
- maxsize -= 3;
- }
- return nbytes;
- }
-
-
- unsigned char get_hqx_byte(flush_needed)
- /* I could implement it by calling readblock, but the hqx decoding has already
- so much overhead for each byte that I thought that any instructions saving
- was welcome, hence I copied the body of readblock deleting instructions which
- are useless when reading one byte at a time
- */
- Boolean *flush_needed;
- {
- if((--hqx_length)<0){
- beep_in_foreground();
- start_of_line();
- printf(UNEXP_EOF);
- raise_hqx_error();
- }
-
- if(more_in_bytes==0){
- *flush_needed=false;
- /* le stesse cose che fa readblock... */
- if(bar_archive)
- bar_check_floppy_swap(0);
- else
- tar_check_floppy_swap(0);
-
- leggi_settore(sect_n,&disk_buffer);
- if(check_error())raise_error();
- check_events();
- more_in_bytes=511;
- sect_n++;
- settori_passati++;
- }
- else
- *flush_needed= !--more_in_bytes;
- return disk_buffer[511-more_in_bytes];
- }
-
-
- void open_info_file()
- /* opens the .info file: that includes building its name... */
- {
- char name_buffer[102];
- register int i,l;
- char *hqx_name=bar_archive ? ((barh_type*)ultimo_header)->name :
- ((struct tarh_type*)ultimo_header)->name;
- extern OSType filecreator,filetype;
- extern Boolean devo_chiudere_out;
- extern IOParam pb;
-
- l=strlen(hqx_name);
- strcpy(name_buffer,hqx_name);
-
- if(l>4 && !ci_strcmp(&name_buffer[l-4],".hqx")){
- for(i=l-1;i>=0 && hqx_name[i]!='/';i--)
- ;
- /* ora i Å -1 o punta ad un '/', quindi la lunghezza del nome Å : */
- i=l-i+1;
- strcpy(&name_buffer[l-3], i==31 ? "inf" : "info");
- }
- else /* if opened by Open File, it may not contain .hqx */
- strcat(name_buffer,".info");
- unix_to_mac(name_buffer);
-
- filecreator=text_creator;
- filetype='TEXT';
- if(create_file(name_buffer,fsWrPerm,false)==0){
- /* non posso controllare che ci stia non sapendo le dimensioni... */
- devo_chiudere_out=false;
- info_file=pb.ioRefNum;
- info_file_open=1;
- }
- else
- info_file_open=-1; /* duplicate name + cancel: don't create an info file ! */
- }
-
-
- void flush_hqx_header(pos)
- /* it's rather complex: it must write data to the console and the .info
- file, but both of them may be disabled.
- Furthermore, it's called when the buffer is officially empty, but obviously
- its bytes still contain the characters which FindStart has read and discarded
- since they were not the start of the BinHex data
- */
- {
- /* attenzione, faccio affidamento sul fatto che nel buffer ci restano i bytes letti,
- e che grazie all'ubbidienza al parametro flush_needed della routine precedente
- quelli non ancora salvati partono all'offset 0 */
-
- register int i,j;
- register char last_char;
- if( ! save_info && ! show_info ) return;
-
- j=512-more_in_bytes-pos;
- if(!j) return;
- if(show_info==1 && j>100)
- printf("=============== hqx info ===============\n\n"); /* la prima volta */
- if(show_info!=0){
- show_info++;
- disable_autoflush(); /* in alcuni casi un messaggio (nuovo disco...) puÿ averlo
- abilitato */
- }
-
- for(i=0;i<j;i++){ /* butto fuori il contenuto del buffer, ma
- togliendo un eventuale inizio della start string
- -- pos!=0 means that the last pos chars might be part of the
- start string, I must not write them
- */
- last_char=disk_buffer[i];
- if(last_char==LF)
- disk_buffer[i]=last_char=CR; /* per la console non serve, per il file sô
- -- put_char already does the conversion, but mac_fwrite does not
- */
- if(show_info) put_char(last_char);
- if(last_char==CR && show_info>=4 && more_in_bytes==0){
- printf(in_Italia?"... (testata lunga, non mostrata per intero)\n\n\n":
- "... (long header, further lines are not shown)\n\n\n");
- enable_autoflush();
- show_info=0;
- }
- }
-
- if( save_info && j>0){
- if(!info_file_open) open_info_file(); /* the info file is opened on the fly
- here, since FindStart did not open it: if no text precedes the
- BinHex data, the info file is not created */
- if(info_file_open>0)
- if(mac_fwrite(disk_buffer,j,info_file)<0){
- beep_in_foreground();
- error_message("File write error !\n");
- }
- }
- }
-
- void hqx_end_of_file()
- {
- hqx_length -= more_in_bytes;
- more_in_bytes=0;
- if(hqx_length>0)
- sect_n+= (hqx_length+511) >>9;
- hqx_length=0;
- }
-
- static void raise_hqx_error()
- /* handles the hqx decoding error by skipping the rest of the file and closing
- the open files so that untar_hqx will be able to return regularly, and the
- extraction or list will continue with next file */
- {
- close_or_del_out_file();
- close_info_file();
- enable_autoflush();
-
- hqx_end_of_file();
-
- if(fase==reading_disk&&file_aperto!=ff_binhex || fase==selected_reading || fase==hack_listing){
- if(! (fase==reading_disk&&listonly || fase==hack_listing) ){
- one_empty_line();
- printf(in_Italia?"****** Estrazione BinHex interrotta":
- "****** BinHex extraction was aborted");
- printf(" ******\n\n");
- }
- longjmp(main_loop,-2);
- }
- else
- longjmp(main_loop,-1);
-
- }
-
-
- /* assembly language is faster: since you must repeat the body of the loop
- for each BIT (not byte !) of the file, a fast CRC routine is essential if
- your BinHex routine must not been very slow... */
- #ifdef ASM
-
- void CalcCRC(current_byte)
- char current_byte;
- /* from calcCRC.a in the deHQX source code by Peter Lewis, adapting
- it to the C parameter passing conventions and the Think-C half-assembly-half-C
- syntax
- */
- {
- asm{
-
- move.w current_crc,d0
- move.b current_byte,d1
-
- move.w #7,d2
- loop:
- lsl.b #1,d1
- roxl.w #1,d0
- bcc.s @noxor
- eor.w #0x1021,d0 ; CRC CCITT
- noxor:
- dbra d2,@loop
- move.w d0,current_crc
- }
- }
-
- #else
-
- void CalcCRC (v)
- {
- int temp;
- register int i;
-
- for (i = 1;i<=8;i++){
- temp = current_crc&0x8000;
- current_crc = (current_crc<<1) | (v>>7)&1 ;
- if( temp )
- current_crc ^= 0x1021;
- v <<= 1;
- }
- }
- #endif
-
-