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

📄 smf_fat.c

📁 the test file for GP32 gameboy hack
💻 C
📖 第 1 页 / 共 5 页
字号:

	FAT_RETURN(drv_no, SM_OK);
}


/**********
 * Function: smGetSizeFile
 * Remarks:
 *	- retrieves file size
 * Parameters
 *	. p_file_name: file name string with full path
 *	. p_size (result): buffer that saves the file size
 **********/
SM_EXPORT ERR_CODE smGetSizeFile(const smchar* p_filename, udword* p_size) 
{
	udword drv_no;
	F_HANDLE h_dir;
	ubyte long_name[MAX_FILE_NAME_LEN + 1];
	ubyte file_info[32];
	udword cluster;
	udword offset;
	ubyte *p_file_name = (ubyte *)p_filename;

	drv_no = sm_GetDrvNo(p_file_name);
	if (drv_no >= MAX_DRIVE)
		return ERR_INVALID_PARAM;

	s_smErr = sm_PreFAT(drv_no);
	if (s_smErr != SM_OK)
		FAT_RETURN(drv_no, s_smErr);

	*p_size = 0;

	s_smErr = sm_CheckPath(drv_no, p_file_name, PATH_EXCEPT_LAST, &h_dir);
	if (s_smErr != SM_OK)
		FAT_RETURN(drv_no, s_smErr);

	sm_ExtractLastName(p_file_name, long_name);

	s_smErr = sm_FindEntryInDirectory(drv_no, FIND_FILE_NAME, h_dir, (udword)long_name, file_info, &cluster, &offset);
	if (s_smErr != SM_OK) 
		FAT_RETURN(drv_no, s_smErr);

	*p_size = (udword)file_info[28] | ((udword)file_info[29] << 8)
		| ((udword)file_info[30] << 16) | ((udword)file_info[31] << 24);

	FAT_RETURN(drv_no, s_smErr);
}


/**********
 * Function: smFileExtend
 * Remarks:
 *	- expands the file size of the opened file
 * Parameters
 *	. h_file: file handle
 *	. size : amount of expand size
 **********/
SM_EXPORT ERR_CODE smFileExtend(F_HANDLE h_file, udword size) 
{
	udword drv_no;
	udword cluster;
	sOPENED_LIST* p_list;
	udword id;
	udword addedClusterCount;
	udword sectorsPerCluster;
	udword clusterSize;

	drv_no = (h_file >> 24) & 0x7f;
	if (drv_no >= MAX_DRIVE)
		return ERR_INVALID_PARAM;

	cluster = h_file & 0xffff;
	id = (h_file >> 16) & 0xff;

	s_smErr = sm_PreFAT(drv_no);
	if (s_smErr != SM_OK) 
		FAT_RETURN(drv_no, s_smErr);

	s_smErr = sm_GetOpenedList(drv_no, cluster, id, &p_list);
	if (s_smErr != SM_OK) 
		FAT_RETURN(drv_no, s_smErr);

	size += p_list->size;
	sectorsPerCluster = s_smInfo[drv_no].pbr.bpb.sectors_per_cluster;
	clusterSize = sectorsPerCluster * SECTOR_SIZE;

	/* check if extended size needs more cluster */
	addedClusterCount = (size + clusterSize - 1) / clusterSize - (p_list->size + clusterSize - 1) / clusterSize;
	if (addedClusterCount) 
	{
		udword curEndSector;
		udword nextEndSector;

		s_smErr = sm_addClusters(drv_no, cluster, addedClusterCount);
		if (s_smErr != SM_OK) 
			FAT_RETURN(drv_no, s_smErr);
#if 0	/* file may not have its clusters continously (dalma, 2000.3.15) */
		curEndSector = s_clusterStartSector[drv_no]	+ (cluster - 2) * sectorsPerCluster
						+ (p_list->size - p_list->size / clusterSize * clusterSize)	/ SECTOR_SIZE;
		nextEndSector = s_clusterStartSector[drv_no] + (cluster + 1 - 2) * sectorsPerCluster - 1;

		if (curEndSector != nextEndSector) 
		{
			s_smErr = sm_eraseSectors(drv_no, curEndSector + 1, nextEndSector - curEndSector);
			if (s_smErr != SM_OK) 
				FAT_RETURN(drv_no, s_smErr);
		}
#endif
	}
	else 
	{
		udword curEndSector;
		udword nextEndSector;

#if 0	/* file may not have its clusters continously (dalma, 2000.3.15) */
		curEndSector = s_clusterStartSector[drv_no]	+ (cluster - 2) * sectorsPerCluster
						+ (p_list->size - p_list->size / clusterSize * clusterSize)	/ SECTOR_SIZE;
		nextEndSector = s_clusterStartSector[drv_no] + (cluster - 2) * sectorsPerCluster
						+ (size - size / clusterSize * clusterSize)	/ SECTOR_SIZE;

		if (curEndSector != nextEndSector) 
		{
			s_smErr = sm_eraseSectors(drv_no, curEndSector + 1, nextEndSector - curEndSector);
			if (s_smErr != SM_OK) 
				FAT_RETURN(drv_no, s_smErr);
		}
#endif	
	}

	FAT_RETURN(drv_no, SM_OK);
}


