-Moved cflash.* and fat.h to main source directory since they're not port-specific code.

-Adjusted makefiles and other sourcefiles accordingly
This commit is contained in:
cyberwarriorx 2006-10-12 16:58:00 +00:00
parent b6e940d480
commit debc860a76
5 changed files with 790 additions and 2 deletions

View File

@ -27,7 +27,7 @@
#include "debug.h"
#include "NDSSystem.h"
#include "windows/cflash.h"
#include "cflash.h"
#include "nds/interrupts.h"
#include "nds/video.h"

View File

@ -12,6 +12,6 @@ libdesmume_a_SOURCES = \
mc.c mc.h \
arm9/GPU.c arm9/GPU.h \
arm9/ARM9.c arm9/ARM9.h \
windows/cflash.c windows/cflash.h fs.h \
cflash.c cflash.h fs.h \
saves.c saves.h
libdesmume_a_LIBADD = fs-$(desmume_arch).$(OBJEXT)

689
desmume/src/cflash.c Normal file
View File

@ -0,0 +1,689 @@
/*
CFLASH.C
CompactFlash/FAT emulation routines for DeSmuME
/Mic, 2006
Portability note: Uses some Win32 API calls, e.g. FindNextFile,
which would have to be replaced for other operating systems.
Logical memory layout:
----------------------
| MBR |
----------------------
| FAT |
----------------------
| Root entries |
----------------------
| Subdirectories |
----------------------
| File data |
----------------------
*/
#include "fs.h"
#include "cflash.h"
#include "NDSSystem.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define SECPERFAT 128
#define SECPERCLUS 16
#define MAXFILES 32768
#define SECRESV 2
#define NUMSECTORS 0x80000
#define NUMCLUSTERS (NUMSECTORS/SECPERCLUS)
#define BYTESPERCLUS (512*SECPERCLUS)
#define DIRENTSPERCLUS ((BYTESPERCLUS)/32)
u16 cf_reg_data,cf_reg_err,cf_reg_sec,cf_reg_lba1,cf_reg_lba2,
cf_reg_lba3,cf_reg_lba4,cf_reg_cmd,cf_reg_sts;
unsigned int CF_REG_DATA,CF_REG_ERR,CF_REG_SEC,CF_REG_LBA1,CF_REG_LBA2,
CF_REG_LBA3,CF_REG_LBA4,CF_REG_CMD,CF_REG_STS;
BOOT_RECORD MBR;
DIR_ENT *files,*dirEntries,**dirEntryPtr;
FILE_INFO *fileLink,*dirEntryLink;
u32 currLBA;
u32 filesysFAT,filesysRootDir,filesysData;
u16 FAT16[SECPERFAT*256];
u16 numExtraEntries[SECPERFAT*256];
DIR_ENT *extraDirEntries[SECPERFAT*256];
int numFiles,fileLevel,maxLevel,dirNum,numRootFiles;
int *dirEntriesInCluster,clusterNum,
firstDirEntCluster,lastDirEntCluster,
lastFileDataCluster;
char *sRomPath;
int activeDirEnt=-1;
u32 bufferStart;
u32 fileStartLBA,fileEndLBA;
u16 freadBuffer[256];
u32 dwBytesRead;
FILE * hFile;
char fpath[255+1];
BOOL cflashDeviceEnabled = FALSE;
char buffer[256];
u32 dummy;
int lfn_checksum() {
int i;
u8 chk;
chk = 0;
for (i=0; i < 11; i++) {
chk = ((chk & 1) ? 0x80 : 0) + (chk >> 1) + (i < 8 ? files[numFiles].name[i] : files[numFiles].ext[i - 8]);
}
return chk;
}
const int lfnPos[13] = {1,3,5,7,9,14,16,18,20,22,24,28,30};
/* Add a DIR_ENT for the files */
void add_file(char *fname, FsEntry * entry) {
int i,j,k,n;
u8 chk;
char *p;
if (numFiles < MAXFILES-1) {
if (strcmp(fname,"..") != 0) {
for (i=strlen(fname)-1; i>=0; i--)
if (fname[i]=='.') break;
if ((i==0)&&(strcmp(fname,".")==0)) i = 1;
if (i<0) i = strlen(fname);
for (j=0; j<i; j++)
files[numFiles].name[j] = fname[j];
for (; j<8; j++)
files[numFiles].name[j] = 0x20;
for (j=0; j<3; j++) {
if ((j+i+1)>=strlen(fname)) break;
files[numFiles].ext[j] = fname[j+i+1];
}
for (; j<3; j++)
files[numFiles].ext[j] = 0x20;
fileLink[maxLevel * ((fileLevel>0)?1:0)].filesInDir += 1;
// See if LFN entries need to be added
if (strlen(entry->cAlternateFileName)>0) {
chk = lfn_checksum();
k = (strlen(entry->cFileName)/13) + (((strlen(entry->cFileName)%13)!=0)?1:0);
numFiles += k;
fileLink[maxLevel * ((fileLevel>0)?1:0)].filesInDir += k;
n = 0;
j = 13;
for (i=0; i<strlen(entry->cFileName); i++) {
if (j == 13) {
n++;
p = (char*)&files[numFiles-n].name[0];
fileLink[numFiles-n].parent = maxLevel * ((fileLevel>0)?1:0);
p[0] = n;
((DIR_ENT*)p)->attrib = ATTRIB_LFN;
p[0xD] = chk;
j = 0;
}
*(p + lfnPos[j]) = entry->cFileName[i];
*(p + lfnPos[j]+1) = 0;
j++;
}
for (; j<13; j++) {
*(p + lfnPos[j]) = entry->cFileName[i];
*(p + lfnPos[j]+1) = 0;
}
p[0] |= 0x40; // END
for (i=strlen(fname)-1; i>=0; i--)
if (fname[i]=='.') break;
if ((i==0)&&(strcmp(fname,".")==0)) i = 1;
if (i<0) i = strlen(fname);
for (j=0; j<i; j++)
files[numFiles].name[j] = fname[j];
for (; j<8; j++)
files[numFiles].name[j] = 0x20;
for (j=0; j<3; j++) {
if ((j+i+1)>=strlen(fname)) break;
files[numFiles].ext[j] = fname[j+i+1];
}
for (; j<3; j++)
files[numFiles].ext[j] = 0x20;
}
//files[numFiles].fileSize = entry->nFileSizeLow;
files[numFiles].fileSize = 0;
if (entry->flags & FS_IS_DIR) {
if (strcmp(fname,".")==0)
fileLink[numFiles].level = maxLevel;
else
fileLink[numFiles].level = maxLevel+1;
files[numFiles].attrib = ATTRIB_DIR;
} else {
files[numFiles].attrib = 0;
}
fileLink[numFiles].parent = maxLevel * ((fileLevel>0)?1:0);
numFiles++;
} else if (fileLevel > 0) {
fileLink[maxLevel * ((fileLevel>0)?1:0)].filesInDir += 1;
strncpy((char*)&files[numFiles].name[0],".. ",8);
strncpy((char*)&files[numFiles].ext[0]," ",3);
fileLink[numFiles].parent = maxLevel * ((fileLevel>0)?1:0);
files[numFiles].attrib = 0x10;
numFiles++;
}
}
}
/* List all files and subdirectories recursively */
void list_files(char *fpath) {
void * hFind;
FsEntry entry;
char DirSpec[255 + 1],SubDir[255+1],fnameu[256];
u32 dwError;
char *fname;
int i,j;
fileLevel++;
maxLevel++;
strncpy(DirSpec, fpath, strlen(fpath)+1);
hFind = FsReadFirst(DirSpec, &entry);
if (hFind == NULL) {
return;
} else {
fname = (strlen(entry.cAlternateFileName)>0)?entry.cAlternateFileName:entry.cFileName;
strcpy(fnameu,fname);
//strupr(fnameu);
add_file(fnameu,&entry);
while (FsReadNext(hFind, &entry) != 0) {
fname = (strlen(entry.cAlternateFileName)>0)?entry.cAlternateFileName:entry.cFileName;
strcpy(fnameu,fname);
//strupr(fnameu);
add_file(fnameu,&entry);
if (numFiles==MAXFILES-1) break;
if ((entry.flags & FS_IS_DIR)&&
(fname[0] != '.')) {
//sprintf(SubDir,"%s\\%s",fpath,fname);
sprintf(SubDir,"%s%c%s",fpath,FS_SEPARATOR,fname);
list_files(SubDir);
}
}
dwError = FsError();
FsClose(hFind);
if (dwError != FS_ERR_NO_MORE_FILES) {
return;
}
}
if (numFiles < MAXFILES) {
fileLink[numFiles].parent = maxLevel * ((fileLevel>0)?1:0);
files[numFiles++].name[0] = 0;
}
fileLevel--;
}
/* Set up the MBR, FAT and DIR_ENTs */
BOOL cflash_build_fat() {
int i,j,k,l,
clust,baseCluster,numClusters,
clusterNum2,rootCluster;
numFiles = 0;
fileLevel = -1;
maxLevel = -1;
sRomPath = szRomPath; // From MMU.cpp
files = (DIR_ENT *) malloc(MAXFILES*sizeof(DIR_ENT));
fileLink = (FILE_INFO *) malloc(MAXFILES*sizeof(FILE_INFO));
if ((files == NULL) || (fileLink == NULL))
return FALSE;
for (i=0; i<MAXFILES; i++) {
files[i].attrib = 0;
files[i].name[0] = FILE_FREE;
files[i].fileSize = 0;
fileLink[i].filesInDir = 0;
extraDirEntries[i] = NULL;
numExtraEntries[i] = 0;
}
list_files(sRomPath);
//wsprintf(buffer,"Found %d files\n",numFiles);
//WriteConsole(hStdOut,buffer,lstrlen(buffer),(u32*)&dummy,NULL);
k = 0;
clusterNum = rootCluster = (SECRESV + SECPERFAT)/SECPERCLUS;
numClusters = 0;
clust = 0;
numRootFiles = 0;
// Allocate memory to hold information about the files
dirEntries = (DIR_ENT *) malloc(numFiles*sizeof(DIR_ENT));
dirEntryLink = (FILE_INFO *) malloc(numFiles*sizeof(FILE_INFO));
dirEntriesInCluster = (int *) malloc(NUMCLUSTERS*sizeof(int));
dirEntryPtr = (DIR_ENT **) malloc(NUMCLUSTERS*sizeof(DIR_ENT*));
if ((dirEntries==NULL) || (dirEntriesInCluster==NULL) || (dirEntryPtr==NULL))
return FALSE;
for (i=0; i<NUMCLUSTERS; i++) {
dirEntriesInCluster[i] = 0;
dirEntryPtr[i] = NULL;
}
// Change the hierarchical layout to a flat one
for (i=0; i<=maxLevel; i++) {
clusterNum2 = clusterNum;
for (j=0; j<numFiles; j++) {
if (fileLink[j].parent == i) {
if (dirEntryPtr[clusterNum] == NULL)
dirEntryPtr[clusterNum] = &dirEntries[k];
dirEntryLink[k] = fileLink[j];
dirEntries[k++] = files[j];
if ((files[j].attrib & ATTRIB_LFN)==0) {
if (files[j].attrib & ATTRIB_DIR) {
if (strncmp((char*)&files[j].name[0],". ",8)==0) {
dirEntries[k-1].startCluster = dirEntryLink[k-1].level;
} else if (strncmp((char*)&files[j].name[0],".. ",8)==0) {
dirEntries[k-1].startCluster = dirEntryLink[k-1].parent;
} else {
clust++;
dirEntries[k-1].startCluster = clust;
l = (fileLink[fileLink[j].level].filesInDir)>>8;
clust += l;
numClusters += l;
}
} else {
dirEntries[k-1].startCluster = clusterNum;
}
}
if (i==0) numRootFiles++;
dirEntriesInCluster[clusterNum]++;
if (dirEntriesInCluster[clusterNum]==256) {
clusterNum++;
}
}
}
clusterNum = clusterNum2 + ((fileLink[i].filesInDir)>>8) + 1;
numClusters++;
}
// Free the file indexing buffer
free(files);
free(fileLink);
// Set up the MBR
MBR.bytesPerSector = 512;
MBR.numFATs = 1;
strcpy((char*)&MBR.OEMName[0],"DESMUM");
strcpy((char*)&MBR.fat16.fileSysType[0],"FAT16 ");
MBR.reservedSectors = SECRESV;
MBR.numSectors = 524288;
MBR.numSectorsSmall = 0;
MBR.sectorsPerCluster = SECPERCLUS;
MBR.sectorsPerFAT = SECPERFAT;
MBR.rootEntries = 512;
MBR.fat16.signature = 0xAA55;
MBR.mediaDesc = 1;
filesysFAT = 0 + MBR.reservedSectors;
filesysRootDir = filesysFAT + (MBR.numFATs * MBR.sectorsPerFAT);
filesysData = filesysRootDir + ((MBR.rootEntries * sizeof(DIR_ENT)) / 512);
// Set up the cluster values for all subdirectories
clust = filesysData / SECPERCLUS;
firstDirEntCluster = clust;
for (i=1; i<numFiles; i++) {
if (((dirEntries[i].attrib & ATTRIB_DIR)!=0) &&
((dirEntries[i].attrib & ATTRIB_LFN)==0)) {
if (dirEntries[i].startCluster > rootCluster)
dirEntries[i].startCluster += clust-rootCluster;
}
}
lastDirEntCluster = clust+numClusters-1;
// Set up the cluster values for all files
clust += numClusters; //clusterNum;
for (i=0; i<numFiles; i++) {
if (((dirEntries[i].attrib & ATTRIB_DIR)==0) &&
((dirEntries[i].attrib & ATTRIB_LFN)==0)) {
dirEntries[i].startCluster = clust;
clust += (dirEntries[i].fileSize/(512*SECPERCLUS));
clust++;
}
}
lastFileDataCluster = clust-1;
// Set up the FAT16
memset(FAT16,0,SECPERFAT*256*sizeof(u16));
FAT16[0] = 0xFF01;
FAT16[1] = 0xFFFF;
for (i=2; i<=lastDirEntCluster; i++)
FAT16[i] = 0xFFFF;
k = 2;
for (i=0; i<numFiles; i++) {
if (((dirEntries[i].attrib & ATTRIB_LFN)==0) &&
(dirEntries[i].name[0] != FILE_FREE)) {
j = 0;
l = dirEntries[i].fileSize - (512*SECPERCLUS);
while (l > 0) {
if (dirEntries[i].startCluster+j < MAXFILES)
FAT16[dirEntries[i].startCluster+j] = dirEntries[i].startCluster+j+1;
j++;
l -= (512*16);
}
if ((dirEntries[i].attrib & ATTRIB_DIR)==0) {
if (dirEntries[i].startCluster+j < MAXFILES)
FAT16[dirEntries[i].startCluster+j] = 0xFFFF;
}
k = dirEntries[i].startCluster+j;
}
}
for (i=(filesysData/SECPERCLUS); i<NUMCLUSTERS; i++) {
if (dirEntriesInCluster[i]==256)
FAT16[i] = i+1;
}
return TRUE;
}
BOOL cflash_init() {
cflashDeviceEnabled = FALSE;
currLBA = 0;
/* Set up addresses for M3CF */
/*CF_REG_DATA = 0x8800000;
CF_REG_ERR = 0x8820000;
CF_REG_SEC = 0x8840000;
CF_REG_LBA1 = 0x8860000;
CF_REG_LBA2 = 0x8880000;
CF_REG_LBA3 = 0x88A0000;
CF_REG_LBA4 = 0x88C0000;
CF_REG_CMD = 0x88E0000;
CF_REG_STS = 0x80C0000;*/
/* Set up addresses for GBAMP */
CF_REG_DATA = 0x9000000;
CF_REG_ERR = 0x9020000;
CF_REG_SEC = 0x9040000;
CF_REG_LBA1 = 0x9060000;
CF_REG_LBA2 = 0x9080000;
CF_REG_LBA3 = 0x90A0000;
CF_REG_LBA4 = 0x90C0000;
CF_REG_CMD = 0x90E0000;
CF_REG_STS = 0x98C0000;
if (activeDirEnt != -1)
fclose(hFile);
activeDirEnt = -1;
fileStartLBA = fileEndLBA = 0xFFFFFFFF;
if (!cflash_build_fat())
return FALSE;
cf_reg_sts = 0x58; // READY
cflashDeviceEnabled = TRUE;
return TRUE;
}
/* Convert a space-padded 8.3 filename into an asciiz string */
void fatstring_to_asciiz(int dirent,char *out,DIR_ENT *d) {
int i,j;
DIR_ENT *pd;
if (d == NULL)
pd = &dirEntries[dirent];
else
pd = d;
for (i=0; i<8; i++) {
if (pd->name[i] == ' ') break;
out[i] = pd->name[i];
}
if ((pd->attrib & 0x10)==0) {
out[i++] = '.';
for (j=0; j<3; j++) {
if (pd->ext[j] == ' ') break;
out[i++] = pd->ext[j];
}
}
out[i] = '\0';
}
/* Resolve the path of a files by working backwards through the directory entries */
void resolve_path(int dirent) {
int i;
char dirname[128];
while (dirEntryLink[dirent].parent > 0) {
for (i=0; i<dirent; i++) {
if ((dirEntryLink[dirent].parent==dirEntryLink[i].level) &&
((dirEntries[i].attrib&ATTRIB_DIR)!=0)) {
fatstring_to_asciiz(i,dirname,NULL);
strcat(fpath,dirname);
strcat(fpath,"\\");
dirent = i;
break;
}
}
}
}
/* Read from a file using a 512 byte buffer */
u16 fread_buffered(int dirent,u32 cluster,u32 offset) {
char fname[32];
int i,j;
offset += cluster*512*SECPERCLUS;
if (dirent == activeDirEnt) {
if ((offset < bufferStart) || (offset >= bufferStart + 512)) {
//SetFilePointer(hFile,offset,NULL,FILE_BEGIN);
fseek(hFile, offset, SEEK_SET);
//ReadFile(hFile,&freadBuffer,512,&dwBytesRead,NULL);
fread(&freadBuffer, 1, 512, hFile);
bufferStart = offset;
}
return freadBuffer[(offset-bufferStart)>>1];
}
if (activeDirEnt != -1)
//CloseHandle(hFile);
fclose(hFile);
strcpy(fpath,sRomPath);
strcat(fpath,"\\");
resolve_path(dirent);
fatstring_to_asciiz(dirent,fname,NULL);
strcat(fpath,fname);
hFile = fopen(fpath, "w");
if (!hFile)
return 0;
fread(&freadBuffer, 1, 512, hFile);
bufferStart = offset;
activeDirEnt = dirent;
fileStartLBA = (dirEntries[dirent].startCluster*512*SECPERCLUS);
fileEndLBA = fileStartLBA + dirEntries[dirent].fileSize;
return freadBuffer[(offset-bufferStart)>>1];
}
/* Read from one of the CF device registers */
unsigned int cflash_read(unsigned int address) {
unsigned char *p;
u16 s;
int i;
u32 cluster,cluster2,cluster3,fileLBA;
//wsprintf(buffer,"Reading from %08X\n",address);
//WriteConsole(hStdOut,buffer,lstrlen(buffer),(u32*)&dummy,NULL);
if (address == CF_REG_STS) {
s = cf_reg_sts;
return s;
} else if (address == CF_REG_DATA) {
cluster = (currLBA / (512 * SECPERCLUS));
cluster2 = (((currLBA/512) - filesysData) / SECPERCLUS) + 2;
if (cf_reg_cmd == 0x20) {
// Reading from the MBR
if (currLBA < 512) {
p = (unsigned char*)&MBR;
s = *(u16 *)(p + currLBA);
// Reading the FAT
} else if ((currLBA >= filesysFAT*512) && (currLBA < filesysRootDir*512)) {
p = (unsigned char*)&FAT16[0];
s = *(u16 *)(p + (currLBA-filesysFAT*512));
// Reading directory entries
} else if ((currLBA >= filesysRootDir*512) &&
(cluster <= lastDirEntCluster)) {
cluster3 = ((currLBA - (SECRESV * 512)) / (512 * SECPERCLUS));
i = (currLBA-(((cluster3-(filesysRootDir/SECPERCLUS))*SECPERCLUS+filesysRootDir)*512)); //(currLBA - cluster*BYTESPERCLUS);
if (i < (dirEntriesInCluster[cluster3]*32)) {
p = (unsigned char*)dirEntryPtr[cluster3];
s = *(u16 *)(p + i);
} else {
i /= 32;
i -= dirEntriesInCluster[cluster3];
if ((i>=0)&&(i<numExtraEntries[cluster3])) {
p = (unsigned char*)extraDirEntries[cluster3];
s = *(u16 *)(p + i*32 + (currLBA&0x1F));
} else if ((currLBA&0x1F)==0) {
s = FILE_FREE;
} else {
s = 0;
}
}
// Reading file data
} else if ((cluster2 > lastDirEntCluster) && (cluster2 <= lastFileDataCluster)) { //else if ((cluster>lastDirEntCluster)&&(cluster<=lastFileDataCluster)) {
fileLBA = currLBA - (filesysData-32)*512; // 32 = # sectors used for the root entries
// Check if the read is from the currently opened file
if ((fileLBA >= fileStartLBA) && (fileLBA < fileEndLBA)) {
cluster = (fileLBA / (512 * SECPERCLUS));
s = fread_buffered(activeDirEnt,cluster-dirEntries[activeDirEnt].startCluster,(fileLBA-fileStartLBA)&(BYTESPERCLUS-1));
} else {
for (i=0; i<numFiles; i++) {
if ((fileLBA>=(dirEntries[i].startCluster*512*SECPERCLUS)) &&
(fileLBA <(dirEntries[i].startCluster*512*SECPERCLUS)+dirEntries[i].fileSize) &&
((dirEntries[i].attrib & (ATTRIB_DIR|ATTRIB_LFN))==0)) {
cluster = (fileLBA / (512 * SECPERCLUS));
s = fread_buffered(i,cluster-dirEntries[i].startCluster,fileLBA&(BYTESPERCLUS-1));
break;
}
}
}
}
currLBA += 2;
return s;
}
} else if (address == CF_REG_CMD) {
s = 0;
return 0;
} else if (address == CF_REG_LBA1) {
s = cf_reg_lba1;
return s;
}
}
/* Write to one of the CF device registers */
void cflash_write(unsigned int address,unsigned int data) {
u32 cluster,cluster2,cluster3,fileLBA;
int i,j,k,l;
unsigned char *p;
u16 s;
DIR_ENT *d;
if (address==CF_REG_STS) {
cf_reg_sts = data&0xFFFF;
} else if (address==CF_REG_DATA) {
} else if (address==CF_REG_CMD) {
cf_reg_cmd = data&0xFF;
cf_reg_sts = 0x58; // READY
} else if (address==CF_REG_LBA1) {
cf_reg_lba1 = data&0xFF;
currLBA = (currLBA&0xFFFFFF00)|cf_reg_lba1;
} else if (address==CF_REG_LBA2) {
cf_reg_lba2 = data&0xFF;
currLBA = (currLBA&0xFFFF00FF)|(cf_reg_lba2<<8);
} else if (address==CF_REG_LBA3) {
cf_reg_lba3 = data&0xFF;
currLBA = (currLBA&0xFF00FFFF)|(cf_reg_lba3<<16);
} else if (address==CF_REG_LBA4) {
cf_reg_lba4 = data&0xFF;
currLBA = (currLBA&0x00FFFFFF)|((cf_reg_lba4&0x0F)<<24);
currLBA *= 512;
}
}
void cflash_close() {
int i;
if (cflashDeviceEnabled) {
cflashDeviceEnabled = FALSE;
for (i=0; i<MAXFILES; i++) {
if (extraDirEntries[i] != NULL)
free(extraDirEntries[i]);
}
if (dirEntries != NULL)
free(dirEntries);
if (dirEntryLink != NULL)
free(dirEntryLink);
if (activeDirEnt != -1)
fclose(hFile);
}
}

