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

📄 smf_fat.c

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

	*p_num = entry_count;

	SMB_FREE_BUF(buf);
	FAT_RETURN(drv_no, SM_OK);
}


/**********
 * Function: smReadDir
 * Remarks:
 *	- retrieves entries' simple information in the directory
 *		"p_dir_name"
 * Parameters
 *	. p_dir_name: directory name string with full path
 *	. entry_start: start index of the entry
 *	. entry_count: number of entries that should be retrieved
 *	. p_buf (result): buffer that saves the entries' information
 *	. p_read_count (result): number of entries that was saved
 * Notes:
 *	- "p_buf" must be prepared for space of
 *		"entry_count * sizeof(sDIR_ENTRY)"
 **********/
SM_EXPORT ERR_CODE smReadDir(const smchar* p_dirname, udword entry_start, udword entry_count, sDIR_ENTRY p_buf[], udword* p_read_count) 
{
	udword drv_no;
	F_HANDLE h_dir;
	ubyte file_info[32];
	udword cluster;
	udword offset;
	udword i, j, k;
	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_read_count = 0;

	for (i = 0; i < entry_count; ++i) 
	{
		s_smErr = sm_FindEntryInDirectory(drv_no, FIND_FILE_INDEX, h_dir, entry_start + i, file_info, &cluster, &offset);
		if (s_smErr != SM_OK) 
		{
			if (s_smErr == ERR_NOT_FOUND) 
			{
				*p_read_count = i;
				FAT_RETURN(drv_no, ERR_EOF);
			}
			else 
				FAT_RETURN(drv_no, s_smErr);
		}

		for (j = 0, k = 0; j < 11; ++j) 
		{
			if (file_info[j] != ' ') 
			{
				if (j == 8) 
				{
					p_buf[i].name[k] = '.';
					++k;
				}

				p_buf[i].name[k] = file_info[j];
				++k;
			}
		}

		p_buf[i].name[k] = 0;
	}

	*p_read_count = entry_count;

	FAT_RETURN(drv_no, SM_OK);
}


/**********
 * Function: smReadDirEx
 * Remarks:
 *	- retrieves entries' full information in the directory "p_dir_name"
 * Parameters
 *	. p_dir_name: directory name string with full path
 *	. entry_start: start index of the entry
 *	. entry_count: number of entries that should be retrieved
 *	. p_buf (result): buffer that saves the entries' information
 *	. p_read_count (result): number of entries that was saved
 * Notes:
 *	- "p_buf" must be prepared for space of
 *		"entry_count * sizeof(sDIR_ENTRY_EX)"
 **********/
SM_EXPORT ERR_CODE smReadDirEx(const smchar* p_dirname, udword entry_start, udword entry_count, sDIR_ENTRY_EX p_buf[],	udword* p_read_count) 
{
	udword drv_no;
	F_HANDLE h_dir;
	ubyte file_info[32];
	udword cluster;
	udword offset;
	udword i, j, k;
	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_read_count = 0;

	for (i = 0; i < entry_count; ++i) 
	{
		s_smErr = sm_FindEntryInDirectory(drv_no, FIND_FILE_INDEX, h_dir, entry_start + i, file_info, &cluster, &offset);
		if (s_smErr != SM_OK) 
		{
			if (s_smErr == ERR_NOT_FOUND) 
			{
				*p_read_count = i;
				FAT_RETURN(drv_no, ERR_EOF);
			}
			else
				FAT_RETURN(drv_no, s_smErr);
		}

		for (j = 0, k = 0; j < 11; ++j) 
		{
			if (file_info[j] != ' ') 
			{
				if (j == 8) 
				{
					p_buf[i].name[k] = '.';
					++k;
				}

				p_buf[i].name[k] = file_info[j];
				++k;
			}
		}
		p_buf[i].name[k] = 0;

#ifdef LONG_FILE_NAME_ENABLE
		s_smErr = sm_GetLongName(drv_no, h_dir, cluster, offset, p_buf[i].long_name);
		if ((s_smErr != SM_OK) && (s_smErr != ERR_FILE_NAME_LEN_TOO_LONG))
			p_buf[i].long_name[0] = 0;
#else
		p_buf[i].long_name[0] = 0;
#endif

		p_buf[i].stat.attr = file_info[11];
		p_buf[i].stat.time.year = 1980 + ((file_info[25] >> 1) & 0x7f);
		p_buf[i].stat.time.month = ((file_info[25] << 3) & 0x08) | ((file_info[24] >> 5) & 0x07);
		p_buf[i].stat.time.day = file_info[24] & 0x1f;
		p_buf[i].stat.time.hour = (file_info[23] >> 3) & 0x1f;
		p_buf[i].stat.time.min = ((file_info[23] << 3) & 0x38) | ((file_info[22] >> 5) & 0x07);
		p_buf[i].stat.time.sec = file_info[22] & 0x1f;
		p_buf[i].stat.time.msec = 0;
		p_buf[i].stat.cluster = (uword)file_info[26] | ((uword)file_info[27] << 8);
		p_buf[i].stat.size = (udword)file_info[28] | ((udword)file_info[29] << 8)
							| ((udword)file_info[30] << 16)	| ((udword)file_info[31] << 24);
	}

	*p_read_count = entry_count;

	FAT_RETURN(drv_no, SM_OK);
}