/**********
 * Function: smCreateDir
 * Remarks:
 *	- creates directory and writes its default sub directory information
 * Parameters
 *	. p_dir_name: directory name that should be created
 *					(ex. dev0:\temp\readme)
 *	. dcreate_mode: reserved
 **********/
SM_EXPORT ERR_CODE smCreateDir(const smchar* p_dirname, udword dcreate_mode) 
{
	udword drv_no;
	udword cluster;
	F_HANDLE h_dir;
	ubyte long_name[MAX_FILE_NAME_LEN + 1];
	ubyte dummy_info[32];
	udword offset;
	sFILE_STAT sStat;
	ubyte *p_dir_name = (ubyte *)p_dirname;
#ifdef	LONG_FILE_NAME_ENABLE
	uword* p_unicode;
	ubyte fat_name[13];
#endif

	drv_no = sm_GetDrvNo(p_dir_name);
	if (drv_no >= MAX_DRIVE)
		return ERR_INVALID_PARAM;

	s_smErr = sm_PreFAT(drv_no);
	if (s_smErr != SM_OK) 
		FAT_RETURN(drv_no, s_smErr);

	s_smErr = sm_CheckPath(drv_no, p_dir_name, PATH_EXCEPT_LAST, &h_dir);
	if (s_smErr != SM_OK) 
		FAT_RETURN(drv_no, s_smErr);

	sm_ExtractLastName(p_dir_name, long_name);

	/* check if the same name exists already */
	s_smErr = sm_FindEntryInDirectory(drv_no, FIND_FILE_NAME, h_dir, (udword)long_name, dummy_info, &cluster, &offset);
	if (s_smErr != ERR_NOT_FOUND)
		FAT_RETURN(drv_no, ERR_FILE_EXIST);

	s_smErr = smcAllocCluster(drv_no, &cluster);
	if (s_smErr != SM_OK)
		FAT_RETURN(drv_no, s_smErr);

	/* directory contents initialize */
	s_smErr = smcSetCluster(drv_no, cluster, 0);
	if (s_smErr != SM_OK)
		FAT_RETURN(drv_no, s_smErr);

	/* FAT table update */
	/* This must be done before another smcAllocCluster() is called */
	SET_FAT_TBL(drv_no, cluster, LAST_CLUSTER);

	/*
	 * new directory contents write
	 * (current dir, parent dir information write)
	 */
	sStat.attr = ATTRIB_DIR;
	sStat.cluster = cluster;
	sStat.size = 0;
	sm_GetTime(&sStat.time);
	
	s_smErr = sm_AddToDirEntry(drv_no, cluster, (ubyte*)".", NULL, &sStat, 0, 0, 0);
	if (s_smErr != SM_OK)
	{
		SET_FAT_TBL(drv_no, cluster, UNUSED_CLUSTER);
		FAT_RETURN(drv_no, s_smErr);
	}

	sStat.cluster = h_dir;
	s_smErr = sm_AddToDirEntry(drv_no, cluster, (ubyte*)"..", NULL, &sStat, 0, 0, 0);
	if (s_smErr != SM_OK)
	{
		SET_FAT_TBL(drv_no, cluster, UNUSED_CLUSTER);
		FAT_RETURN(drv_no, s_smErr);
	}

	/* parent directory contents update */
#ifdef	LONG_FILE_NAME_ENABLE
	p_unicode = (uword*)SM_MALLOC(MAX_FILE_NAME_LEN+2);
	if(p_unicode == NULL)
	{
		SET_FAT_TBL(drv_no, cluster, UNUSED_CLUSTER);
		FAT_RETURN(drv_no, ERR_OUT_OF_MEMORY);
	}

	sStat.cluster = cluster;
	if(sm_ConvertToFATName(long_name, fat_name))
	{
		SM_MBS_TO_UNICODE(p_unicode, long_name, 0);	
		s_smErr = sm_AddToDirEntry(drv_no, h_dir, long_name, p_unicode, &sStat, 0, 0, 0);
	}
	else
		s_smErr = sm_AddToDirEntry(drv_no, h_dir, long_name, NULL, &sStat, 0, 0, 0);

	SM_FREE(p_unicode);
#else
	sStat.cluster = cluster;
	s_smErr = sm_AddToDirEntry(drv_no, h_dir, long_name, NULL, &sStat, 0, 0, 0);
#endif	
	if (s_smErr != SM_OK)
	{
		SET_FAT_TBL(drv_no, cluster, UNUSED_CLUSTER);
		FAT_RETURN(drv_no, s_smErr);
	}

	sm_FATUpdate(drv_no);

	FAT_RETURN(drv_no, SM_OK);
}


