#include <stdio.h>
#include <conio.h>
#include <alloc.h>
#include <dos.h>
#include <ctype.h>

typedef struct _PART_ENTRY_
{
  unsigned char flag;
  unsigned char beg_head;
  unsigned beg_sec_cyl;
  unsigned char sys;
  unsigned char end_head;
  unsigned end_sec_cyl;
  unsigned long rel_sec;
  unsigned long size;
} PART_ENTRY;

typedef struct _MBOOT_
{
  char boot_prg[0x1be];
  PART_ENTRY part_table[4];
  unsigned char signature[2];
} MBOOT;

typedef struct _EBPB_
{
  unsigned int sectsize;
  char clustsize;
  unsigned int ressecs;
  char fatcnt;
  unsigned int rootsize;
  unsigned int totsecs;
  char media;
  unsigned int fatsize;
  unsigned int seccnt;
  unsigned int headcnt;
  unsigned int hiddensec_low;
  unsigned int hiddensec_hi;
  unsigned long drvsecs;
} EBPB;

typedef struct _BOOT_
{
  char jmp[3];
  char oem[8];
  EBPB bpb;
  char drive;
  char reserved;
  char signature;
  unsigned volser_lo;
  unsigned volser_hi;
  char label[11];
  char fat_format[8];
  char boot_code[450];
} BOOT;

typedef struct _FTIME_
{
  unsigned sec : 5, min : 6, hour : 5;
} FTIME;

typedef struct _FDATE_
{
  unsigned day : 5, month : 4, year : 7;
} FDATE;

typedef struct _FITEM_
{
  char name[8];
  char ext[3];
  char attr;
  char reserved[10];
  FTIME time;
  FDATE date;
  unsigned cluster_nu;
  unsigned long size;
} FITEM;

union REGS reg;
struct SREGS segreg;

struct {
  unsigned long first_sect;
  unsigned nsect;
  void far* buf;
} cb;

int main(void) {
  int i, k;
  int  root_begin;
  unsigned long filecluster, filesector, tmp, fat[128];
  unsigned char root_heads,root_sectors,root_cycl;
  unsigned char fat_heads, fat_sectors, fat_cycl;
  char drive = 'c';
  char boot[512];
  BOOT far* boot_rec = (BOOT far*) boot;
  BOOT b;
  FITEM *root_buffer, far *rptr;
  MBOOT mb;
  unsigned long start;
  system("cls");
  reg.h.ah = 2;
  reg.h.dl = 0x80;
  reg.h.dh = 0;
  reg.h.ch = 0;
  reg.h.cl = 1;
  reg.h.al = 1;
  segreg.es = FP_SEG(&mb);
  reg.x.bx = FP_OFF(&mb);
  int86x(0x13,&reg,&reg,&segreg);
  start = mb.part_table[0].rel_sec;

  reg.h.ah = 2;
  reg.h.al = 1;
  reg.h.dh = 1;
  reg.h.dl = 0x80;
  reg.x.cx = 1;
  segreg.es = FP_SEG(boot);
  reg.x.bx = FP_OFF(boot);

  int86x(0x13,&reg,&reg,&segreg);

  if(reg.x.cflag) {
    printf("\nerror1");
    system("pause");
    return(-1);
  }

  root_begin = start + *((int*)&boot[0x0e]) + *((int*)&boot[0x24]) * *((char*)&boot[0x10]);
  root_cycl =     root_begin / ( *((int*)&boot[0x18]) * *((int*)&boot[0x1a]) );
  root_heads =   (root_begin % ( *((int*)&boot[0x18]) * *((int*)&boot[0x1a]) ) / *((int*)&boot[0x18]) );
  root_sectors = (root_begin % ( *((int*)&boot[0x18]) * *((int*)&boot[0x1a]) ) % *((int*)&boot[0x18]) + 1 );
  root_buffer = (FITEM *) malloc(512);
  if(root_buffer == NULL) {
    printf("\nout of memery");
    system("pause");
    return(-1);
  }



  reg.h.ah = 2;
  reg.h.al = 1;
  reg.h.ch = root_cycl;
  reg.h.cl = root_sectors;
  reg.h.dh = root_heads;
  reg.h.dl = 0x80;
  segreg.ds = FP_SEG(root_buffer);
  reg.x.bx = FP_OFF(root_buffer);

  int86x(0x13,&reg,&reg,&segreg);
  printf("\n"
    "\nFilename    Attr.   Date      Time     Cluster    Size"
    "\n------------------------------------------------------");
    rptr = root_buffer;
    printf("\n");
  for(k = 0; k < 16; k++) {
    if(rptr->name[0] == 0 ||
       rptr->name[0] == (char)0xF6) break;
    if(k==10){
    for(i=0; i<8; i++)
      printf("%c",rptr->name[i]);
    printf(".");
    for(i=0; i<3; i++)
      printf("%c",rptr->ext[i]);

    printf(" %d    %02d-%02d-%02d  %02d:%02d:%02d ",
      rptr->attr, rptr->date.day,
      rptr->date.month, rptr->date.year + 1980,
      rptr->time.hour, rptr->time.min,
      rptr->time.sec * 2);

    printf(" %-6lx   %lu",
      (long)rptr->cluster_nu, (long)rptr->size);
    filecluster = (long) rptr->cluster_nu;
    }
    rptr++;

  }

  printf("\n\nSectors:\n%lx --> ", filecluster);


  do {
      filesector = (filecluster / 128);
      tmp = start + *((int*)&boot[0x0e]) + filesector;
      fat_cycl    = tmp / ( *((int*)&boot[0x18]) * *((int*)&boot[0x1a]) );
      fat_heads  = (tmp % ( *((int*)&boot[0x18]) * *((int*)&boot[0x1a]) ) ) / *((int*)&boot[0x18]);
      fat_sectors= (tmp % ( *((int*)&boot[0x18]) * *((int*)&boot[0x1a]) ) ) % *((int*)&boot[0x18]) + 1;
      reg.h.ah = 2;
      reg.h.dl = 0x80;
      reg.h.dh = fat_heads;
      reg.x.cx = (fat_cycl << 8) + ((fat_cycl&0x300) >> 2) + fat_sectors;
      reg.h.al = 1;
      segreg.es = FP_SEG(fat);
      reg.x.bx = FP_OFF(fat);
      int86x(0x13,&reg,&reg,&segreg);
      filecluster = fat[(filecluster%128)];
      if(filecluster != 0xfffffff)
		printf("%lx --> ", filecluster);
      else
		printf("EOF\n");
      } while (filecluster < 0xfffffff);


  free(root_buffer);
  system("pause");
  return 0;
}