/**********
 * Function: smReadStat
 * Remarks:
 *	- retrieves file(directory) information
 * Parameters
 *	. p_name: file(directory) name string with full path
 *	. p_stat (result): buffer that saves the file(directory) information
 * Notes:
 *	- "p_stat" must be prepared for space of "sizeof(sFILE_STAT)"
 *	- if "p_name" indicates root directory, it returns ERR_ROOT_DIR
 **********/
SM_EXPORT ERR_CODE smReadStat(const smchar* p_entry_name, sFILE_STAT* p_stat) 
{
	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_name = (ubyte *)p_entry_name;

	drv_no = sm_GetDrvNo(p_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_name, PATH_EXCEPT_LAST, &h_dir);
	if (s_smErr != SM_OK) 
	{
		s_smErr =  sm_CheckPath(drv_no, p_name, PATH_FULL, &h_dir);
		if (s_smErr == SM_OK) 
		{
			if (h_dir == ROOT_HANDLE)
				FAT_RETURN(drv_no, ERR_ROOT_DIR);
			else
				FAT_RETURN(drv_no, ERR_INVALID_PARAM);
		}
		else
			FAT_RETURN(drv_no, s_smErr);
	}

	sm_ExtractLastName(p_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_stat->attr = file_info[11];
	p_stat->time.year = 1980 + ((file_info[25] >> 1) & 0x7f);
	p_stat->time.month = ((file_info[25] << 3) & 0x08) | ((file_info[24] >> 5) & 0x07);
	p_stat->time.day = file_info[24] & 0x1f;
	p_stat->time.hour = (file_info[23] >> 3) & 0x1f;
	p_stat->time.min = ((file_info[23] << 3) & 0x38) | ((file_info[22] >> 5) & 0x07);
	p_stat->time.sec = file_info[22] & 0x1f;
	p_stat->time.msec = 0;
	p_stat->cluster = (udword)file_info[26] | ((udword)file_info[27] << 8);
	p_stat->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: smWriteStat
 * Remarks:
 *	- updates the file(directory) information
 * Parameters
 *	. p_name: file(directory) name string with full path
 *	. p_stat (result): file(directory) information pointer
 * Notes:
 *	- p_stat->cluster, p_stat->size is not adapted. these are not the
 *		values user can change
 *	- if "p_name" indicates root directory, it returns ERR_ROOT_DIR
 **********/
SM_EXPORT ERR_CODE smWriteStat(const smchar* p_entry_name, const sFILE_STAT* p_stat) 
{
	udword drv_no;
	F_HANDLE h_dir;
	ubyte long_name[MAX_FILE_NAME_LEN + 1];
	ubyte file_info[32];
	udword cluster;
	udword offset;
	ubyte year;
	ubyte *p_name = (ubyte *)p_entry_name;

	drv_no = sm_GetDrvNo(p_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_name, PATH_EXCEPT_LAST, &h_dir);
	if (s_smErr != SM_OK) 
	{
		s_smErr =  sm_CheckPath(drv_no, p_name, PATH_FULL, &h_dir);
		if (s_smErr == SM_OK) 
		{
			if (h_dir == ROOT_HANDLE)
				FAT_RETURN(drv_no, ERR_ROOT_DIR);
			else
				FAT_RETURN(drv_no, ERR_INVALID_PARAM);
		}
		else
			FAT_RETURN(drv_no, s_smErr);
	}

	sm_ExtractLastName(p_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);

	file_info[11] = (ubyte)(p_stat->attr & 0xff);

	/* file_info[22-23] <= time */
	/*	Hour | Min | Sec => 5bit | 6bit | 5bit(half value) */
	file_info[22] = ((p_stat->time.sec >> 1) & 0x1f) | ((p_stat->time.min << 5) & 0xe0);
	file_info[23] = ((p_stat->time.min >> 3) & 0x07) | ((p_stat->time.hour << 3) & 0xf8);

	/* file_info[24-25] <= date */
	/*	Year | Month | Day => 7bit | 4bit | 5bit */
	file_info[24] = ((p_stat->time.day) & 0x1f)	| ((p_stat->time.month << 5) & 0xe0);
	if (p_stat->time.year > 1980)
		year = p_stat->time.year - 1980;
	else
		year = 0;

	file_info[25] = ((p_stat->time.month >> 3) & 0x01) | ((year << 1) & 0xfe);

	s_smErr = smcWriteCluster(drv_no, cluster, offset, file_info, 32);
	if (s_smErr != SM_OK)
		FAT_RETURN(drv_no, s_smErr);

	FAT_RETURN(drv_no, SM_OK);
}


#ifdef LONG_FILE_NAME_ENABLE
/**********
 * Function: smSetLongName
 * Remarks:
 *	- set the long name
 * Parameters
 *	. p_file_name: file name that exists (ex. dev0:\temp\readme.txt)
 *	. p_long_name: long name(without directory path) that is in Unicode
 * Notes:
 *	- SMFS does not support creation of file with its long name becuase
 *		it needs very large Unicode table. Instead, it is possible to
 *		set its long name using this function in the environment that
 *		has methods for Unicode translation
 **********/
SM_EXPORT ERR_CODE smSetLongName(const smchar* p_filename, const uword* p_long_name) 
{
	udword drv_no;
	F_HANDLE h_dir;
	ubyte long_name[MAX_FILE_NAME_LEN + 1];
	ubyte file_info[32];
	udword cluster;
	udword offset;
	sFILE_STAT sStat;
	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);

	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);

	/* search existing file for use of the 32 byte file_info */
	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);
	
	sStat.attr = file_info[11];
	sStat.cluster = file_info[26] | ((udword)file_info[27] << 8);
	sStat.size = file_info[28] | ((udword)file_info[29] << 8) | ((udword)file_info[30] << 16) | ((udword)file_info[31] << 24);
	sStat.time.year = 1980 + ((file_info[25] >> 1) & 0x7f);
	sStat.time.month = ((file_info[25] << 3) & 0x08) | ((file_info[24] >> 5) & 0x07);
	sStat.time.day = file_info[24] & 0x1f;
	sStat.time.hour = (file_info[23] >> 3) & 0x1f;
	sStat.time.min = ((file_info[23] << 3) & 0x38) | ((file_info[22] >> 5) & 0x07);
	sStat.time.sec = file_info[22] & 0x1f;
	sStat.time.msec = 0;

	/* delete existing entry */
	s_smErr = sm_DeleteFromDirEntry(drv_no, h_dir, long_name);
	if (s_smErr != SM_OK)
		FAT_RETURN(drv_no, s_smErr);

	/* set new entry with long file name */
	s_smErr = sm_AddToDirEntry(drv_no, h_dir, (const ubyte*)long_name, p_long_name, &sStat, 0, 0, 0);
	if (s_smErr != SM_OK)
		FAT_RETURN(drv_no, s_smErr);

	FAT_RETURN(drv_no, SM_OK);
}


