⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 fat16.c

📁 Build ourself a MP3 Player
💻 C
📖 第 1 页 / 共 2 页
字号:
#include "fat16.h"
#include "string.h"

// After enabling the card, use this to extract the drive
// info and find the FAT and root dir
boolean FAT_Init() {
  if (!CF_isValid)
      return FALSE;
      
  // Get the MBR
  //printf("Fetching MBR.. ");
  CF_CurrSector = (int32)0x0;
  CF_StartSectorRead();

  // go to the first MBR boot record
  CF_ReadSkipInt16(0xE3);

  // read the boot sector location from MBR
  BPB_StartSector = CF_ReadInt16();
  //printf("Getting BPB from sector 0x%lx.. ", BPB_StartSector);
  CF_CurrSector = (int32)BPB_StartSector;
  CF_StartSectorRead();

  CF_ReadSkipBytes(11); // skip jmpboot and OEMName

  BPB_BytesPerSector = CF_ReadInt16();
  printf("# bytes/sectors: %ld\n\r", BPB_BytesPerSector);
  BPB_SectorsPerCluster = CF_ReadByte();
  printf("# sectors/cluster: %d\n\r", BPB_SectorsPerCluster);
  BPB_ReservedSectorCount = CF_ReadInt16();
  printf("# reserved sectors: %ld\n\r", BPB_ReservedSectorCount);
  BPB_NumFATs = CF_ReadByte();
  printf("# FATs: %d\n\r", BPB_NumFATs);
  BPB_RootDirEntryCount = CF_ReadInt16();
  printf("# / entries: %ld\n\r", BPB_RootDirEntryCount);

  CF_ReadSkipBytes(3);  // skip total # sectors and media

  BPB_FATSize = CF_ReadInt16();

  // calculate where the fat and root directory are
  FAT_StartSector =
    BPB_StartSector + BPB_ReservedSectorCount;
  FAT_RootDirNumSectors =
    ((BPB_RootDirEntryCount * 32) + (BPB_BytesPerSector - 1)) / BPB_BytesPerSector;
  FAT_RootDirStartSector =
    FAT_StartSector + ((int16) BPB_NumFATs * (int16) BPB_FATSize);
  FAT_FirstDataSector =
    FAT_RootDirStartSector + FAT_RootDirNumSectors;

  // set CWD to be root dir
  CWD_NAME[0] = '/'; CWD_NAME[1] = 0;
  CWD_StartSector = (int32)FAT_RootDirStartSector;
  CWD_CurrSector = CWD_StartSector;
  CWD_NumEntries = BPB_RootDirEntryCount;

   printf("FAT starts at sector 0x%lx\n\r", FAT_StartSector);
   printf("/ starts at sector 0x%8lx\n\r", CWD_StartSector);
   return TRUE;
}

// returns # of free clusters (ie those with 0x0 as the value in FAT)
int16 FAT_findFreeClusters(void) {
   int16 freeclusters = 0;
   int16 i, j;
   int16 fatentry;

   for (i=0; i< BPB_FATSize; i++) {
      CF_CurrSector = FAT_StartSector+i;
      CF_StartSectorRead();
      for (j=0; j<256; j++) {
        fatentry = CF_ReadInt16();
         if (fatentry == 0x0) {
            freeclusters++;
         }
     }
   }
   return freeclusters;
}

/************************ directory stuff */

// prints out the files in the current directory
void FAT_ListDir(void) {
  int16 filenum;
  byte ret;
  int32 totalspace, freespace;

  freespace = ((int32)(FAT_findFreeClusters())) * 2;
  printf("Free Space: %4ld\n\r", freespace); // in kB

  filenum = 0;
  while (1) {
    ret = FAT_LoadFileInCWD(filenum);
    if (ret == FAT_END_OF_DIR) {
	   puts("<EOD>");
	   return;
    }
    if ((ret != FAT_FILE_DELETED) && (ret != FAT_LONG_FILENAME)) {
      FAT_PrintCurrFileInfo();
    }
    filenum++;
  }
}

// used by ListDir
void FAT_PrintCurrFileInfo() {
  printf("%s   %8lx (cluster 0x%lx, sector 0x%lx)\n\r" , File_Name, File_Size,
		File_StartCluster, FAT_ConvertClusterToSector(File_StartCluster));
  if (File_Attr & FAT_IS_DIR)
    puts(" <DIR>");
  else
    putc('\n');
}


// cd into a directory off the current working directory
// This works, but i dont use it in this version...
boolean FAT_ChangeDir(char *dir) {
	byte result;

	result = FAT_loadFileWithName(dir);
	if (result == false)
		return result;

	if (! (File_Attr & FAT_IS_DIR))
		return false;

	// ok change to that dirs
	strncpy(CWD_Name, File_Name, 12);
	CWD_StartSector = FAT_ConvertClusterToSector(File_StartCluster);
	CWD_CurrSector = CWD_StartSector;
}