26
desmume/src/cflash.h Normal file
View File

@ -0,0 +1,26 @@
/*
CFLASH.H
Mic, 2006
*/
#ifndef __CFLASH_H__
#define __CFLASH_H__
#include "fat.h"
typedef struct {
int level,parent,filesInDir;
} FILE_INFO;
BOOL cflash_init();
unsigned int cflash_read(unsigned int address);
void cflash_write(unsigned int address,unsigned int data);
void cflash_close();
#endif

73
desmume/src/fat.h Normal file
View File

@ -0,0 +1,73 @@
/*
FAT.H
Mic, 2006
Structures taken from Michael Chisholm's FAT library
*/
#ifndef __FAT_H__
#define __FAT_H__
#include "types.h"
#define ATTRIB_DIR 0x10
#define ATTRIB_LFN 0x0F
#define FILE_FREE 0xE5
#define __PACKED __attribute__((__packed__))
// Boot Sector - must be packed
typedef struct
{
u8 jmpBoot[3] __PACKED;
u8 OEMName[8] __PACKED;
// BIOS Parameter Block
u16 bytesPerSector __PACKED;
u8 sectorsPerCluster __PACKED;
u16 reservedSectors __PACKED;
u8 numFATs __PACKED;
u16 rootEntries __PACKED;
u16 numSectorsSmall __PACKED;
u8 mediaDesc __PACKED;
u16 sectorsPerFAT __PACKED;
u16 sectorsPerTrk __PACKED;
u16 numHeads __PACKED;
u32 numHiddenSectors __PACKED;
u32 numSectors __PACKED;
struct
{
// Ext BIOS Parameter Block for FAT16
u8 driveNumber __PACKED;
u8 reserved1 __PACKED;
u8 extBootSig __PACKED;
u32 volumeID __PACKED;
u8 volumeLabel[11] __PACKED;
u8 fileSysType[8] __PACKED;
// Bootcode
u8 bootCode[448] __PACKED;
u16 signature __PACKED;
} fat16;
} BOOT_RECORD;
// Directory entry - must be packed
typedef struct
{
u8 name[8] __PACKED;
u8 ext[3] __PACKED;
u8 attrib __PACKED;
u8 reserved __PACKED;
u8 cTime_ms __PACKED;
u16 cTime __PACKED;
u16 cDate __PACKED;
u16 aDate __PACKED;
u16 startClusterHigh __PACKED;
u16 mTime __PACKED;
u16 mDate __PACKED;
u16 startCluster __PACKED;
u32 fileSize __PACKED;
} DIR_ENT;
#endif