/*
    cgm2as - converts .cgm files to Vectrex 6809 assembly (A09 format)

    Usage: cgm2as file scale [xoffset yoffset]

    - Don't give any extension, .cgm is assumed
    - Supports only line, rect and polygon primitives
    - Before jsr set (a,b) to position the image.

    Marq/L!T 2000
 */

#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define MAXSTR 1000
#define MAXCOLS 1000
#define VERYMUCH 100000     /* Max size of FCB-clauses */

/* Scales an integer by scale*/
int imul(int i,double scale)
{
    return((int)(scale*(double)i));
}

int main(int argc,char *argv[])
{
    FILE    *s,
            *d;

    double  scale;

    char    sname[MAXSTR],
            dname[MAXSTR],
            str[MAXSTR],
            datas[VERYMUCH]={0},
            c;

    int     r,g,b,
            n,
            labelnum=0,
            inte,
            intensity[MAXCOLS],
            flag,flag2,
            x,y,
            x2,y2,
            oldx,oldy,
            xoff=0,yoff=0;

    if(argc<3)
    {
        fprintf(stderr,"Usage: cgm2as file scale [xoffset yoffset]\n");
        return(EXIT_FAILURE);
    }

    strcpy(sname,argv[1]);  /* Compose file names  */
    strcat(sname,".cgm");
    strcpy(dname,argv[1]);
    strcat(dname,".as9");

    scale=atof(argv[2]);    /* Get scale and x/y offsets */
    if(argc==5)
    {
        xoff=atoi(argv[3]);
        yoff=atoi(argv[4]);
    }

    s=fopen(sname,"rb");
    d=fopen(dname,"wb");

    if(s==NULL || d==NULL)
    {
        fprintf(stderr,"File error.\n");
        return(EXIT_FAILURE);
    }

    fscanf(s,"%s",str);     /* Is it a metafile at all? */
    if(strcmp("BEGMF",str))
    {
        fprintf(stderr,"Invalid CGM data\n");
        return(EXIT_FAILURE);
    }

    /* Print drawing code label... */
    fprintf(d,"draw%s\n",argv[1]);
    fprintf(d,"\tpshs\td\n\n");

    while(strcmp("colrtable",str)) /* Find color table */
        fscanf(s,"%s",str);
    fscanf(s,"%s",str);

    flag=1;
    n=0;
    while(flag) /* Convert the colors to Vectrex intensities */
    {
        fscanf(s,"%d%d%s",&r,&g,str);
        if(str[strlen(str)-1]==';') /* Last color? */
            flag=0;
        b=atoi(str);

        intensity[n]=127-(r+g+b)/6;
        n++;
    }

    flag=1;
    while(flag)    /* Scan through the drawing commands */
    {
        fscanf(s,"%s",str);

        /* Color change found */
        if(!strcmp("edgecolr",str) || !strcmp("linecolr",str))
        {
            fscanf(s,"%s",str);
            inte=intensity[atoi(str)-1];

            fprintf(d,"; Set intensity\n");
            fprintf(d,"\tlda\t#%d\n",inte);
            fprintf(d,"\tjsr\t$f2ab\n\n");
        }

        /* line or poly found */
        if(!strcmp("line",str) || !strcmp("polygon",str))
        {
            if(!strcmp("line",str))
                fprintf(d,"; Line(s)\n");
            else
                fprintf(d,"; Polygon\n");

            sprintf(str,"%s%d\n",argv[1],labelnum);
            strcat(datas,str);

            n=oldx=oldy=0;

            flag2=1;
            c=0;
            while(flag2)    /* Go through the coords */
            {
                while(c!='(')
                    c=fgetc(s);

                fscanf(s,"%d",&x);
                fgetc(s);
                fscanf(s,"%d",&y);

                fgetc(s);
                if((c=fgetc(s))==';')
                    flag2=0;

                /* Print the read coords to fcb-clauses */
                if(!n)
                {
                    sprintf(str,"\tfcb\t%d,%d\n",yoff+imul(y-oldy,scale),
                                                 xoff+imul(x-oldx,scale));
                }
                else
                {
                    sprintf(str,"\tfcb\t%d,%d\n",imul(y-oldy,scale),
                                                 imul(x-oldx,scale));
                }

                strcat(datas,str);

                oldx=x;
                oldy=y;
                n++;
            }

            /* Print the necessary assembly */
            fprintf(d,"\tjsr\t$f354\n");
            fprintf(d,"\tpuls\td\n");
            fprintf(d,"\tpshs\td\n");
            fprintf(d,"\tjsr\t$f2fc\n");

            fprintf(d,"\tldx\t#%s%d\n",argv[1],labelnum);
            labelnum++;
            fprintf(d,"\tlda\t#%d\n",n-1);
            fprintf(d,"\tldb\t#128\n");
            fprintf(d,"\tjsr\t$f3b7\n\n");
        }        

        /* Rectangle found */
        if(!strcmp("rect",str))
        {
            fprintf(d,"; Rectangle\n");

            sprintf(str,"%s%d\n",argv[1],labelnum);
            strcat(datas,str);

            /* Read the rectangle coordinates */
            for(c=0;c!='(';)
                c=fgetc(s);
            fscanf(s,"%d",&x);
            fgetc(s);
            fscanf(s,"%d",&y);

            for(c=0;c!='(';)
                c=fgetc(s);
            fscanf(s,"%d",&x2);
            fgetc(s);
            fscanf(s,"%d",&y2);

            /* Starting point */
            sprintf(str,"\tfcb\t%d,%d\n",yoff+imul(y,scale),
                                         xoff+imul(x,scale));
            strcat(datas,str);

            /* Go through the vertices */
            sprintf(str,"\tfcb\t%d,%d\n",imul(y2-y,scale),0);
            strcat(datas,str);
            sprintf(str,"\tfcb\t%d,%d\n",0,imul(x2-x,scale));
            strcat(datas,str);
            sprintf(str,"\tfcb\t%d,%d\n",imul(y-y2,scale),0);
            strcat(datas,str);
            sprintf(str,"\tfcb\t%d,%d\n",0,imul(x-x2,scale));
            strcat(datas,str);

            /* Print the necessary assembly */
            fprintf(d,"\tjsr\t$f354\n");
            fprintf(d,"\tpuls\td\n");
            fprintf(d,"\tpshs\td\n");
            fprintf(d,"\tjsr\t$f2fc\n");

            fprintf(d,"\tldx\t#%s%d\n",argv[1],labelnum);
            labelnum++;
            fprintf(d,"\tlda\t#%d\n",4);
            fprintf(d,"\tldb\t#128\n");
            fprintf(d,"\tjsr\t$f3b7\n\n");
        }

        if(feof(s))
            flag=0;
    }

    fprintf(d,"\tpuls\td\n");
    fprintf(d,"\trts\n");   /* Return from drawing routine */

    fprintf(d,"%s",datas);  /* Print the FCB-clauses */

    fclose(s);
    fclose(d);
    return(EXIT_SUCCESS);
}

/* EOS */
