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

📄 smf_fat.c

📁 the test file for GP32 gameboy hack
💻 C
📖 第 1 页 / 共 5 页
字号:
	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);

	*p_read_count = 0;

	/*
	 * head_count: read size before the cache area
	 * cache_count: read size in the cache area
	 * tail_count: read size after the cache area
	 */
	head_count = tail_count = 0;
#ifndef WRITE_CACHE_DISABLE
	cache_count = 0;
#endif
	remaining_count = count;

#ifndef WRITE_CACHE_DISABLE
	if (p_list->cache.count) 
	{
		/* p_list->f_ptr is before the cache area */
		if (p_list->f_ptr < p_list->cache.f_ptr) 
		{
			head_count	= (p_list->cache.f_ptr - p_list->f_ptr > remaining_count) 
							? remaining_count	: (p_list->cache.f_ptr - p_list->f_ptr);
			remaining_count -= head_count;

			if (remaining_count > 0) 
			{
				cache_count = (p_list->cache.count > remaining_count) ? remaining_count : p_list->cache.count;
				remaining_count -= cache_count;

				tail_count = remaining_count;
			}
		}
		/* p_list->f_ptr is in the cache area */
		else if (p_list->f_ptr < p_list->cache.f_ptr + p_list->cache.count) 
		{
			cache_count	= (p_list->cache.count - (p_list->f_ptr - p_list->cache.f_ptr) > remaining_count)
							?  remaining_count : (p_list->cache.count - (p_list->f_ptr - p_list->cache.f_ptr));
			remaining_count -= cache_count;

			tail_count = remaining_count;
		}
		/* p_list->f_ptr is after the cache area */
		else 
		{
			tail_count = remaining_count;
		}
	}
	else 
	{
		head_count = remaining_count;
	}
#else
	head_count = remaining_count;
#endif

	read_sum = 0;

	if (head_count) 
	{
		s_smErr = sm_ReadFromDisk(drv_no, p_list, p_buf, head_count, &read_result);
		if ((s_smErr != SM_OK) && (s_smErr != ERR_EOF)) 
			FAT_RETURN(drv_no, s_smErr);

		read_sum += read_result;
	}

#ifndef WRITE_CACHE_DISABLE
	if (cache_count) 
	{
		udword cluster_size;
		udword walked_cluster_count;

		offset = p_list->f_ptr - p_list->cache.f_ptr;
		SM_MEMCPY((char*)p_buf + head_count, p_list->cache.p_buf + offset, cache_count);

		/* update current cluster */
		cluster_size = s_smInfo[drv_no].pbr.bpb.sectors_per_cluster * SECTOR_SIZE;
		walked_cluster_count = (p_list->f_ptr % cluster_size + cache_count) / cluster_size;
		if (walked_cluster_count > 0) 
		{
			while (walked_cluster_count-- > 0) 
			{
				p_list->old_cur_cluster = p_list->cur_cluster;
				p_list->cur_cluster = GET_FAT_TBL(drv_no, p_list->cur_cluster);
				if (p_list->cur_cluster == LAST_CLUSTER) 
					FAT_RETURN(drv_no, ERR_INTERNAL);
			}
		}

		p_list->f_ptr += cache_count;

		read_sum += cache_count;
	}
#endif

	if (tail_count) 
	{
#ifndef WRITE_CACHE_DISABLE
		s_smErr = sm_ReadFromDisk(drv_no, p_list, (ubyte*)p_buf + head_count + cache_count, tail_count, &read_result);
#else
		s_smErr = sm_ReadFromDisk(drv_no, p_list, (ubyte*)p_buf + head_count, tail_count, &read_result);
#endif
		if ((s_smErr != SM_OK) && (s_smErr != ERR_EOF)) 
			FAT_RETURN(drv_no, s_smErr);

		read_sum += read_result;
	}

	*p_read_count = read_sum;

	if (count > read_sum) 
		FAT_RETURN(drv_no, ERR_EOF);

	FAT_RETURN(drv_no, s_smErr);
}


/**********
 * Function: smWriteFile
 * Remarks:
 *	- write the contents of the p_buf to the file
 * Parameters
 *	. h_file: handle of opened file
 *	. p_buf: writing contents
 *	. count: amount of writing contents
 **********/
