/**************************************************************************** * * _f_postformat * * erase fats, erase root directory, reset variables after formatting * * INPUTS * phy - media physical descriptor * fattype - one of this definitions F_FAT12_MEDIA,F_FAT16_MEDIA,F_FAT32_MEDIA * * RETURNS * error code or zero if successful * ***************************************************************************/ static unsigned char _f_postformat ( F_PHY * phy, unsigned char fattype ) { unsigned long a; unsigned char ret; _f_buildsectors( phy ); /*get positions*/ if ( gl_volume.mediatype != fattype ) { return F_ERR_MEDIATOOSMALL; } gl_volume.fatsector = (unsigned long)( -1 ); { unsigned char * ptr = (unsigned char *)gl_sector; unsigned char j = 2; unsigned long i; psp_memset( ptr, 0, F_SECTOR_SIZE ); switch ( gl_volume.mediatype ) { case F_FAT16_MEDIA: j = 3; break; case F_FAT32_MEDIA: j = 11; break; } *ptr = gl_volume.bootrecord.media_descriptor; psp_memset( ptr + 1, 0xff, j ); if ( gl_volume.mediatype == F_FAT32_MEDIA ) { *( ptr + 8 ) = (unsigned char)( F_CLUSTER_LAST & 0xff ); } (void)_f_writeglsector( gl_volume.firstfat.sector ); (void)_f_writeglsector( gl_volume.firstfat.sector + gl_volume.firstfat.num ); psp_memset( ptr, 0, ( j + 1 ) ); for ( i = 1 ; i < gl_volume.firstfat.num ; i++ ) { (void)_f_writeglsector( gl_volume.firstfat.sector + i ); (void)_f_writeglsector( gl_volume.firstfat.sector + i + gl_volume.firstfat.num ); } } for ( a = 0 ; a < gl_volume.root.num ; a++ ) /*reset root direntries*/ { ret = _f_writeglsector( gl_volume.root.sector + a ); if ( ret ) { return ret; } } return _f_writebootrecord( phy ); } /* _f_postformat */
/**************************************************************************** * * fn_hardformat * * Making a complete format on media, independently from master boot record, * according to media physical * * INPUTS * fattype - one of this definitions F_FAT12_MEDIA,F_FAT16_MEDIA,F_FAT32_MEDIA * * RETURNS * error code or zero if successful * ***************************************************************************/ unsigned char fn_hardformat ( unsigned char fattype ) { unsigned char ret; int mdrv_ret; F_PHY phy; ret = _f_getvolume(); if ( ret && ( ret != F_ERR_NOTFORMATTED ) ) { return ret; } gl_volume.state = F_STATE_NEEDMOUNT; psp_memset( &phy, 0, sizeof( F_PHY ) ); mdrv_ret = mdrv->getphy( mdrv, &phy ); if ( mdrv_ret ) { return F_ERR_ONDRIVE; } ret = _f_prepareformat( &phy, fattype ); /*no partition*/ if ( ret ) { return ret; } return _f_postformat( &phy, fattype ); } /* fn_hardformat */
/**************************************************************************** * * fn_getfreespace * * get total/free/used/bad diskspace * * INPUTS * pspace - pointer where to store the information * * RETURNS * error code * ***************************************************************************/ unsigned char fn_getfreespace ( F_SPACE * pspace ) { unsigned char ret; unsigned long a; unsigned long clustersize; ret = _f_getvolume(); if ( ret ) { return ret; } psp_memset( pspace, 0, sizeof( F_SPACE ) ); pspace->total = gl_volume.maxcluster; gl_volume.fatsector = (unsigned long)-1; for ( a = 2 ; a < gl_volume.maxcluster + 2 ; a++ ) { unsigned long value; ret = _f_getclustervalue( a, &value ); if ( ret ) { return ret; } if ( !value ) { ++( pspace->free ); } else if ( value == F_CLUSTER_BAD ) { ++( pspace->bad ); } else { ++( pspace->used ); } } clustersize = (unsigned long)( gl_volume.bootrecord.sector_per_cluster * F_SECTOR_SIZE ); for ( a = 0 ; ( clustersize & 1 ) == 0 ; a++ ) { clustersize >>= 1; } pspace->total_high = ( pspace->total ) >> ( 32 - a ); pspace->total <<= a; pspace->free_high = ( pspace->free ) >> ( 32 - a ); pspace->free <<= a; pspace->used_high = ( pspace->used ) >> ( 32 - a ); pspace->used <<= a; pspace->bad_high = ( pspace->bad ) >> ( 32 - a ); pspace->bad <<= a; return F_NO_ERROR; } /* fn_getfreespace */
/**************************************************************************** * * _f_extend * * Extend file to a certain size * ***************************************************************************/ static unsigned char _f_extend ( long size ) { unsigned long _size; unsigned char rc; size -= gl_file.filesize; _size = (unsigned long)size; rc = _f_getcurrsector(); if ( rc ) { return rc; } psp_memset( gl_sector + gl_file.relpos, 0, ( F_SECTOR_SIZE - gl_file.relpos ) ); if ( gl_file.relpos + _size > F_SECTOR_SIZE ) { _size -= ( F_SECTOR_SIZE - gl_file.relpos ); while ( _size ) { if ( _f_emptywritebuffer() ) { return F_ERR_WRITE; } psp_memset( gl_sector, 0, F_SECTOR_SIZE ); _size -= ( _size > F_SECTOR_SIZE ? F_SECTOR_SIZE : _size ); } } else { _size += gl_file.relpos; } gl_file.modified = 1; gl_file.filesize += size; gl_file.abspos = gl_file.filesize & ( ~( F_SECTOR_SIZE - 1 ) ); gl_file.relpos = _size; return F_NO_ERROR; } /* _f_extend */
/**************************************************************************** * * _f_writebootrecord * * writing boot record onto a volume, it uses number of hidden sector variable * * INPUTS * phy - media physical descriptor * * RETURNS * error code or zero if successful * ***************************************************************************/ static unsigned char _f_writebootrecord ( F_PHY * phy ) { unsigned char jump_code[] = { 0xeb, 0x3c, 0x90 }; unsigned char oem_name[] = "MSDOS5.0"; unsigned char executable_marker[] = { 0x55, 0xaa }; unsigned char * ptr = (unsigned char *)gl_sector; unsigned char rs; unsigned short mre; unsigned char ret; unsigned char _n = 0; if ( gl_volume.mediatype == F_FAT32_MEDIA ) { /*write FS_INFO*/ unsigned char a; rs = 32 + 4; mre = 0; psp_memset( ptr, 0, F_SECTOR_SIZE ); for ( a = 0 ; a < rs ; a++ ) { ret = _f_writeglsector( a ); /*erase reserved area*/ if ( ret ) { return ret; } } ptr = _setlong( 0x41615252, ptr ); /*signature*/ ptr = _setcharzero( 480, ptr ); /*reserved*/ ptr = _setlong( 0x61417272, ptr ); /*signature*/ ptr = _setlong( 0xffffffff, ptr ); /*no last*/ ptr = _setlong( 0xffffffff, ptr ); /*no hint*/ ptr = _setcharzero( 12, ptr ); /*reserved*/ ptr = _setlong( 0xaa550000, ptr ); /*trail*/ ret = _f_writeglsector( 1 ); /*write FSINFO*/ if ( ret ) { return ret; } ret = _f_writeglsector( 1 + 6 ); /*write FSINFO*/ if ( ret ) { return ret; } } else { rs = 1; mre = 512; } ptr = (unsigned char *)gl_sector; ptr = _setchar( jump_code, sizeof( jump_code ), ptr ); ptr = _setchar( oem_name, sizeof( oem_name ) - 1, ptr ); ptr = _setword( F_SECTOR_SIZE, ptr ); *ptr++ = gl_volume.bootrecord.sector_per_cluster; ptr = _setword( rs, ptr ); /* reserved sectors */ *ptr++ = 2; /* number of FATs */ ptr = _setword( mre, ptr ); /* max root entry */ if ( phy->number_of_sectors < 0x10000 ) { ptr = _setword( (unsigned short)phy->number_of_sectors, ptr ); } else { ptr = _setword( 0, ptr ); } *ptr++ = 0xf0; /* media descriptor */ ptr = _setword( (unsigned short)gl_volume.bootrecord.sector_per_FAT, ptr ); ptr = _setword( phy->sector_per_track, ptr ); ptr = _setword( phy->number_of_heads, ptr ); ptr = _setlong( 0, ptr ); /* number of hidden sectors */ if ( phy->number_of_sectors >= 0x10000 ) { ptr = _setlong( phy->number_of_sectors, ptr ); } else { ptr = _setlong( 0, ptr ); /* number of sectors */ } if ( gl_volume.mediatype == F_FAT32_MEDIA ) { ptr = _setlong( gl_volume.bootrecord.sector_per_FAT32, ptr ); ptr = _setword( 0, ptr ); ptr = _setword( 0, ptr ); ptr = _setlong( 2, ptr ); ptr = _setword( 1, ptr ); ptr = _setword( 6, ptr ); ptr = _setchar( NULL, 12, ptr ); _n = 28; } ptr = _setword( 0, ptr ); /* logical drive num */ *ptr++ = 0x29; /* extended signature */ ptr = _setlong( 0x11223344, ptr ); ptr = _setchar( (const unsigned char *)"NO NAME ", 11, ptr ); /* volume name */ switch ( gl_volume.mediatype ) { case F_FAT12_MEDIA: ptr = _setchar( (const unsigned char *)"FAT12 ", 8, ptr ); break; case F_FAT16_MEDIA: ptr = _setchar( (const unsigned char *)"FAT16 ", 8, ptr ); break; case F_FAT32_MEDIA: ptr = _setchar( (const unsigned char *)"FAT32 ", 8, ptr ); break; default: return F_ERR_INVALIDMEDIA; } /* switch */ ptr = _setchar( 0, 448 - _n, ptr ); ptr = _setchar( executable_marker, sizeof( executable_marker ), ptr ); if ( _n ) { ret = _f_writeglsector( 6 ); if ( ret ) { return ret; } } return _f_writeglsector( 0 ); /*write bootrecord*/ } /* _f_writebootrecord */
/**************************************************************************** * * fn_open * * open a file for reading/writing/appending * * INPUTS * * filename - which file need to be opened * mode - string how to open ("r"-read, "w"-write, "w+"-overwrite, "a"-append * * RETURNS * * F_FILE pointer if successfully * 0 - if any error * ***************************************************************************/ F_FILE * fn_open ( const char * filename, const char * mode ) { F_DIRENTRY * de; F_NAME fsname; unsigned short date; unsigned short time; unsigned char m_mode = F_FILE_CLOSE; if ( mode[1] == 0 ) { if ( mode[0] == 'r' ) { m_mode = F_FILE_RD; } if ( mode[0] == 'w' ) { m_mode = F_FILE_WR; } if ( mode[0] == 'a' ) { m_mode = F_FILE_A; } } if ( ( mode[1] == '+' ) && ( mode[2] == 0 ) ) { if ( mode[0] == 'r' ) { m_mode = F_FILE_RDP; } if ( mode[0] == 'w' ) { m_mode = F_FILE_WRP; } if ( mode[0] == 'a' ) { m_mode = F_FILE_AP; } } if ( m_mode == F_FILE_CLOSE ) { return 0; /*invalid mode*/ } if ( _f_setfsname( filename, &fsname ) ) { return 0; /*invalid name*/ } if ( _f_checknamewc( fsname.filename, fsname.fileext ) ) { return 0; /*invalid name*/ } if ( fsname.filename[0] == '.' ) { return 0; } if ( _f_getvolume() ) { return 0; /*cant open any*/ } if ( gl_file.mode != F_FILE_CLOSE ) { return 0; } psp_memset( &gl_file, 0, sizeof( F_FILE ) ); if ( !_f_findpath( &fsname, &gl_file.dirpos ) ) { return 0; } switch ( m_mode ) { case F_FILE_RDP: /*r*/ case F_FILE_RD: /*r*/ if ( !_f_findfilewc( fsname.filename, fsname.fileext, &gl_file.dirpos, &de, 0 ) ) { return 0; } if ( de->attr & F_ATTR_DIR ) { return 0; /*directory*/ } gl_file.startcluster = _f_getdecluster( de ); if ( gl_file.startcluster ) { _f_clustertopos( gl_file.startcluster, &gl_file.pos ); gl_file.filesize = _f_getlong( &de->filesize ); gl_file.abspos = (unsigned long) (-1 * (long) F_SECTOR_SIZE); if ( _f_fseek( 0 ) ) { return 0; } } #if F_FILE_CHANGED_EVENT if ( m_mode == F_FILE_RDP ) { _f_createfullname( gl_file.filename, sizeof( gl_file.filename ), fsname.path, fsname.filename, fsname.fileext ); } #endif break; case F_FILE_AP: case F_FILE_A: /*a*/ psp_memcpy( &( gl_file.pos ), &( gl_file.dirpos ), sizeof( F_POS ) ); if ( _f_findfilewc( fsname.filename, fsname.fileext, &gl_file.dirpos, &de, 0 ) ) { if ( de->attr & ( F_ATTR_DIR | F_ATTR_READONLY ) ) { return 0; } gl_file.startcluster = _f_getdecluster( de ); gl_file.filesize = _f_getlong( &de->filesize ); if ( gl_file.startcluster ) { _f_clustertopos( gl_file.startcluster, &gl_file.pos ); gl_file.abspos = (unsigned long) (-1 * (long) F_SECTOR_SIZE); /*forcing seek to read 1st sector! abspos=0;*/ if ( _f_fseek( (long)gl_file.filesize ) ) { gl_file.mode = F_FILE_CLOSE; return 0; } } } else { psp_memcpy( &( gl_file.dirpos ), &( gl_file.pos ), sizeof( F_POS ) ); _f_clustertopos( gl_file.dirpos.cluster, &gl_file.pos ); if ( _f_addentry( &fsname, &gl_file.dirpos, &de ) ) { return 0; /*couldnt be added*/ } de->attr |= F_ATTR_ARC; /*set as archiv*/ if ( _f_writeglsector( (unsigned long)-1 ) ) { return 0; } } #if F_FILE_CHANGED_EVENT _f_createfullname( gl_file.filename, sizeof( gl_file.filename ), fsname.path, fsname.filename, fsname.fileext ); #endif break; case F_FILE_WR: /*w*/ case F_FILE_WRP: /*w+*/ _f_clustertopos( gl_file.dirpos.cluster, &gl_file.pos ); if ( _f_findfilewc( fsname.filename, fsname.fileext, &gl_file.pos, &de, 0 ) ) { unsigned long cluster = _f_getdecluster( de ); /*exist*/ if ( de->attr & ( F_ATTR_DIR | F_ATTR_READONLY ) ) { return 0; } psp_memcpy( &( gl_file.dirpos ), &( gl_file.pos ), sizeof( F_POS ) ); _f_setlong( de->filesize, 0 ); /*reset size;*/ de->attr |= F_ATTR_ARC; /*set as archiv*/ _f_setword( de->clusterlo, 0 ); /*no points anywhere*/ _f_setword( de->clusterhi, 0 ); if ( gl_volume.mediatype == F_FAT32_MEDIA ) { f_igettimedate( &time, &date ); _f_setword( &de->crtdate, date ); /*if there is realtime clock then creation date could be set from*/ _f_setword( &de->crttime, time ); /*if there is realtime clock then creation time could be set from*/ _f_setword( &de->lastaccessdate, date ); /*if there is realtime clock then creation date could be set from*/ } if ( _f_writeglsector( (unsigned long)-1 ) ) { return 0; } if ( _f_removechain( cluster ) ) { return 0; /*remove */ } } else { if ( _f_addentry( &fsname, &gl_file.dirpos, &de ) ) { return 0; /*couldnt be added*/ } psp_memset( &gl_file, 0, 21 ); de->attr |= F_ATTR_ARC; /*set as archiv*/ if ( _f_writeglsector( (unsigned long)-1 ) ) { return 0; } } #if F_FILE_CHANGED_EVENT _f_createfullname( gl_file.filename, sizeof( gl_file.filename ), fsname.path, fsname.filename, fsname.fileext ); #endif break; default: return 0; /*invalid mode*/ } /* switch */ gl_file.mode = m_mode; /* lock it */ return (F_FILE *)1; } /* fn_open */
/**************************************************************************** * * _f_extend * * Extend file to a certain size * ***************************************************************************/ static unsigned char _f_extend ( long size ) { unsigned long _size; unsigned char rc; size -= gl_file.filesize; _size = (unsigned long)size; if ( gl_file.startcluster == 0 ) { if ( _f_stepnextsector() ) { return F_ERR_WRITE; } } else { if ( ( gl_file.relpos > 0 ) && ( gl_file.relpos < F_SECTOR_SIZE ) ) { rc = _f_getcurrsector(); if ( rc ) { return rc; } } } if ( gl_file.relpos + _size >= F_SECTOR_SIZE ) { if ( gl_file.relpos < F_SECTOR_SIZE ) { psp_memset( gl_sector + gl_file.relpos, 0, ( F_SECTOR_SIZE - gl_file.relpos ) ); _size -= ( F_SECTOR_SIZE - gl_file.relpos ); if ( _f_writeglsector( gl_file.pos.sector ) ) { return F_ERR_WRITE; } } if ( _f_stepnextsector() ) { return F_ERR_WRITE; } psp_memset( gl_sector, 0, F_SECTOR_SIZE ); while ( _size >= F_SECTOR_SIZE ) { if ( _f_writeglsector( gl_file.pos.sector ) ) { return F_ERR_WRITE; } if ( _f_stepnextsector() ) { return F_ERR_WRITE; } psp_memset( gl_sector, 0, F_SECTOR_SIZE ); _size -= F_SECTOR_SIZE; } } else { psp_memset( gl_sector + gl_file.relpos, 0, ( F_SECTOR_SIZE - gl_file.relpos ) ); _size += gl_file.relpos; } gl_file.modified = 1; gl_file.filesize += size; gl_file.abspos = gl_file.filesize & ( ~( F_SECTOR_SIZE - 1 ) ); gl_file.relpos = _size; return F_NO_ERROR; } /* _f_extend */