#include "fat12.h"
#include "mode16.h"
#include "graph16.h"
#include "math.h"
#include "type.h"
FAT_ENTRY far * root=MK_FP(0x220,0);
BS_FAT12 far* boot=MK_FP(0x7c0,0);
BYTE far * fat=MK_FP(0x100,0);
// retrouve une entree dans le dossier root
int find_entry(char *c)
{
int i,j;
for(i=0;i<224;i++)
{
for(j=0;j<11;j++)
{
if(c[j]!=root[i].Name[j])
break;
}
if(j>=11)
break;
}
if(i>=224)
return -1;
else
return i;
}
// Lit un secteur LBA
BYTE read_sector(WORD lba,char far* buffer)
{
WORD c,h,s;
c=lba/18;
if(c%2==0)
{
h=0;
c=(WORD)c/2;
}
else
{
h=1;
c=(WORD)(c-1)/2;
}
s=(WORD)(lba%18)+1;
return read_sector_chs((BYTE)c,(BYTE)h,(BYTE)s,buffer);
}
// lit un secteur de disquette
BYTE read_sector_chs(BYTE cylinder,BYTE head,BYTE sector,char far* buffer)
{
BYTE err,drive;
drive=boot->DriveNumber;
asm{
les bx,buffer;
mov ax,0x0201;
mov dl,drive;
mov dh,head;
mov ch,cylinder;
mov cl,sector;
int 0x13;
mov err,ah;
}
return err;
}
WORD get_next_sector(WORD sector)
{
WORD next = 0;
WORD index=(sector*3)/2;
if(sector%2)
{
next=fat[index+1];
next<<=4;
next|=fat[index]>>4;
}
else
{
next=fat[index+1]&0x0F;
next<<=8;
next|=fat[index];
}
return next;
}
int get_max_sectors(WORD sect)
{
int result=1;
while((sect=get_next_sector(sect))<0xFF8)
result++;
return result;
}
struct
{
WORD size;
WORD a_0_15;
BYTE a_16_23;
BYTE flag;
WORD reserved;
}temp_gdt[6]={{0,0,0,0,0},
{0,0,0,0,0},
{0xFFFF,0x0000,0x02,0x93,0},
{0xFFFF,0x0000,0x10,0x93,0},
{0,0,0,0,0},
{0,0,0,0,0}};
BYTE move_block(BYTE off,WORD size)
{
BYTE err;
temp_gdt[3].a_16_23=off;
asm{
mov ax,ds;
mov es,ax;
mov si,offset temp_gdt;
mov ah,0x87;
mov cx,size;
int 0x15;
mov err,ah;
}
return err;
}
int load_12()
{
WORD sect,nmax,n=0;
int index;
char far*buffer=(char far*)MK_FP(0x2000,0);
DWORD far* kernel_size=(DWORD far*)MK_FP(0x2000,0);
BYTE offset=0x10;
if((index=find_entry("KERNEL BIN"))==-1)
return-1;
sect=root[index].ClusterLow;
nmax=get_max_sectors(sect);
gotoxy(0,21);
print_text("Chargement du system");
while(n<nmax)
{
if(read_sector(sect+31,buffer))
return -1;
n++;
buffer+=512;
if(n%128==0)
{
if(move_block(offset,0x8000))
return -1;
offset++;
}
draw_bar(ldiv(lmul(n,100),nmax));
if((sect=get_next_sector(sect))>=0xFF8)
{
if(n%128)
move_block(offset,FP_OFF(buffer)/2);
break;
}
}
*kernel_size=root[index].Size;
return 0;
}