/************************** Loading files */
//looks in CWD for file with given name
boolean FAT_loadFileWithName(char *filename) {
  int16 filenum;
  byte ret;

  filenum = 0;

	while (1) {
		ret = FAT_LoadFileInCWD(filenum);
		if (ret == FAT_END_OF_DIR) {
			//puts("<EOD>");
			break;
		}
		if ((ret != FAT_FILE_DELETED) && (ret != FAT_LONG_FILENAME)) {
			if (stricmp(File_Name, filename) == 0) {
				printf("Found %s!\n", filename);
				return true;
	 		} else {
			//	printf("%s and %s do not match\n\r", filename, File_Name);
			}
		}
	filenum++;
	}
  return false;
}

// tries to load the number in directory slot #filenum
byte FAT_LoadFileInCWD(int16 filenumber) {
  char c;

  CWD_CurrSector = CWD_StartSector;

  if (filenumber > 16) {
    while (filenumber > 16) {
       CWD_CurrSector++;
       filenumber -= 16;
    }
  }

  File_DirEntryNum = filenumber;
  File_DirSectorNum = CWD_CurrSector;

  // start reading the directory sector
  CF_CurrSector = (int32)File_DirSectorNum;
  CF_StartSectorRead();

  filenumber &= 0x000F;

  CF_ReadSkipInt16(filenumber<<4);

  c = CF_ReadByte();
  if (c == 0x0)
    return FAT_END_OF_DIR;
  if (c == FAT_FILE_DELETED)
    return FAT_FILE_DELETED;

	// Read file information from directory
	File_Name[0] = c;
	for (c=1; c<11; c++) {
		File_Name[c] = CF_ReadByte();
	}
	File_Name[11] = 0;
	File_Attr =  CF_ReadByte();
	if (File_Attr == 0xf) { // long filename
		return FAT_LONG_FILENAME;
	}
	CF_ReadSkipBytes(14);
	File_StartCluster = CF_ReadInt16();
	File_CurrCluster = File_StartCluster;
	File_Size = CF_ReadInt32();
	File_CurrSectorNumInCluster = 0;

  return true;
}

/**************************** Reading files */
boolean FAT_StartReadFileNum(int num) {
	byte result;

	if (FAT_loadFileInCWD(num) != true)
		return 0;

	File_CurrByte = 0;
	File_CurrSectorNumInCluster = 0;
	File_CurrCluster = File_StartCluster;
	File_CurrSector = (FAT_ConvertClusterToSector(File_CurrCluster)) + File_CurrSectorNumInCluster;
	CF_CurrSector = File_CurrSector;
	CF_StartSectorRead();
	return true;
}

boolean FAT_StartReadFile(char *name) {
	byte result;

	if (FAT_loadFileWithName(name) == false)
		return 0;

	File_CurrByte = 0;
	File_CurrSectorNumInCluster = 0;
	File_CurrCluster = File_StartCluster;
	File_CurrSector = (FAT_ConvertClusterToSector(File_CurrCluster)) + File_CurrSectorNumInCluster;
	CF_CurrSector = File_CurrSector;
	CF_StartSectorRead();
	return 1;
}


// finds the next sector of the current file thru the FAT and
// loads that into the buff, returns 0 if EOF
byte FAT_ReadNextSectorIntoBuff() {
	int16 idx;
	byte c;

	if (File_CurrByte >= File_Size)
		return 0;

	// get the current sector indicated
	if (File_CurrSectorNumInCluster == BPB_SectorsPerCluster) {
		// find next cluster
		//printf("getting next cluster..");
		File_CurrCluster = FAT_GetNextCluster(File_CurrCluster);
      if (File_CurrCluster ==0 || File_CurrCluster > 0xfff7) {
         return 0;
      }
		File_CurrSectorNumInCluster = 0;
	}
	File_CurrSector = (int32)FAT_ConvertClusterToSector(File_CurrCluster);
	//printf("%8lx ", File_CurrSector);
	File_CurrSector += File_CurrSectorNumInCluster;
	//printf("cluster 0x%lx, #%d -> sector 0x%8lx\n\r", File_CurrCluster, File_CurrSectorNumInCluster, File_CurrSector);
	CF_CurrSector = File_CurrSector;
	CF_StartSectorRead();

	CF_ReadSectorIntoBuff();
	File_CurrByte += 512;
	File_CurrSectorNumInCluster++;
	return 1;
}

// returns the next byte in the current file
byte FAT_ReadNextFileByte() {
	int16 idx;
	byte c;

	if (File_CurrByte >= File_Size)
		return 0;
	c = CF_ReadByte();
	idx = File_CurrByte & 0x1ff;
	File_CurrByte++;
	idx++;
	if (idx == BPB_BytesPerSector) {
		idx = 0;
		// get next sector in cluster!
		File_CurrSectorNumInCluster++;
		//printf("getting next sector..");
		// check if we need next cluster;
		if (File_CurrSectorNumInCluster == BPB_SectorsPerCluster) {

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -