/* This must be adjusted so the whole thing just fits in memory */
char filler[28000]; 

#asm 8080
DSEG
ENTRY::
    JMP bios?
#endasm


char *dmaadr;
char *arg;
char call;

struct fcb {
    	char drive;
	char name[8];
	char ext[3];
	char junk1[4];
	char desc;
	char name2[8];
	char ext2[3];
	char junk2[4];
	char junk3;
};



bios()
{
#asm 8080
	XCHG
	SHLD	arg?
	MOV	A,C
	STA	call?
;	CALL	en?
	CALL	bios2?
;	PUSH	H
;	CALL	ex?
;	POP	H
	XCHG		;SAVE RETURN VAL IN DE
	LHLD	arg?
	XCHG		;RETURN ORIG CONTENTS OF DE
	LDA	call?
	MOV	C,A	;RETURN ORIG CONTENTS OF C
	MOV	A,L
	MOV	B,H	;STRICT COMPATIBILITY
#endasm
}


#ifdef DEBUG

en()
{
    char line[80];

    sprintf(line,"    call %d arg %x\n",call, arg);
    write(1,line,strlen(line));
}

ex(stat)
int stat;
{
    char line[80];
    sprintf(line, "    exit stat %d\n",stat);
    write(1,line,strlen(line));
}
 
#endif

	
bios2()
{
    char c;
    char *ptr;

    switch (call)
    {

	case 0:
	_exit();

	case 1:
	case 3:
	conin:
	read(0,&c,1);
	if (c == '\n')
	    c = '\r';
	return(c);

	case 2:
	case 4:
	conout:
	if (arg == '\r')
	    return(0);
	c = arg;
	write(1,&c,1);
	break;

	case 5:
	if (arg == '\r')
	    return(0);
	c = arg;
	write(2,&c,1);
	break;
	
	case 6:
	if (arg == -1)
	    goto conin;
	goto conout;

	case 7:
	case 8:
	break;

	case 9:
	ptr = (char *)arg;
	while (*ptr != '$')
	{
	    if (*ptr != '\r')
		write(1,ptr,1);
	    ++ptr;
	}
	break;

	case 10:
	rdbuf(arg);
	break;

	case 11:
	break;

	case 12:
	break;

	case 13:
	case 14:
	break;

	case 15:
	return(openfile(arg));

	case 16:
	return(closefile(arg));

	case 17:
	case 18:
	return(255);

	case 19:
	return(delete(arg));

	case 20:
	return(readfile(arg));

	case 21:
	return (writefile(arg));

	case 22:
	return(makefile(arg));

	case 23:
	return(rename(arg));

	case 24:
	return (1);

	case 25:
	break;

	case 26:
	dmaadr = (char *)arg;
	break;

	default:
	break;

    }

    return(0);
}



char *
getname(blk)
struct fcb *blk;
{
    int j;
    static char name[16];
    char *p;

    p = name;
    for (j=0; j<8; ++j)
    {
	if (!blk->name[j] || blk->name[j] == ' ')
	    break;

	*p++ = chlower(blk->name[j]);
    }

    *p++ = '.';

    for (j=0; j<3; ++j)
    {
	if (!blk->ext[j] || blk->ext[j] == ' ')
	    break;

	*p++ = chlower(blk->ext[j]);
    }

    *p = '\0';

    return(name);
}


openfile(blk)
struct fcb *blk;
{
    int desc;

    desc = open(getname(blk), 2);

    if (desc == -1)
	return (255);

    blk->desc = desc;
    return (0);
}


makefile(blk)
struct fcb *blk;
{
    int desc;

    desc = creat(getname(blk), 0666);

    if (desc == -1)
	return (255);

    blk->desc = desc;
    return (0);
}


closefile(blk)
struct fcb *blk;
{
    if (close(blk->desc) == -1)
 	return(255);

    return(0);
}


delete(blk)
struct fcb *blk;
{
    if (unlink(getname(blk)) == -1)
 	return(255);

    return(0);
}

rename(blk)
struct fcb *blk;
{
    static char cmd[40];

    strcpy(cmd, "mv ");
    strcat(cmd, getname(blk));
    strcat(cmd, " ");
    strcat(cmd, getname( (struct fcb *)&(blk->desc)));
    system(cmd);
    return(0);
}


readfile(blk)
struct fcb *blk;
{
    int nread;
    int j;

    nread = read(blk->desc, dmaadr, 128);
    if (nread == -1)
 	return (255);

    if (nread < 128)
	dmaadr[nread] = 0x1a;

    for (j=0; j < nread; ++j)
    {
	if (dmaadr[j] == '\n')
	    dmaadr[j] = '\r';
    }
    return(0);
}


writefile(blk)
struct fcb *blk;
{
    if (write(blk->desc, dmaadr, 128) != 128)
	return(255);

    return(0);
}



rdbuf(arg)
char *arg;
{
    int nread;

    nread = read(0, arg+2, *arg & 0xff);
    --nread;  /* Forget about newline */
    arg[nread+2] = '\0';   /* Remove newline */
    arg[1] = nread;
}


_main(argc, argv)
int argc;
char *argv[];
{
    char *p;
    char *q;

#ifdef DEBUG
    write(1,"Start\n",6);
#endif

    p = (char *)0x80;

    if (argc == 1)
    {
 	*p = 0;
    }
    else
    {
	*p++ = strlen(argv[1])+1;
        *p++ = ' ';
    
        q = argv[1];
        for (q=argv[1]; q < argv[1] + 125; ++q)
        {
	    *p++ = chupper(*q);
	    if (!*q)
	        break;
    	}
    }

    dmaadr = (char *)0x80;

#asm 8080
    MVI	A,0C3H
    STA 0000
    STA 0005
    LXI H,done?
    SHLD 0001

    LXI	H, ENTRY
    SHLD 6
    SPHL

    LXI H,010AH	;specific to m80
    JMP 438FH
#endasm
    
}


done()
{
    _exit(0);
}
