/******************************************************************************
** JEDEC.c
*******************************************************************************
**
** description:
**
** This file contains some functions to load and save GAL data in JEDEC format.
**
******************************************************************************/






/********************************* includes **********************************/

#include <exec/types.h>
#include <exec/memory.h>
#include <libraries/dos.h>
#include <libraries/locale.h>
#include <stdio.h>
#include <ctype.h>
#include <stdio.h>

#include <proto/locale.h>
#include <proto/dos.h>
#include <proto/intuition.h>
#include <proto/exec.h>

#include "GALer.h"
#include "Localize.h"





/********************************** defines **********************************/
 




/******************************** functions **********************************/





/******************************** variables **********************************/
 
extern  struct  AppString { LONG   as_ID;
                            STRPTR as_Str;
                          };

extern  struct  AppString AppStrings[];

extern  int     MaxFuseAdr, RowSize, XORSize, GALType;
extern  char    path;

extern  struct  Configuration   Config;
extern  struct  Catalog         *catalog;

struct  JedecStruct     Jedec;


int     linenum, JedecSecurity, JedecGALType;
int     oldMaxFuseAdr, oldRowSize, oldXORSize;

UBYTE   *actptr, *buffend;







/******************************************************************************
** PutJedec()
*******************************************************************************
** input:   none
** output:  none
**
** remarks: read GAL and generate JEDEC structure and write JEDEC file
******************************************************************************/

void PutJedec(void)
{

    if (GALTypeRequest(AppStrings[MSG_READGAL_JED].as_Str))
    {
        if (ReadGALParameter(YES))              /* get parameter or GAL */
            return;                             /* error -> return      */

        PrintText(AppStrings[MSG_READING_GAL].as_Str, 1);

        ReadGALToJedec();                                  /* read GAL */

        PrintText(AppStrings[MSG_LOWER_OK].as_Str, 0);

        if (MyFileReq(AppStrings[MSG_WRITE_JED].as_Str, ".jed", YES, SAVE))
            WriteJedecFile(GALType);

    }
}





/******************************************************************************
** FileChecksum()
*******************************************************************************
** input:   buff    ActBuffer structure of file buffer
**
** output:          16 bit checksum of the JEDEC structure
**
** remarks: This function calculates the JEDEC file checksum. The start and
**          the end of the area for which the checksum should be calculated
**          must be marked by <STX> and <ETX>!.
******************************************************************************/

int FileChecksum(struct ActBuffer buff)
{
    int checksum;


    checksum = 0;

    while (*buff.Entry != 0x2)                  /* search for <STX> */
        IncPointer(&buff);

    while (*buff.Entry != 0x3)
    {                                           /* search for <ETX> and */
        checksum += *buff.Entry;                /* add values           */

        IncPointer(&buff);
    }

    checksum += 0x3;                              /* add <ETX> too */

    return(checksum);                             /* ready */
}





/******************************************************************************
** FuseChecksum()
*******************************************************************************
** input:   galtype     type of GAL
**
** output:              16 bit checksum of the JEDEC structure
**
** remarks: This function does calculate the fuse checksum of the JEDEC
**          structure.
******************************************************************************/

int FuseChecksum(int galtype)
{
    int     checksum, byte, n;
    BYTE    *ptr, *ptrXOR, *ptrS1;



    ptr    = &Jedec.GALLogic[0] - 1L;
    ptrXOR = &Jedec.GALXOR[0];
    ptrS1  = &Jedec.GALS1[0];

    n = checksum = byte = 0;

    for (;;)
    {

        if (galtype == GAL16V8)
        {
            if (n == XOR16)
            {
                ptr = &Jedec.GALXOR[0];
            }
            else
            {
                if (n == XOR16+8)
                {
                    ptr = &Jedec.GALSig[0];
                }
                else
                {
                    if (n == NUMOFFUSES16)
                        break;
                    else
                        ptr++;
                }
            }
        }


        if (galtype == GAL20V8)
        {
            if (n == XOR20)
            {
                ptr = &Jedec.GALXOR[0];
            }
            else
            {
                if (n == XOR20+8)
                {
                    ptr = &Jedec.GALSig[0];
                }
                else
                {
                    if (n == NUMOFFUSES20)
                        break;
                    else
                        ptr++;
                }
            }
        }


        if (galtype == GAL22V10)
        {
            if (n >= XOR22V10 && n < XOR22V10 + 20)
            {
                if (!(n % 2))
                    ptr = ++ptrXOR;
                else
                    ptr = ++ptrS1;
            }
            else
            {
                if (n == SIG22V10)
                    ptr = &Jedec.GALSig[0] - 1L;

                if (n == SIG22V10 + SIG_SIZE)
                    break;
                else
                    ptr++;
            }
        }


        if (galtype == GAL20RA10)
        {
            if (n == XOR20RA10)
            {
                ptr = &Jedec.GALXOR[0];
            }
            else
            {
                if (n == SIG20RA10 + SIG_SIZE)
                    break;
                else
                    ptr++;
            }
        }


        byte |= (*ptr << (n+8) % 8);

        if (!((n + 9)%8))
        {
            checksum += byte;
            byte = 0;
        }

        n++;
    }

    checksum += byte;

    return(checksum);
}





/******************************************************************************
** MakeJedecBuff()
*******************************************************************************
** input:   buff     ActBuffer structure for the ram buffer
**          galtype  type of GAL
**
** output:  0:  o.k.
**         -1:  not enough free memory
**
** remarks: generates the JEDEC file in a ram buffer
******************************************************************************/
 
int MakeJedecBuff(struct ActBuffer buff, int galtype)
{
    UBYTE   mystrng[10];
    struct  ActBuffer buff2;
    int     n, m, bitnum, bitnum2, flag;
    int     MaxFuseAdr, RowSize, XORSize;


    switch (galtype)
    {

         case  GAL16V8:
                 MaxFuseAdr = MAX_FUSE_ADR16; /* This variables are defined  */
                 RowSize    = ROW_SIZE_16V8;  /* both globally AND locally!  */
                 XORSize    = 8;              /* All assignments concern to  */
                 break;                       /* the locale variables!!!!    */

         case GAL20V8:
                 MaxFuseAdr = MAX_FUSE_ADR20;
                 RowSize    = ROW_SIZE_20V8;
                 XORSize    = 8;
                 break;

         case GAL22V10:
                 MaxFuseAdr = MAX_FUSE_ADR22V10;
                 RowSize    = ROW_SIZE_22V10;
                 XORSize    = 10;
                 break;

         case GAL20RA10:
                 MaxFuseAdr = MAX_FUSE_ADR20RA10;
                 RowSize    = ROW_SIZE_20RA10;
                 XORSize    = 10;
                 break;
    }



    buff2 = buff;

    if (Config.JedecFileChk)
        if (AddString(&buff, (UBYTE *)"\2\n"))          /* <STX> */
            return(-1);

                                        /*** make header of JEDEC file ***/
    if (AddString(&buff, (UBYTE *)"Used Program:   GALer V2.0\n"))
        return(-1);

    if (AddString(&buff, (UBYTE *)"GAL-Assembler:  GALer V2.0\n"))
        return(-1);

    if (galtype == GAL16V8)
    {
        if (AddString(&buff, (UBYTE *)"Device:         GAL16V8\n\n"))
            return(-1);
    }

    if (galtype == GAL20V8)
    {
        if (AddString(&buff, (UBYTE *)"Device:         GAL20V8\n\n"))
            return(-1);
    }

    if (galtype == GAL20RA10)
    {
        if (AddString(&buff, (UBYTE *)"Device:         GAL20RA10\n\n"))
            return(-1);
    }

    if (galtype == GAL22V10)
    {
        if (AddString(&buff, (UBYTE *)"Device:         GAL22V10\n\n"))
            return(-1);
    }


    if (AddString(&buff, (UBYTE *)"*F0\n"))     /* default value of fuses */
        return(-1);

    if (Config.JedecSecBit)
    {                                               /* Security-Bit */
        if (AddString(&buff, (UBYTE *)"*G1\n"))
            return(-1);
    }
    else
        if (AddString(&buff, (UBYTE *)"*G0\n"))
            return(-1);


    if (galtype == GAL16V8)                       /* number of fuses */
        if (AddString(&buff, (UBYTE *)"*QF2194\n"))
            return(-1);

    if (galtype == GAL20V8)
        if (AddString(&buff, (UBYTE *)"*QF2706\n"))
            return(-1);
      
    if (galtype == GAL20RA10)
        if (AddString(&buff, (UBYTE *)"*QF3274\n"))
            return(-1);

    if (galtype == GAL22V10)
        if (AddString(&buff, (UBYTE *)"*QF5892\n"))
            return(-1);

                                                /*** make fuse-matrix ***/

    bitnum = 0;

    for (m = 0; m < RowSize; m++)
    {
        flag = 0;

        bitnum2 = bitnum;

        for (n = 0; n <= MaxFuseAdr; n++)
        {
            if (Jedec.GALLogic[bitnum2])
            {
                flag = 1;
                break;
            }

            bitnum2++;
        }

        if (flag)
        {
            sprintf((char *)&mystrng[0], "*L%04d \0", bitnum);

            if (AddString(&buff, (UBYTE *)&mystrng[0]))
                return(-1);

            for (n=0; n<=MaxFuseAdr; n++)
            {
                if (AddByte(&buff, (UBYTE)(Jedec.GALLogic[bitnum] + '0')))
                    return(-1);
                bitnum++;
            }

            if (AddByte(&buff, (UBYTE)'\n'))
                return(-1);

        }
        else
            bitnum = bitnum2;
    }

    if (!flag)
        bitnum = bitnum2;


                                                /*** XOR-Bits ***/
    sprintf((char *)&mystrng[0], "*L%04d \0", bitnum);    /* add fuse adr. */
    if (AddString(&buff, (UBYTE *)&mystrng[0]))
        return(-1);

    for (n = 0; n < XORSize; n++)
    {
        if (AddByte(&buff, (UBYTE)(Jedec.GALXOR[n] + '0')))
            return(-1);
        bitnum++;

        if (galtype == GAL22V10)
        {                                           /*** S1 of 22V10 ***/
            if (AddByte(&buff, (UBYTE)(Jedec.GALS1[n] + '0')))
                return(-1);
            bitnum++;
        }
    }

    if (AddByte(&buff, (UBYTE)'\n'))
        return(-1);


                                                /*** Signature ***/
    sprintf((char *)&mystrng[0], "*L%04d \0", bitnum);

    if (AddString(&buff, (UBYTE *)&mystrng[0]))
        return(-1);

    for (n = 0; n < SIG_SIZE; n++)
    {
        if (AddByte(&buff, (UBYTE)(Jedec.GALSig[n] + '0')))
            return(-1);
        bitnum++;
    }

    if (AddByte(&buff, (UBYTE)'\n'))
        return(-1);



    if ((galtype == GAL16V8) || (GALType == GAL20V8))
    {
                                                        /*** AC1-Bits ***/
        sprintf((char *)&mystrng[0], "*L%04d \0", bitnum);
        if (AddString(&buff, (UBYTE *)&mystrng[0]))
            return(-1);

        for (n = 0; n < AC1_SIZE; n++)
        {
            if (AddByte(&buff, (UBYTE)(Jedec.GALAC1[n] + '0')))
                return(-1);
            bitnum++;
        }

        if (AddByte(&buff, (UBYTE)'\n'))
            return(-1);


                                                        /*** PT-Bits ***/
        sprintf((char *)&mystrng[0], "*L%04d \0", bitnum);
        if (AddString(&buff, (UBYTE *)&mystrng[0]))
            return(-1);

        for (n = 0; n < PT_SIZE; n++)
        {
            if (AddByte(&buff, (UBYTE)(Jedec.GALPT[n] + '0')))
                return(-1);
            bitnum++;
        }

        if (AddByte(&buff, (UBYTE)'\n'))
            return(-1);


                                                        /*** SYN-Bit ***/
        sprintf((char *)&mystrng[0], "*L%04d \0", bitnum);

        if (AddString(&buff, (UBYTE *)&mystrng[0]))
            return(-1);

        if (AddByte(&buff, (UBYTE)(Jedec.GALSYN + '0')))
            return(-1);

        if (AddByte(&buff, (UBYTE)'\n'))
            return(-1);

        bitnum++;


                                                        /*** AC0-Bit ***/
        sprintf((char *)&mystrng[0], "*L%04d \0", bitnum);

        if (AddString(&buff, (UBYTE *)&mystrng[0]))
            return(-1);

        if (AddByte(&buff, (UBYTE)(Jedec.GALAC0 + '0')))
            return(-1);

        if (AddByte(&buff, (UBYTE)'\n'))
            return(-1);

    }



    if (Config.JedecFuseChk)
    {                                   /* add fuse-checksum */
        sprintf((char *)&mystrng[0], "*C%04x\n\0", FuseChecksum(GALType));

        if (AddString(&buff, (UBYTE *)&mystrng[0]))
            return(-1);
    }


    if (AddString(&buff, (UBYTE *)"*\n"))                 /* closing '*' */
        return(-1);


    if (Config.JedecFileChk)
    {
        if (AddByte(&buff, (UBYTE)0x3))                     /* <ETX> */
            return(-1);

        sprintf((char *)&mystrng[0], "%04x\n\0", FileChecksum(buff2));

        if (AddString(&buff, (UBYTE *)&mystrng[0]))
            return(-1);
    }


    return(0);
}





