
#define SOH     '\x01'
#define STX     '\x02'
#define EOT     '\x04'
#define ACK     '\x06'
#define NAK     '\x15'
#define CAN     '\x18'
#define CRC     '\x43'
#define	CR	'\x0D'

#define	XM_FILE		0
#define	XM_FSIZE	2
#define	XM_TBLK		3
#define	XM_SSIZE	4
#define	XM_SBLK		5
#define	XM_RSIZE	6
#define	XM_RBLK		7
#define	XM_TMOVR	8
#define	XM_RETRY	9
#define	XM_MSG		10

#define	DSP_WAIT	50000

static void Send(ch)
int	ch;
{
    unsigned int st;

    RSB_send(port,ch,&st);
}
static void Send_str(arg,n)
UCHAR	*arg;
int	n;
{
    unsigned int st;

    while ( n-- > 0 )
	RSB_send(port,(int)*(arg++),&st);
}
static int Recive()
{
    int    i,ch;
    unsigned int st;
/*
    for ( i = 0 ; RSB_receive(port,&ch,&st) != 0 ; ) {
	if ( ++i > 20000 )
	    return ERR;
    }
*/
    if ( RSB_receive(port,&ch,&st) != 0 )
	return ERR;
    else 
        return (ch & 0xFF);
}
static int  Recive_str(arg,n)
UCHAR	*arg;
int	n;
{
    int	    ch;

    while ( n-- > 0 ) {
        if ( (ch = Recive()) == ERR )
	    return ERR;
	*(arg++) = ch;
    }
    return FALSE;
}
static int Send_blk(fp,bk)
FILE    *fp;
int     bk;
{
    int     i,j;
    UCHAR   head[3];
    UCHAR   *p,tmp[128];

    head[0]=SOH;
    head[1]=bk;
    head[2]=255-bk;

    if ( (i=fread(tmp,1,128,fp)) <= 0 ) {
	Send(EOT);
        return ERR;
    }

    for ( p=tmp+i ; i < 128 ; i++ )
        *(p++)='\0';
    for ( j = i = 0 ; i < 128 ; i++,j &= 0xff )
        j += tmp[i];

    Send_str(head,3);
    Send_str(tmp,128);
    Send(j);

    return FALSE;
}
/*************************************************
   <<< X-Modem UpLoad Abort Hit ESC Key >>>

File Name    A:WINK.EXP
File Size    xxxx	    Total Block  xxxx
Send Size    xxxx	    Send Block   xxxx
Recive Size  xxxx	    Recive Block xxxx
Time Over    xxxx	    ReTry Count  xxxx
Message      xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

012345678901234567890123456789012345678901234567890
***************************************************/
void	Xmd_wind(md,file)
char	*md,*file;
{
    int    i;
    long   l;
    char   tmp[160];
    static char *menu[]={
	"File Name",	"",
	"File Size",	"Total Block",
	"Send Size",	"Send Block",
	"Recive Size",	"Recive Block",
	"Time Over",	"ReTry Count",
	"Message",
	NULL
    };

    Dmy_form(tmp,50,0x98,0x95,0x99); 
    wrtstr(tmp,15,7,0x05);

    Dmy_form(tmp,50,0x96,0x20,0x96); 
    for ( i = 0 ; i < 9 ; i++ )
        wrtstr(tmp,15,8+i,0x05);

    Dmy_form(tmp,50,0x9A,0x95,0x9B); 
    wrtstr(tmp,15,17,0x05);

    sprintf(tmp,"<<< X-Modem %s Abort Hit ESC Key >>>",md);
    wrtstr(tmp,20,8,0x01);

    for ( i = 0 ; menu[i] != NULL ; i++ )
	wrtstr(menu[i],17 + (i % 2) * 28,10 + i / 2,0x05);

    wrtstr(file,30,10,0x05);
}
void	Xmd_msg(msg)
char	*msg;
{
    wrtstr(msg,30,15,0x05);
}
void	Xmd_val(no,val)
int	no;
long	val;
{
    char    tmp[40];

    sprintf(tmp,"%ld",val);
    wrtstr(tmp,30 + (no % 2) * 28,10 + no / 2,0x05);
}
void    Up_Xmodem(file)
char    *file;
{
    int     i,ch,bk,nk,ef;
    unsigned int ec;
    FILE    *fp;
    long    size;
    char    tmp[80];

    Xmd_wind("UpLoad",file);
    if ( (fp = fopen(file,"rb")) == NULL ) {
	Xmd_msg("File Not Found");
	Soft_Timer(DSP_WAIT);
	return;
    }
    fseek(fp,0L,2);
    size = (long)ftell(fp);
    fseek(fp,0L,0);
    Xmd_val(XM_FSIZE,size);
    Xmd_val(XM_TBLK,(size + 127) / 128);

    for ( bk = 1, nk = 0, ef = FALSE, size = 0 ; ; ) {
	if ( kbhit() != 0 ) {
	    ch = Get_key(&ec);
	    if ( ch == 0x1B || ec == 0x7200 ) {
		Xmd_msg("Abort Xmodem Upload !!");
	        Send(CAN);
		Soft_Timer(DSP_WAIT);
		break;
	    }
	}
	for ( i = 0 ; i < 5 ; i++ ) {
	    if ( (ch = Recive()) != ERR ) 
		break;
	    Xmd_val(XM_TMOVR,i);
	}
	if ( i >= 5 ) {
	    Xmd_msg("Time Over Aobrt !!");
	    Soft_Timer(DSP_WAIT);
	    break;
	}
	if ( ch == ACK ) {
	    size += 128; nk = 0; bk++;
	    if ( ef != FALSE ) {
		Xmd_msg("End of Upload !!");
		break;
	    }
	    if ( Send_blk(fp,bk) != FALSE )
		ef = TRUE;
	    else {
		Xmd_val(XM_SSIZE,size + 128);
		Xmd_val(XM_SBLK,bk);
	    }
	} else if ( ch == NAK ) {
	    if ( nk++ > 0 )
		Xmd_val(XM_RETRY,nk);
	    fseek(fp,size,SEEK_SET);
	    if ( Send_blk(fp,bk) != FALSE )
		ef = TRUE;
	    else {
		Xmd_val(XM_SSIZE,size + 128);
		Xmd_val(XM_SBLK,bk);
	    }
	} else if ( ch == CAN ) {
            Xmd_msg("Recive Cansel Code !!");
	    Soft_Timer(DSP_WAIT);
            break;
        }
        if ( nk >= 5 ) {
            Xmd_msg("ReTry Over Abort !!");
	    Send(CAN);
	    Soft_Timer(DSP_WAIT);
	    break;
	}
    }
    fclose(fp);
}
void	Down_Xmodem(file)
char	*file;
{
    int     i,j,ch,bk,nk,ef;
    unsigned int ec;
    long    size;
    FILE    *fp;
    UCHAR   tmp[128];

    Xmd_wind("DownLoad",file);
    if ( (fp = fopen(file,"wb")) == NULL ) {
	wrtstr("ﾌｧｲﾙが作成出来ません",30,1,0x12);
	return;
    }
    for ( ef = TRUE,bk = 1,size = 0,nk = 0 ; ; ) {
	if ( kbhit() != 0 ) {
	    ch = Get_key(&ec);
	    if ( ch == 0x1B || ec == 0x7200 ) {
		Xmd_msg("Abort Xmodem Upload !!");
	        Send(CAN);
		Soft_Timer(DSP_WAIT);
		break;
	    }
	}
	for ( i = 0 ; i < 5 ; i++ ) {
	    if ( ef == FALSE )
		Send(ACK);
	    else if ( Flaing == FALSE )
		Send(NAK);
	    else {
		Send(NAK); Send(ACK);
	    }
	    if ( (ch = Recive()) != ERR ) 
		break;
	    Xmd_val(XM_TMOVR,i);
	}
	if ( i >= 5 ) {
	    Xmd_msg("Time Over Aobrt !!");
	    Soft_Timer(DSP_WAIT);
	    break;
	}
	if ( ch == EOT ) {
	    Xmd_msg("End of DownLoad !!");
	    if ( Flaing == FALSE )
		Send(ACK);
	    break;
	} else if ( ch == CAN ) {
            Xmd_msg("Recive Cansel Code !!");
	    Soft_Timer(DSP_WAIT);
            break;
        } else if ( ch == SOH ) {
            if ( Recive() != (bk & 0xff) )
		goto ERROR;
            if ( (255 - Recive()) != (bk & 0xff) )
		goto ERROR;
	    if ( Recive_str(tmp,128) != FALSE )
		goto ERROR;
	    for ( j = i = 0 ; i < 128 ; i++,j &= 0xff )
		j += tmp[i];
	    if ( Recive() != j )
		goto ERROR;

	    fwrite(tmp,1,128,fp);
	    size += 128;
	    Xmd_val(XM_RSIZE,size);
	    Xmd_val(XM_RBLK,bk);
	    ef = FALSE;
	    nk = 0;
	    bk++;
	    continue;
	}
ERROR:  Recive_str(tmp,128);	/* Dummy */
	ef = TRUE;
	Xmd_val(XM_RETRY,++nk);
        if ( nk >= 5 ) {
            Xmd_msg("ReTry Over Abort !!");
	    Send(CAN);
	    Soft_Timer(DSP_WAIT);
	    break;
	}
    }
    fclose(fp);
}
/**************************
    Auto Login
**************************/
int	htob(ch)
int     ch;
{
    int     i=0;

    if ( ch >= 'a' && ch <= 'z' )
	ch &= 0xDF;
    if ( '0' <= ch && ch <= '9' )
        i = ch - '0';
    else if ( 'A' <= ch && ch <= 'F' )
        i = ch - 'A' + 10;
    return i;
}
int	Wait_recive(tick)
int	tick;
{
    int     len,ch;
    unsigned int st;
    long    l,s;

    gtime(&l); l += tick;
    do {
	RSB_read(port,&len);
    	if ( len > 0 ) {
	    RSB_receive(port,&ch,&st);
	    BakPut(ch); Dsp_vram(cvram);
	    return ch;
	}
	gtime(&s);
    } while ( kbhit() == 0 && s < l );
    return ERR;
}
void	RS_Sleep(tick)
int	tick;
{
    int     len,ch;
    unsigned int st;
    long    l,s;

    gtime(&l); l += tick;
    do {
	RSB_read(port,&len);
    	if ( len > 0 ) {
	    while ( len-- > 0 ) {
	        RSB_receive(port,&ch,&st);
	        BakPut(ch);
	    }
	    Dsp_vram(cvram);
	}
	gtime(&s);
    } while ( kbhit() == 0 && s < l );
}
int	cmpstr(arg)
char    *arg;
{
    int     ch,wt;
    register char    *p;

    for ( p = arg,wt = 0 ; isdigit(*p) ; p++ )
	wt = wt * 10 + *p - '0';
    if ( *p == ',' && wt > 0 )
	arg = p + 1;
    else
	wt = 30;

    for ( p=arg ; *p != ']' ; ) {
        if ( (ch=Wait_recive(wt)) == ERR )
            return ERR;
        if ( ch == (*p & 0xff) )
            p++;
        else
            p=arg;
    }
    return FALSE;
}
int	cmpmac(arg)
char    *arg;
{
    int     ch,wt;
    register char    *p;

    for ( p = arg,wt = 0 ; isdigit(*p) ; p++ )
	wt = wt * 10 + *p - '0';
    if ( *p == ',' && wt > 0 )
	arg = p + 1;
    else
	wt = 5;

    for ( p=arg ; *p != '}' ; ) {
        if ( (ch=Wait_recive(wt)) == ERR )
            return ERR;
        if ( ch == (*p & 0xff) )
            p++;
        else
            p=arg;
    }
    return FALSE;
}
int	runlog(arg)
register char    *arg;
{
    int     ch;
    char    *p;
    char    *adr=NULL;

    for ( ; *arg != '\0' ; arg++ ) {
        switch(*arg) {
            case '<':
                Send(CR);
                break;
            case '>':
                while ( (ch=Wait_recive(30)) != CR ) {
		    if ( ch == ERR )
			return ERR;
                    if ( kbhit() != 0 )
                        return TRUE;
                }
                break;
            case '$':
                Send( htob(*(++arg)) << 4 | htob(*(++arg)) );
                break;
            case '\\':
                Send(*(++arg));
                break;
            case '*':
                RS_Sleep(2);
                break;
            case '?':
		adr = arg;
		break;
            case '@':
		adr = NULL;
		break;
            case '[':
                if ( cmpstr(++arg) != FALSE )
                    return ERR;
                while ( *arg != ']' ) arg++;
                break;
            case '{':
		if ( adr == NULL ) {
                    for ( p = arg ; *p != '?' && *p != '\0' ; p++ )
		    if ( *p == '?' )
		        adr = p;
		    else
		        return ERR;
		}
                if ( cmpmac(++arg) != FALSE ) {
		    if ( kbhit() != 0 )
			return ERR;
		    arg = adr;
		} else
                    while ( *arg != '}' ) arg++;
                break;
            default:
                Send(*arg);
                break;
        }
        if ( kbhit() != 0 )
            return TRUE;
    }
    return FALSE;
}
char    *Auto_menu[21]={ NULL };
char    *Auto_para[21];

