00001 00002 00003 00023 /********************************************************************* 00024 * Software License Agreement 00025 * 00026 * Copyright (C) 2002-2008 Microchip Technology Inc. All rights 00027 * reserved. 00028 * 00029 * Microchip licenses to you the right to use, modify, copy, and 00030 * distribute: 00031 * (i) the Software when embedded on a Microchip microcontroller or 00032 * digital signal controller product ("Device") which is 00033 * integrated into Licensee's product; or 00034 * (ii) ONLY the Software driver source files ENC28J60.c and 00035 * ENC28J60.h ported to a non-Microchip device used in 00036 * conjunction with a Microchip ethernet controller for the 00037 * sole purpose of interfacing with the ethernet controller. 00038 * 00039 * You should refer to the license agreement accompanying this 00040 * Software for additional information regarding your rights and 00041 * obligations. 00042 * 00043 * THE SOFTWARE AND DOCUMENTATION ARE PROVIDED "AS IS" WITHOUT 00044 * WARRANTY OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT 00045 * LIMITATION, ANY WARRANTY OF MERCHANTABILITY, FITNESS FOR A 00046 * PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT SHALL 00047 * MICROCHIP BE LIABLE FOR ANY INCIDENTAL, SPECIAL, INDIRECT OR 00048 * CONSEQUENTIAL DAMAGES, LOST PROFITS OR LOST DATA, COST OF 00049 * PROCUREMENT OF SUBSTITUTE GOODS, TECHNOLOGY OR SERVICES, ANY CLAIMS 00050 * BY THIRD PARTIES (INCLUDING BUT NOT LIMITED TO ANY DEFENSE 00051 * THEREOF), ANY CLAIMS FOR INDEMNITY OR CONTRIBUTION, OR OTHER 00052 * SIMILAR COSTS, WHETHER ASSERTED ON THE BASIS OF CONTRACT, TORT 00053 * (INCLUDING NEGLIGENCE), BREACH OF WARRANTY, OR OTHERWISE. 00054 * 00055 * 00056 * Author Date Comment 00057 *~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 00058 * Elliott Wood 07/2007 Complete rewrite as MPFS2 00059 * E. Wood 04/2008 Updated as MPFS2.1 00060 ********************************************************************/ 00061 #define __MPFS2_C 00062 00063 #include "TCPIP.h" 00064 00065 #if defined(STACK_USE_MPFS2) 00066 00067 // MODIFIX: Added inlude for huffman decoding support: 00068 #include "huffman.h" 00069 00070 00071 //Supports long file names to 64 characters 00072 #define MAX_FILE_NAME_LEN (64u) 00073 00074 /* 00075 * MPFS Structure: 00076 * [M][P][F][S] 00077 * [BYTE Ver Hi][BYTE Ver Lo][WORD Number of Files] 00078 * [Name Hash 0][Name Hash 1]...[Name Hash N] 00079 * [File Record 0][File Record 1]...[File Record N] 00080 * [String 0][String 1]...[String N] 00081 * [File Data 0][File Data 1]...[File Data N] 00082 * 00083 * Name Hash (2 bytes): 00084 * hash = 0 00085 * for each(byte in name) 00086 * hash += byte 00087 * hash <<= 1 00088 * 00089 * Technically this means the hash only includes the 00090 * final 15 characters of a name. 00091 * 00092 * File Record Structure (22 bytes): 00093 * [DWORD String Ptr][DWORD Data Ptr] 00094 * [DWORD Len][DWORD Timestamp][DWORD Microtime] 00095 * [WORD Flags] 00096 * 00097 * Pointers are absolute addresses within the MPFS image. 00098 * Timestamp is the UNIX timestamp 00099 * Microtime is currently unimplemented 00100 * 00101 * String Structure (1 to 64 bytes): 00102 * ["path/to/file.ext"][0x00] 00103 * 00104 * File Data Structure (arbitrary length): 00105 * [File Data] 00106 * 00107 * Unlike previous versions, there are no delimiters. 00108 * 00109 * Name hash is calculated as follows: 00110 * hash = 0 00111 * for each(byte in name) 00112 * hash += byte, hash <<= 1 00113 * 00114 * When a file has an index, that index file has no file name, 00115 * but is accessible as the file immediately following in the image. 00116 * 00117 * Current version is 2.1 00118 */ 00119 00120 /**************************************************************************** 00121 Section: 00122 Module-Only Globals and Functions 00123 ***************************************************************************/ 00124 00125 // Track the MPFS File Handles 00126 // MPFSStubs[0] is reserved for internal use (FAT access) 00127 static MPFS_STUB MPFSStubs[MAX_MPFS_HANDLES+1]; 00128 00129 // Allows the MPFS to be locked, preventing access during updates 00130 static BOOL isMPFSLocked; 00131 00132 // FAT record cache 00133 static MPFS_FAT_RECORD fatCache; 00134 00135 // ID of currently loaded fatCache 00136 static WORD fatCacheID; 00137 00138 // Number of files in this MPFS image 00139 static WORD numFiles; 00140 00141 00142 static void _LoadFATRecord(WORD fatID); 00143 static void _Validate(void); 00144 00145 /**************************************************************************** 00146 Section: 00147 EEPROM vs Flash Storage Settings 00148 ***************************************************************************/ 00149 00150 #if defined(MPFS_USE_EEPROM) 00151 00152 // Beginning address of MPFS Image 00153 #define MPFS_HEAD MPFS_RESERVE_BLOCK 00154 00155 // Track the last read address to prevent unnecessary 00156 // data overhead to switch locations. 00157 MPFS_PTR lastRead; 00158 00159 00160 #elif defined(MPFS_USE_SPI_FLASH) 00161 00162 // Beginning address of MPFS Image 00163 #define MPFS_HEAD MPFS_RESERVE_BLOCK 00164 00165 #else 00166 00167 // An address where MPFS data starts in program memory. 00168 #if defined(__18CXX) || defined(__C32__) 00169 extern ROM BYTE MPFS_Start[]; 00170 #define MPFS_HEAD ((DWORD)(&MPFS_Start[0])) 00171 #else 00172 extern DWORD MPFS_Start; 00173 #define MPFS_HEAD MPFS_Start; 00174 #endif 00175 00176 #endif 00177 00178 /**************************************************************************** 00179 Section: 00180 Stack-Level Functions 00181 ***************************************************************************/ 00182 00183 /***************************************************************************** 00184 Function: 00185 void MPFSInit(void) 00186 00187 Summary: 00188 Initializes the MPFS module. 00189 00190 Description: 00191 Sets all MPFS handles to closed, and initializes access to the EEPROM 00192 if necessary. 00193 00194 Precondition: 00195 None 00196 00197 Parameters: 00198 None 00199 00200 Returns: 00201 None 00202 00203 Remarks: 00204 This function is called only one during lifetime of the application. 00205 ***************************************************************************/ 00206 void MPFSInit(void) 00207 { 00208 BYTE i; 00209 00210 for(i = 1; i <= MAX_MPFS_HANDLES; i++) 00211 { 00212 MPFSStubs[i].addr = MPFS_INVALID; 00213 } 00214 00215 #if defined(MPFS_USE_EEPROM) 00216 // Initialize the EEPROM access routines. 00217 XEEInit(); 00218 lastRead = MPFS_INVALID; 00219 #endif 00220 00221 #if defined(MPFS_USE_SPI_FLASH) 00222 // Initialize SPI Flash access routines. 00223 SPIFlashInit(); 00224 #endif 00225 00226 // Validate the image and load numFiles 00227 _Validate(); 00228 00229 isMPFSLocked = FALSE; 00230 00231 } 00232 00233 /**************************************************************************** 00234 Section: 00235 Handle Management Functions 00236 ***************************************************************************/ 00237 00238 /***************************************************************************** 00239 Function: 00240 MPFS_HANDLE MPFSOpen(BYTE* cFile) 00241 00242 Description: 00243 Opens a file in the MPFS2 file system. 00244 00245 Precondition: 00246 None 00247 00248 Parameters: 00249 cFile - a null terminated file name to open 00250 00251 Returns: 00252 An MPFS_HANDLE to the opened file if found, or MPFS_INVALID_HANDLE 00253 if the file could not be found or no free handles exist. 00254 ***************************************************************************/ 00255 MPFS_HANDLE MPFSOpen(BYTE* cFile) 00256 { 00257 MPFS_HANDLE hMPFS; 00258 WORD nameHash, i; 00259 WORD hashCache[8]; 00260 BYTE *ptr, c; 00261 00262 // Initialize c to avoid "may be used uninitialized" compiler warning 00263 c = 0; 00264 00265 // Make sure MPFS is unlocked and we got a filename 00266 if(*cFile == '\0' || isMPFSLocked == TRUE) 00267 return MPFS_INVALID_HANDLE; 00268 00269 // Calculate the name hash to speed up searching 00270 for(nameHash = 0, ptr = cFile; *ptr != '\0'; ptr++) 00271 { 00272 nameHash += *ptr; 00273 nameHash <<= 1; 00274 } 00275 00276 // Find a free file handle to use 00277 for(hMPFS = 1; hMPFS <= MAX_MPFS_HANDLES; hMPFS++) 00278 if(MPFSStubs[hMPFS].addr == MPFS_INVALID) 00279 break; 00280 if(hMPFS == MAX_MPFS_HANDLES) 00281 return MPFS_INVALID_HANDLE; 00282 00283 // Read in hashes, and check remainder on a match. Store 8 in cache for performance 00284 for(i = 0; i < numFiles; i++) 00285 { 00286 // For new block of 8, read in data 00287 if((i & 0x07) == 0) 00288 { 00289 MPFSStubs[0].addr = 8 + i*2; 00290 MPFSStubs[0].bytesRem = 16; 00291 MPFSGetArray(0, (BYTE*)hashCache, 16); 00292 } 00293 00294 // If the hash matches, compare the full filename 00295 if(hashCache[i&0x07] == nameHash) 00296 { 00297 _LoadFATRecord(i); 00298 MPFSStubs[hMPFS].addr = fatCache.string; 00299 MPFSStubs[hMPFS].bytesRem = 255; 00300 MPFSStubs[hMPFS].offset = 0; // MODIFIX: Added for huffman decoding. 00301 00302 // Loop over filename to perform comparison 00303 for(ptr = cFile; *ptr != '\0'; ptr++) 00304 { 00305 MPFSGet(hMPFS, &c); 00306 if(*ptr != c) 00307 break; 00308 } 00309 00310 MPFSGet(hMPFS, &c); 00311 00312 if(c == '\0' && *ptr == '\0') 00313 {// Filename matches, so return true 00314 MPFSStubs[hMPFS].addr = fatCache.data; 00315 MPFSStubs[hMPFS].bytesRem = fatCache.len; 00316 MPFSStubs[hMPFS].fatID = i; 00317 00318 // MODIFIX: Added the following lines for huffman encoding support. 00319 if (fatCache.flags & MPFS2_FLAG_ISCOMPRESSED) 00320 { 00321 MPFSStubs[hMPFS].offset = 0x01; 00322 } 00323 else 00324 { 00325 MPFSStubs[hMPFS].offset = 0; 00326 } 00327 // MODIFIX: END 00328 00329 return hMPFS; 00330 } 00331 } 00332 } 00333 00334 // No file name matched, so return nothing 00335 return MPFS_INVALID_HANDLE; 00336 } 00337 00338 /***************************************************************************** 00339 Function: 00340 MPFS_HANDLE MPFSOpenROM(ROM BYTE* cFile) 00341 00342 Description: 00343 Opens a file in the MPFS2 file system. 00344 00345 Precondition: 00346 None 00347 00348 Parameters: 00349 cFile - a null terminated file name to open 00350 00351 Returns: 00352 An MPFS_HANDLE to the opened file if found, or MPFS_INVALID_HANDLE 00353 if the file could not be found or no free handles exist. 00354 00355 Remarks: 00356 This function is aliased to MPFSOpen on non-PIC18 platforms. 00357 ***************************************************************************/ 00358 #if defined(__18CXX) 00359 MPFS_HANDLE MPFSOpenROM(ROM BYTE* cFile) 00360 { 00361 MPFS_HANDLE hMPFS; 00362 WORD nameHash, i; 00363 WORD hashCache[8]; 00364 ROM BYTE *ptr; 00365 BYTE c; 00366 00367 // Make sure MPFS is unlocked and we got a filename 00368 if(*cFile == '\0' || isMPFSLocked == TRUE) 00369 return MPFS_INVALID_HANDLE; 00370 00371 // Calculate the name hash to speed up searching 00372 for(nameHash = 0, ptr = cFile; *ptr != '\0'; ptr++) 00373 { 00374 nameHash += *ptr; 00375 nameHash <<= 1; 00376 } 00377 00378 // Find a free file handle to use 00379 for(hMPFS = 1; hMPFS <= MAX_MPFS_HANDLES; hMPFS++) 00380 if(MPFSStubs[hMPFS].addr == MPFS_INVALID) 00381 break; 00382 if(hMPFS == MAX_MPFS_HANDLES) 00383 return MPFS_INVALID_HANDLE; 00384 00385 // Read in hashes, and check remainder on a match. Store 8 in cache for performance 00386 for(i = 0; i < numFiles; i++) 00387 { 00388 // For new block of 8, read in data 00389 if((i & 0x07) == 0) 00390 { 00391 MPFSStubs[0].addr = 8 + i*2; 00392 MPFSStubs[0].bytesRem = 16; 00393 MPFSGetArray(0, (BYTE*)hashCache, 16); 00394 } 00395 00396 // If the hash matches, compare the full filename 00397 if(hashCache[i&0x07] == nameHash) 00398 { 00399 _LoadFATRecord(i); 00400 MPFSStubs[hMPFS].addr = fatCache.string; 00401 MPFSStubs[hMPFS].bytesRem = 255; 00402 MPFSStubs[hMPFS].offset = 0; // MODIFIX: Added for huffman decoding. 00403 00404 // Loop over filename to perform comparison 00405 for(ptr = cFile; *ptr != '\0'; ptr++) 00406 { 00407 MPFSGet(hMPFS, &c); 00408 if(*ptr != c) 00409 break; 00410 } 00411 00412 MPFSGet(hMPFS, &c); 00413 00414 if(c == '\0' && *ptr == '\0') 00415 {// Filename matches, so return true 00416 MPFSStubs[hMPFS].addr = fatCache.data; 00417 MPFSStubs[hMPFS].bytesRem = fatCache.len; 00418 MPFSStubs[hMPFS].fatID = i; 00419 00420 // MODIFIX: Added the following lines for huffman encoding support. 00421 if (fatCache.flags & MPFS2_FLAG_HASINDEX) 00422 { 00423 MPFSStubs[hMPFS].offset = 0x01; 00424 } 00425 else 00426 { 00427 MPFSStubs[hMPFS].offset = 0; 00428 } 00429 // MODIFIX: END 00430 00431 return hMPFS; 00432 } 00433 } 00434 } 00435 00436 // No file name matched, so return nothing 00437 return MPFS_INVALID_HANDLE; 00438 } 00439 #endif 00440 00441 /***************************************************************************** 00442 Function: 00443 MPFS_HANDLE MPFSOpenID(WORD hFatID) 00444 00445 Summary: 00446 Quickly re-opens a file. 00447 00448 Description: 00449 Quickly re-opens a file in the MPFS2 file system. Use this function 00450 along with MPFSGetID() to quickly re-open a file without tying up 00451 a permanent MPFSStub. 00452 00453 Precondition: 00454 None 00455 00456 Parameters: 00457 hFatID - the ID of a previous opened file in the FAT 00458 00459 Returns: 00460 An MPFS_HANDLE to the opened file if found, or MPFS_INVALID_HANDLE 00461 if the file could not be found or no free handles exist. 00462 ***************************************************************************/ 00463 MPFS_HANDLE MPFSOpenID(WORD hFatID) 00464 { 00465 MPFS_HANDLE hMPFS; 00466 00467 // Make sure MPFS is unlocked and we got a valid id 00468 if(isMPFSLocked == TRUE || hFatID > numFiles) 00469 return MPFS_INVALID_HANDLE; 00470 00471 // Find a free file handle to use 00472 for(hMPFS = 1; hMPFS <= MAX_MPFS_HANDLES; hMPFS++) 00473 if(MPFSStubs[hMPFS].addr == MPFS_INVALID) 00474 break; 00475 if(hMPFS == MAX_MPFS_HANDLES) 00476 return MPFS_INVALID_HANDLE; 00477 00478 // Load the FAT record 00479 _LoadFATRecord(hFatID); 00480 00481 // Set up the file handle 00482 MPFSStubs[hMPFS].fatID = hFatID; 00483 MPFSStubs[hMPFS].addr = fatCache.data; 00484 MPFSStubs[hMPFS].bytesRem = fatCache.len; 00485 00486 00487 // MODIFIX: Added the following lines for huffman encoding support. 00488 if (fatCache.flags & MPFS2_FLAG_HASINDEX) 00489 { 00490 MPFSStubs[hMPFS].offset = 0x01; 00491 } 00492 else 00493 { 00494 MPFSStubs[hMPFS].offset = 0; 00495 } 00496 // MODIFIX: END 00497 00498 00499 return hMPFS; 00500 } 00501 00502 /***************************************************************************** 00503 Function: 00504 void MPFSClose(MPFS_HANDLE hMPFS) 00505 00506 Summary: 00507 Closes a file. 00508 00509 Description: 00510 Closes a file and releases its stub back to the pool of available 00511 handles. 00512 00513 Precondition: 00514 None 00515 00516 Parameters: 00517 hMPFS - the file handle to be closed 00518 00519 Returns: 00520 None 00521 ***************************************************************************/ 00522 void MPFSClose(MPFS_HANDLE hMPFS) 00523 { 00524 if(hMPFS != 0u && hMPFS <= MAX_MPFS_HANDLES) 00525 MPFSStubs[hMPFS].addr = MPFS_INVALID; 00526 } 00527 00528 00529 /**************************************************************************** 00530 Section: 00531 Data Reading Functions 00532 ***************************************************************************/ 00533 00534 // MODIFIX: Added the following function! 00535 void MPFSGetArrayHuffman(MPFS_HANDLE hMPFS, BYTE* cData, WORD wLen) 00536 { 00537 BYTE currentValue; 00538 BYTE offset = MPFSStubs[hMPFS].offset; 00539 ROM BYTE* addr; 00540 BYTE bytesRead = 0; 00541 00542 MPFSStubs[hMPFS].bytesRem -= wLen; 00543 addr = (ROM BYTE*)(MPFSStubs[hMPFS].addr + MPFS_HEAD); 00544 currentValue = *addr; 00545 00546 while(wLen) 00547 { 00548 HUFFMAN_CODE_TYPE mask = MAX_HUFFMAN_CODE_MASK; 00549 HUFFMAN_CODE_TYPE code = 0; 00550 BYTE codeLength = 1; 00551 BYTE codeIndex = 0; 00552 00553 while(1) 00554 { 00555 if (offset & currentValue) 00556 { 00557 code |= mask; 00558 } 00559 00560 offset = offset << 1; 00561 if (offset == 0) 00562 { 00563 addr++; 00564 currentValue = *addr; 00565 bytesRead++; 00566 offset = 0x01; 00567 } 00568 00569 00570 if (HuffmanCode[codeIndex].CodeLength == codeLength) 00571 { 00572 if (HuffmanCode[codeIndex].StartCode <= code) 00573 { 00574 break; 00575 } 00576 00577 codeIndex++; 00578 } 00579 00580 00581 codeLength++; 00582 mask = mask >> 1; 00583 } 00584 00585 00586 if (cData) 00587 { 00588 // Fetch the character from the table: 00589 BYTE index = HuffmanCode[codeIndex].CharacterIndex; 00590 code = (code - HuffmanCode[codeIndex].StartCode); 00591 00592 while(code) 00593 { 00594 code -= mask; 00595 index++; 00596 } 00597 00598 *cData = HuffmanCharacter[index]; 00599 cData++; 00600 } 00601 00602 wLen--; 00603 } 00604 00605 00606 MPFSStubs[hMPFS].offset = offset; 00607 MPFSStubs[hMPFS].addr += bytesRead; 00608 } 00609 // MODIFIX: END 00610 00611 00612 /***************************************************************************** 00613 Function: 00614 BOOL MPFSGet(MPFS_HANDLE hMPFS, BYTE* c) 00615 00616 Description: 00617 Reads a byte from a file. 00618 00619 Precondition: 00620 The file handle referenced by hMPFS is already open. 00621 00622 Parameters: 00623 hMPFS - the file handle from which to read 00624 c - Where to store the byte that was read 00625 00626 Return Values: 00627 TRUE - The byte was successfully read 00628 FALSE - No byte was read because either the handle was invalid or 00629 the end of the file has been reached. 00630 ***************************************************************************/ 00631 BOOL MPFSGet(MPFS_HANDLE hMPFS, BYTE* c) 00632 { 00633 // Make sure we're reading a valid address 00634 if(hMPFS > MAX_MPFS_HANDLES) 00635 return FALSE; 00636 if( MPFSStubs[hMPFS].addr == MPFS_INVALID || 00637 MPFSStubs[hMPFS].bytesRem == 0u) 00638 return FALSE; 00639 00640 // MODIFIX: Added the following lines for huffman decoding support: 00641 if (MPFSStubs[hMPFS].offset) 00642 { 00643 MPFSGetArrayHuffman(hMPFS, c, 1); 00644 return TRUE; 00645 } 00646 // MODIFIX: END 00647 00648 if(c == NULL) 00649 { 00650 MPFSStubs[hMPFS].addr++; 00651 MPFSStubs[hMPFS].bytesRem--; 00652 return TRUE; 00653 } 00654 00655 00656 // Read function for EEPROM 00657 #if defined(MPFS_USE_EEPROM) 00658 // For performance, cache the last read address 00659 if(MPFSStubs[hMPFS].addr != lastRead+1) 00660 XEEBeginRead(MPFSStubs[hMPFS].addr + MPFS_HEAD); 00661 *c = XEERead(); 00662 lastRead = MPFSStubs[hMPFS].addr; 00663 MPFSStubs[hMPFS].addr++; 00664 #elif defined(MPFS_USE_SPI_FLASH) 00665 SPIFlashReadArray(MPFSStubs[hMPFS].addr + MPFS_HEAD, c, 1); 00666 MPFSStubs[hMPFS].addr++; 00667 #else 00668 #if defined(__C30__) 00669 { 00670 DWORD addr; 00671 DWORD_VAL read; 00672 BYTE i; 00673 00674 // MPFS Images are addressed by the byte; Program memory by the word. 00675 // 00676 // Flash program memory is 24 bits wide and only even words are 00677 // implemented. The upper byte of the upper word is read as 0x00. 00678 // Address in program memory of any given byte is (MPFSAddr * 2) / 3 00679 // 00680 // We will read 24 bits at a time, but need to support using only 00681 // fractions of the first and last byte. 00682 00683 // Find the beginning address in program memory. 00684 addr = (MPFSStubs[hMPFS].addr / 3) << 1; 00685 00686 // Find where to start in that first 3 bytes 00687 read.Val = (addr * 3) >> 1; 00688 if(read.Val == MPFSStubs[hMPFS].addr) 00689 i = 0; 00690 else if(read.Val+1 == MPFSStubs[hMPFS].addr) 00691 i = 1; 00692 else 00693 i = 2; 00694 00695 // Add in the MPFS starting address offset 00696 addr += MPFS_HEAD; 00697 00698 // Update the MPFS Handle 00699 MPFSStubs[hMPFS].addr++; 00700 00701 // Read the DWORD 00702 read.Val = ReadProgramMemory(addr & 0x00FFFFFF); 00703 *c = read.v[i]; 00704 00705 } 00706 #else 00707 { 00708 DWORD dwHITECHWorkaround = MPFS_HEAD; 00709 *c = *((ROM BYTE*)(MPFSStubs[hMPFS].addr+dwHITECHWorkaround)); 00710 MPFSStubs[hMPFS].addr++; 00711 } 00712 #endif 00713 #endif 00714 00715 MPFSStubs[hMPFS].bytesRem--; 00716 return TRUE; 00717 } 00718 00719 /***************************************************************************** 00720 Function: 00721 WORD MPFSGetArray(MPFS_HANDLE hMPFS, BYTE* cData, WORD wLen) 00722 00723 Description: 00724 Reads a series of bytes from a file. 00725 00726 Precondition: 00727 The file handle referenced by hMPFS is already open. 00728 00729 Parameters: 00730 hMPFS - the file handle from which to read 00731 cData - where to store the bytes that were read 00732 wLen - how many bytes to read 00733 00734 Returns: 00735 The number of bytes successfully read. If this is less than wLen, 00736 an EOF occurred while attempting to read. 00737 ***************************************************************************/ 00738 WORD MPFSGetArray(MPFS_HANDLE hMPFS, BYTE* cData, WORD wLen) 00739 { 00740 // Make sure we're reading a valid address 00741 if(hMPFS > MAX_MPFS_HANDLES) 00742 return 0; 00743 00744 // Determine how many we can actually read 00745 if(wLen > MPFSStubs[hMPFS].bytesRem) 00746 wLen = MPFSStubs[hMPFS].bytesRem; 00747 00748 // Make sure we're reading a valid address 00749 if(MPFSStubs[hMPFS].addr == MPFS_INVALID || wLen == 0) 00750 return 0; 00751 00752 // MODIFIX: Added the following lines for huffman decoding support: 00753 if (MPFSStubs[hMPFS].offset) 00754 { 00755 MPFSGetArrayHuffman(hMPFS, cData, wLen); 00756 return wLen; 00757 } 00758 // MODIFIX: END 00759 00760 00761 if(cData == NULL) 00762 { 00763 MPFSStubs[hMPFS].addr += wLen; 00764 MPFSStubs[hMPFS].bytesRem -= wLen; 00765 return wLen; 00766 } 00767 00768 // Read the data 00769 #if defined(MPFS_USE_EEPROM) 00770 XEEReadArray(MPFSStubs[hMPFS].addr+MPFS_HEAD, cData, wLen); 00771 MPFSStubs[hMPFS].addr += wLen; 00772 MPFSStubs[hMPFS].bytesRem -= wLen; 00773 lastRead = MPFS_INVALID; 00774 #elif defined(MPFS_USE_SPI_FLASH) 00775 SPIFlashReadArray(MPFSStubs[hMPFS].addr+MPFS_HEAD, cData, wLen); 00776 MPFSStubs[hMPFS].addr += wLen; 00777 MPFSStubs[hMPFS].bytesRem -= wLen; 00778 #else 00779 #if defined(__C30__) 00780 { 00781 DWORD addr; 00782 DWORD_VAL read; 00783 WORD count; 00784 BYTE i; 00785 00786 // MPFS Images are addressed by the byte; Program memory by the word. 00787 // 00788 // Flash program memory is 24 bits wide and only even words are 00789 // implemented. The upper byte of the upper word is read as 0x00. 00790 // Address in program memory of any given byte is (MPFSAddr * 2) / 3 00791 // 00792 // We will read 24 bits at a time, but need to support using only 00793 // fractions of the first and last byte. 00794 00795 // Find the beginning address in program memory. 00796 addr = (MPFSStubs[hMPFS].addr / 3) << 1; 00797 00798 // Find where to start in that first 3 bytes 00799 read.Val = (addr * 3) >> 1; 00800 if(read.Val == MPFSStubs[hMPFS].addr) 00801 i = 0; 00802 else if(read.Val+1 == MPFSStubs[hMPFS].addr) 00803 i = 1; 00804 else 00805 i = 2; 00806 00807 // Add in the MPFS starting address offset 00808 addr += MPFS_HEAD; 00809 00810 // Update the MPFS Handle 00811 MPFSStubs[hMPFS].addr += wLen; 00812 MPFSStubs[hMPFS].bytesRem -= wLen; 00813 00814 // Read the first DWORD 00815 read.Val = ReadProgramMemory(addr & 0x00FFFFFF); 00816 addr += 2; 00817 00818 // Copy values as needed 00819 for(count = wLen; count > 0; cData++, count--) 00820 { 00821 // Copy the next value in 00822 *cData = read.v[i++]; 00823 00824 // Check if a new DWORD is needed 00825 if(i == 3 && count != 1) 00826 {// Read in a new DWORD 00827 read.Val = ReadProgramMemory(addr & 0x00FFFFFF); 00828 addr += 2; 00829 i = 0; 00830 } 00831 } 00832 00833 } 00834 #else 00835 { 00836 DWORD dwHITECHWorkaround = MPFS_HEAD; 00837 memcpypgm2ram(cData, (ROM void*)(MPFSStubs[hMPFS].addr + dwHITECHWorkaround), wLen); 00838 MPFSStubs[hMPFS].addr += wLen; 00839 MPFSStubs[hMPFS].bytesRem -= wLen; 00840 } 00841 #endif 00842 #endif 00843 00844 return wLen; 00845 } 00846 00847 /***************************************************************************** 00848 Function: 00849 BOOL MPFSGetLong(MPFS_HANDLE hMPFS, DWORD* ul) 00850 00851 Description: 00852 Reads a DWORD or Long value from the MPFS. 00853 00854 Precondition: 00855 The file handle referenced by hMPFS is already open. 00856 00857 Parameters: 00858 hMPFS - the file handle from which to read 00859 ul - where to store the DWORD or long value that was read 00860 00861 Returns: 00862 TRUE - The byte was successfully read 00863 FALSE - No byte was read because either the handle was invalid or 00864 the end of the file has been reached. 00865 ***************************************************************************/ 00866 BOOL MPFSGetLong(MPFS_HANDLE hMPFS, DWORD* ul) 00867 { 00868 return ( MPFSGetArray(hMPFS, (BYTE*)ul, 4) == 4 ); 00869 } 00870 00871 /***************************************************************************** 00872 Function: 00873 BOOL MPFSSeek(MPFS_HANDLE hMPFS, DWORD dwOffset, MPFS_SEEK_MODE tMode) 00874 00875 Description: 00876 Moves the current read pointer to a new location. 00877 00878 Precondition: 00879 The file handle referenced by hMPFS is already open. 00880 00881 Parameters: 00882 hMPFS - the file handle to seek with 00883 dwOffset - offset from the specified position in the specified direction 00884 tMode - one of the MPFS_SEEK_MODE constants 00885 00886 Returns: 00887 TRUE - the seek was successful 00888 FALSE - either the new location or the handle itself was invalid 00889 ***************************************************************************/ 00890 BOOL MPFSSeek(MPFS_HANDLE hMPFS, DWORD dwOffset, MPFS_SEEK_MODE tMode) 00891 { 00892 DWORD temp; 00893 00894 // Make sure a valid file is open 00895 if(hMPFS > MAX_MPFS_HANDLES) 00896 return FALSE; 00897 if(MPFSStubs[hMPFS].addr == MPFS_INVALID) 00898 return FALSE; 00899 00900 switch(tMode) 00901 { 00902 // Seek offset bytes from start 00903 case MPFS_SEEK_START: 00904 temp = MPFSGetSize(hMPFS); 00905 if(dwOffset > temp) 00906 return FALSE; 00907 00908 MPFSStubs[hMPFS].addr = MPFSGetStartAddr(hMPFS) + dwOffset; 00909 MPFSStubs[hMPFS].bytesRem = temp - dwOffset; 00910 return TRUE; 00911 00912 // Seek forwards offset bytes 00913 case MPFS_SEEK_FORWARD: 00914 if(dwOffset > MPFSStubs[hMPFS].bytesRem) 00915 return FALSE; 00916 00917 MPFSStubs[hMPFS].addr += dwOffset; 00918 MPFSStubs[hMPFS].bytesRem -= dwOffset; 00919 return TRUE; 00920 00921 // Seek backwards offset bytes 00922 case MPFS_SEEK_REWIND: 00923 temp = MPFSGetStartAddr(hMPFS); 00924 if(MPFSStubs[hMPFS].addr < temp + dwOffset) 00925 return FALSE; 00926 00927 MPFSStubs[hMPFS].addr -= dwOffset; 00928 MPFSStubs[hMPFS].bytesRem += dwOffset; 00929 return TRUE; 00930 00931 // Seek so that offset bytes remain in file 00932 case MPFS_SEEK_END: 00933 temp = MPFSGetSize(hMPFS); 00934 if(dwOffset > temp) 00935 return FALSE; 00936 00937 MPFSStubs[hMPFS].addr = MPFSGetEndAddr(hMPFS) - dwOffset; 00938 MPFSStubs[hMPFS].bytesRem = dwOffset; 00939 return TRUE; 00940 00941 default: 00942 return FALSE; 00943 } 00944 } 00945 00946 00947 /**************************************************************************** 00948 Section: 00949 Data Writing Functions 00950 ***************************************************************************/ 00951 00952 /***************************************************************************** 00953 Function: 00954 MPFS_HANDLE MPFSFormat(void) 00955 00956 Summary: 00957 Prepares the MPFS image for writing. 00958 00959 Description: 00960 Prepares the MPFS image for writing and locks the image so that other 00961 processes may not access it. 00962 00963 Precondition: 00964 None 00965 00966 Parameters: 00967 None 00968 00969 Returns: 00970 An MPFS handle that can be used for MPFSPut commands, or 00971 MPFS_INVALID_HANDLE when the EEPROM failed to initialize for writing. 00972 00973 Remarks: 00974 In order to prevent misreads, the MPFS will be inaccessible until 00975 MPFSClose is called. This function is not available when the MPFS 00976 is stored in internal Flash program memory. 00977 ***************************************************************************/ 00978 #if defined(MPFS_USE_EEPROM) || defined(MPFS_USE_SPI_FLASH) 00979 MPFS_HANDLE MPFSFormat(void) 00980 { 00981 00982 BYTE i; 00983 00984 // Close all files 00985 for(i = 0; i < MAX_MPFS_HANDLES; i++) 00986 MPFSStubs[i].addr = MPFS_INVALID; 00987 00988 // Lock the image 00989 isMPFSLocked = TRUE; 00990 00991 #if defined(MPFS_USE_EEPROM) 00992 // Set FAT ptr for writing 00993 MPFSStubs[0].addr = 0; 00994 MPFSStubs[0].fatID = 0xffff; 00995 MPFSStubs[0].bytesRem = MPFS_WRITE_PAGE_SIZE - ( ((BYTE)MPFSStubs[0].addr+MPFS_HEAD) & (MPFS_WRITE_PAGE_SIZE-1) ); 00996 00997 // Set up EEPROM for writing 00998 if( XEEBeginWrite(MPFSStubs[0].addr+MPFS_HEAD) == XEE_SUCCESS ) 00999 return 0x00; 01000 01001 return MPFS_INVALID_HANDLE; 01002 #else 01003 // Set up SPI Flash for writing 01004 SPIFlashBeginWrite(MPFS_HEAD); 01005 return 0x00; 01006 #endif 01007 } 01008 #endif 01009 01010 /***************************************************************************** 01011 Function: 01012 WORD MPFSPutArray(MPFS_HANDLE hMPFS, BYTE *cData, WORD wLen) 01013 01014 Description: 01015 Writes an array of data to the MPFS image. 01016 01017 Precondition: 01018 MPFSFormat was sucessfully called. 01019 01020 Parameters: 01021 hMPFS - the file handle for writing 01022 cData - the array of bytes to write 01023 wLen - how many bytes to write 01024 01025 Returns: 01026 The number of bytes successfully written. 01027 01028 Remarks: 01029 For EEPROM, the actual write may not initialize until the internal write 01030 page is full. To ensure that previously written data gets stored, 01031 MPFSPutEnd must be called after the last call to MPFSPutArray. 01032 ***************************************************************************/ 01033 #if defined(MPFS_USE_EEPROM) || defined(MPFS_USE_SPI_FLASH) 01034 WORD MPFSPutArray(MPFS_HANDLE hMPFS, BYTE* cData, WORD wLen) 01035 { 01036 #if defined(MPFS_USE_EEPROM) 01037 // Write to the EEPROM 01038 WORD count; 01039 01040 for(count = 0; count < wLen; count++) 01041 { 01042 XEEWrite(cData[count]); 01043 01044 MPFSStubs[hMPFS].addr++; 01045 MPFSStubs[hMPFS].bytesRem--; 01046 01047 if(MPFSStubs[hMPFS].bytesRem == 0) 01048 { 01049 MPFSPutEnd(FALSE); 01050 isMPFSLocked = TRUE; 01051 XEEBeginWrite(MPFSStubs[hMPFS].addr+MPFS_HEAD); 01052 MPFSStubs[hMPFS].bytesRem = MPFS_WRITE_PAGE_SIZE; 01053 } 01054 } 01055 01056 return count; 01057 01058 #else 01059 // Write to the SPI Flash 01060 SPIFlashWriteArray(cData, wLen); 01061 #endif 01062 } 01063 #endif 01064 01065 /***************************************************************************** 01066 Function: 01067 void MPFSPutEnd(void) 01068 01069 Description: 01070 Finalizes an MPFS writing operation. 01071 01072 Precondition: 01073 MPFSFormat and MPFSPutArray were sucessfully called. 01074 01075 Parameters: 01076 final - TRUE if the application is done writing, FALSE if MPFS2 called 01077 this function locally. 01078 01079 Returns: 01080 None 01081 ***************************************************************************/ 01082 #if defined(MPFS_USE_EEPROM) || defined(MPFS_USE_SPI_FLASH) 01083 void MPFSPutEnd(BOOL final) 01084 { 01085 isMPFSLocked = FALSE; 01086 01087 #if defined(MPFS_USE_EEPROM) 01088 XEEEndWrite(); 01089 while(XEEIsBusy()); 01090 #endif 01091 01092 if(final) 01093 _Validate(); 01094 } 01095 #endif 01096 01097 01098 /**************************************************************************** 01099 Section: 01100 Meta Data Accessors 01101 ***************************************************************************/ 01102 01103 /***************************************************************************** 01104 Function: 01105 static void _LoadFATRecord(WORD fatID) 01106 01107 Description: 01108 Loads the FAT record for a specified handle. 01109 01110 Precondition: 01111 None 01112 01113 Parameters: 01114 fatID - the ID of the file whose FAT is to be loaded 01115 01116 Returns: 01117 None 01118 01119 Remarks: 01120 The FAT record will be stored in fatCache. 01121 ***************************************************************************/ 01122 static void _LoadFATRecord(WORD fatID) 01123 { 01124 if(fatID == fatCacheID || fatID >= numFiles) 01125 return; 01126 01127 // Read the FAT record to the cache 01128 MPFSStubs[0].bytesRem = 22; 01129 MPFSStubs[0].addr = 8 + numFiles*2 + fatID*22; 01130 MPFSStubs[0].offset = 0; // MODIFIX: Added this line for initialize. 01131 MPFSGetArray(0, (BYTE*)&fatCache, 22); 01132 fatCacheID = fatID; 01133 } 01134 01135 /***************************************************************************** 01136 Function: 01137 DWORD MPFSGetTimestamp(MPFS_HANDLE hMPFS) 01138 01139 Description: 01140 Reads the timestamp for the specified file. 01141 01142 Precondition: 01143 The file handle referenced by hMPFS is already open. 01144 01145 Parameters: 01146 hMPFS - the file handle from which to read the metadata 01147 01148 Returns: 01149 The timestamp that was read as a DWORD 01150 ***************************************************************************/ 01151 DWORD MPFSGetTimestamp(MPFS_HANDLE hMPFS) 01152 { 01153 // Make sure a valid file is open 01154 if(hMPFS > MAX_MPFS_HANDLES) 01155 return 0x00000000; 01156 if(MPFSStubs[hMPFS].addr == MPFS_INVALID) 01157 return 0x00000000; 01158 01159 // Move to the point for reading 01160 _LoadFATRecord(MPFSStubs[hMPFS].fatID); 01161 return fatCache.timestamp; 01162 } 01163 01164 /***************************************************************************** 01165 Function: 01166 DWORD MPFSGetMicrotime(MPFS_HANDLE hMPFS) 01167 01168 Description: 01169 Reads the microtime portion of a file's timestamp. 01170 01171 Precondition: 01172 The file handle referenced by hMPFS is already open. 01173 01174 Parameters: 01175 hMPFS - the file handle from which to read the metadata 01176 01177 Returns: 01178 The microtime that was read as a DWORD 01179 ***************************************************************************/ 01180 DWORD MPFSGetMicrotime(MPFS_HANDLE hMPFS) 01181 { 01182 // Make sure a valid file is open 01183 if(hMPFS > MAX_MPFS_HANDLES) 01184 return 0x00000000; 01185 if(MPFSStubs[hMPFS].addr == MPFS_INVALID) 01186 return 0x00000000; 01187 01188 // Move to the point for reading 01189 _LoadFATRecord(MPFSStubs[hMPFS].fatID); 01190 return fatCache.microtime; 01191 } 01192 01193 /***************************************************************************** 01194 Function: 01195 WORD MPFSGetFlags(MPFS_HANDLE hMPFS) 01196 01197 Description: 01198 Reads a file's flags. 01199 01200 Precondition: 01201 The file handle referenced by hMPFS is already open. 01202 01203 Parameters: 01204 hMPFS - the file handle from which to read the metadata 01205 01206 Returns: 01207 The flags that were associated with the file 01208 ***************************************************************************/ 01209 WORD MPFSGetFlags(MPFS_HANDLE hMPFS) 01210 { 01211 // Make sure a valid file is open 01212 if(hMPFS > MAX_MPFS_HANDLES) 01213 return 0x0000; 01214 if(MPFSStubs[hMPFS].addr == MPFS_INVALID) 01215 return 0x0000; 01216 01217 //move to the point for reading 01218 _LoadFATRecord(MPFSStubs[hMPFS].fatID); 01219 return fatCache.flags; 01220 } 01221 01222 /***************************************************************************** 01223 Function: 01224 DWORD MPFSGetSize(MPFS_HANDLE hMPFS) 01225 01226 Description: 01227 Reads the size of a file. 01228 01229 Precondition: 01230 The file handle referenced by hMPFS is already open. 01231 01232 Parameters: 01233 hMPFS - the file handle from which to read the metadata 01234 01235 Returns: 01236 The size that was read as a DWORD 01237 ***************************************************************************/ 01238 DWORD MPFSGetSize(MPFS_HANDLE hMPFS) 01239 { 01240 // Make sure a valid file is open 01241 if(hMPFS > MAX_MPFS_HANDLES) 01242 return 0x00000000; 01243 if(MPFSStubs[hMPFS].addr == MPFS_INVALID) 01244 return 0x00000000; 01245 01246 // Move to the point for reading 01247 _LoadFATRecord(MPFSStubs[hMPFS].fatID); 01248 return fatCache.len; 01249 } 01250 01251 /***************************************************************************** 01252 Function: 01253 DWORD MPFSGetBytesRem(MPFS_HANDLE hMPFS) 01254 01255 Description: 01256 Determines how many bytes remain to be read. 01257 01258 Precondition: 01259 The file handle referenced by hMPFS is already open. 01260 01261 Parameters: 01262 hMPFS - the file handle from which to read the metadata 01263 01264 Returns: 01265 The number of bytes remaining in the file as a DWORD 01266 ***************************************************************************/ 01267 #if 0 01268 DWORD MPFSGetBytesRem(MPFS_HANDLE hMPFS) 01269 { 01270 // Make sure a valid file is open 01271 if(hMPFS > MAX_MPFS_HANDLES) 01272 return 0x00000000; 01273 if(MPFSStubs[hMPFS].addr == MPFS_INVALID) 01274 return 0x00000000; 01275 01276 return MPFSStubs[hMPFS].bytesRem; 01277 } 01278 #endif 01279 01280 /***************************************************************************** 01281 Function: 01282 MPFS_PTR MPFSGetStartAddr(MPFS_HANDLE hMPFS) 01283 01284 Description: 01285 Reads the starting address of a file. 01286 01287 Precondition: 01288 The file handle referenced by hMPFS is already open. 01289 01290 Parameters: 01291 hMPFS - the file handle from which to read the metadata 01292 01293 Returns: 01294 The starting address of the file in the MPFS image 01295 ***************************************************************************/ 01296 MPFS_PTR MPFSGetStartAddr(MPFS_HANDLE hMPFS) 01297 { 01298 // Make sure a valid file is open 01299 if(hMPFS > MAX_MPFS_HANDLES) 01300 return 0; 01301 if(MPFSStubs[hMPFS].addr == MPFS_INVALID) 01302 return MPFS_INVALID; 01303 01304 // Move to the point for reading 01305 _LoadFATRecord(MPFSStubs[hMPFS].fatID); 01306 return fatCache.data; 01307 } 01308 01309 /***************************************************************************** 01310 Function: 01311 MPFS_PTR MPFSGetEndAddr(MPFS_HANDLE hMPFS) 01312 01313 Description: 01314 Determines the ending address of a file. 01315 01316 Precondition: 01317 The file handle referenced by hMPFS is already open. 01318 01319 Parameters: 01320 hMPFS - the file handle from which to read the metadata 01321 01322 Returns: 01323 The address just after the file ends (start address of next file) 01324 ***************************************************************************/ 01325 MPFS_PTR MPFSGetEndAddr(MPFS_HANDLE hMPFS) 01326 { 01327 // Make sure a valid file is open 01328 if(hMPFS > MAX_MPFS_HANDLES) 01329 return MPFS_INVALID; 01330 if(MPFSStubs[hMPFS].addr == MPFS_INVALID) 01331 return MPFS_INVALID; 01332 01333 // Move to the point for reading 01334 _LoadFATRecord(MPFSStubs[hMPFS].fatID); 01335 return fatCache.data + fatCache.len; 01336 } 01337 01338 /***************************************************************************** 01339 Function: 01340 BOOL MPFSGetFilename(MPFS_HANDLE hMPFS, BYTE* cName, WORD wLen) 01341 01342 Description: 01343 Reads the file name of a file that is already open. 01344 01345 Precondition: 01346 The file handle referenced by hMPFS is already open. 01347 01348 Parameters: 01349 hMPFS - the file handle from which to determine the file name 01350 cName - where to store the name of the file 01351 wLen - the maximum length of data to store in cName 01352 01353 Return Values: 01354 TRUE - the file name was successfully located 01355 FALSE - the file handle provided is not currently open 01356 ***************************************************************************/ 01357 BOOL MPFSGetFilename(MPFS_HANDLE hMPFS, BYTE* cName, WORD wLen) 01358 { 01359 DWORD addr; 01360 01361 // Make sure a valid file is open 01362 if(hMPFS > MAX_MPFS_HANDLES) 01363 return FALSE; 01364 if(MPFSStubs[hMPFS].addr == MPFS_INVALID) 01365 return FALSE; 01366 01367 // Move to the point for reading 01368 _LoadFATRecord(MPFSStubs[hMPFS].fatID); 01369 addr = fatCache.string; 01370 MPFSStubs[0].addr = addr; 01371 MPFSStubs[0].bytesRem = 255; 01372 01373 // Read the value and return 01374 MPFSGetArray(0, cName, wLen); 01375 return TRUE; 01376 } 01377 01378 /***************************************************************************** 01379 Function: 01380 DWORD MPFSGetPosition(MPFS_HANDLE hMPFS) 01381 01382 Description: 01383 Determines the current position in the file 01384 01385 Precondition: 01386 The file handle referenced by hMPFS is already open. 01387 01388 Parameters: 01389 hMPFS - the file handle for which to determine position 01390 01391 Returns: 01392 The position in the file as a DWORD (or MPFS_PTR) 01393 01394 Remarks: 01395 Calling MPFSSeek(hMPFS, pos, MPFS_SEEK_START) will return the pointer 01396 to this position at a later time. (Where pos is the value returned by 01397 this function.) 01398 ***************************************************************************/ 01399 DWORD MPFSGetPosition(MPFS_HANDLE hMPFS) 01400 { 01401 return MPFSStubs[hMPFS].addr - MPFSGetStartAddr(hMPFS); 01402 } 01403 01404 /***************************************************************************** 01405 Function: 01406 WORD MPFSGetID(MPFS_HANDLE hMPFS) 01407 01408 Description: 01409 Determines the ID in the FAT for a file. 01410 01411 Precondition: 01412 The file handle referenced by hMPFS is already open. 01413 01414 Parameters: 01415 hMPFS - the file handle from which to read the metadata 01416 01417 Returns: 01418 The ID in the FAT for this file 01419 01420 Remarks: 01421 Use this function in association with MPFSOpenID to quickly access file 01422 without permanently reserving a file handle. 01423 ***************************************************************************/ 01424 WORD MPFSGetID(MPFS_HANDLE hMPFS) 01425 { 01426 return MPFSStubs[hMPFS].fatID; 01427 } 01428 01429 01430 /**************************************************************************** 01431 Section: 01432 Utility Functions 01433 ***************************************************************************/ 01434 01435 /***************************************************************************** 01436 Function: 01437 void _Validate(void) 01438 01439 Summary: 01440 Validates the MPFS Image 01441 01442 Description: 01443 Verifies that the MPFS image is valid, and reads the number of 01444 available files from the image header. This function is called on 01445 boot, and again after any image is written. 01446 01447 Precondition: 01448 None 01449 01450 Parameters: 01451 None 01452 01453 Returns: 01454 None 01455 ***************************************************************************/ 01456 static void _Validate(void) 01457 { 01458 // Validate the image and update numFiles 01459 MPFSStubs[0].addr = 0; 01460 MPFSStubs[0].bytesRem = 8; 01461 MPFSStubs[0].offset = 0; // MODIFIX: Added this line for huffman decoding. 01462 MPFSGetArray(0, (BYTE*)&fatCache, 6); 01463 if(!memcmppgm2ram((void*)&fatCache, (ROM void*)"MPFS\x02\x01", 6)) 01464 MPFSGetArray(0, (BYTE*)&numFiles, 2); 01465 else 01466 numFiles = 0; 01467 fatCacheID = MPFS_INVALID_FAT; 01468 } 01469 #endif //#if defined(STACK_USE_MPFS2)
1.5.5