SM_EXPORT ERR_CODE smWriteFile(F_HANDLE h_file, const void* p_buf, udword count) 
{
	udword drv_no;
	udword cluster;
	const ubyte* p_write;
	udword write_count;
	sOPENED_LIST* p_list;
	udword id;

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

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

	p_write = (const ubyte*)p_buf;
	write_count = count;

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

	if (!(p_list->mode & OPEN_W))
		FAT_RETURN(drv_no, ERR_NOT_PERMITTED);

#ifndef WRITE_CACHE_DISABLE
	if ((p_list->cache.count != 0) && (p_list->f_ptr != p_list->cache.f_ptr + p_list->cache.count)) 
	{
		sm_WriteCacheToDisk(drv_no, p_list);
	}

	if (p_list->cache.count + write_count < s_cacheSize[drv_no]) 
	{
		udword cluster_size;
		udword walked_cluster_count;

		SM_MEMCPY(p_list->cache.p_buf + p_list->cache.count, p_write, write_count);

		p_list->cache.count += write_count;

		/* update current cluster */
		cluster_size = s_smInfo[drv_no].pbr.bpb.sectors_per_cluster * SECTOR_SIZE;
		walked_cluster_count = (p_list->f_ptr % cluster_size + write_count) / cluster_size;
		if (walked_cluster_count > 0) 
		{
			while (walked_cluster_count-- > 0) 
			{
				p_list->old_cur_cluster = p_list->cur_cluster;
				p_list->cur_cluster = GET_FAT_TBL(drv_no, p_list->cur_cluster);
			}
		}
		p_list->f_ptr += write_count;
		if (p_list->size < p_list->f_ptr) 
			p_list->size = p_list->f_ptr;
	}
	else 
	{
		s_smErr = sm_WriteCacheToDisk(drv_no, p_list);
		if (s_smErr != SM_OK)
			FAT_RETURN(drv_no, s_smErr);

		s_smErr = sm_WriteToDisk(drv_no, p_list, p_write, write_count);
		if (s_smErr != SM_OK)
			FAT_RETURN(drv_no, s_smErr);

		p_list->cache.f_ptr = p_list->f_ptr;
	}

	FAT_RETURN(drv_no, SM_OK);
#else
	s_smErr = sm_WriteToDisk(drv_no, p_list, p_write, write_count);
	FAT_RETURN(drv_no, s_smErr);
#endif
}


/**********
 * Function: smSeekFile
 * Remarks:
 *	- moves the file pointer
 * Parameters
 *	. h_file: handle of opened file
 *	. seek_mode: FROM_CURRENT, FROM_BEGIN, FROM_END
 *	. offset: amount of movement
 *	. p_old_offset (result): file pointer before it is moved
 **********/
SM_EXPORT ERR_CODE smSeekFile(F_HANDLE h_file, udword seek_mode, dword offset, dword* p_old_offset) 
{
	udword drv_no;
	udword cluster;
	sOPENED_LIST* p_list;
	udword id;
	udword cluster_size;

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

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

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

	*p_old_offset = p_list->f_ptr;

	if (seek_mode == FROM_CURRENT) 
	{
		if (offset >= 0) 
		{
			udword walked_cluster_count;

			/* update current cluster */
			walked_cluster_count = (p_list->f_ptr % cluster_size + offset) / cluster_size;
			if (walked_cluster_count > 0) 
			{
				while (walked_cluster_count-- > 0) 
				{
					p_list->old_cur_cluster = p_list->cur_cluster;
					p_list->cur_cluster = GET_FAT_TBL(drv_no, p_list->cur_cluster);
				}
			}

			p_list->f_ptr += offset;
			if (p_list->f_ptr > p_list->size)
				p_list->f_ptr = p_list->size;
		}
		else 
		{
			udword i;

			if (p_list->f_ptr > (udword)(-offset))
				p_list->f_ptr += offset;
			else 
				p_list->f_ptr= 0;

			/* update current cluster */
			p_list->cur_cluster = p_list->cluster;
			p_list->old_cur_cluster = 0;
			for (i = cluster_size; i <= p_list->f_ptr; i += cluster_size) 
			{
				p_list->old_cur_cluster = p_list->cur_cluster;
				p_list->cur_cluster = GET_FAT_TBL(drv_no, p_list->cur_cluster);
			}
		}
	}
	else if (seek_mode == FROM_BEGIN) 
	{
		udword i;

		if (offset >= 0) 
		{
			p_list->f_ptr = offset;
			if (p_list->f_ptr > p_list->size) 
				p_list->f_ptr = p_list->size;
		}
		else 
			p_list->f_ptr = 0;

		/* update current cluster */
		p_list->cur_cluster = p_list->cluster;
		p_list->old_cur_cluster = 0;
		for (i = cluster_size; i <= p_list->f_ptr; i += cluster_size) 
		{
			p_list->old_cur_cluster = p_list->cur_cluster;
			p_list->cur_cluster = GET_FAT_TBL(drv_no, p_list->cur_cluster);
		}
	}
	else if (seek_mode == FROM_END) 
	{
		udword i;

		if (offset >= 0)
			p_list->f_ptr = p_list->size;
		else 
		{
			if (p_list->size < (udword)(-offset)) 
				p_list->f_ptr = 0;
			else
				p_list->f_ptr = p_list->size + offset;
		}

		/* update current cluster */
		p_list->cur_cluster = p_list->cluster;
		p_list->old_cur_cluster = 0;
		for (i = cluster_size; i <= p_list->f_ptr; i += cluster_size) 
		{
			p_list->old_cur_cluster = p_list->cur_cluster;
			p_list->cur_cluster = GET_FAT_TBL(drv_no, p_list->cur_cluster);
		}
	}
	else
		FAT_RETURN(drv_no, ERR_INVALID_PARAM);

	FAT_RETURN(drv_no, SM_OK);
}


/**********
 * Function: smCloseFile
 * Remarks:
 *	- close the opened file
 *	- updates file modified time, date, and the size
 * Parameters
 *	. h_file: opened file handle that should be closed
 * Notes:
 *	- if FAT_UPDATE_WHEN_CLOSE is defined, the FAT table must be updated.
 *		if not defined, it is updated everytime the file handle chain
 *		structure is changed
 **********/
SM_EXPORT ERR_CODE smCloseFile(F_HANDLE h_file) 
{
	udword drv_no;
	udword cluster;
	sOPENED_LIST* p_list;
	sTIME time_val;
	ubyte file_info[32];
	udword cluster_no;
	udword offset;
	udword id;

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

	if (p_list->mode & OPEN_W) 
	{
#ifndef WRITE_CACHE_DISABLE
		if (p_list->cache.count != 0)
			sm_WriteCacheToDisk(drv_no, p_list);
#endif

		s_smErr = sm_FindEntryInDirectory(drv_no, FIND_CLUSTER,	p_list->h_parent, cluster, file_info, &cluster_no, &offset);
		if (s_smErr != SM_OK) 
			FAT_RETURN(drv_no, s_smErr);

		sm_GetTime(&time_val);
		if (time_val.year > 1980)
			time_val.year -= 1980;
		else 
			time_val.year = 0;

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

		/* file_info[24-25] <= date */
		/*	Year | Month | Day => 7bit | 4bit | 5bit */
		file_info[24] = (time_val.day & 0x1f) | ((time_val.month << 5) & 0xe0);
		file_info[25] = ((time_val.month >> 3) & 0x01) | ((time_val.year << 1) & 0xfe);

		/* file_info[28-31] <= file size */
		file_info[28] = (ubyte)(p_list->size & 0xff);
		file_info[29] = (ubyte)((p_list->size >> 8) & 0xff);
		file_info[30] = (ubyte)((p_list->size >> 16) & 0xff);
		file_info[31] = (ubyte)((p_list->size >> 24) & 0xff);

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

		sm_prepareFileClose(drv_no, p_list);

#ifdef FAT_UPDATE_WHEN_FILE_CLOSE
		sm_FATUpdate(drv_no);
#endif
	}

	sm_DeleteFromOpenedFileList(drv_no, cluster);

	FAT_RETURN(drv_no, SM_OK);
}


/**********
 * Function: smRemoveFile
 * Remarks:
 *	- remove file and update FAT table
 * Parameters
 *	. p_file_name: file name that should be removed
 **********/
SM_EXPORT ERR_CODE smRemoveFile(const smchar* p_filename) 
{
	udword drv_no;
	F_HANDLE h_dir;
	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_RemoveFile(drv_no, h_dir, long_name);
	if (s_smErr != SM_OK)
		FAT_RETURN(drv_no, s_smErr);

⌨️ 快捷键说明

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