/*ProfiPacket - packet radio terminal program
  Copyright (C) 1999  Alexander Feigl

  This program is free software; you can redistribute it and/or modify
  it under the terms of the GNU General Public License as published by
  the Free Software Foundation; either version 2 of the License, or
  (at your option) any later version.

  This program is distributed in the hope that it will be useful,
  but WITHOUT ANY WARRANTY; without even the implied warranty of
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  GNU General Public License for more details.

  You should have received a copy of the GNU General Public License
  along with this program; if not, write to the Free Software
  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA

  Author:

  Alexander Feigl
  Burachstraße 51

  D-88250 Weingarten

  Mail : Alexander.Feigl@gmx.de
*/

#ifdef HAVE_CONFIG_H
#include "config.h"
#endif

#ifdef __GNUC__
#define _storage_text_ __attribute__ ((section(".text")))
#else
#define _storage_text_
#endif


#include "global.h"
#include "QSO.h"
#include "GUIProtos.h"

#ifdef AmigaOS

#include <exec/memory.h>
#include <dos/exall.h>
#include <clib/exec_protos.h>
#include <clib/dos_protos.h>
#ifdef __GNUC__
extern void *SysBase;
extern void *DOSBase;
#include <inline/exec.h>
#include <inline/dos.h>
#endif /*__GNUC__*/

#else

#include "amigaemu.h"

#endif /*AmigaOS*/



typedef unsigned short crctabtype[256];

static const crctabtype crc16_table = {
  0, 0xc0c1L, 0xc181L, 0x140, 0xc301L, 0x3c0, 0x280, 0xc241L, 0xc601L, 0x6c0,
  0x780, 0xc741L, 0x500, 0xc5c1L, 0xc481L, 0x440, 0xcc01L, 0xcc0, 0xd80,
  0xcd41L, 0xf00, 0xcfc1L, 0xce81L, 0xe40, 0xa00, 0xcac1L, 0xcb81L, 0xb40,
  0xc901L, 0x9c0, 0x880, 0xc841L, 0xd801L, 0x18c0, 0x1980, 0xd941L, 0x1b00,
  0xdbc1L, 0xda81L, 0x1a40, 0x1e00, 0xdec1L, 0xdf81L, 0x1f40, 0xdd01L, 0x1dc0,
  0x1c80, 0xdc41L, 0x1400, 0xd4c1L, 0xd581L, 0x1540, 0xd701L, 0x17c0, 0x1680,
  0xd641L, 0xd201L, 0x12c0, 0x1380, 0xd341L, 0x1100, 0xd1c1L, 0xd081L, 0x1040,
  0xf001L, 0x30c0, 0x3180, 0xf141L, 0x3300, 0xf3c1L, 0xf281L, 0x3240, 0x3600,
  0xf6c1L, 0xf781L, 0x3740, 0xf501L, 0x35c0, 0x3480, 0xf441L, 0x3c00, 0xfcc1L,
  0xfd81L, 0x3d40, 0xff01L, 0x3fc0, 0x3e80, 0xfe41L, 0xfa01L, 0x3ac0, 0x3b80,
  0xfb41L, 0x3900, 0xf9c1L, 0xf881L, 0x3840, 0x2800, 0xe8c1L, 0xe981L, 0x2940,
  0xeb01L, 0x2bc0, 0x2a80, 0xea41L, 0xee01L, 0x2ec0, 0x2f80, 0xef41L, 0x2d00,
  0xedc1L, 0xec81L, 0x2c40, 0xe401L, 0x24c0, 0x2580, 0xe541L, 0x2700, 0xe7c1L,
  0xe681L, 0x2640, 0x2200, 0xe2c1L, 0xe381L, 0x2340, 0xe101L, 0x21c0, 0x2080,
  0xe041L, 0xa001L, 0x60c0, 0x6180, 0xa141L, 0x6300, 0xa3c1L, 0xa281L, 0x6240,
  0x6600, 0xa6c1L, 0xa781L, 0x6740, 0xa501L, 0x65c0, 0x6480, 0xa441L, 0x6c00,
  0xacc1L, 0xad81L, 0x6d40, 0xaf01L, 0x6fc0, 0x6e80, 0xae41L, 0xaa01L, 0x6ac0,
  0x6b80, 0xab41L, 0x6900, 0xa9c1L, 0xa881L, 0x6840, 0x7800, 0xb8c1L, 0xb981L,
  0x7940, 0xbb01L, 0x7bc0, 0x7a80, 0xba41L, 0xbe01L, 0x7ec0, 0x7f80, 0xbf41L,
  0x7d00, 0xbdc1L, 0xbc81L, 0x7c40, 0xb401L, 0x74c0, 0x7580, 0xb541L, 0x7700,
  0xb7c1L, 0xb681L, 0x7640, 0x7200, 0xb2c1L, 0xb381L, 0x7340, 0xb101L, 0x71c0,
  0x7080, 0xb041L, 0x5000, 0x90c1L, 0x9181L, 0x5140, 0x9301L, 0x53c0, 0x5280,
  0x9241L, 0x9601L, 0x56c0, 0x5780, 0x9741L, 0x5500, 0x95c1L, 0x9481L, 0x5440,
  0x9c01L, 0x5cc0, 0x5d80, 0x9d41L, 0x5f00, 0x9fc1L, 0x9e81L, 0x5e40, 0x5a00,
  0x9ac1L, 0x9b81L, 0x5b40, 0x9901L, 0x59c0, 0x5880, 0x9841L, 0x8801L, 0x48c0,
  0x4980, 0x8941L, 0x4b00, 0x8bc1L, 0x8a81L, 0x4a40, 0x4e00, 0x8ec1L, 0x8f81L,
  0x4f40, 0x8d01L, 0x4dc0, 0x4c80, 0x8c41L, 0x4400, 0x84c1L, 0x8581L, 0x4540,
  0x8701L, 0x47c0, 0x4680, 0x8641L, 0x8201L, 0x42c0, 0x4380, 0x8341L, 0x4100,
  0x81c1L, 0x8081L, 0x4040
};