/******************************************************************************
** MakeJedecBuff()
*******************************************************************************
** input:   galtype     type of GAL
**
** output:  none
**
** remarks: generats the JEDEC file out of the JEDEC structure
******************************************************************************/
 
void WriteJedecFile(int galtype)
{
    struct  ActBuffer       mybuff;
    struct  Buffer          *first_buff;
    BPTR    fh;
    extern  char    path;
    UBYTE   *filebuffer, *filebuffer2;
    long    result;



    if (!(first_buff = (struct Buffer *)AllocMem((long)sizeof(struct Buffer),
                                                  MEMF_PUBLIC|MEMF_CLEAR)))
    {
        ErrorReq(2);                                /* out of memory? */
        return;
    }

    mybuff.ThisBuff = first_buff;
    mybuff.Entry    = (UBYTE *)(&first_buff->Entries[0]);
    mybuff.BuffEnd  = (UBYTE *)first_buff + (long)sizeof(struct Buffer);



    if (MakeJedecBuff(mybuff, galtype))
    {                                       /* put JEDEC in ram-buffer */
        FreeBuffer(first_buff);             /* error?                  */
        ErrorReq(2);
        return;
    }

    PrintText(AppStrings[MSG_WRITING_JED].as_Str, 1);

    if ((fh = Open(&path, (long)MODE_NEWFILE)))
    {
        for (;;)
        {
            filebuffer = filebuffer2 = mybuff.Entry;

            while (filebuffer2 < mybuff.BuffEnd)
            {                                   /* get size of buffer */
                if (!*filebuffer2)
                    break;
                filebuffer2++;
            }
                                                /* save buffer */
            result = Write(fh, (char *)filebuffer,
                           (long)(filebuffer2 - filebuffer));

            if (result == -1L)
            {                                   /* write error? */
                Close(fh);
                FreeBuffer(first_buff);
                PrintText(AppStrings[MSG_ERROR].as_Str ,0);
                ErrorReq(13);
                return;
            }

            if (!mybuff.ThisBuff->Next)         /* more buffers here? */
                break;                          /* no, then cancel */

            mybuff.ThisBuff = mybuff.ThisBuff->Next;
            mybuff.Entry    = (UBYTE *)(&mybuff.ThisBuff->Entries[0]);
            mybuff.BuffEnd  = (UBYTE *)mybuff.ThisBuff + (long)sizeof(struct Buffer);
        }

        Close(fh);
    }
    else
    {
        FreeBuffer(first_buff);                     /* error?, then cancel*/
        PrintText(AppStrings[MSG_ERROR].as_Str ,0);
        ErrorReq(13);                               /* can't open file */
        return;
    }

    PrintText(AppStrings[MSG_LOWER_OK].as_Str, 0);
    FreeBuffer(first_buff);
}





