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

📄 smf_fat.c

📁 the test file for GP32 gameboy hack
💻 C
📖 第 1 页 / 共 5 页
字号:
		FAT_RETURN(drv_no, s_smErr);

	cluster_size = s_smInfo[drv_no].pbr.bpb.sectors_per_cluster * SECTOR_SIZE;
	total_clusters = (s_smInfo[drv_no].pbr.bpb.total_sectors ? s_smInfo[drv_no].pbr.bpb.total_sectors : s_smInfo[drv_no].pbr.bpb.huge_sectors - 1) 
					/ s_smInfo[drv_no].pbr.bpb.sectors_per_cluster + 1;
	p_info->total_size = total_clusters * s_smInfo[drv_no].pbr.bpb.sectors_per_cluster * SECTOR_SIZE;
	p_info->sector_per_cluster = s_smInfo[drv_no].pbr.bpb.sectors_per_cluster;
	p_info->sector_size = SECTOR_SIZE;

	p_info->used_size = p_info->free_size = p_info->bad_cluster_num = 0;


	for (i = 2; i < total_clusters + 2; ++i) 
	{
		fat_val = GET_FAT_TBL(drv_no, i);

		if (fat_val == UNUSED_CLUSTER) 
			p_info->free_size += cluster_size;
		else if (fat_val == DEFECTIVE_CLUSTER)
			++p_info->bad_cluster_num;
		else 
			p_info->used_size += cluster_size;
	}

	FAT_RETURN(drv_no, SM_OK);
}


/**********
 * Function: smFormatVol
 * Remarks:
 *	- lower layer format, get device info from lower layer,
 *		set MBR/PBR/FAT, and initialize FAT layer variables
 * Parameters:
 *	. p_vol_name: volumn name that is mounted (ex. "dev0:")
 *	. p_label: label string
 *	. format_id: FORMAT_NORMAL, FORMAT_RESCUE
 *	. p_bad_count (result): number of error blocks
 * Notes:
 *	- do not implements sm_PreFAT as in other API's, but lock is needed
 *	- format_id is not used now (reserved)
 **********/