static const crctabtype ccitt_table = {
  0, 0x1021, 0x2042, 0x3063, 0x4084, 0x50a5, 0x60c6, 0x70e7, 0x8108L, 0x9129L,
  0xa14aL, 0xb16bL, 0xc18cL, 0xd1adL, 0xe1ceL, 0xf1efL, 0x1231, 0x210, 0x3273,
  0x2252, 0x52b5, 0x4294, 0x72f7, 0x62d6, 0x9339L, 0x8318L, 0xb37bL, 0xa35aL,
  0xd3bdL, 0xc39cL, 0xf3ffL, 0xe3deL, 0x2462, 0x3443, 0x420, 0x1401, 0x64e6,
  0x74c7, 0x44a4, 0x5485, 0xa56aL, 0xb54bL, 0x8528L, 0x9509L, 0xe5eeL,
  0xf5cfL, 0xc5acL, 0xd58dL, 0x3653, 0x2672, 0x1611, 0x630, 0x76d7, 0x66f6,
  0x5695, 0x46b4, 0xb75bL, 0xa77aL, 0x9719L, 0x8738L, 0xf7dfL, 0xe7feL,
  0xd79dL, 0xc7bcL, 0x48c4, 0x58e5, 0x6886, 0x78a7, 0x840, 0x1861, 0x2802,
  0x3823, 0xc9ccL, 0xd9edL, 0xe98eL, 0xf9afL, 0x8948L, 0x9969L, 0xa90aL,
  0xb92bL, 0x5af5, 0x4ad4, 0x7ab7, 0x6a96, 0x1a71, 0xa50, 0x3a33, 0x2a12,
  0xdbfdL, 0xcbdcL, 0xfbbfL, 0xeb9eL, 0x9b79L, 0x8b58L, 0xbb3bL, 0xab1aL,
  0x6ca6, 0x7c87, 0x4ce4, 0x5cc5, 0x2c22, 0x3c03, 0xc60, 0x1c41, 0xedaeL,
  0xfd8fL, 0xcdecL, 0xddcdL, 0xad2aL, 0xbd0bL, 0x8d68L, 0x9d49L, 0x7e97,
  0x6eb6, 0x5ed5, 0x4ef4, 0x3e13, 0x2e32, 0x1e51, 0xe70, 0xff9fL, 0xefbeL,
  0xdfddL, 0xcffcL, 0xbf1bL, 0xaf3aL, 0x9f59L, 0x8f78L, 0x9188L, 0x81a9L,
  0xb1caL, 0xa1ebL, 0xd10cL, 0xc12dL, 0xf14eL, 0xe16fL, 0x1080, 0xa1, 0x30c2,
  0x20e3, 0x5004, 0x4025, 0x7046, 0x6067, 0x83b9L, 0x9398L, 0xa3fbL, 0xb3daL,
  0xc33dL, 0xd31cL, 0xe37fL, 0xf35eL, 0x2b1, 0x1290, 0x22f3, 0x32d2, 0x4235,
  0x5214, 0x6277, 0x7256, 0xb5eaL, 0xa5cbL, 0x95a8L, 0x8589L, 0xf56eL,
  0xe54fL, 0xd52cL, 0xc50dL, 0x34e2, 0x24c3, 0x14a0, 0x481, 0x7466, 0x6447,
  0x5424, 0x4405, 0xa7dbL, 0xb7faL, 0x8799L, 0x97b8L, 0xe75fL, 0xf77eL,
  0xc71dL, 0xd73cL, 0x26d3, 0x36f2, 0x691, 0x16b0, 0x6657, 0x7676, 0x4615,
  0x5634, 0xd94cL, 0xc96dL, 0xf90eL, 0xe92fL, 0x99c8L, 0x89e9L, 0xb98aL,
  0xa9abL, 0x5844, 0x4865, 0x7806, 0x6827, 0x18c0, 0x8e1, 0x3882, 0x28a3,
  0xcb7dL, 0xdb5cL, 0xeb3fL, 0xfb1eL, 0x8bf9L, 0x9bd8L, 0xabbbL, 0xbb9aL,
  0x4a75, 0x5a54, 0x6a37, 0x7a16, 0xaf1, 0x1ad0, 0x2ab3, 0x3a92, 0xfd2eL,
  0xed0fL, 0xdd6cL, 0xcd4dL, 0xbdaaL, 0xad8bL, 0x9de8L, 0x8dc9L, 0x7c26,
  0x6c07, 0x5c64, 0x4c45, 0x3ca2, 0x2c83, 0x1ce0, 0xcc1, 0xef1fL, 0xff3eL,
  0xcf5dL, 0xdf7cL, 0xaf9bL, 0xbfbaL, 0x8fd9L, 0x9ff8L, 0x6e17, 0x7e36,
  0x4e55, 0x5e74, 0x2e93, 0x3eb2, 0xed1, 0x1ef0
};


