#include <dos.h>
#include <dpmi.h>
#include <string.h>
#include <stdio.h>
#include <time.h>
#include <libp.h>

static unsigned getdta(void)
{
	DPMI_REGS regs;
	regs.b.ah = 0x2f;
	regs.h.flags = 0x72;
	regs.h.ss = 0;
	regs.h.sp = 0;
	dpmi_simulate_real_interrupt(0x21,&regs);
	return (regs.h.es << 16) + regs.h.bx;

}
static void setdta(unsigned dta)
{
	DPMI_REGS regs;
	regs.b.ah = 0x1a;
	regs.h.flags = 0x72;
	regs.h.ss = 0;
	regs.h.sp = 0;
	regs.h.ds = dta >> 16;
	regs.h.dx = dta & 0xffff;
	dpmi_simulate_real_interrupt(0x21,&regs);
}
int bdos(int func, unsigned regdx, int regal)
{
	DPMI_REGS regs;
	regs.b.ah = func;
	regs.b.al = regal;
	regs.h.dx = regdx;
	regs.h.flags = 0x72;
	regs.h.ss = 0;
	regs.h.sp = 0;
	dpmi_simulate_real_interrupt(0x21,&regs);
	return regs.b.al;
}
int _dos_getdrive(int *drive)
{
	DPMI_REGS regs;
	regs.b.ah = 0x19;
	regs.h.flags = 0x72;
	regs.h.ss = 0;
	regs.h.sp = 0;
	dpmi_simulate_real_interrupt(0x21,&regs);

	*drive = regs.b.al+1;
	return 0;
}
int _dos_setdrive(int drive, int *numdrives)
{
	DPMI_REGS regs;
	regs.b.ah = 0x0e;
	regs.b.dl = drive;
	regs.h.flags = 0x72;
	regs.h.ss = 0;
	regs.h.sp = 0;
	dpmi_simulate_real_interrupt(0x21,&regs);
	
}
int _dos_getpwd(char *buf, int drive)
{
	DPMI_REGS regs;
	SELECTOR sel,para;
	if (dpmi_alloc_real_memory(&sel,&para,0x5))
		return 8;
	regs.b.ah = 0x47;
	regs.h.flags = 0x72;
	regs.h.ss = 0;
	regs.h.sp = 0;
	regs.h.ds = para;
	regs.h.dx = drive;
	regs.h.si = 0;
	dpmi_simulate_real_interrupt(0x21,&regs);
	dpmi_copy_to_ds(buf,sel,0,65);
	dpmi_dealloc_real_memory(sel);
	return strlen(buf);
}
int _dos_setpwd(char *buf)
{
	DPMI_REGS regs;
	SELECTOR sel,para;
	if (dpmi_alloc_real_memory(&sel,&para,0x8))
		return 8;
	dpmi_copy_from_ds(sel,0,buf,strlen(buf)+1);
	regs.b.ah = 0x3b;
	regs.h.flags = 0x72;
	regs.h.ss = 0;
	regs.h.sp = 0;
	regs.h.ds = para;
	regs.h.dx = 0;
	dpmi_simulate_real_interrupt(0x21,&regs);
	dpmi_dealloc_real_memory(sel);
	return 0;
}
int _dos_findfirst(char *string, int attr, struct find_t *buf)
{
	DPMI_REGS regs;
	SELECTOR sel,para;
	SELECTOR nsel,npara;
	long dta = getdta();
	if (dpmi_alloc_real_memory(&sel,&para,0x3))
		return 8;
	if (dpmi_alloc_real_memory(&nsel,&npara,0x8)) {
		dpmi_dealloc_real_memory(sel);
		return 8;
	}
	setdta((long)para << 16);
	dpmi_copy_from_ds(nsel,0,string,strlen(string)+1);
	regs.b.ah = 0x4e;
	regs.h.flags = 0x72;
	regs.h.ss = 0;
	regs.h.sp = 0;
	regs.h.ds = npara;
	regs.h.dx = 0;
	regs.h.cx = attr;
	dpmi_simulate_real_interrupt(0x21,&regs);
	dpmi_copy_to_ds(buf,sel,0,48);
	dpmi_dealloc_real_memory(sel);
	dpmi_dealloc_real_memory(nsel);
	setdta(dta);
	if (regs.h.flags & 1)
		return regs.b.al;
	else
		return 0;
}
int _dos_findnext(struct find_t *buf)
{
	DPMI_REGS regs;
	SELECTOR sel,para;
	long dta = getdta();
	if (dpmi_alloc_real_memory(&sel,&para,0x3))
		return 8;
	setdta((long)para << 16);
	dpmi_copy_from_ds(sel,0,buf,48);
	regs.b.ah = 0x4f;
	regs.h.flags = 0x72;
	regs.h.ss = 0;
	regs.h.sp = 0;
	dpmi_simulate_real_interrupt(0x21,&regs);
	dpmi_copy_to_ds(buf,sel,0,48);
	dpmi_dealloc_real_memory(sel);
	setdta(dta);
	if (regs.h.flags & 1)
		return regs.b.al;
	else
		return 0;
}
unsigned _dos_open(char *name,int mode, int *fd)
{
	*fd = _ll_open(name,mode);
	if (*fd == 0)
		return 2;
	return 0;
}
unsigned _dos_close(int fd)
{
	_ll_close(fd);
	return 0;
}
unsigned _dos_setftime(int fd, unsigned short date, unsigned short time)
{
	DPMI_REGS regs;
	regs.b.al = 1;
	regs.h.bx = fd;
	regs.h.cx = time;
	regs.h.dx = date;
	if (!__doscall(0x57,&regs))
		return 2;
	return 0;
}
unsigned _dos_getftime(int fd, unsigned short *date, unsigned short *time)
{
	DPMI_REGS regs;
	regs.b.al = 0;
	regs.h.bx = fd;
	if (!__doscall(0x57,&regs))
		return 2;
	
	*date = regs.h.dx;
	*time = regs.h.cx;
	return 0;
}