SM_EXPORT ERR_CODE smFormatVol(const smchar* p_volumn_name, const smchar* p_label, udword format_id, udword* p_bad_count) 
{
	udword drv_no;
	udword i, j;
	sSM_INFO sm_info;
	const sDEV_INFO* dev_info;
	udword pbr_sector;
	udword block;
	udword sector;
	udword offset;
	udword changed_pblock;
	udword needed_blocks;
	udword needed_sectors;
	udword fat_sectors;
	udword root_sectors;
	udword err_count;
	ubyte* acFATBuf;
	ubyte *p_vol_name = (ubyte *)p_volumn_name;

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

	/*
	 * lower layer format. all physical blocks are erased now.
	 */
	format_id = (format_id == FORMAT_RESCUE) ? LPT_FORMAT_RESCUE : LPT_FORMAT_NORMAL;
	s_smErr = smlFormatVol(drv_no, format_id, &err_count);
	if (s_smErr != SM_OK)
		return s_smErr;

	*p_bad_count = err_count;

	/*
	 * get device info
	 */
	s_smErr = smlGetDeviceInfo(drv_no, &dev_info);
	if (s_smErr != SM_OK)
		return s_smErr;

	fat_sectors = (dev_info->allS <= 128000)
					? (((dev_info->LBpV + 2) * 3 / 2 - 1) / dev_info->szS + 1)
					: (((dev_info->LBpV + 2) * 2 - 1) / dev_info->szS + 1);
	root_sectors = (ROOT_DIR_ENTRY * 32 - 1) / SECTOR_SIZE + 1;
	needed_sectors = 1 + 2 * fat_sectors + root_sectors;
	/* let 0th block reserved only for MBR */
	needed_blocks = (needed_sectors - 1) / dev_info->SpB + 2;
	pbr_sector = needed_blocks * dev_info->SpB - needed_sectors;

	/* set MBR values */
	sm_info.mbr.partition_entry[0].def_boot = 0x80;
	sm_info.mbr.partition_entry[0].start_cyl = (pbr_sector / dev_info->SpH) / dev_info->HpC;
	sm_info.mbr.partition_entry[0].start_head = (pbr_sector / dev_info->SpH) % dev_info->HpC;
	sm_info.mbr.partition_entry[0].start_sector	= (pbr_sector % dev_info->SpH) + 1;
	sm_info.mbr.partition_entry[0].pt_type = 1;		/*??? */
	sm_info.mbr.partition_entry[0].end_cyl = dev_info->CpV - 1;
	sm_info.mbr.partition_entry[0].end_head = dev_info->HpC - 1;
	sm_info.mbr.partition_entry[0].end_sector = dev_info->SpH;
	sm_info.mbr.partition_entry[0].start_lba_sector = pbr_sector;
	sm_info.mbr.partition_entry[0].total_available_sectors = dev_info->CpV * dev_info->HpC * dev_info->SpH - pbr_sector;
	sm_info.mbr.signature = 0x55aa;

	/* set PBR values */
	SM_MEMCPY(&sm_info.pbr.oem_name[0], "SMFS1.0", 8);
	sm_info.pbr.bpb.bytes_per_sector = dev_info->szS;
	sm_info.pbr.bpb.sectors_per_cluster = dev_info->SpB;
	sm_info.pbr.bpb.reserved_sectors = 1;		/*??? */
	sm_info.pbr.bpb.fat_num = 2;
	sm_info.pbr.bpb.root_entry = ROOT_DIR_ENTRY;
/*	sm_info.pbr.bpb.total_sectors
		= (dev_info->allS <= 65535) ? dev_info->allS : 0; */
	sm_info.pbr.bpb.total_sectors = (sm_info.mbr.partition_entry[0].total_available_sectors	<= 65535)
									? sm_info.mbr.partition_entry[0].total_available_sectors : 0;
	sm_info.pbr.bpb.format_type = 0xf8;
	sm_info.pbr.bpb.sectors_in_fat = fat_sectors;
	sm_info.pbr.bpb.sectors_per_track = dev_info->SpH;	/*??? */
	sm_info.pbr.bpb.head_num = dev_info->HpC;
	sm_info.pbr.bpb.hidden_sectors = pbr_sector;
/*	sm_info.pbr.bpb.huge_sectors
		= (dev_info->allS <= 65535) ? 0 : dev_info->allS; */
	sm_info.pbr.bpb.huge_sectors = (sm_info.mbr.partition_entry[0].total_available_sectors <= 65535)
									? 0	: sm_info.mbr.partition_entry[0].total_available_sectors;
	sm_info.pbr.drive_num = 0x80;
	sm_info.pbr.reserved = 0;
	sm_info.pbr.ext_boot_signature = 0x29;
	sm_info.pbr.vol_id = 0;		/*??? */
	SM_MEMSET(&sm_info.pbr.vol_label[0], ' ', 11);
	for (i = 0; i < 11; ++i) 
	{
		if (p_label[i] == 0)
			break;

		sm_info.pbr.vol_label[i] = p_label[i];
	}
	if (dev_info->allS <= 128000) 		/* 64MB */
		sm_info.pbr.file_sys_type = FS_FAT12;
	else 
		sm_info.pbr.file_sys_type = FS_FAT16;

	sm_info.pbr.signature = 0x55aa;

	/* write MBR & PBR */
	s_smErr = sm_WriteSMInfo(drv_no, &sm_info);
	if (s_smErr != SM_OK)
		return s_smErr;

	/*
	 * register new logical blocks until the end of root_dir_entry
	 */
	block = (pbr_sector + (2 * sm_info.pbr.bpb.sectors_in_fat) + ((ROOT_DIR_ENTRY * 32 - 1) / SECTOR_SIZE + 1))	/ sm_info.pbr.bpb.sectors_per_cluster;
	for (i = pbr_sector / sm_info.pbr.bpb.sectors_per_cluster + 1;	i <= block; ++i) 
	{
		smlGetNewSpecifiedBlock(drv_no, i, &changed_pblock);
	}

	/*
	 * FAT table write
	 */
	acFATBuf = SMB_ALLOC_BUF();
	if (!acFATBuf)
		return ERR_OUT_OF_MEMORY;

	SM_MEMSET(acFATBuf, 0, SECTOR_SIZE);
	block = (pbr_sector + 1) / sm_info.pbr.bpb.sectors_per_cluster;
	offset = ((pbr_sector + 1) % sm_info.pbr.bpb.sectors_per_cluster) * SECTOR_SIZE;

	for (i = 0; i < 2; ++i) 
	{
		acFATBuf[0] = 0xf8;
		acFATBuf[1] = 0xff;
		acFATBuf[2] = 0xff;

		s_smErr = smlWriteBlock(drv_no, block, offset, acFATBuf, SECTOR_SIZE);
		if (s_smErr != SM_OK) 
		{
			SMB_FREE_BUF(acFATBuf);
			return s_smErr;
		}

		offset += SECTOR_SIZE;
		if (offset >= sm_info.pbr.bpb.sectors_per_cluster * SECTOR_SIZE) 
		{
			++block;
			offset = 0;
		}

		acFATBuf[0] = 0;
		acFATBuf[1] = 0;
		acFATBuf[2] = 0;

		for (j = 1; j < sm_info.pbr.bpb.sectors_in_fat; ++j) 
		{
			s_smErr = smlWriteBlock(drv_no, block, offset, acFATBuf, SECTOR_SIZE);
			if (s_smErr != SM_OK) 
			{
				SMB_FREE_BUF(acFATBuf);
				return s_smErr;
			}

			offset += SECTOR_SIZE;
			if (offset >= sm_info.pbr.bpb.sectors_per_cluster * SECTOR_SIZE) 
			{
				++block;
				offset = 0;
			}
		}
	}

	/*
	 * Root Dir Entry write (empty)
	 */
	SM_MEMSET(acFATBuf, 0, SECTOR_SIZE);
	sector = root_sectors;
	for (i = 0; i < sector; ++i) 
	{
		s_smErr = smlWriteBlock(drv_no, block, offset, acFATBuf, SECTOR_SIZE);
		if (s_smErr != SM_OK) 
		{
			SMB_FREE_BUF(acFATBuf);
			return s_smErr;
		}

		offset += SECTOR_SIZE;
		if (offset >= sm_info.pbr.bpb.sectors_per_cluster * SECTOR_SIZE) 
		{
			++block;
			offset = 0;
		}
	}
	SMB_FREE_BUF(acFATBuf);

	/*
	 * FAT variables initialize
	 */
	sm_FATInit(drv_no);

	return SM_OK;
}


