/********************************************************************* * Function: void MPFSGetFilename(MPFS_HANDLE hMPFS, BYTE *name, WORD len) * * PreCondition: hMPFS is a valid open file handle * * Input: hMPFS: the file to locate the start address of * name: buffer to place the filename in * len: size of buffer * * Output: name: the filename of the current file * * Side Effects: None * * Overview: Finds the filename of the currently opened file * * Note: None ********************************************************************/ BOOL MPFSGetFilename(MPFS_HANDLE hMPFS, BYTE *name, WORD len) { 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(hMPFS); MPFSStubs[0].addr += 4; MPFSGetArray(0, (BYTE*)&(addr), 4); MPFSStubs[0].addr = addr; MPFSStubs[0].bytesRem = 255; // Read the value and return MPFSGet(0, name); len--; for(; len > 0 && *name != '\0'; len--) { name++; MPFSGet(0, name); } return TRUE; }
/********************************************************************* * Function: BOOL MPFSGetLong(DWORD *ul) * * PreCondition: MPFSOpen() and MPFSBeginGet() * * Input: ul: pointer to an DWORD to read * * Output: TRUE on success * FALSE on EOF * * Side Effects: None * * Overview: Reads an DWORD value from an MPFS file * * Note: None ********************************************************************/ BOOL MPFSGetLong(DWORD *ul) { BYTE* b = (BYTE*)ul; *(b) = MPFSGet(); if(MPFSIsEOF()) return FALSE; *(b+1) = MPFSGet(); *(b+2) = MPFSGet(); *(b+3) = MPFSGet(); return TRUE; }
/********************************************************************* * Function: static BOOL HTTPSendFile(void) * * PreCondition: curHTTP.file and curHTTP.offsets have both been * opened for reading. * * Input: None * * Output: TRUE if EOF was reached and reading is done * FALSE if more data remains * * Side Effects: None * * Overview: This function serves the next chunk of curHTTP's * file, up to a) available TX FIFO or b) up to * the next recorded callback index, whichever comes * first. * * Note: None ********************************************************************/ static BOOL HTTPSendFile(void) { WORD numBytes, len; BYTE c, data[64]; // Determine how many bytes we can read right now numBytes = mMIN(TCPIsPutReady(sktHTTP), curHTTP.nextCallback - curHTTP.byteCount); // Get/put as many bytes as possible curHTTP.byteCount += numBytes; while(numBytes > 0) { len = MPFSGetArray(curHTTP.file, data, mMIN(numBytes, 64)); if(len == 0) return TRUE; else TCPPutArray(sktHTTP, data, len); numBytes -= len; } // Check if a callback index was reached if(curHTTP.byteCount == curHTTP.nextCallback) { // Update the state machine smHTTP = SM_HTTP_SEND_FROM_CALLBACK; curHTTP.callbackPos = 0; // Read past the variable name and close the MPFS MPFSGet(curHTTP.file, NULL); do { if(!MPFSGet(curHTTP.file, &c)) break; curHTTP.byteCount++; } while(c != '~'); curHTTP.byteCount++; // Read in the callback address and next offset MPFSGetLong(curHTTP.offsets, &(curHTTP.callbackID)); if(!MPFSGetLong(curHTTP.offsets, &(curHTTP.nextCallback))) { curHTTP.nextCallback = 0xffffffff; MPFSClose(curHTTP.offsets); curHTTP.offsets = MPFS_INVALID_HANDLE; } } // We are not done sending a file yet... return FALSE; }
/********************************************************************* * Function: MPFS MPFSSeek(MPFS offset) * * PreCondition: MPFSGetBegin() is already called. * * Input: offset - Offset from current pointer * * Output: New MPFS handle located to given offset * * Side Effects: None. * * Overview: None * * Note: None. ********************************************************************/ MPFS MPFSSeek(MPFS offset) { MPFS i; MPFSGetBegin(_currentFile); i = (MPFS)0; while(i++ != offset) MPFSGet(); MPFSGetEnd(); return _currentHandle; }
/********************************************************************* * Function: MPFS MPFSSeek(MPFS_OFFSET offset) * * PreCondition: MPFSGetBegin() is already called. * * Input: offset - Offset from current pointer * * Output: New MPFS handle located to given offset * * Side Effects: None. * * Overview: None * * Note: None. ********************************************************************/ MPFS MPFSSeek(MPFS_OFFSET offset) { WORD i; MPFSGetBegin(_currentFile); i = 0; while(i++ != offset) MPFSGet(); MPFSGetEnd(); return _currentHandle; }
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; }
MPFS_HANDLE MPFSOpenROM(ROM BYTE* file) { MPFS_HANDLE hMPFS; WORD nameHash, i; ROM BYTE* ptr; BYTE c; // Make sure MPFS is unlocked and we got a filename if(*file == '\0' || isMPFSLocked == TRUE) return MPFS_INVALID_HANDLE; // Calculate the name hash for faster searching for(nameHash = 0, ptr = file; *ptr != '\0'; ptr++) nameHash += *ptr; // 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; // Initialize the FAT pointer MPFSStubs[0].addr = 0; // Read in the number of records MPFSStubs[0].bytesRem = 8; MPFSGetArray(0, NULL, 6); MPFSGetArray(0, (BYTE*)&i, 2); MPFSStubs[0].bytesRem = i * (24); // Read in FAT records and compare the hash for(i = 0; MPFSGetArray(0, (BYTE*)&(MPFSStubs[hMPFS].fatID), 2) == 2; i++) { if(MPFSStubs[hMPFS].fatID == nameHash) {// If the hash matches, compare the full filename MPFSGetArray(0, NULL, 2); MPFSGetArray(0, (BYTE*)&(MPFSStubs[hMPFS].addr), 4); MPFSStubs[hMPFS].bytesRem = 255; // Loop over the filename for(ptr = file; *ptr != '\0'; ptr++) { MPFSGet(hMPFS, &c); if(*ptr != c) break; } MPFSGet(hMPFS, &c); if(c == '\0' && *ptr == '\0') {// Filename matches, so return true MPFSGetArray(0, (BYTE*)&(MPFSStubs[hMPFS].addr), 4); MPFSGetArray(0, (BYTE*)&(MPFSStubs[hMPFS].bytesRem), 4); MPFSStubs[hMPFS].fatID = i; return hMPFS; } else {// No match, so skip to next MPFSGetArray(0, NULL, 16); } } else {// No match, so skip to next MPFSGetArray(0, NULL, 22); } } // No file name matched, so return nothing MPFSStubs[hMPFS].addr = MPFS_INVALID; 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; }