/**********
 * Function: smRemoveDir
 * Remarks:
 *	- remove directory
 * Parameters
 *	. p_dir_name: directory name that should be removed
 *	. ddel_mode: ALWAYS_DELETE, NOT_IF_NOT_EMPTY
 **********/
SM_EXPORT ERR_CODE smRemoveDir(const smchar* p_dirname, udword ddel_mode) 
{
	udword drv_no;
	F_HANDLE h_dir;
	F_HANDLE handle;
	ubyte long_name[MAX_FILE_NAME_LEN + 1];
	ubyte file_info[32];
	udword cluster;
	udword offset;
	udword i;
	ubyte *p_dir_name = (ubyte *)p_dirname;

	drv_no = sm_GetDrvNo(p_dir_name);
	if (drv_no >= MAX_DRIVE)
		return ERR_INVALID_PARAM;

	s_smErr = sm_PreFAT(drv_no);
	if (s_smErr != SM_OK)
		FAT_RETURN(drv_no, s_smErr);

	/* if the given name is root directory, it returns error here */
	s_smErr = sm_CheckPath(drv_no, p_dir_name, PATH_EXCEPT_LAST, &h_dir);
	if (s_smErr != SM_OK)
		FAT_RETURN(drv_no, s_smErr);

	sm_ExtractLastName(p_dir_name, long_name);

	s_smErr = sm_FindEntryInDirectory(drv_no, FIND_FILE_NAME, h_dir, (udword)long_name, file_info, &cluster, &offset);
	if (s_smErr != SM_OK)
		FAT_RETURN(drv_no, SM_OK);

	/* check if the parameter is directory */
	if (!(file_info[11] & 0x10))
		FAT_RETURN(drv_no, ERR_INVALID_PARAM);

	handle = file_info[26] | ((udword)file_info[27] << 8);

	if (ddel_mode == ALWAYS_DELETE) 
	{
		/*
		 * It deletes the first bottommost directory and its files
		 * again and again, and at last there is no more subdirectory.
		 * Then sm_RemoveFirstBottommostDir() deletes all the files in
		 * the "p_dir_name" directory, and returns ERR_NO_MORE_ENTRY.
		 *
		 * *** It is implemented not to use recursive call to save
		 * 		stack size.
		 *		Instead, it takes more time.
		 */
		s_smErr = SM_OK;
		while (s_smErr == SM_OK) 
		{
			s_smErr = sm_RemoveFirstBottommostDir(drv_no, handle);
		}

		if (s_smErr != ERR_NO_MORE_ENTRY)
			FAT_RETURN(drv_no, s_smErr);
	}
	else 
	{
		/* check if the directory has any entry */
		for (i = 0; i < 3; ++i) 
		{
			s_smErr = sm_FindEntryInDirectory(drv_no, FIND_FILE_INDEX, handle, i, file_info, &cluster, &offset);
			if (s_smErr != SM_OK) 
			{
				if (s_smErr == ERR_NOT_FOUND) 
				{
					/*
					 * this is the only case that the remove should be
					 * continued
					 */
					break;
				}
				else 
					FAT_RETURN(drv_no, s_smErr);
			}

			if (file_info[0] == '.')			/* skip ".", ".." */
				continue;
			else 
				FAT_RETURN(drv_no, ERR_DIR_NOT_EMPTY);
		}
	}

	/* deletes the directory itself from its parent entries */
	s_smErr = sm_RemoveFile(drv_no, h_dir, long_name);
	if (s_smErr != SM_OK)
		FAT_RETURN(drv_no, s_smErr);

	FAT_RETURN(drv_no, SM_OK);
}