/**********
 * Function: smMountVol
 * Remarks:
 *	- maps string volumn name to the drive. Default name is
 *		"dev0", .., "dev99"
 * Parameters
 *	. drv_no: drive number that is initialized in configuration file
 *	. p_vol_name: string volumn name that is mapped to the drive
 **********/
SM_EXPORT ERR_CODE smMountVol(udword drv_no, const smchar* p_volumn_name) 
{
	ubyte *p_vol_name = (ubyte *)p_volumn_name;

	if (SM_STRLEN((char*)p_vol_name) > MAX_DRIVE_NAME_LEN)
		return ERR_INVALID_PARAM;

	SM_STRCPY((char*)s_drvName[drv_no], (char*)p_vol_name);

	return SM_OK;
}


/**********
 * Function: smUnmountVol
 * Remarks:
 *	- reverts to the default string volumn name
 *		(ex. "dev0", .., "dev99")
 * Parameters
 *	. drv_no: drive number that is initialized in configuration file
 **********/
SM_EXPORT ERR_CODE smUnmountVol(udword drv_no) 
{
	ubyte name[10];

	SM_STRCPY((char*)name, "dev");
	if (drv_no < 10) 
	{
		name[4] = (ubyte)drv_no + '0';
		name[5] = 0;
	}
#if (MAX_DRIVE >= 10)
	else if (drv_no < 100) 
	{
		name[4] = drv_no / 10 + '0';
		name[5] = drv_no % 10 + '0';
		name[6] = 0;
	}
	else 
	{
		name[4] = drv_no / 100 + '0';
		name[5] = (drv_no / 10) % 10 + '0';
		name[6] = drv_no % 10 + '0';
		name[7] = 0;
	}
#endif

	SM_STRCPY((char*)s_drvName[drv_no], (char*)name);

	return SM_OK;
}


/**********
 * Function: smMoveFile
 * Remarks:
 *  - move a file or directory to a new directory
 *  - old path and new path should be on the same volume
 *  - new path must not already exist
 * Parameters
 *  . old_name: path of old file or directory
 *  . new_name: path of new file or directory
 **********/