void	Auto_log()
{
    static int  no=ERR;

    if ( Auto_menu[0] == NULL )
	goto ENDOF;

    if ( Sel_menu(Auto_menu,20,2,&no) != FALSE )
	goto ENDOF;

    wrtstr(SPCSTR,30,1,0x1F);
    if ( runlog(Auto_para[no]) == ERR )
	wrtstr("オ−トを中断しました",30,1,0x15);

ENDOF:
    Dsp_vram(cvram);
    Dsp_free();
}

char	*Auto_log_file="WINK.DEF";

void	Auto_log_init()
{
    int     i,mx=0;
    FILE    *fp;
    char    *p,*s,*n;
    char    tmp[256];
    char    work[4096];

    if ( (p = getenv("WINKAUTO")) != NULL )
	Auto_log_file = p;

    if ( (fp = fopen(Auto_log_file,"r")) == NULL )
	return;

    while ( (p = fgets(tmp,256,fp)) != NULL ) {
	while ( isspace(*p) ) p++;
	while ( p != NULL && *p == '#' ) {
	    for ( s = ++p ; *s != '\n' && *s != '\0' ; s++ );
	    *s = '\0';
	    if ( (n = Auto_menu[mx] = (char *)malloc(22)) == NULL )
		goto ENDOF;
	    for ( i = 0 ; i < 20 && *p != '\0' ; i++ )
		*(n++) = *(p++);
	    for ( ; i < 20 ; i++ )
		*(n++) = ' ';
	    *n = '\0';
	    for ( s = work ; (p = fgets(tmp,256,fp)) != NULL ; ) {
		while ( isspace(*p) ) p++;
		if ( *p == '#' )
		    break;
		while ( *p != '\n' && *p != '\0' )
		    *(s++) = *(p++);
	    }
	    *s = '\0';
	    if ( (Auto_para[mx] = (char *)malloc(strlen(work)+1)) == NULL )
		goto ENDOF;
	    strcpy(Auto_para[mx],work);
	    if ( ++mx >= 20 )
	        goto ENDOF;
	}
    }
ENDOF:
    fclose(fp);
    Auto_menu[mx] = NULL;
}