/**********
 * Function: smGetLongName
 * Remarks:
 *	- get the long name
 * Parameters
 *	. p_file_name: file name that exists (ex. dev0:\temp\readme.txt)
 *	. p_long_name: long name(without directory path) that is in Unicode
 * Notes:
 *	- p_long_name is returned with Unicode
 **********/
SM_EXPORT ERR_CODE smGetLongName(const smchar* p_filename, uword* p_long_name) 
{
	udword drv_no;
	F_HANDLE h_dir;
	ubyte file_info[32];
	udword cluster;
	udword offset;
	ubyte *p_file_name = (ubyte *)p_filename;
	ubyte long_name[MAX_FILE_NAME_LEN + 1];

	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);

	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);

	s_smErr = sm_GetLongName(drv_no, h_dir, cluster, offset, p_long_name);
	if (s_smErr != SM_OK) 
	{
		if(s_smErr != ERR_FILE_NAME_LEN_TOO_LONG)
			p_long_name[0] = 0;
			
		FAT_RETURN(drv_no, s_smErr);
	}

	FAT_RETURN(drv_no, SM_OK);
}
#endif		/* LONG_FILE_NAME_ENABLE */


/**********
 * Function: smGetVolInfo
 * Remarks:
 *	- get volumn information
 * Parameters
 *	. p_vol_name: volumn name that is mounted (ex. "dev0:")
 *	. p_info (result): pointer of volumn info structure
 **********/
SM_EXPORT ERR_CODE smGetVolInfo(const smchar* p_volumn_name, sVOL_INFO* p_info) 
{
	udword drv_no;
	udword total_clusters;
	udword cluster_size;
	udword fat_val;
	udword i;
	ubyte *p_vol_name = (ubyte *)p_volumn_name;

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

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

⌨️ 快捷键说明

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