/*

fat_dpb.c -- FATとDPBの操作関数

*/

#include<stdio.h>
#include<dos.h>
#include<ctype.h>
#include<process.h>
#include<farstr.h>
#include"dmove86.h"

extern	struct DPB	Dpb;
extern	int		Drive;
extern	unsigned int	Fatsize;

int	getdpb(void)
{	union REGS	regs;
	struct SREGS	seg;

	regs.h.ah = 0x32;
	regs.h.dl = Drive + 1;
	int86x(0x21,&regs,&regs,&seg);

	if	(regs.h.al == 0xff)
		return -1;

	Dpb = *(struct DPB far *)MK_FP(seg.ds, regs.x.bx);

	Fatsize = (Dpb.data_sec - Dpb.iplsectors
			- Dpb.root_entry/(Dpb.seclen >> 5)) / Dpb.fatnum;

#ifdef	DEBUG
	printf("FAT size = %u\n",Fatsize);
#endif

	return 0;
}

unsigned far	*getfat(void)
{
	unsigned int	af;
	unsigned int	pos;

	char far	*buf;

	buf = (char far *)farmalloc((unsigned long)Dpb.seclen * Fatsize);

	if	(buf == 0) 
	{
#ifdef	DEBUG
		printf("Not enough memory for malloc()\n");
#endif
		return 0 ;
	}

	for (pos=0 ; pos<Fatsize ; pos++)
	{
		af = rdabssec((void far *)(buf + pos*Dpb.seclen),
				Dpb.iplsectors+pos,Drive);
#ifdef	DEBUG
		printf("AF=%4x\n",af);
#endif
	}

	if	(Dpb.maxclu < 0xff7)
	{	/* 12ビットFAT */

		unsigned far 	*fat;

		fat=(unsigned far *)farmalloc
				((Dpb.maxclu+2) * sizeof(unsigned));

		if	(fat == 0)
		{
			farfree(buf);
			return 0;
		}

		for	(pos=0 ; pos < Dpb.maxclu/2 ; pos++)
		{
			fat[pos*2  ] = buf[pos*3  ]+ (buf[pos*3+1]&0x0f) * 256;
			fat[pos*2+1] = buf[pos*3+1]/16	+ buf[pos*3+2]*16;

			if	(fat[pos*2  ] > 0xff6)	fat[pos*2  ] |= 0xf000;
			if	(fat[pos*2+1] > 0xff6)	fat[pos*2+1] |= 0xf000;
		}
		farfree(buf);
		return (fat);
	}

	else 	return (unsigned far *)buf;
}
