/***************************************************************************** Function: MPFS_HANDLE MPFSOpenID(WORD hFatID) Summary: Quickly re-opens a file. Description: Quickly re-opens a file in the MPFS2 file system. Use this function along with MPFSGetID() to quickly re-open a file without tying up a permanent MPFSStub. Precondition: None Parameters: hFatID - the ID of a previous opened file in the FAT Returns: An MPFS_HANDLE to the opened file if found, or MPFS_INVALID_HANDLE if the file could not be found or no free handles exist. ***************************************************************************/ MPFS_HANDLE MPFSOpenID(WORD hFatID) { MPFS_HANDLE hMPFS; // Make sure MPFS is unlocked and we got a valid id if(isMPFSLocked == TRUE || hFatID > numFiles) return MPFS_INVALID_HANDLE; // Find a free file handle to use for(hMPFS = 1; hMPFS <= MAX_MPFS_HANDLES; hMPFS++) if(MPFSStubs[hMPFS].addr == MPFS_INVALID) break; if(hMPFS == MAX_MPFS_HANDLES) return MPFS_INVALID_HANDLE; // Load the FAT record _LoadFATRecord(hFatID); // Set up the file handle MPFSStubs[hMPFS].fatID = hFatID; MPFSStubs[hMPFS].addr = fatCache.data; MPFSStubs[hMPFS].bytesRem = fatCache.len; return hMPFS; }
/***************************************************************************** Function: MPFS_PTR MPFSGetEndAddr(MPFS_HANDLE hMPFS) Description: Determines the ending address of a file. Precondition: The file handle referenced by hMPFS is already open. Parameters: hMPFS - the file handle from which to read the metadata Returns: The address just after the file ends (start address of next file) ***************************************************************************/ MPFS_PTR MPFSGetEndAddr(MPFS_HANDLE hMPFS) { // Make sure a valid file is open if(hMPFS > MAX_MPFS_HANDLES) return MPFS_INVALID; if(MPFSStubs[hMPFS].addr == MPFS_INVALID) return MPFS_INVALID; // Move to the point for reading _LoadFATRecord(MPFSStubs[hMPFS].fatID); return fatCache.data + fatCache.len; }
/***************************************************************************** Function: DWORD MPFSGetSize(MPFS_HANDLE hMPFS) Description: Reads the size of a file. Precondition: The file handle referenced by hMPFS is already open. Parameters: hMPFS - the file handle from which to read the metadata Returns: The size that was read as a DWORD ***************************************************************************/ DWORD MPFSGetSize(MPFS_HANDLE hMPFS) { // Make sure a valid file is open if(hMPFS > MAX_MPFS_HANDLES) return 0x00000000; if(MPFSStubs[hMPFS].addr == MPFS_INVALID) return 0x00000000; // Move to the point for reading _LoadFATRecord(MPFSStubs[hMPFS].fatID); return fatCache.len; }
/***************************************************************************** Function: BOOL MPFSGetFilename(MPFS_HANDLE hMPFS, BYTE* cName, WORD wLen) Description: Reads the file name of a file that is already open. Precondition: The file handle referenced by hMPFS is already open. Parameters: hMPFS - the file handle from which to determine the file name cName - where to store the name of the file wLen - the maximum length of data to store in cName Return Values: TRUE - the file name was successfully located FALSE - the file handle provided is not currently open ***************************************************************************/ BOOL MPFSGetFilename(MPFS_HANDLE hMPFS, BYTE* cName, WORD wLen) { DWORD addr; // Make sure a valid file is open if(hMPFS > MAX_MPFS_HANDLES) return FALSE; if(MPFSStubs[hMPFS].addr == MPFS_INVALID) return FALSE; // Move to the point for reading _LoadFATRecord(MPFSStubs[hMPFS].fatID); addr = fatCache.string; MPFSStubs[0].addr = addr; MPFSStubs[0].bytesRem = 255; // Read the value and return MPFSGetArray(0, cName, wLen); return TRUE; }
MPFS_HANDLE MPFSOpenROM(ROM BYTE* cFile) { MPFS_HANDLE hMPFS; WORD nameHash, i; WORD hashCache[8]; ROM BYTE *ptr; BYTE c; // Make sure MPFS is unlocked and we got a filename if(*cFile == '\0' || isMPFSLocked == TRUE) return MPFS_INVALID_HANDLE; // Calculate the name hash to speed up searching for(nameHash = 0, ptr = cFile; *ptr != '\0'; ptr++) { nameHash += *ptr; nameHash <<= 1; } // Find a free file handle to use for(hMPFS = 1; hMPFS <= MAX_MPFS_HANDLES; hMPFS++) if(MPFSStubs[hMPFS].addr == MPFS_INVALID) break; if(hMPFS == MAX_MPFS_HANDLES) return MPFS_INVALID_HANDLE; // Read in hashes, and check remainder on a match. Store 8 in cache for performance for(i = 0; i < numFiles; i++) { // For new block of 8, read in data if((i & 0x07) == 0u) { MPFSStubs[0].addr = 8 + i*2; MPFSStubs[0].bytesRem = 16; MPFSGetArray(0, (BYTE*)hashCache, 16); } // If the hash matches, compare the full filename if(hashCache[i&0x07] == nameHash) { _LoadFATRecord(i); MPFSStubs[0].addr = fatCache.string; MPFSStubs[0].bytesRem = 255; // Loop over filename to perform comparison for(ptr = cFile; *ptr != '\0'; ptr++) { MPFSGet(0, &c); if(*ptr != c) break; } MPFSGet(0, &c); if(c == '\0' && *ptr == '\0') {// Filename matches, so return true MPFSStubs[hMPFS].addr = fatCache.data; MPFSStubs[hMPFS].bytesRem = fatCache.len; MPFSStubs[hMPFS].fatID = i; return hMPFS; } } } // No file name matched, so return nothing return MPFS_INVALID_HANDLE; }
/***************************************************************************** Function: int MPFS_Stat ( const char* filewithDisk, uintptr_t stat_str ) Description: Returns the status (property) of the file Precondition: None Parameters: filewithDisk - string containing the Disk number appended to file name stat_str - pointer to structure which will return the file status Returns: Success - MPFS_OK Failure - MPFS_NO_FILE */ int MPFS_Stat ( const char* filewithDisk, uintptr_t stat_str ) { uint16_t nameHash = 0, ix = 0; uint16_t hashCache[8] = {}; const char *ptr = (const char *)NULL, *ptr1 = (const char *)NULL; uint8_t c = 0; const char* cFile = filewithDisk + 3; // Take the file name without the disk number (ignore "0:/", so increment 2) unsigned char i = 0; MPFS_STATUS *stat = (MPFS_STATUS *) stat_str; if ( mpfsObject.mpfsMediaHandle == DRV_HANDLE_INVALID ) { /* no opened media/uninitialized */ return 1; } /* Make sure MPFS is unlocked and we got a filename */ if ( *cFile == '\0' ) { return 1; } if ( mpfsObject.isMPFSLocked == true ) { return 1; } /* Calculate the name hash to speed up searching */ for ( nameHash = 0, ptr = cFile; *ptr != '\0'; ptr++ ) { nameHash += *ptr; nameHash <<= 1; } /* Read in hashes, and check remainder on a match. Store 8 in cache for performance. */ for ( ix = 0; ix < mpfsObject.numFiles; ix++ ) { /* For new block of 8, read in data */ if ( ( ix & 0x07 ) == 0u ) { MPFSStubs[0].addr = 8 + ix * 2; MPFSStubs[0].bytesRem = 16; MPFSGetArray ( 0, ( uint8_t* )hashCache, 16 ); } /* If the hash matches, compare the full filename */ if ( hashCache[ix&0x07] == nameHash ) { _LoadFATRecord(ix); MPFSStubs[0].addr = fatCache.string; MPFSStubs[0].bytesRem = 255; /* Loop over filename to perform comparison */ for ( ptr = cFile; *ptr != '\0'; ptr++ ) { MPFSGet ( 0, &c ); if( *ptr != c ) { break; } } MPFSGet ( 0, &c ); if ( ( c == '\0' ) && ( *ptr == '\0' ) ) { stat->fattrib = fatCache.flags; stat->fdate = (unsigned short)(fatCache.timestamp >> 16); stat->ftime = (unsigned short)(fatCache.timestamp); stat->fsize = fatCache.len; for ( ptr1 = cFile, i = 0; *ptr1 != '\0'; ptr1++, i++ ) { stat->fname[i] = *ptr1; } /* Return the status */ return 0; } }
int MPFS_Open ( uintptr_t handle, const char* filewithDisk, uint8_t mode ) { uint16_t nameHash = 0, ix = 0; uint16_t hashCache[8] = {}; volatile const char *ptr = (volatile const char *)NULL; uint8_t c = 0; uint32_t hMPFS = 0; volatile const char* cFile = filewithDisk + 3; // Take the file name without the disk number (ignore "0:/", so increment 3) if ( mpfsObject.mpfsMediaHandle == DRV_HANDLE_INVALID ) { /* no opened media/uninitialized */ return MPFS_INVALID_HANDLE; } /* Make sure MPFS is unlocked and we got a filename */ if ( *cFile == '\0' ) { return MPFS_INVALID_HANDLE; } if ( mpfsObject.isMPFSLocked == true ) { return MPFS_INVALID_HANDLE; } /* Calculate the name hash to speed up searching */ for ( nameHash = 0, ptr = cFile; *ptr != '\0'; ptr++ ) { nameHash += *ptr; nameHash <<= 1; } // Take a free file object as we want to open the MPFS file for(hMPFS = 1; hMPFS <= SYS_FS_MAX_FILES ; hMPFS++) { if( MPFSStubs[hMPFS].addr == MPFS_INVALID ) // not in use, so take it { break; } } /* If there is already more files opened than the allowed limit */ if( hMPFS >= SYS_FS_MAX_FILES + 1 ) { return MPFS_INVALID_HANDLE; } /* Read in hashes, and check remainder on a match. Store 8 in cache for performance. */ for ( ix = 0; ix < mpfsObject.numFiles; ix++ ) { /* For new block of 8, read in data */ if ( ( ix & 0x07 ) == 0u ) { MPFSStubs[0].addr = 8 + ix * 2; MPFSStubs[0].bytesRem = 16; MPFSGetArray ( 0, ( uint8_t* )hashCache, 16 ); } /* If the hash matches, compare the full filename */ if ( hashCache[ix&0x07] == nameHash ) { _LoadFATRecord(ix); MPFSStubs[0].addr = fatCache.string; MPFSStubs[0].bytesRem = 255; /* Loop over filename to perform comparison */ for ( ptr = cFile; *ptr != '\0'; ptr++ ) { MPFSGet ( 0, &c ); if( *ptr != c ) { break; } } MPFSGet ( 0, &c ); if ( ( c == '\0' ) && ( *ptr == '\0' ) ) { /* Filename matches, so return true */ MPFSStubs[hMPFS].addr = fatCache.data; MPFSStubs[hMPFS].bytesRem = fatCache.len; MPFSStubs[hMPFS].fatID = ix; /* Send the reference to the higher layer */ MPFSStubs[hMPFS].index = hMPFS; *(uintptr_t *)handle = MPFSStubs[hMPFS].index; /* Return the status */ return MPFS_OK; } } } /* No file name matched, so return nothing */ return MPFS_NO_FILE; }