SM_EXPORT ERR_CODE smMoveFile(const smchar* old_name, const smchar* new_name) 
{
	udword drv_no;
	F_HANDLE h_dir;
	F_HANDLE h_new_dir;
	F_HANDLE h_file;
	ubyte fileInfo[32];
	udword cluster;
	udword offset;
	ubyte oldName[MAX_FILE_NAME_LEN + 1];
	ubyte newName[MAX_FILE_NAME_LEN + 1];
	ubyte * oldPath = (ubyte *)old_name;
	ubyte * newPath = (ubyte *)new_name;
	sFILE_STAT sStat;
#ifdef	LONG_FILE_NAME_ENABLE
	uword* p_unicode;
	ubyte fat_name[13];
#endif

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

	/* if different volumes, fail */
	if (drv_no != sm_GetDrvNo(newPath)) 
		return ERR_INVALID_PARAM;

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

	/* check if old & new directories are the same. */
	s_smErr = sm_CheckPath(drv_no, oldPath, PATH_EXCEPT_LAST, &h_dir);
	if (s_smErr != SM_OK)
		FAT_RETURN(drv_no, ERR_FILE_NOT_EXIST);

	s_smErr = sm_CheckPath(drv_no, newPath, PATH_EXCEPT_LAST, &h_new_dir);
	if (s_smErr != SM_OK)
		FAT_RETURN(drv_no, ERR_FILE_EXIST);

	/* check if newPath exist. if so, fail */
	s_smErr = sm_CheckPath(drv_no, newPath, PATH_FULL, &h_file);
	if (s_smErr == SM_OK)
		FAT_RETURN(drv_no, s_smErr);

	sm_ExtractLastName(oldPath, oldName);
	sm_ExtractLastName(newPath, newName);

	/* retrieve old file or directory info */
	s_smErr = sm_FindEntryInDirectory(drv_no, FIND_FILE_NAME, h_dir, (udword)oldName, fileInfo, &cluster, &offset);
	if (s_smErr != SM_OK) 
		FAT_RETURN(drv_no, s_smErr);

	/* delete old file */
	s_smErr = sm_DeleteFromDirEntry(drv_no, h_dir, oldName);
	if (s_smErr != SM_OK)
		FAT_RETURN(drv_no, s_smErr);

	/* create new directory entry */
	sStat.attr = fileInfo[11];
	sStat.cluster = fileInfo[26] | ((udword)fileInfo[27] << 8);
	sStat.size = fileInfo[28] | ((udword)fileInfo[29] << 8) | ((udword)fileInfo[30] << 16) | ((udword)fileInfo[31] << 24);
	sStat.time.year = 1980 + ((fileInfo[25] >> 1) & 0x7f);
	sStat.time.month = ((fileInfo[25] << 3) & 0x08) | ((fileInfo[24] >> 5) & 0x07);
	sStat.time.day = fileInfo[24] & 0x1f;
	sStat.time.hour = (fileInfo[23] >> 3) & 0x1f;
	sStat.time.min = ((fileInfo[23] << 3) & 0x38) | ((fileInfo[22] >> 5) & 0x07);
	sStat.time.sec = fileInfo[22] & 0x1f;
	sStat.time.msec = 0;

#ifdef	LONG_FILE_NAME_ENABLE
	p_unicode = (uword*)SM_MALLOC(MAX_FILE_NAME_LEN+2);
	if(p_unicode == NULL)
	{
		FAT_RETURN(drv_no, ERR_OUT_OF_MEMORY);
	}

	if(sm_ConvertToFATName(newName, fat_name))
	{
		SM_MBS_TO_UNICODE(p_unicode, newName, 0);	
		s_smErr = sm_AddToDirEntry(drv_no, h_new_dir, newName, p_unicode, &sStat, 0, 0, 0);
	}
	else
		s_smErr = sm_AddToDirEntry(drv_no, h_new_dir, newName, NULL, &sStat, 0, 0, 0);

	SM_FREE(p_unicode);
#else
	s_smErr = sm_AddToDirEntry(drv_no, h_new_dir, newName, NULL, &sStat, 0, 0, 0);
#endif	

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

	FAT_RETURN(drv_no, SM_OK);
}



/**********
 * Function: smRenameFile
 * Remarks:
 *  - rename a file or directory
 *  - old path and new path should have the same parent path
 *  - new path must not already exist
 * Parameters
 *  . old_name: path of old file or directory
 *  . new_name: path of new file or directory
 * Notes
 *	- smRemoveFile deletes old_name and create new_name, but smRenameFile
 *		just renames old_name to new_name at the same position
 *	- This API is not recommended to use in normal case. It could have a lot of overheads
 *		that shifts the whole block contents in the worst case
 **********/
SM_EXPORT ERR_CODE smRenameFile(const smchar* old_name, const smchar* new_name) 
{
	udword drv_no;
	F_HANDLE h_dir;
	F_HANDLE h_new_dir;
	F_HANDLE h_file;
	ubyte fileInfo[32];
	udword cluster;
	udword offset;
	sFILE_STAT sStat;
	ubyte oldName[MAX_FILE_NAME_LEN + 1];
	ubyte newName[MAX_FILE_NAME_LEN + 1];
	ubyte * oldPath = (ubyte *)old_name;
	ubyte * newPath = (ubyte *)new_name;
#ifdef	LONG_FILE_NAME_ENABLE
	uword* p_unicode;
	ubyte fat_name[13];
#endif

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

	/* if different volumes, fail */
	if (drv_no != sm_GetDrvNo(newPath)) 
		return ERR_INVALID_PARAM;

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

	/* check if old & new directories are the same. */
	s_smErr = sm_CheckPath(drv_no, oldPath, PATH_EXCEPT_LAST, &h_dir);
	if (s_smErr != SM_OK)
		FAT_RETURN(drv_no, ERR_FILE_NOT_EXIST);

	s_smErr = sm_CheckPath(

⌨️ 快捷键说明

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