/**********
 * Function: smGetListNumber
 * Remarks:
 *	- retrieves the number of entry in the directory "p_dir_name"
 * Parameters
 *	. p_dir_name: directory name string with full path
 *	. p_num (result): the number of entry in the directory
 **********/
SM_EXPORT ERR_CODE smGetListNumDir(const smchar* p_dirname, udword* p_num) 
{
	udword drv_no;
	F_HANDLE h_dir;
	udword cluster;
	udword offset;
	udword cluster_size;
	udword i, j;
	udword entry_count;
	udword sector_count;
	ubyte* buf;
	ubyte *p_dir_name = (ubyte *)p_dirname;

	drv_no = sm_GetDrvNo(p_dir_name);
	if (drv_no >= MAX_DRIVE)
		return ERR_INVALID_PARAM;

	s_smErr = sm_PreFAT(drv_no);
	if (s_smErr != SM_OK)
		FAT_RETURN(drv_no, s_smErr);

	s_smErr = sm_CheckPath(drv_no, p_dir_name, PATH_FULL, &h_dir);
	if (s_smErr != SM_OK)
		FAT_RETURN(drv_no, s_smErr);

	*p_num = 0;

	cluster_size = s_smInfo[drv_no].pbr.bpb.sectors_per_cluster * SECTOR_SIZE;
	entry_count = 0;

	buf = SMB_ALLOC_BUF();
	if (!buf)
		FAT_RETURN(drv_no, ERR_OUT_OF_MEMORY);

	if (h_dir == ROOT_HANDLE) 
	{
		for (i = s_rootStartSector[drv_no]; i < s_rootStartSector[drv_no] + s_rootSectors[drv_no]; ++i) 
		{
			s_smErr = smlReadSector(drv_no, i, 0, buf, SECTOR_SIZE);
			if (s_smErr != SM_OK) 
			{
				SMB_FREE_BUF(buf);
				FAT_RETURN(drv_no, s_smErr);
			}

			for (j = 0; j < SECTOR_SIZE; j += 32) 
			{
				/*
				 * exclude no file, deleted file, entry for long file
				 * name
				 */
				if(buf[j] == 0)
					break;

				if ((buf[j] != 0xe5) && ((buf[j + 11] & 0xf) != 0xf)) 
					++entry_count;
			}

			if(j < SECTOR_SIZE)
				break;
		}
	}
	else 
	{
		cluster = h_dir & 0xffff;

		while (cluster != LAST_CLUSTER) 
		{
			for (offset = 0; offset < cluster_size;	offset += SECTOR_SIZE) 
			{
				s_smErr = smcReadCluster(drv_no, cluster, offset, buf, SECTOR_SIZE);
				if (s_smErr != SM_OK) 
				{
					SMB_FREE_BUF(buf);
					FAT_RETURN(drv_no, s_smErr);
				}

				for (j = 0; j < SECTOR_SIZE; j += 32) 
				{
					/*
					 * exclude no file, deleted file, entry for long
					 * file name
					 */
					if(buf[j] == 0)
						break;

					if ((buf[j] != 0xe5) && ((buf[j + 11] & 0xf) != 0xf)) 
						++entry_count;
				}

				if(j < SECTOR_SIZE)
					break;
			}

			cluster = GET_FAT_TBL(drv_no, cluster);

			/*
			 * this is the case that FAT table is not updated correctly
			 */
			if (cluster == UNUSED_CLUSTER) 
			{
				SMB_FREE_BUF(buf);
				FAT_RETURN(drv_no, ERR_INCORRECT_FAT);
			}
		}
	}

⌨️ 快捷键说明

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