/******************************************************************************
** SearchNextChar()
*******************************************************************************
** input:   none
**
** output:  0:  no character found
**         -1:  no more characters (end of file)
**
** remarks: increments pointer to next character which is no TAB
**          SPACE, CR
**          starts searching at actptr + 1
******************************************************************************/

int SearchNextChar(void)
{

    actptr++;

    while (*actptr)
    {
        switch (*actptr)
        {
            case  ' ':
            case 0x09:
                break;

            case 0x0A:
                linenum++;
                break;

            default:
                return(0);
        }
        actptr++;
    }
    return(-1);

}



 

/******************************************************************************
** SearchNextAsterix()
*******************************************************************************
** input:   none
**
** output:  0:  found a '*'
**         -1:  no more characters (end of file)
**
** remarks: searches for '*' up to the end of the file
**          starts searching at actptr
******************************************************************************/
 
int SearchNextAsterix(void)
{

    while (*actptr)
    {
        if (*actptr == '*')
            return(0);

        if (*actptr == 0x0A)
            linenum++;
        actptr++;
    }

    return(-1);
}





/******************************************************************************
** GetJedec()
*******************************************************************************
** input:   *jedecfile  pointer to file name (".jed")
**
** output:   0:  no error occured
**         <>0:  error occured
**
** remarks: This function reads a JEDEC file, checks it and generates
**          the JEDEC structure.
******************************************************************************/

int GetJedec(UBYTE *jedecfile)
{
    extern  char    path;
    LONG    filesize;
    UBYTE   *filebuff, *ptr, *jedbuff, *jedptr;
    int     n;
    int     QFflag, QPflag, Fflag, Gflag, Cflag;
    int     Lflag, STXflag, ETXflag, FCHKflag;
    int     errornum, fuse_chk, file_chk;
    unsigned int    num, fuse;
    unsigned int    QF, QP, F;



    JedecGALType = NOT_SPECIFIED;

    filesize = FileSize(jedecfile);

    switch (filesize)
    {
        case -1L:
            ErrorReq(1);
            return(-1);
            break;

        case -2L:
            ErrorReq(2);
            return(-2);
            break;

        case 0L:
            ErrorReq(4);
            return(-4);
            break;
    }


    if ((filebuff = (UBYTE *)AllocMem(filesize+2L, MEMF_PUBLIC|MEMF_CLEAR)))
    {

        if ((ReadFile(jedecfile, filesize, filebuff)))
        {

            PrintText(AppStrings[MSG_FILE_LOADED].as_Str, 1);

            actptr = filebuff;                         /* initialize variables */
            linenum  = 1;
            errornum = 0;
            fuse     = 0;
            QFflag = QPflag = Fflag = Gflag = Cflag = Lflag = 0;
            FCHKflag = ETXflag = STXflag = 0;

            if (!(jedbuff = (UBYTE *)AllocMem((long)sizeof(Jedec),
                                              MEMF_PUBLIC|MEMF_CLEAR)))
            {
                FreeMem(filebuff, filesize);
                ErrorReq(2);                   /* no more free memory */
                return(-2);
            }

            jedptr = jedbuff;


            if (SearchNextAsterix())
            {                 /* point to first instruction */
                FreeMem(jedbuff, (long)sizeof(Jedec)); /* buffer for the  */
                FreeMem(filebuff, filesize);           /* JEDEC strucutre */
                JedecError(1, YES);             /* unexpected end of file */
                return(1);
            }


            for (;;)
            {
                if (SearchNextChar())           /* is there any character left? */
                    break;                      /* no, then end this loop       */

                switch (*actptr)
                {
                    case 'Q':                   /*instructions introduced by Q*/
                        actptr++;
                        if (*actptr == 'F')
                        {                       /*number of fuses in this file*/
                            if (QFflag)
                            {                   /* Befehl darf innerhalb des */
                                errornum = 7;   /* Jedec-Files nur einmal    */
                                break;          /* vorkommen                 */
                            }

                            actptr++;

                            if (!isdigit(*actptr))
                            {                       /* is there a number? */
                                errornum = 4;       /* no, then error     */
                                break;
                            }

                            if (!sscanf((char *)actptr, "%d", &QF))
                            {
                                errornum = 3;
                                break;
                            }

                            while (isdigit(*actptr))           /* skip number */
                                actptr++;

                            QFflag = 1;

                            if (QF != 2194 && QF != 2706 && QF != 3274 && QF != 5892)
                            {
                                errornum = 22;          /* unknown QF, then error */
                                break;
                            }

                            if (QF == 2194)     /* get out of *QF type of GAL */
                                JedecGALType = GAL16V8;

                            if (QF == 2706)
                                JedecGALType = GAL20V8;

                            if (QF == 5892)
                                JedecGALType = GAL22V10;

                            if (QF == 3274)
                                JedecGALType = GAL20RA10;

                            break;
                        }
                                                /* commands introduced by a P */
                        if (*actptr == 'P')
                        {                       /* number of pins */
                            if (QPflag)
                            {                   /* this instructions is allowed */
                                errornum = 8;   /* just once                    */
                                break;
                            }

                            actptr++;

                            if (!isdigit(*actptr))
                            {                              /* is there a number? */
                                errornum = 4;              /* no, then error     */
                                break;
                            }

                            if (!sscanf((char *)actptr, "%d", &QP))
                            {
                                errornum = 3;
                                break;
                            }

                            while (isdigit(*actptr))        /* skip number */
                                actptr++;

                            QPflag = 1;
                            break;
                        }

                        errornum = 2;                   /* no QF,QP, then error */
                        break;


                    case 'F':                      /*** Fuse-Default ***/
                        actptr++;

                        if (*actptr == '0')
                            F = 0;
                        else
                            if (*actptr == '1')
                                F = 1;
                            else
                            {                           /* no 0 or 1 after F */
                                errornum = 5;           /* then error        */
                                break;
                            }

                        for (n=fuse; n<sizeof(Jedec); n++)  /* default value */
                            *(jedbuff + (long)n) = F;

                        Fflag = 1;
                        break;


                    case 'P':                   /*pins for test vectors */
                    case 'V':                   /*test vector           */
                    case 'N':                   /*comment               */
                        break;                  /*do nothing            */


                    case 'C':                   /*** Fuse-Checksum ***/
                        if (Cflag)
                        {                       /* only one fuse-chk. allowed */
                            errornum = 24;
                            break;
                        }

                        actptr++;

                        if (!isxdigit(*actptr))
                        {                           /* is there a hex. number? */
                            errornum = 4;           /* no, then error          */
                            break;
                        }

                        if (!sscanf((char *)actptr, "%x", &fuse_chk))
                        {
                            errornum = 3;
                            break;
                        }

                        while (isxdigit(*actptr))            /* skip hex. number*/
                            actptr++;

                        Cflag = 1;
                        break;


                    case 'L':                      /*** Fuse-Adresse ***/
                        if (Cflag)
                        {                          /* after *C no *L allowed */
                            errornum = 10;
                            break;
                        }

                        actptr++;

                        if (!isdigit(*actptr))
                        {                           /* is there a dez. number? */
                            errornum = 4;           /* no, then error          */
                            break;
                        }

                        if (!sscanf((char *)actptr, "%d", &num))
                        {
                            errornum = 3;
                            break;
                        }

                        while (isdigit(*actptr))      /* skip dez. number */
                            actptr++;

                        if (num < fuse)
                        {                      /* is fuse adr. too low? */
                            errornum = 17;
                            break;
                        }

                        if ((num > fuse) && !Fflag)
                        {                           /* skip fuse address */
                            errornum = 18;          /* was there a *F? */
                            break;                  /* no, then error  */
                        }

                        if (SearchNextChar())
                        {                         /* no more characters?         */
                            errornum = 1;         /* then unexpected end of file */
                            break;
                        }


                        fuse = num;

                        for (;;)
                        {                           /*examine fuses*/
                            if ((*actptr == '1') || (*actptr == '0'))
                            {
                                *(jedbuff + (long)fuse) = *actptr - '0';
                            }
                            else
                            {
                                if (*actptr == '*')   /* next instruction? */
                                    break;            /* yes, then ready   */
                                else
                                {               /* no, then error '*' expected */
                                    errornum = 19;
                                    break;
                                }
                            }

                            if (SearchNextChar())
                            {                     /* no more characters?         */
                                errornum = 1;     /* then unexpected end of file */
                                break;
                            }
                            fuse++;

                        }

                        Lflag = 1;
                        break;


                    case 'G':                      /*** Security ***/
                        if (QPflag)
                        {                      /* this instruction may appear */
                            errornum = 8;      /* just one time in the file   */
                            break;
                        }
                        actptr++;

                        if (*actptr == '0')
                            JedecSecurity = 0;
                        else
                            if (*actptr == '1')
                                JedecSecurity = 1;
                            else
                            {                       /*  no 0 nor 1 after G? */
                                errornum = 5;       /*  then error          */
                                break;
                            }

                        Gflag = 1;
                        break;


                    case 0x02:                     /*** <STX> ***/
                        break;


                    case 0x03:                     /*** <ETX> then File-Checksum ***/
                        ptr = filebuff;
                        file_chk = 0;
                        while (*ptr)
                        {
                            if (*ptr == 0x02)
                            {                        /* multiple <STX> */
                                if (STXflag)
                                {
                                    errornum = 12;
                                    break;
                                }

                                if (ETXflag)
                                {                           /* STX before ETX? */
                                    errornum = 14;
                                    break;
                                }
                                STXflag = 1;
                            }

                            if (*ptr == 0x03)
                            {                        /* <ETX> */
                                if (ETXflag)
                                {                           /* mulitple? */
                                    errornum = 13;
                                    break;
                                }

                                if (!STXflag)
                                {                          /* STX vor ETX? */
                                    errornum = 14;
                                    break;
                                }
                                ETXflag = 1;
                            }

                            if (STXflag && !ETXflag)       /* add to checksum */
                                file_chk += *ptr;

                            ptr++;
                        }

                        file_chk += 0x03;                  /* add ETX */
                        actptr++;

                        if (!isxdigit(*actptr))
                        {                           /* is there a hex. number? */
                            errornum = 4;           /* no, then error          */
                            break;
                        }

                        if (!sscanf((char *)actptr, "%x", &num))
                        {
                            errornum = 3;
                            break;
                        }

                        while (isxdigit(*actptr))   /* skip hex. number */
                            actptr++;

                        if (file_chk != num)
                        {
                            if (!TxtRequest(AppStrings[MSG_BAD_FILECHK].as_Str,
                                            AppStrings[MSG_CONT_GAD].as_Str,
                                            AppStrings[MSG_CANCEL_GAD].as_Str))
                            {
                                errornum = 16;
                                break;
                            }
                        }

                        FCHKflag = 1;
                        break;
                    }


                    if (errornum)
                    {                       /* was there an error? yes, then end */
                        FreeMem(jedbuff, (long)sizeof(Jedec));
                        FreeMem(filebuff, filesize);
                        JedecError(errornum, YES);
                        return(errornum);
                    }

                    if (FCHKflag)                   /* File-Checksum?       */
                        break;                      /* yes, then break loop */

                    if (SearchNextAsterix())        /* search for final '*' */
                        errornum = 9;
                }


                if (!Lflag && !Fflag)
                {                                            /* no fuses?    */
                    FreeMem(filebuff, filesize);             /* then error   */
                    FreeMem(jedbuff, (long)sizeof(Jedec));   /* free buffers */
                    JedecError(21, NO);
                    return(21);
                }

                if (QFflag)
                {                              /* does *L.. fit to *QF? */
                    if ((fuse != QF && !Fflag) || (fuse > QF))
                    {
                        FreeMem(filebuff, filesize);       /* no, then error */
                        FreeMem(jedbuff, (long)sizeof(Jedec));
                        JedecError(20, NO);
                        return(20);
                    }
                }
                else
                {
                    if (Fflag)
                    {                             /* try to identify the type of */
                        if (fuse > 3274 && fuse <= 5892) /* GAL for which this   */
                            JedecGALType = GAL20RA10;    /* JEDEC file is        */

                        if (fuse <= 2194)        /* less than 2194 fuses => 16V8 */
                            JedecGALType = GAL16V8;

                        if (fuse > 5892)
                        {                     /* too many fuses for the known  */
                            FreeMem(jedbuff, (long)sizeof(Jedec)); /* types of */
                            FreeMem(filebuff, filesize);      /* GALs => error */
                            JedecError(6, NO);
                            return(23);
                        }
                    }
                    else
                    {
                        if (fuse != 2194 && fuse != 2706 && fuse !=5892 && fuse != 3274)
                        {
                            FreeMem(jedbuff, (long)sizeof(Jedec));
                            FreeMem(filebuff, filesize);
                            JedecError(6, NO);
                            return(6);
                    }

                    if (fuse == 2194)            /* if there was no QF and no    */
                        JedecGALType = GAL16V8;  /* F instruction, identify type */
                                                 /* of GAL by the last fuse      */
                    if (fuse == 2706)            /* address                      */
                        JedecGALType = GAL20V8;

                    if (fuse == 5892)
                        JedecGALType = GAL22V10;

                    if (fuse == 3274)
                        JedecGALType = GAL20RA10;

                }
            }

            if (FCHKflag)                              /*file checksum?*/
                if (!SearchNextChar())
                {                           /* are there any more characters? */
                    FreeMem(filebuff, filesize);           /* yes, then error */
                    FreeMem(jedbuff, (long)sizeof(Jedec));
                    JedecError(15, YES);
                    return(15);
                }


                                            /*** initialize JEDEC structure ***/
            for (n = 0; n < sizeof(Jedec); n++)
            {

                if (JedecGALType == GAL16V8)
                {                               /*** GAL16V8 ***/

                    if ((n < 2048) || (n > 5807 && n < 5816) || (n > 5817 && n < 5956))
                    {
                        Jedec.GALLogic[n] = *jedptr; /*get matrix, XOR, signature*/
                        jedptr++;                    /*AC1, PT, SYN and AC0      */
                    }
                    else
                        Jedec.GALLogic[n] = 0;

                }

                if (JedecGALType == GAL20V8)
                {                               /*** GAL20V8 ***/

                    if ((n < 2560) || (n > 5807 && n < 5816) || (n > 5817 && n < 5956))
                    {
                        Jedec.GALLogic[n] = *jedptr; /*get matrix, XOR, signature*/
                        jedptr++;                    /*AC1, PT, SYN and AC0      */
                    }
                    else
                        Jedec.GALLogic[n] = 0;

                }


                if (JedecGALType == GAL22V10)
                {                               /*** GAL22V10 ***/

                    if (n < 5808 || (n > 5817 && n < 5882))
                    {
                        Jedec.GALLogic[n] = *jedptr; /* get matrix, signature */
                        jedptr++;
                    }
                    else
                    {
                        if (n > 5807 && n < 5818)
                        {
                            Jedec.GALXOR[n - 5808] = *jedptr;   /* get XORs */
                            jedptr++;

                            Jedec.GALS1[n - 5808] = *jedptr;    /* get S1 */
                            jedptr++;
                        }
                        else
                            if (n < 5956 || n > 5965)  /*don't erase S1, it's*/
                                Jedec.GALLogic[n] = 0; /*set when n>5807     */
                    }
                }


                if (JedecGALType == GAL20RA10)
                {                               /*** GAL20RA10 ***/

                    if ((n < 3200) || (n > 5807 && n < 5882))
                    {                                      /* get matrix, XOR */
                        Jedec.GALLogic[n] = *jedptr;       /* and signature   */
                        jedptr++;
                    }
                    else
                        Jedec.GALLogic[n] = 0;

                }


            }


            if (Cflag)
            {                       /* test whether checksum is o.k. or not */
                if (fuse_chk != FuseChecksum(JedecGALType))
                {
                    if (!TxtRequest(AppStrings[MSG_BAD_FUSECHK].as_Str,
                       AppStrings[MSG_CONT_GAD].as_Str,
                       AppStrings[MSG_CANCEL_GAD].as_Str))
                    {
                        FreeMem(filebuff, filesize);
                        FreeMem(jedbuff, (long)sizeof(Jedec));
                        JedecError(11, NO);         /* bad fuse checksum */
                        return(11);
                    }
                }
            }

            FreeMem(jedbuff, (long)sizeof(Jedec)); /* free JEDEC struct. buf. */
            FreeMem(filebuff, filesize);           /* free JEDEC file buffer  */
            return(0);                             /* no error occured        */

        }
        else
        {
            ErrorReq(3);                            /* read error */
            FreeMem(filebuff, filesize);
            return(-2);
        }

    }
    else
    {
        ErrorReq(2);                            /* not enough free memory */
        return(-2);
    }

}





/******************************************************************************
** JedecError()
*******************************************************************************
** input:   errornum    error number
**          flag        signs whether there should be a line number printed
**                      or not
**
** output:  none
**
** remarks: prints an error text
******************************************************************************/
 
void JedecError(int errornum, int flag)
{

    if (flag)
        PrintErrorLine(linenum);

    switch (errornum)
    {
        case  1:
            PrintText(AppStrings[MSG_ERR_JED1].as_Str, 1);
            break;

        case  2:
            PrintText(AppStrings[MSG_ERR_JED2].as_Str, 1);
            break;

        case  3:
            PrintText(AppStrings[MSG_ERR_JED3].as_Str, 1);
            break;

        case  4:
            PrintText(AppStrings[MSG_ERR_JED4].as_Str, 1);
            break;

        case  5:
            PrintText(AppStrings[MSG_ERR_JED5].as_Str, 1);
            break;

        case  6:
            PrintText(AppStrings[MSG_ERR_JED6].as_Str, 1);
            break;

        case  7:
            PrintText(AppStrings[MSG_ERR_JED7].as_Str, 1);
            break;

        case  8:
            PrintText(AppStrings[MSG_ERR_JED8].as_Str, 1);
            break;

        case  9:
            PrintText(AppStrings[MSG_ERR_JED9].as_Str, 1);
            break;

        case 10:
            PrintText(AppStrings[MSG_ERR_JED10].as_Str, 1);
            break;

        case 11:
            PrintText(AppStrings[MSG_ERR_JED11].as_Str, 1);
            break;

        case 12:
            PrintText(AppStrings[MSG_ERR_JED12].as_Str, 1);
            break;

        case 13:
            PrintText(AppStrings[MSG_ERR_JED13].as_Str, 1);
            break;

        case 14:
            PrintText(AppStrings[MSG_ERR_JED14].as_Str, 1);
            break;

        case 15:
            PrintText(AppStrings[MSG_ERR_JED15].as_Str, 1);
            break;

        case 16:
            PrintText(AppStrings[MSG_ERR_JED16].as_Str, 1);
            break;

        case 17:
            PrintText(AppStrings[MSG_ERR_JED17].as_Str, 1);
            break;

        case 18:
            PrintText(AppStrings[MSG_ERR_JED18].as_Str, 1);
            break;

        case 19:
            PrintText(AppStrings[MSG_ERR_JED19].as_Str, 1);
            break;

        case 20:
            PrintText(AppStrings[MSG_ERR_JED20].as_Str, 1);
            break;

        case 21:
            PrintText(AppStrings[MSG_ERR_JED21].as_Str, 1);
            break;

        case 22:
            PrintText(AppStrings[MSG_ERR_JED22].as_Str, 1);
            break;

        case 23:
            PrintText(AppStrings[MSG_ERR_JED23].as_Str, 1);
            break;

        case 24:
            PrintText(AppStrings[MSG_ERR_JED24].as_Str, 1);
            break;

        case 25:
            PrintText(AppStrings[MSG_ERR_JED25].as_Str, 1);
            break;

    }

    ErrorReq(5);
}






/* EOF */