void crc_16(unsigned char Data, unsigned short *crc)
{
  *crc = ((*crc) >> 8) ^ crc16_table[((*crc) ^ Data) & 0xff];
}


void crc_16_buf(unsigned char *adr, long size, unsigned short *crc)
{
  while (size-- > 0)
    *crc = ((*crc) >> 8) ^ crc16_table[((*crc) ^ *adr++) & 0xff];
}


void crcfcs(unsigned char Data, unsigned short *crc)
{
  *crc = ((*crc) >> 8) ^ ccitt_table[((*crc) ^ Data) & 0xff];
}


void crcfcs_buf(unsigned char *adr, long size, unsigned short *crc)
{
  while (size-- > 0)
    *crc = ((*crc) >> 8) ^ ccitt_table[((*crc) ^ *adr++) & 0xff];
}


void crcthp(unsigned char Data, unsigned short *crc)
{
  *crc = ((*crc) << 8) ^ Data ^ ccitt_table[(*crc) >> 8];
}


void crcthp_buf(unsigned char *adr, long size, unsigned short *crc)
{
  while (size-- > 0)
    *crc = ((*crc) << 8) ^ *adr++ ^ ccitt_table[(*crc) >> 8];
}


void crcfbb(unsigned char Data, unsigned short *crc)
{
  *crc = ((*crc) << 8) ^ ccitt_table[((*crc) >> 8) ^ Data];
}


void crcfbb_buf(unsigned char *adr, long size, unsigned short *crc)
{
  while (size-- > 0)
    *crc = ((*crc) << 8) ^ ccitt_table[((*crc) >> 8) ^ *adr++];
}


void checksum16(unsigned char Data, unsigned short *crc)
{
  *crc += Data;
}


void checksum16_buf(unsigned char *adr, long size, unsigned short *crc)
{
  while (size-- > 0)
    *crc += *adr++;
}


void checksum8(unsigned char Data, unsigned short *crc)
{
  *crc = (*crc + Data) & 0xff;
}


void checksum8_buf(unsigned char *adr, long size, unsigned short *crc)
{
  while (size-- > 0)
    *crc += *adr++;
  *crc &= 0xff;
}


signed long CRCFile_FromTo(const unsigned char *fname,signed long from,
                          signed long to)
 {
  unsigned char *memptr;
  BPTR file;
  unsigned short crc;
  unsigned long offi;


  offi=0;
  memptr=AllocVec(8192,1);
  if (memptr==NULL) return(-1);

  file=Open((unsigned char *) fname,MODE_OLDFILE);
  if (file==NULL)
   {
    FreeVec(memptr);
    return(-1);
   }

  crc=0;

  if (from!=-1)
   {
    offi=from;
    if (Seek(file,from,OFFSET_BEGINNING)==-1)
     {
      Close(file);
      return(-1);
     }
   }

  while (1)
   {
    signed long readbytes;

    readbytes=8192;
    if (to!=-1)
     {
      if (offi+8192>to) readbytes=to-offi;
     }
    if (readbytes<=0) break;

    readbytes=Read(file,memptr,readbytes);
    if (readbytes==-1)
     {
      Close(file);
      FreeVec(memptr);
      return(-1);
     }
    crcthp_buf(memptr,readbytes,&crc);
    if (readbytes!=8192) break;
   }

  Close(file);
  FreeVec(memptr);
  return(crc);
 }



signed long QSO_CRCFile(const unsigned char *fname)
 {
  return(CRCFile_FromTo(fname,-1,-1));
 }

signed long QSO_CRCFileUntil(const unsigned char *fname,unsigned long offset)
 {
  return(CRCFile_FromTo(fname,-1,offset));
 }

signed long QSO_CRCFileOffset(const unsigned char *fname,unsigned long offset)
 {
  return(CRCFile_FromTo(fname,offset,-1));
 }

